From 4a6b768c4257cbb15451ce975bf0c0c3096c7e75 Mon Sep 17 00:00:00 2001 From: Dan Rosen Date: Sun, 17 Jul 2011 12:23:30 -0700 Subject: [PATCH 001/811] added Option.none_() for parity with some_(). --- core/src/main/fj/data/Option.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/fj/data/Option.java b/core/src/main/fj/data/Option.java index aa765424..70dea272 100644 --- a/core/src/main/fj/data/Option.java +++ b/core/src/main/fj/data/Option.java @@ -626,6 +626,14 @@ public static Option some(final T t) { return new Some(t); } + public static F> none_() { + return new F>() { + public Option f(final T t) { + return none(); + } + }; + } + /** * Constructs an optional value that has no value. * From ee4268bcb12931f21fef240ca306fd8992c8ce7a Mon Sep 17 00:00:00 2001 From: Martin Grotzke Date: Tue, 30 Aug 2011 22:26:22 +0200 Subject: [PATCH 002/811] Add isNullOrEmpty, isNullOrBlank and isNotNullOrBlank to Strings. --- core/src/main/java/fj/function/Strings.java | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index 4a1a159d..c1381f06 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -2,7 +2,10 @@ import fj.F; import fj.F2; +import fj.data.Stream; import static fj.Function.curry; +import static fj.function.Booleans.not; +import static fj.function.Characters.isWhitespace; /** * Curried string functions. @@ -14,8 +17,41 @@ private Strings() { throw new UnsupportedOperationException(); } + /** + * This function checks if a given String contains any non-whitespace character + * (according to {@link Character#isWhitespace(char)}) and if it's also not + * null and not empty (""). + * + * @see #isNullOrBlank + * @see Character#isWhitespace(char) + * @see Characters#isWhitespace + */ + public static final F isNotNullOrBlank = new F() { + @Override + public Boolean f(final String a) { + return isNotNullOrEmpty.f(a) && Stream.fromString(a).find(not(isWhitespace)).isSome(); + } + }; + + /** + * This function checks if a given String is whitespace (according to {@link Character#isWhitespace(char)}), + * empty ("") or null. + * + * @see #isNotNullOrBlank + * @see Character#isWhitespace(char) + * @see Characters#isWhitespace + */ + public static final F isNullOrBlank = new F() { + @Override + public Boolean f(final String a) { + return isNullOrEmpty.f(a) || Stream.fromString(a).find(not(isWhitespace)).isNone(); + } + }; + /** * This function checks if a given String is neither null nor empty. + * + * @see #isNullOrEmpty */ public static final F isNotNullOrEmpty = new F() { @Override @@ -24,6 +60,18 @@ public Boolean f(final String a) { } }; + /** + * This function checks if a given String is null or empty ({@link String#isEmpty()}). + * + * @see #isNotNullOrEmpty + */ + public static final F isNullOrEmpty = new F() { + @Override + public Boolean f(final String a) { + return a == null || a.length() == 0; + } + }; + /** * A curried version of {@link String#isEmpty()}. */ From 86d1b7c1f80f2fb51af091904e14782bfc3fc399 Mon Sep 17 00:00:00 2001 From: Piotr Bzdyl Date: Wed, 29 Feb 2012 09:47:15 +0100 Subject: [PATCH 003/811] Implemented scan operations. Added scanLeft, scanLeft1, scanRight and scanRight1 to Array class. --- core/src/main/java/fj/data/Array.java | 136 ++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) mode change 100644 => 100755 core/src/main/java/fj/data/Array.java diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java old mode 100644 new mode 100755 index 0f78de53..949367f0 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -291,6 +291,142 @@ public B foldLeft(final F2 f, final B b) { return foldLeft(curry(f), b); } + /** + * Performs a fold left accummulating and returns an array of the intermediate results. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (initial value/previous result and next array element) + * @param b The beginning value to start the application from. + * @return The array containing all intermediate results of the left-fold reduction. + */ + @SuppressWarnings({"unchecked"}) + public Array scanLeft(final F> f, final B b) { + final Object[] bs = new Object[a.length]; + B x = b; + + for (int i = 0; i < a.length; i++) { + x = f.f(x).f((A) a[i]); + bs[i] = x; + } + + return new Array(bs); + } + + /** + * Performs a left-fold accummulating and returns an array of the intermediate results. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (initial value/previous result and next array element) + * @param b The beginning value to start the application from. + * @return The array containing all intermediate results of the left-fold reduction. + */ + public Array scanLeft(final F2 f, final B b) { + return scanLeft(curry(f), b); + } + + /** + * Performs a left-fold accummulating using first array element as a starting value + * and returns an array of the intermediate results. + * It will fail for empty arrays. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (next array element and first array element/previous result) + * @return The array containing all intermediate results of the left-fold reduction. + */ + @SuppressWarnings({"unchecked"}) + public Array scanLeft1(final F> f) { + final Object[] bs = new Object[a.length]; + A x = get(0); + + for (int i = 1; i < a.length; i++) { + x = f.f(x).f((A) a[i]); + bs[i] = x; + } + + return new Array(bs); + } + + /** + * Performs a left-fold accummulating using first array element as a starting value + * and returns an array of the intermediate results. + * It will fail for empty arrays. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (next array element and first array element/previous result) + * @return The array containing all intermediate results of the left-fold reduction. + */ + public Array scanLeft1(final F2 f) { + return scanLeft1(curry(f)); + } + + /** + * Performs a right-fold accummulating and returns an array of the intermediate results. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (previous array element and initial value/previous result) + * @param b The beginning value to start the application from. + * @return The array containing all intermediate results of the right-fold reduction. + */ + @SuppressWarnings({"unchecked"}) + public Array scanRight(final F>f, final B b) { + final Object[] bs = new Object[a.length]; + B x = b; + + for (int i = a.length - 1; i >= 0; i--) { + x = f.f((A) a[i]).f(x); + bs[i] = x; + } + + return new Array(bs); + } + + /** + * Performs a right-fold accummulating and returns an array of the intermediate results. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (previous array element and initial value/previous result) + * @param b The beginning value to start the application from. + * @return The array containing all intermediate results of the right-fold reduction. + */ + public Array scanRight(final F2 f, final B b) { + return scanRight(curry(f), b); + } + + /** + * Performs a right-fold accummulating using last array element as a starting value + * and returns an array of the intermediate results. + * It will fail for empty arrays. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (previous array element and last array element/previous result) + * @return The array containing all intermediate results of the right-fold reduction. + */ + @SuppressWarnings({"unchecked"}) + public Array scanRight1(final F>f) { + final Object[] bs = new Object[a.length]; + A x = get(length() - 1); + + for (int i = a.length - 2; i >= 0; i--) { + x = f.f((A) a[i]).f(x); + bs[i] = x; + } + + return new Array(bs); + } + + /** + * Performs a right-fold accummulating using last array element as a starting value + * and returns an array of the intermediate results. + * It will fail for empty arrays. + * This function runs in constant stack space. + * + * @param f The function to apply on each argument pair (previous array element and last array element/previous result) + * @return The array containing all intermediate results of the right-fold reduction. + */ + public Array scanRight1(final F2 f) { + return scanRight1(curry(f)); + } + /** * Binds the given function across each element of this array with a final join. * From e07e5f858d9b259207621bb083faca243372e3a3 Mon Sep 17 00:00:00 2001 From: Piotr Bzdyl Date: Fri, 9 Mar 2012 12:08:40 +0100 Subject: [PATCH 004/811] Fixed scan1 functions. --- core/src/main/java/fj/data/Array.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 949367f0..bc29151f 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -337,6 +337,7 @@ public Array scanLeft(final F2 f, final B b) { public Array scanLeft1(final F> f) { final Object[] bs = new Object[a.length]; A x = get(0); + bs[0] = x; for (int i = 1; i < a.length; i++) { x = f.f(x).f((A) a[i]); @@ -405,6 +406,7 @@ public Array scanRight(final F2 f, final B b) { public Array scanRight1(final F>f) { final Object[] bs = new Object[a.length]; A x = get(length() - 1); + bs[length() - 1] = x; for (int i = a.length - 2; i >= 0; i--) { x = f.f((A) a[i]).f(x); From 9bbdf226779f1bcd66ed8b757b151a0ea684b06e Mon Sep 17 00:00:00 2001 From: Piotr Bzdyl Date: Fri, 9 Mar 2012 12:09:42 +0100 Subject: [PATCH 005/811] Added Array's scan functions tests. --- core/src/test/fj/data/CheckArray.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) mode change 100644 => 100755 core/src/test/fj/data/CheckArray.scala diff --git a/core/src/test/fj/data/CheckArray.scala b/core/src/test/fj/data/CheckArray.scala old mode 100644 new mode 100755 index 6dad84f0..a1c8a446 --- a/core/src/test/fj/data/CheckArray.scala +++ b/core/src/test/fj/data/CheckArray.scala @@ -62,6 +62,23 @@ object CheckArray extends Properties("Array") { a.foldLeft(((a: Array[String], b: String) => array[String](scala.Array(b): _*).append(a)), empty[String]), a.reverse.foldRight((a: String, b: Array[String]) => array[String](scala.Array(a): _*).append(b), empty[String]))) + property("scans") = forAll((a: Array[Int], z: Int) => { + val add = (x: Int, y: Int) => x + y + val left = a.scanLeft(add, z) + val right = a.reverse().scanRight(add, z).reverse() + + arrayEqual(Equal.anyEqual[Int]).eq(left, right) + }) + + property("scans1") = forAll((a: Array[Int]) => + (a.length() > 0) ==> { + val add = (x: Int, y: Int) => x + y + val left = a.scanLeft1(add) + val right = a.reverse().scanRight1(add).reverse() + + arrayEqual(Equal.anyEqual[Int]).eq(left, right) + }) + property("bindLeftIdentity") = forAll((a: Array[String], s: String) => { def f(s: String) = array[String](scala.Array(s.reverse): _*) arrayEqual(stringEqual).eq( From a90516b417b9aee6b55622918acd9fb239868aeb Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Tue, 14 May 2013 06:47:09 +0900 Subject: [PATCH 006/811] fix V8#tail javadoc --- core/src/main/java/fj/data/vector/V8.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index 4ed66206..c74d0d04 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -153,9 +153,9 @@ public A _8() { } /** - * Returns all but the first element of this vector, as a vector-6. + * Returns all but the first element of this vector, as a vector-7. * - * @return all but the first element of this vector, as a vector-6. + * @return all but the first element of this vector, as a vector-7. */ public V7 tail() { return tail; From 0ff8cfbe694e898b9046983f4559fc4bb557dfa3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 19 Nov 2013 13:10:01 +1000 Subject: [PATCH 007/811] Moved files to be suitable for Gradle project --- core/src/test/{ => scala}/fj/ArbitraryP.scala | 0 core/src/test/{ => scala}/fj/Implicit.scala | 0 core/src/test/scala/fj/JavaTest.java | 21 +++ core/src/test/{ => scala}/fj/Tests.scala | 0 .../control/parallel/ArbitraryParModule.scala | 0 .../control/parallel/ArbitraryStrategy.scala | 0 .../fj/control/parallel/CheckParModule.scala | 0 .../fj/control/parallel/CheckStrategy.scala | 0 .../{ => scala}/fj/data/ArbitraryArray.scala | 0 .../fj/data/ArbitraryHashMap.scala | 0 .../fj/data/ArbitraryHashSet.scala | 0 .../{ => scala}/fj/data/ArbitraryList.scala | 0 .../{ => scala}/fj/data/ArbitraryOption.scala | 0 .../{ => scala}/fj/data/ArbitrarySet.scala | 0 .../{ => scala}/fj/data/ArbitraryStream.scala | 0 .../{ => scala}/fj/data/ArbitraryTree.scala | 0 .../fj/data/ArbitraryTreeMap.scala | 0 .../test/{ => scala}/fj/data/CheckArray.scala | 0 .../{ => scala}/fj/data/CheckHashMap.scala | 0 .../{ => scala}/fj/data/CheckHashSet.scala | 0 .../test/{ => scala}/fj/data/CheckIO.scala | 0 .../{ => scala}/fj/data/CheckIteratee.scala | 0 .../test/{ => scala}/fj/data/CheckList.scala | 0 .../{ => scala}/fj/data/CheckOption.scala | 0 .../test/{ => scala}/fj/data/CheckSet.scala | 0 .../{ => scala}/fj/data/CheckStream.scala | 0 .../test/{ => scala}/fj/data/CheckTree.scala | 0 .../{ => scala}/fj/data/CheckTreeMap.scala | 0 core/src/test/{ => scala}/fj/package.scala | 0 .../main/{ => java}/fj/demo/Array_bind.java | 0 .../main/{ => java}/fj/demo/Array_exists.java | 0 .../main/{ => java}/fj/demo/Array_filter.java | 0 .../{ => java}/fj/demo/Array_foldLeft.java | 0 .../main/{ => java}/fj/demo/Array_forall.java | 0 .../main/{ => java}/fj/demo/Array_map.java | 0 .../main/{ => java}/fj/demo/ChequeWrite.java | 0 .../{ => java}/fj/demo/Comonad_example.java | 70 ++++---- .../main/{ => java}/fj/demo/HList_append.java | 80 ++++----- .../{ => java}/fj/demo/HList_foldRight.java | 0 .../main/{ => java}/fj/demo/List_apply.java | 32 ++-- .../src/main/{ => java}/fj/demo/List_map.java | 0 .../main/{ => java}/fj/demo/List_sort.java | 0 .../main/{ => java}/fj/demo/Option_bind.java | 0 .../{ => java}/fj/demo/Option_filter.java | 0 .../main/{ => java}/fj/demo/Option_map.java | 0 demo/src/main/{ => java}/fj/demo/Primes2.java | 82 ++++----- demo/src/main/{ => java}/fj/demo/Set_map.java | 40 ++--- .../main/{ => java}/fj/demo/Stream_Test.java | 32 ++-- .../{ => java}/fj/demo/TreeMap_Update.java | 38 ++-- .../{ => java}/fj/demo/concurrent/Fibs.java | 116 ++++++------- .../fj/demo/concurrent/MapReduce.java | 164 +++++++++--------- .../{ => java}/fj/demo/concurrent/Ping.java | 0 .../fj/demo/concurrent/PingPong.java | 0 .../{ => java}/fj/demo/concurrent/Pong.java | 0 .../fj/demo/concurrent/WordCount.java | 0 .../{ => java}/fj/demo/euler/Problem1.java | 36 ++-- .../{ => java}/fj/demo/euler/Problem2.java | 48 ++--- .../{ => java}/fj/demo/euler/Problem3.java | 110 ++++++------ .../{ => java}/fj/demo/euler/Problem4.java | 54 +++--- .../fj/demo/test/AdditionCommutes.java | 0 .../demo/test/AdditionCommutesParallel.java | 68 ++++---- .../fj/demo/test/EqualsHashCode.java | 0 .../fj/demo/test/IntegerOverflow.java | 0 .../fj/demo/test/JavaLinkedList.java | 0 .../fj/demo/test/ListFunctorLaws.java | 0 .../fj/demo/test/OptionMonadFunctorLaw.java | 0 .../main/{ => java}/fj/demo/test/Reflect.java | 0 .../fj/demo/test/StringBuilderReverse.java | 0 .../fj/demo/test/Triangulation.java | 0 69 files changed, 506 insertions(+), 485 deletions(-) rename core/src/test/{ => scala}/fj/ArbitraryP.scala (100%) rename core/src/test/{ => scala}/fj/Implicit.scala (100%) create mode 100644 core/src/test/scala/fj/JavaTest.java rename core/src/test/{ => scala}/fj/Tests.scala (100%) rename core/src/test/{ => scala}/fj/control/parallel/ArbitraryParModule.scala (100%) rename core/src/test/{ => scala}/fj/control/parallel/ArbitraryStrategy.scala (100%) rename core/src/test/{ => scala}/fj/control/parallel/CheckParModule.scala (100%) rename core/src/test/{ => scala}/fj/control/parallel/CheckStrategy.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryArray.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryHashMap.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryHashSet.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryList.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryOption.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitrarySet.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryStream.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryTree.scala (100%) rename core/src/test/{ => scala}/fj/data/ArbitraryTreeMap.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckArray.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckHashMap.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckHashSet.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckIO.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckIteratee.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckList.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckOption.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckSet.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckStream.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckTree.scala (100%) rename core/src/test/{ => scala}/fj/data/CheckTreeMap.scala (100%) rename core/src/test/{ => scala}/fj/package.scala (100%) rename demo/src/main/{ => java}/fj/demo/Array_bind.java (100%) rename demo/src/main/{ => java}/fj/demo/Array_exists.java (100%) rename demo/src/main/{ => java}/fj/demo/Array_filter.java (100%) rename demo/src/main/{ => java}/fj/demo/Array_foldLeft.java (100%) rename demo/src/main/{ => java}/fj/demo/Array_forall.java (100%) rename demo/src/main/{ => java}/fj/demo/Array_map.java (100%) rename demo/src/main/{ => java}/fj/demo/ChequeWrite.java (100%) rename demo/src/main/{ => java}/fj/demo/Comonad_example.java (97%) rename demo/src/main/{ => java}/fj/demo/HList_append.java (97%) rename demo/src/main/{ => java}/fj/demo/HList_foldRight.java (100%) rename demo/src/main/{ => java}/fj/demo/List_apply.java (96%) rename demo/src/main/{ => java}/fj/demo/List_map.java (100%) rename demo/src/main/{ => java}/fj/demo/List_sort.java (100%) rename demo/src/main/{ => java}/fj/demo/Option_bind.java (100%) rename demo/src/main/{ => java}/fj/demo/Option_filter.java (100%) rename demo/src/main/{ => java}/fj/demo/Option_map.java (100%) rename demo/src/main/{ => java}/fj/demo/Primes2.java (96%) rename demo/src/main/{ => java}/fj/demo/Set_map.java (96%) rename demo/src/main/{ => java}/fj/demo/Stream_Test.java (96%) rename demo/src/main/{ => java}/fj/demo/TreeMap_Update.java (96%) rename demo/src/main/{ => java}/fj/demo/concurrent/Fibs.java (97%) rename demo/src/main/{ => java}/fj/demo/concurrent/MapReduce.java (97%) rename demo/src/main/{ => java}/fj/demo/concurrent/Ping.java (100%) rename demo/src/main/{ => java}/fj/demo/concurrent/PingPong.java (100%) rename demo/src/main/{ => java}/fj/demo/concurrent/Pong.java (100%) rename demo/src/main/{ => java}/fj/demo/concurrent/WordCount.java (100%) rename demo/src/main/{ => java}/fj/demo/euler/Problem1.java (96%) rename demo/src/main/{ => java}/fj/demo/euler/Problem2.java (96%) rename demo/src/main/{ => java}/fj/demo/euler/Problem3.java (97%) rename demo/src/main/{ => java}/fj/demo/euler/Problem4.java (97%) rename demo/src/main/{ => java}/fj/demo/test/AdditionCommutes.java (100%) rename demo/src/main/{ => java}/fj/demo/test/AdditionCommutesParallel.java (97%) rename demo/src/main/{ => java}/fj/demo/test/EqualsHashCode.java (100%) rename demo/src/main/{ => java}/fj/demo/test/IntegerOverflow.java (100%) rename demo/src/main/{ => java}/fj/demo/test/JavaLinkedList.java (100%) rename demo/src/main/{ => java}/fj/demo/test/ListFunctorLaws.java (100%) rename demo/src/main/{ => java}/fj/demo/test/OptionMonadFunctorLaw.java (100%) rename demo/src/main/{ => java}/fj/demo/test/Reflect.java (100%) rename demo/src/main/{ => java}/fj/demo/test/StringBuilderReverse.java (100%) rename demo/src/main/{ => java}/fj/demo/test/Triangulation.java (100%) diff --git a/core/src/test/fj/ArbitraryP.scala b/core/src/test/scala/fj/ArbitraryP.scala similarity index 100% rename from core/src/test/fj/ArbitraryP.scala rename to core/src/test/scala/fj/ArbitraryP.scala diff --git a/core/src/test/fj/Implicit.scala b/core/src/test/scala/fj/Implicit.scala similarity index 100% rename from core/src/test/fj/Implicit.scala rename to core/src/test/scala/fj/Implicit.scala diff --git a/core/src/test/scala/fj/JavaTest.java b/core/src/test/scala/fj/JavaTest.java new file mode 100644 index 00000000..3882de89 --- /dev/null +++ b/core/src/test/scala/fj/JavaTest.java @@ -0,0 +1,21 @@ +package fj; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created with IntelliJ IDEA. + * User: MarkPerry + * Date: 19/11/13 + * Time: 12:06 PM + * To change this template use File | Settings | File Templates. + */ +public class JavaTest { + + @Test + public void test1() { + System.out.println("Hello world"); + Assert.assertTrue(true); + } + +} diff --git a/core/src/test/fj/Tests.scala b/core/src/test/scala/fj/Tests.scala similarity index 100% rename from core/src/test/fj/Tests.scala rename to core/src/test/scala/fj/Tests.scala diff --git a/core/src/test/fj/control/parallel/ArbitraryParModule.scala b/core/src/test/scala/fj/control/parallel/ArbitraryParModule.scala similarity index 100% rename from core/src/test/fj/control/parallel/ArbitraryParModule.scala rename to core/src/test/scala/fj/control/parallel/ArbitraryParModule.scala diff --git a/core/src/test/fj/control/parallel/ArbitraryStrategy.scala b/core/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala similarity index 100% rename from core/src/test/fj/control/parallel/ArbitraryStrategy.scala rename to core/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala diff --git a/core/src/test/fj/control/parallel/CheckParModule.scala b/core/src/test/scala/fj/control/parallel/CheckParModule.scala similarity index 100% rename from core/src/test/fj/control/parallel/CheckParModule.scala rename to core/src/test/scala/fj/control/parallel/CheckParModule.scala diff --git a/core/src/test/fj/control/parallel/CheckStrategy.scala b/core/src/test/scala/fj/control/parallel/CheckStrategy.scala similarity index 100% rename from core/src/test/fj/control/parallel/CheckStrategy.scala rename to core/src/test/scala/fj/control/parallel/CheckStrategy.scala diff --git a/core/src/test/fj/data/ArbitraryArray.scala b/core/src/test/scala/fj/data/ArbitraryArray.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryArray.scala rename to core/src/test/scala/fj/data/ArbitraryArray.scala diff --git a/core/src/test/fj/data/ArbitraryHashMap.scala b/core/src/test/scala/fj/data/ArbitraryHashMap.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryHashMap.scala rename to core/src/test/scala/fj/data/ArbitraryHashMap.scala diff --git a/core/src/test/fj/data/ArbitraryHashSet.scala b/core/src/test/scala/fj/data/ArbitraryHashSet.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryHashSet.scala rename to core/src/test/scala/fj/data/ArbitraryHashSet.scala diff --git a/core/src/test/fj/data/ArbitraryList.scala b/core/src/test/scala/fj/data/ArbitraryList.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryList.scala rename to core/src/test/scala/fj/data/ArbitraryList.scala diff --git a/core/src/test/fj/data/ArbitraryOption.scala b/core/src/test/scala/fj/data/ArbitraryOption.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryOption.scala rename to core/src/test/scala/fj/data/ArbitraryOption.scala diff --git a/core/src/test/fj/data/ArbitrarySet.scala b/core/src/test/scala/fj/data/ArbitrarySet.scala similarity index 100% rename from core/src/test/fj/data/ArbitrarySet.scala rename to core/src/test/scala/fj/data/ArbitrarySet.scala diff --git a/core/src/test/fj/data/ArbitraryStream.scala b/core/src/test/scala/fj/data/ArbitraryStream.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryStream.scala rename to core/src/test/scala/fj/data/ArbitraryStream.scala diff --git a/core/src/test/fj/data/ArbitraryTree.scala b/core/src/test/scala/fj/data/ArbitraryTree.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryTree.scala rename to core/src/test/scala/fj/data/ArbitraryTree.scala diff --git a/core/src/test/fj/data/ArbitraryTreeMap.scala b/core/src/test/scala/fj/data/ArbitraryTreeMap.scala similarity index 100% rename from core/src/test/fj/data/ArbitraryTreeMap.scala rename to core/src/test/scala/fj/data/ArbitraryTreeMap.scala diff --git a/core/src/test/fj/data/CheckArray.scala b/core/src/test/scala/fj/data/CheckArray.scala similarity index 100% rename from core/src/test/fj/data/CheckArray.scala rename to core/src/test/scala/fj/data/CheckArray.scala diff --git a/core/src/test/fj/data/CheckHashMap.scala b/core/src/test/scala/fj/data/CheckHashMap.scala similarity index 100% rename from core/src/test/fj/data/CheckHashMap.scala rename to core/src/test/scala/fj/data/CheckHashMap.scala diff --git a/core/src/test/fj/data/CheckHashSet.scala b/core/src/test/scala/fj/data/CheckHashSet.scala similarity index 100% rename from core/src/test/fj/data/CheckHashSet.scala rename to core/src/test/scala/fj/data/CheckHashSet.scala diff --git a/core/src/test/fj/data/CheckIO.scala b/core/src/test/scala/fj/data/CheckIO.scala similarity index 100% rename from core/src/test/fj/data/CheckIO.scala rename to core/src/test/scala/fj/data/CheckIO.scala diff --git a/core/src/test/fj/data/CheckIteratee.scala b/core/src/test/scala/fj/data/CheckIteratee.scala similarity index 100% rename from core/src/test/fj/data/CheckIteratee.scala rename to core/src/test/scala/fj/data/CheckIteratee.scala diff --git a/core/src/test/fj/data/CheckList.scala b/core/src/test/scala/fj/data/CheckList.scala similarity index 100% rename from core/src/test/fj/data/CheckList.scala rename to core/src/test/scala/fj/data/CheckList.scala diff --git a/core/src/test/fj/data/CheckOption.scala b/core/src/test/scala/fj/data/CheckOption.scala similarity index 100% rename from core/src/test/fj/data/CheckOption.scala rename to core/src/test/scala/fj/data/CheckOption.scala diff --git a/core/src/test/fj/data/CheckSet.scala b/core/src/test/scala/fj/data/CheckSet.scala similarity index 100% rename from core/src/test/fj/data/CheckSet.scala rename to core/src/test/scala/fj/data/CheckSet.scala diff --git a/core/src/test/fj/data/CheckStream.scala b/core/src/test/scala/fj/data/CheckStream.scala similarity index 100% rename from core/src/test/fj/data/CheckStream.scala rename to core/src/test/scala/fj/data/CheckStream.scala diff --git a/core/src/test/fj/data/CheckTree.scala b/core/src/test/scala/fj/data/CheckTree.scala similarity index 100% rename from core/src/test/fj/data/CheckTree.scala rename to core/src/test/scala/fj/data/CheckTree.scala diff --git a/core/src/test/fj/data/CheckTreeMap.scala b/core/src/test/scala/fj/data/CheckTreeMap.scala similarity index 100% rename from core/src/test/fj/data/CheckTreeMap.scala rename to core/src/test/scala/fj/data/CheckTreeMap.scala diff --git a/core/src/test/fj/package.scala b/core/src/test/scala/fj/package.scala similarity index 100% rename from core/src/test/fj/package.scala rename to core/src/test/scala/fj/package.scala diff --git a/demo/src/main/fj/demo/Array_bind.java b/demo/src/main/java/fj/demo/Array_bind.java similarity index 100% rename from demo/src/main/fj/demo/Array_bind.java rename to demo/src/main/java/fj/demo/Array_bind.java diff --git a/demo/src/main/fj/demo/Array_exists.java b/demo/src/main/java/fj/demo/Array_exists.java similarity index 100% rename from demo/src/main/fj/demo/Array_exists.java rename to demo/src/main/java/fj/demo/Array_exists.java diff --git a/demo/src/main/fj/demo/Array_filter.java b/demo/src/main/java/fj/demo/Array_filter.java similarity index 100% rename from demo/src/main/fj/demo/Array_filter.java rename to demo/src/main/java/fj/demo/Array_filter.java diff --git a/demo/src/main/fj/demo/Array_foldLeft.java b/demo/src/main/java/fj/demo/Array_foldLeft.java similarity index 100% rename from demo/src/main/fj/demo/Array_foldLeft.java rename to demo/src/main/java/fj/demo/Array_foldLeft.java diff --git a/demo/src/main/fj/demo/Array_forall.java b/demo/src/main/java/fj/demo/Array_forall.java similarity index 100% rename from demo/src/main/fj/demo/Array_forall.java rename to demo/src/main/java/fj/demo/Array_forall.java diff --git a/demo/src/main/fj/demo/Array_map.java b/demo/src/main/java/fj/demo/Array_map.java similarity index 100% rename from demo/src/main/fj/demo/Array_map.java rename to demo/src/main/java/fj/demo/Array_map.java diff --git a/demo/src/main/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java similarity index 100% rename from demo/src/main/fj/demo/ChequeWrite.java rename to demo/src/main/java/fj/demo/ChequeWrite.java diff --git a/demo/src/main/fj/demo/Comonad_example.java b/demo/src/main/java/fj/demo/Comonad_example.java similarity index 97% rename from demo/src/main/fj/demo/Comonad_example.java rename to demo/src/main/java/fj/demo/Comonad_example.java index c7c887d7..169a534f 100644 --- a/demo/src/main/fj/demo/Comonad_example.java +++ b/demo/src/main/java/fj/demo/Comonad_example.java @@ -1,35 +1,35 @@ -package fj.demo; - -import fj.F; -import fj.P; -import static fj.data.List.asString; -import static fj.data.List.fromString; -import fj.data.Stream; -import static fj.data.Stream.join; -import static fj.data.Stream.single; -import fj.data.Zipper; -import static fj.data.Zipper.fromStream; - -/** - * Example of using a Zipper comonad to get all the permutations of a String. - */ - -public class Comonad_example { - public static void main(final String[] args) { - for (final Stream p : perms(fromString(args[0]).toStream())) { - System.out.println(asString(p.toList())); - } - } - - public static Stream> perms(final Stream s) { - Stream> r = single(Stream.nil()); - for (final Zipper z : fromStream(s)) - r = join(z.cobind(new F, Stream>>() { - public Stream> f(final Zipper zp) { - return perms(zp.lefts().reverse().append(zp.rights())) - .map(Stream.cons().f(zp.focus()).o(P.>p1())); - } - }).toStream()); - return r; - } -} +package fj.demo; + +import fj.F; +import fj.P; +import static fj.data.List.asString; +import static fj.data.List.fromString; +import fj.data.Stream; +import static fj.data.Stream.join; +import static fj.data.Stream.single; +import fj.data.Zipper; +import static fj.data.Zipper.fromStream; + +/** + * Example of using a Zipper comonad to get all the permutations of a String. + */ + +public class Comonad_example { + public static void main(final String[] args) { + for (final Stream p : perms(fromString(args[0]).toStream())) { + System.out.println(asString(p.toList())); + } + } + + public static Stream> perms(final Stream s) { + Stream> r = single(Stream.nil()); + for (final Zipper z : fromStream(s)) + r = join(z.cobind(new F, Stream>>() { + public Stream> f(final Zipper zp) { + return perms(zp.lefts().reverse().append(zp.rights())) + .map(Stream.cons().f(zp.focus()).o(P.>p1())); + } + }).toStream()); + return r; + } +} diff --git a/demo/src/main/fj/demo/HList_append.java b/demo/src/main/java/fj/demo/HList_append.java similarity index 97% rename from demo/src/main/fj/demo/HList_append.java rename to demo/src/main/java/fj/demo/HList_append.java index a1dc3efa..28405dbe 100644 --- a/demo/src/main/fj/demo/HList_append.java +++ b/demo/src/main/java/fj/demo/HList_append.java @@ -1,40 +1,40 @@ -package fj.demo; - -import static fj.data.hlist.HList.HCons; -import static fj.data.hlist.HList.HNil; -import static fj.data.hlist.HList.HAppend.append; -import static fj.data.hlist.HList.HAppend; -import static fj.data.hlist.HList.nil; - -/** - * Append two heterogeneous lists - */ -public class HList_append { - public static void main(final String[] args) { - // The two lists - final HCons>> a = - nil().extend(true).extend(3).extend("Foo"); - final HCons>> b = - nil().extend(new Integer[]{1, 2}).extend("Bar").extend(4.0); - - // A lot of type annotation - final HAppend>>, - HCons>>> zero = append(); - final HAppend, HCons>>, - HCons>>>> one = append(zero); - final HAppend>, HCons>>, - HCons>>>>> two = append(one); - final HAppend>>, - HCons>>, - HCons>>>>>> - three = append(two); - - // And all of that lets us append one list to the other. - final HCons>>>>> - x = three.append(a, b); - - // And we can access the components of the concatenated list in a type-safe manner - System.out.println(x.head()); // Foo - System.out.println(x.tail().tail().tail().tail().head()); // Bar - } -} +package fj.demo; + +import static fj.data.hlist.HList.HCons; +import static fj.data.hlist.HList.HNil; +import static fj.data.hlist.HList.HAppend.append; +import static fj.data.hlist.HList.HAppend; +import static fj.data.hlist.HList.nil; + +/** + * Append two heterogeneous lists + */ +public class HList_append { + public static void main(final String[] args) { + // The two lists + final HCons>> a = + nil().extend(true).extend(3).extend("Foo"); + final HCons>> b = + nil().extend(new Integer[]{1, 2}).extend("Bar").extend(4.0); + + // A lot of type annotation + final HAppend>>, + HCons>>> zero = append(); + final HAppend, HCons>>, + HCons>>>> one = append(zero); + final HAppend>, HCons>>, + HCons>>>>> two = append(one); + final HAppend>>, + HCons>>, + HCons>>>>>> + three = append(two); + + // And all of that lets us append one list to the other. + final HCons>>>>> + x = three.append(a, b); + + // And we can access the components of the concatenated list in a type-safe manner + System.out.println(x.head()); // Foo + System.out.println(x.tail().tail().tail().tail().head()); // Bar + } +} diff --git a/demo/src/main/fj/demo/HList_foldRight.java b/demo/src/main/java/fj/demo/HList_foldRight.java similarity index 100% rename from demo/src/main/fj/demo/HList_foldRight.java rename to demo/src/main/java/fj/demo/HList_foldRight.java diff --git a/demo/src/main/fj/demo/List_apply.java b/demo/src/main/java/fj/demo/List_apply.java similarity index 96% rename from demo/src/main/fj/demo/List_apply.java rename to demo/src/main/java/fj/demo/List_apply.java index 09c00505..022ec63b 100644 --- a/demo/src/main/fj/demo/List_apply.java +++ b/demo/src/main/java/fj/demo/List_apply.java @@ -1,17 +1,17 @@ -package fj.demo; - -import fj.F; -import fj.data.List; -import static fj.data.List.list; -import static fj.data.List.single; -import static fj.function.Integers.*; -import static fj.Show.intShow; -import static fj.Show.listShow; - -public class List_apply { - public static void main(final String[] a) { - final List> fs = single(subtract.f(2)).cons(multiply.f(2)).cons(add.f(2)); - final List three = list(3); - listShow(intShow).println(three.apply(fs)); // Prints out: <5,6,-1> - } +package fj.demo; + +import fj.F; +import fj.data.List; +import static fj.data.List.list; +import static fj.data.List.single; +import static fj.function.Integers.*; +import static fj.Show.intShow; +import static fj.Show.listShow; + +public class List_apply { + public static void main(final String[] a) { + final List> fs = single(subtract.f(2)).cons(multiply.f(2)).cons(add.f(2)); + final List three = list(3); + listShow(intShow).println(three.apply(fs)); // Prints out: <5,6,-1> + } } \ No newline at end of file diff --git a/demo/src/main/fj/demo/List_map.java b/demo/src/main/java/fj/demo/List_map.java similarity index 100% rename from demo/src/main/fj/demo/List_map.java rename to demo/src/main/java/fj/demo/List_map.java diff --git a/demo/src/main/fj/demo/List_sort.java b/demo/src/main/java/fj/demo/List_sort.java similarity index 100% rename from demo/src/main/fj/demo/List_sort.java rename to demo/src/main/java/fj/demo/List_sort.java diff --git a/demo/src/main/fj/demo/Option_bind.java b/demo/src/main/java/fj/demo/Option_bind.java similarity index 100% rename from demo/src/main/fj/demo/Option_bind.java rename to demo/src/main/java/fj/demo/Option_bind.java diff --git a/demo/src/main/fj/demo/Option_filter.java b/demo/src/main/java/fj/demo/Option_filter.java similarity index 100% rename from demo/src/main/fj/demo/Option_filter.java rename to demo/src/main/java/fj/demo/Option_filter.java diff --git a/demo/src/main/fj/demo/Option_map.java b/demo/src/main/java/fj/demo/Option_map.java similarity index 100% rename from demo/src/main/fj/demo/Option_map.java rename to demo/src/main/java/fj/demo/Option_map.java diff --git a/demo/src/main/fj/demo/Primes2.java b/demo/src/main/java/fj/demo/Primes2.java similarity index 96% rename from demo/src/main/fj/demo/Primes2.java rename to demo/src/main/java/fj/demo/Primes2.java index 7abe85f8..c2d71204 100644 --- a/demo/src/main/fj/demo/Primes2.java +++ b/demo/src/main/java/fj/demo/Primes2.java @@ -1,41 +1,41 @@ -package fj.demo; - -import fj.P1; -import static fj.data.Enumerator.naturalEnumerator; - -import fj.Show; -import fj.data.Natural; -import static fj.data.Natural.*; -import fj.data.Stream; -import static fj.data.Stream.*; -import static fj.Ord.naturalOrd; -import static fj.Show.naturalShow; -import static fj.Show.streamShow; - -import java.math.BigInteger; - -/** - * Prints all primes less than n - */ -public class Primes2 { - // Finds primes in a given stream. - public static Stream sieve(final Stream xs) { - return cons(xs.head(), new P1>() { - public Stream _1() { - return sieve(xs.tail()._1().removeAll(naturalOrd.equal().eq(ZERO).o(mod.f(xs.head())))); - } - }); - } - - // A stream of all primes less than n. - public static Stream primes(final Natural n) { - return sieve(forever(naturalEnumerator, natural(2).some())).takeWhile(naturalOrd.isLessThan(n)); - } - - public static void main(final String[] a) { - final Natural n = natural(new BigInteger(a[0])).some(); - final Show> s = streamShow(naturalShow); - - s.println(primes(n)); - } -} +package fj.demo; + +import fj.P1; +import static fj.data.Enumerator.naturalEnumerator; + +import fj.Show; +import fj.data.Natural; +import static fj.data.Natural.*; +import fj.data.Stream; +import static fj.data.Stream.*; +import static fj.Ord.naturalOrd; +import static fj.Show.naturalShow; +import static fj.Show.streamShow; + +import java.math.BigInteger; + +/** + * Prints all primes less than n + */ +public class Primes2 { + // Finds primes in a given stream. + public static Stream sieve(final Stream xs) { + return cons(xs.head(), new P1>() { + public Stream _1() { + return sieve(xs.tail()._1().removeAll(naturalOrd.equal().eq(ZERO).o(mod.f(xs.head())))); + } + }); + } + + // A stream of all primes less than n. + public static Stream primes(final Natural n) { + return sieve(forever(naturalEnumerator, natural(2).some())).takeWhile(naturalOrd.isLessThan(n)); + } + + public static void main(final String[] a) { + final Natural n = natural(new BigInteger(a[0])).some(); + final Show> s = streamShow(naturalShow); + + s.println(primes(n)); + } +} diff --git a/demo/src/main/fj/demo/Set_map.java b/demo/src/main/java/fj/demo/Set_map.java similarity index 96% rename from demo/src/main/fj/demo/Set_map.java rename to demo/src/main/java/fj/demo/Set_map.java index 4b0c142c..592057ca 100644 --- a/demo/src/main/fj/demo/Set_map.java +++ b/demo/src/main/java/fj/demo/Set_map.java @@ -1,20 +1,20 @@ -package fj.demo; - -import fj.F; -import fj.data.Set; -import static fj.data.Set.empty; -import fj.Ord; -import static fj.Show.intShow; -import static fj.Show.listShow; - -public final class Set_map { - public static void main(final String[] args) { - final Set a = empty(Ord.intOrd).insert(1).insert(2).insert(3).insert(4).insert(5).insert(6); - final Set b = a.map(Ord.intOrd, new F() { - public Integer f(final Integer i) { - return i / 2; // divide each integer by 2 - } - }); - listShow(intShow).println(b.toList()); // [3,2,1,0] - } -} +package fj.demo; + +import fj.F; +import fj.data.Set; +import static fj.data.Set.empty; +import fj.Ord; +import static fj.Show.intShow; +import static fj.Show.listShow; + +public final class Set_map { + public static void main(final String[] args) { + final Set a = empty(Ord.intOrd).insert(1).insert(2).insert(3).insert(4).insert(5).insert(6); + final Set b = a.map(Ord.intOrd, new F() { + public Integer f(final Integer i) { + return i / 2; // divide each integer by 2 + } + }); + listShow(intShow).println(b.toList()); // [3,2,1,0] + } +} diff --git a/demo/src/main/fj/demo/Stream_Test.java b/demo/src/main/java/fj/demo/Stream_Test.java similarity index 96% rename from demo/src/main/fj/demo/Stream_Test.java rename to demo/src/main/java/fj/demo/Stream_Test.java index 967f6ff4..47dd5937 100644 --- a/demo/src/main/fj/demo/Stream_Test.java +++ b/demo/src/main/java/fj/demo/Stream_Test.java @@ -1,16 +1,16 @@ -package fj.demo; - -import static fj.data.Enumerator.naturalEnumerator; -import static fj.data.Natural.natural; -import static fj.data.Stream.forever; -import static fj.Show.naturalShow; -import static fj.Show.unlineShow; - -/** - * Produces natural numbers forever. - */ -public class Stream_Test { - public static void main(final String[] args) { - unlineShow(naturalShow).println(forever(naturalEnumerator, natural(3).some(), 2)); - } -} +package fj.demo; + +import static fj.data.Enumerator.naturalEnumerator; +import static fj.data.Natural.natural; +import static fj.data.Stream.forever; +import static fj.Show.naturalShow; +import static fj.Show.unlineShow; + +/** + * Produces natural numbers forever. + */ +public class Stream_Test { + public static void main(final String[] args) { + unlineShow(naturalShow).println(forever(naturalEnumerator, natural(3).some(), 2)); + } +} diff --git a/demo/src/main/fj/demo/TreeMap_Update.java b/demo/src/main/java/fj/demo/TreeMap_Update.java similarity index 96% rename from demo/src/main/fj/demo/TreeMap_Update.java rename to demo/src/main/java/fj/demo/TreeMap_Update.java index 614134f0..b73fda5d 100644 --- a/demo/src/main/fj/demo/TreeMap_Update.java +++ b/demo/src/main/java/fj/demo/TreeMap_Update.java @@ -1,19 +1,19 @@ -package fj.demo; - -import fj.data.TreeMap; -import static fj.data.TreeMap.empty; -import static fj.function.Integers.add; -import static fj.Ord.stringOrd; - -/** - * Queries and updates an entry in a TreeMap in one go. - */ -public class TreeMap_Update { - public static void main(final String[] a) { - TreeMap map = empty(stringOrd); - map = map.set("foo", 2); - map = map.update("foo", add.f(3))._2(); - System.out.println(map.get("foo").some()); // 5 - } -} - +package fj.demo; + +import fj.data.TreeMap; +import static fj.data.TreeMap.empty; +import static fj.function.Integers.add; +import static fj.Ord.stringOrd; + +/** + * Queries and updates an entry in a TreeMap in one go. + */ +public class TreeMap_Update { + public static void main(final String[] a) { + TreeMap map = empty(stringOrd); + map = map.set("foo", 2); + map = map.update("foo", add.f(3))._2(); + System.out.println(map.get("foo").some()); // 5 + } +} + diff --git a/demo/src/main/fj/demo/concurrent/Fibs.java b/demo/src/main/java/fj/demo/concurrent/Fibs.java similarity index 97% rename from demo/src/main/fj/demo/concurrent/Fibs.java rename to demo/src/main/java/fj/demo/concurrent/Fibs.java index 1e06df4d..018f92a5 100644 --- a/demo/src/main/fj/demo/concurrent/Fibs.java +++ b/demo/src/main/java/fj/demo/concurrent/Fibs.java @@ -1,58 +1,58 @@ -package fj.demo.concurrent; - -import static fj.Bottom.error; -import fj.Effect; -import fj.F; -import fj.P; -import fj.P2; -import fj.Unit; -import fj.data.List; -import fj.control.parallel.Actor; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import static fj.data.List.range; -import static fj.function.Integers.add; -import static fj.control.parallel.Promise.join; -import static fj.control.parallel.Promise.promise; -import static fj.control.parallel.Actor.actor; - -import java.text.MessageFormat; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/** - * Parallel Fibonacci numbers. - * Based on a Haskell example by Don Stewart. - * Author: Runar - */ -public class Fibs - {private static final int CUTOFF = 35; - - public static void main(final String[] args) - {if (args.length < 1) - throw error("This program takes an argument: number_of_threads"); - - final int threads = Integer.parseInt(args[0]); - final ExecutorService pool = Executors.newFixedThreadPool(threads); - final Strategy su = Strategy.executorStrategy(pool); - final Strategy> spi = Strategy.executorStrategy(pool); - - // This actor performs output and detects the termination condition. - final Actor> out = actor(su, new Effect>() - {public void e(final List fs) - {for (final P2 p : fs.zipIndex()) - {System.out.println(MessageFormat.format("n={0} => {1}", p._2(), p._1()));} - pool.shutdown();}}); - - // A parallel recursive Fibonacci function - final F> fib = new F>() - {public Promise f(final Integer n) - {return n < CUTOFF ? promise(su, P.p(seqFib(n))) : f(n - 1).bind(f(n - 2), add);}}; - - System.out.println("Calculating Fibonacci sequence in parallel..."); - join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} - - // The sequential version of the recursive Fibonacci function - public static int seqFib(final int n) - {return n < 2 ? n : seqFib(n - 1) + seqFib(n - 2);}} - +package fj.demo.concurrent; + +import static fj.Bottom.error; +import fj.Effect; +import fj.F; +import fj.P; +import fj.P2; +import fj.Unit; +import fj.data.List; +import fj.control.parallel.Actor; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import static fj.data.List.range; +import static fj.function.Integers.add; +import static fj.control.parallel.Promise.join; +import static fj.control.parallel.Promise.promise; +import static fj.control.parallel.Actor.actor; + +import java.text.MessageFormat; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Parallel Fibonacci numbers. + * Based on a Haskell example by Don Stewart. + * Author: Runar + */ +public class Fibs + {private static final int CUTOFF = 35; + + public static void main(final String[] args) + {if (args.length < 1) + throw error("This program takes an argument: number_of_threads"); + + final int threads = Integer.parseInt(args[0]); + final ExecutorService pool = Executors.newFixedThreadPool(threads); + final Strategy su = Strategy.executorStrategy(pool); + final Strategy> spi = Strategy.executorStrategy(pool); + + // This actor performs output and detects the termination condition. + final Actor> out = actor(su, new Effect>() + {public void e(final List fs) + {for (final P2 p : fs.zipIndex()) + {System.out.println(MessageFormat.format("n={0} => {1}", p._2(), p._1()));} + pool.shutdown();}}); + + // A parallel recursive Fibonacci function + final F> fib = new F>() + {public Promise f(final Integer n) + {return n < CUTOFF ? promise(su, P.p(seqFib(n))) : f(n - 1).bind(f(n - 2), add);}}; + + System.out.println("Calculating Fibonacci sequence in parallel..."); + join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} + + // The sequential version of the recursive Fibonacci function + public static int seqFib(final int n) + {return n < 2 ? n : seqFib(n - 1) + seqFib(n - 2);}} + diff --git a/demo/src/main/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java similarity index 97% rename from demo/src/main/fj/demo/concurrent/MapReduce.java rename to demo/src/main/java/fj/demo/concurrent/MapReduce.java index 16794bef..f4f4d8b5 100644 --- a/demo/src/main/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -1,83 +1,83 @@ -package fj.demo.concurrent; - -import fj.F; -import fj.P1; -import fj.Unit; -import fj.control.parallel.ParModule; -import static fj.control.parallel.ParModule.parModule; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import static fj.data.LazyString.fromStream; -import fj.data.List; -import static fj.data.List.list; -import fj.data.Option; -import static fj.data.Option.fromNull; -import fj.data.Stream; -import static fj.data.Stream.fromString; -import static fj.Monoid.longAdditionMonoid; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.concurrent.ExecutorService; -import static java.util.concurrent.Executors.newFixedThreadPool; - -/* Performs a parallel word count over files given as program arguments. */ -public class MapReduce { - - // Count words of documents in parallel - public static Promise countWords(final List> documents, - final ParModule m) { - return m.parFoldMap(documents, new F, Long>() { - public Long f(final Stream document) { - return (long) fromStream(document).words().length(); - } - }, longAdditionMonoid); - } - - // Main program does the requisite IO gymnastics - public static void main(final String[] args) { - final List> documents = list(args).map( - new F() { - public BufferedReader f(final String fileName) { - try { - return new BufferedReader(new FileReader(new File(fileName))); - } catch (FileNotFoundException e) { - throw new Error(e); - } - } - }.andThen(new F>() { - public Stream f(final BufferedReader reader) { - final Option s; - try { - s = fromNull(reader.readLine()); - } catch (IOException e) { - throw new Error(e); - } - if (s.isSome()) - return fromString(s.some()).append(new P1>() { - public Stream _1() { - return f(reader); - } - }); - else { - try { - reader.close(); - } catch (IOException e) { - throw new Error(e); - } - return Stream.nil(); - } - } - })); - - final ExecutorService pool = newFixedThreadPool(16); - final ParModule m = parModule(Strategy.executorStrategy(pool)); - - System.out.println("Word Count: " + countWords(documents, m).claim()); - - pool.shutdown(); - } +package fj.demo.concurrent; + +import fj.F; +import fj.P1; +import fj.Unit; +import fj.control.parallel.ParModule; +import static fj.control.parallel.ParModule.parModule; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import static fj.data.LazyString.fromStream; +import fj.data.List; +import static fj.data.List.list; +import fj.data.Option; +import static fj.data.Option.fromNull; +import fj.data.Stream; +import static fj.data.Stream.fromString; +import static fj.Monoid.longAdditionMonoid; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import static java.util.concurrent.Executors.newFixedThreadPool; + +/* Performs a parallel word count over files given as program arguments. */ +public class MapReduce { + + // Count words of documents in parallel + public static Promise countWords(final List> documents, + final ParModule m) { + return m.parFoldMap(documents, new F, Long>() { + public Long f(final Stream document) { + return (long) fromStream(document).words().length(); + } + }, longAdditionMonoid); + } + + // Main program does the requisite IO gymnastics + public static void main(final String[] args) { + final List> documents = list(args).map( + new F() { + public BufferedReader f(final String fileName) { + try { + return new BufferedReader(new FileReader(new File(fileName))); + } catch (FileNotFoundException e) { + throw new Error(e); + } + } + }.andThen(new F>() { + public Stream f(final BufferedReader reader) { + final Option s; + try { + s = fromNull(reader.readLine()); + } catch (IOException e) { + throw new Error(e); + } + if (s.isSome()) + return fromString(s.some()).append(new P1>() { + public Stream _1() { + return f(reader); + } + }); + else { + try { + reader.close(); + } catch (IOException e) { + throw new Error(e); + } + return Stream.nil(); + } + } + })); + + final ExecutorService pool = newFixedThreadPool(16); + final ParModule m = parModule(Strategy.executorStrategy(pool)); + + System.out.println("Word Count: " + countWords(documents, m).claim()); + + pool.shutdown(); + } } \ No newline at end of file diff --git a/demo/src/main/fj/demo/concurrent/Ping.java b/demo/src/main/java/fj/demo/concurrent/Ping.java similarity index 100% rename from demo/src/main/fj/demo/concurrent/Ping.java rename to demo/src/main/java/fj/demo/concurrent/Ping.java diff --git a/demo/src/main/fj/demo/concurrent/PingPong.java b/demo/src/main/java/fj/demo/concurrent/PingPong.java similarity index 100% rename from demo/src/main/fj/demo/concurrent/PingPong.java rename to demo/src/main/java/fj/demo/concurrent/PingPong.java diff --git a/demo/src/main/fj/demo/concurrent/Pong.java b/demo/src/main/java/fj/demo/concurrent/Pong.java similarity index 100% rename from demo/src/main/fj/demo/concurrent/Pong.java rename to demo/src/main/java/fj/demo/concurrent/Pong.java diff --git a/demo/src/main/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java similarity index 100% rename from demo/src/main/fj/demo/concurrent/WordCount.java rename to demo/src/main/java/fj/demo/concurrent/WordCount.java diff --git a/demo/src/main/fj/demo/euler/Problem1.java b/demo/src/main/java/fj/demo/euler/Problem1.java similarity index 96% rename from demo/src/main/fj/demo/euler/Problem1.java rename to demo/src/main/java/fj/demo/euler/Problem1.java index a9c0cd22..4c70a035 100644 --- a/demo/src/main/fj/demo/euler/Problem1.java +++ b/demo/src/main/java/fj/demo/euler/Problem1.java @@ -1,18 +1,18 @@ -package fj.demo.euler; - -import fj.F; -import static fj.data.List.range; -import static fj.function.Integers.sum; - -import static java.lang.System.out; - -/** - * Add all the natural numbers below one thousand that are multiples of 3 or 5. - */ -public class Problem1 { - public static void main(final String[] args) { - out.println(sum(range(0, 1000).filter(new F() { - public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} - }))); - } -} +package fj.demo.euler; + +import fj.F; +import static fj.data.List.range; +import static fj.function.Integers.sum; + +import static java.lang.System.out; + +/** + * Add all the natural numbers below one thousand that are multiples of 3 or 5. + */ +public class Problem1 { + public static void main(final String[] args) { + out.println(sum(range(0, 1000).filter(new F() { + public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} + }))); + } +} diff --git a/demo/src/main/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java similarity index 96% rename from demo/src/main/fj/demo/euler/Problem2.java rename to demo/src/main/java/fj/demo/euler/Problem2.java index f3638a23..faf91ddd 100644 --- a/demo/src/main/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -1,24 +1,24 @@ -package fj.demo.euler; - -import fj.F2; -import fj.data.Stream; -import static fj.data.Stream.cons; -import static fj.function.Integers.even; -import static fj.function.Integers.sum; -import static fj.Ord.intOrd; - -import static java.lang.System.out; - -/** - * Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million. - */ -public class Problem2 { - public static void main(final String[] args) { - final Stream fibs = new F2>() { - public Stream f(final Integer a, final Integer b) { - return cons(a, curry().f(b).lazy().f(a + b)); - } - }.f(1, 2); - out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); - } -} +package fj.demo.euler; + +import fj.F2; +import fj.data.Stream; +import static fj.data.Stream.cons; +import static fj.function.Integers.even; +import static fj.function.Integers.sum; +import static fj.Ord.intOrd; + +import static java.lang.System.out; + +/** + * Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million. + */ +public class Problem2 { + public static void main(final String[] args) { + final Stream fibs = new F2>() { + public Stream f(final Integer a, final Integer b) { + return cons(a, curry().f(b).lazy().f(a + b)); + } + }.f(1, 2); + out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); + } +} diff --git a/demo/src/main/fj/demo/euler/Problem3.java b/demo/src/main/java/fj/demo/euler/Problem3.java similarity index 97% rename from demo/src/main/fj/demo/euler/Problem3.java rename to demo/src/main/java/fj/demo/euler/Problem3.java index d14aef33..c3c6dde1 100644 --- a/demo/src/main/fj/demo/euler/Problem3.java +++ b/demo/src/main/java/fj/demo/euler/Problem3.java @@ -1,55 +1,55 @@ -package fj.demo.euler; - -import fj.F; -import fj.P1; -import static fj.data.Enumerator.naturalEnumerator; -import fj.data.Natural; -import static fj.data.Natural.ZERO; -import static fj.data.Natural.natural; -import fj.data.Stream; -import static fj.data.Stream.*; -import fj.data.vector.V2; -import static fj.Ord.naturalOrd; -import static fj.Show.naturalShow; - -/** - * Find the largest prime factor of a composite number. - */ -public class Problem3 { - // An infinite stream of all the primes. - public static final Stream primes = cons(natural(2).some(), new P1>() { - public Stream _1() { - return forever(naturalEnumerator, natural(3).some(), 2).filter(new F() { - public Boolean f(final Natural n) {return primeFactors(n).length() == 1;} - }); - } - }); - - //Finds factors of a given number. - public static Stream factor(final Natural n, final Natural p, final P1> ps) { - Stream ns = cons(p, ps); - Stream ret = nil(); - while (ns.isNotEmpty() && ret.isEmpty()) { - final Natural h = ns.head(); - final P1> t = ns.tail(); - if (naturalOrd.isGreaterThan(h.multiply(h), n)) - ret = single(n); - else { - final V2 dm = n.divmod(h); - if (naturalOrd.eq(dm._2(), ZERO)) - ret = cons(h, new P1>() { - public Stream _1() {return factor(dm._1(), h, t);} - }); - else ns = ns.tail()._1(); - } - } - return ret; - } - - // Finds the prime factors of a given number. - public static Stream primeFactors(final Natural n) {return factor(n, natural(2).some(), primes.tail());} - - public static void main(final String[] args) { - naturalShow.println(primeFactors(natural(600851475143L).some()).last()); - } -} +package fj.demo.euler; + +import fj.F; +import fj.P1; +import static fj.data.Enumerator.naturalEnumerator; +import fj.data.Natural; +import static fj.data.Natural.ZERO; +import static fj.data.Natural.natural; +import fj.data.Stream; +import static fj.data.Stream.*; +import fj.data.vector.V2; +import static fj.Ord.naturalOrd; +import static fj.Show.naturalShow; + +/** + * Find the largest prime factor of a composite number. + */ +public class Problem3 { + // An infinite stream of all the primes. + public static final Stream primes = cons(natural(2).some(), new P1>() { + public Stream _1() { + return forever(naturalEnumerator, natural(3).some(), 2).filter(new F() { + public Boolean f(final Natural n) {return primeFactors(n).length() == 1;} + }); + } + }); + + //Finds factors of a given number. + public static Stream factor(final Natural n, final Natural p, final P1> ps) { + Stream ns = cons(p, ps); + Stream ret = nil(); + while (ns.isNotEmpty() && ret.isEmpty()) { + final Natural h = ns.head(); + final P1> t = ns.tail(); + if (naturalOrd.isGreaterThan(h.multiply(h), n)) + ret = single(n); + else { + final V2 dm = n.divmod(h); + if (naturalOrd.eq(dm._2(), ZERO)) + ret = cons(h, new P1>() { + public Stream _1() {return factor(dm._1(), h, t);} + }); + else ns = ns.tail()._1(); + } + } + return ret; + } + + // Finds the prime factors of a given number. + public static Stream primeFactors(final Natural n) {return factor(n, natural(2).some(), primes.tail());} + + public static void main(final String[] args) { + naturalShow.println(primeFactors(natural(600851475143L).some()).last()); + } +} diff --git a/demo/src/main/fj/demo/euler/Problem4.java b/demo/src/main/java/fj/demo/euler/Problem4.java similarity index 97% rename from demo/src/main/fj/demo/euler/Problem4.java rename to demo/src/main/java/fj/demo/euler/Problem4.java index 3dcf66f7..c021d920 100644 --- a/demo/src/main/fj/demo/euler/Problem4.java +++ b/demo/src/main/java/fj/demo/euler/Problem4.java @@ -1,27 +1,27 @@ -package fj.demo.euler; - -import fj.F; -import static fj.Function.flip; -import fj.data.Stream; -import static fj.data.Stream.iterate; -import static fj.function.Integers.multiply; -import static fj.function.Integers.subtract; -import static fj.Equal.charEqual; -import static fj.Equal.streamEqual; -import static fj.Ord.intOrd; -import static fj.Show.intShow; - -/** - * Find the largest palindrome made from the product of two 3-digit numbers. - */ -public class Problem4 { - public static void main(final String[] a) { - final Stream tdl = iterate(flip(subtract).f(1), 999).takeWhile(intOrd.isGreaterThan(99)); - intShow.println(tdl.tails().bind(tdl.zipWith(multiply)).filter(new F() { - public Boolean f(final Integer i) { - final Stream s = intShow.show(i); - return streamEqual(charEqual).eq(s.reverse().take(3), s.take(3)); - } - }).foldLeft1(intOrd.max)); - } -} +package fj.demo.euler; + +import fj.F; +import static fj.Function.flip; +import fj.data.Stream; +import static fj.data.Stream.iterate; +import static fj.function.Integers.multiply; +import static fj.function.Integers.subtract; +import static fj.Equal.charEqual; +import static fj.Equal.streamEqual; +import static fj.Ord.intOrd; +import static fj.Show.intShow; + +/** + * Find the largest palindrome made from the product of two 3-digit numbers. + */ +public class Problem4 { + public static void main(final String[] a) { + final Stream tdl = iterate(flip(subtract).f(1), 999).takeWhile(intOrd.isGreaterThan(99)); + intShow.println(tdl.tails().bind(tdl.zipWith(multiply)).filter(new F() { + public Boolean f(final Integer i) { + final Stream s = intShow.show(i); + return streamEqual(charEqual).eq(s.reverse().take(3), s.take(3)); + } + }).foldLeft1(intOrd.max)); + } +} diff --git a/demo/src/main/fj/demo/test/AdditionCommutes.java b/demo/src/main/java/fj/demo/test/AdditionCommutes.java similarity index 100% rename from demo/src/main/fj/demo/test/AdditionCommutes.java rename to demo/src/main/java/fj/demo/test/AdditionCommutes.java diff --git a/demo/src/main/fj/demo/test/AdditionCommutesParallel.java b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java similarity index 97% rename from demo/src/main/fj/demo/test/AdditionCommutesParallel.java rename to demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java index 3758cabe..c254b67b 100644 --- a/demo/src/main/fj/demo/test/AdditionCommutesParallel.java +++ b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java @@ -1,34 +1,34 @@ -package fj.demo.test; - -import fj.F2; -import fj.P1; -import fj.control.parallel.Strategy; -import static fj.test.Arbitrary.arbInteger; -import static fj.test.CheckResult.summary; -import fj.test.Property; -import static fj.test.Property.prop; -import static fj.test.Property.propertyP; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -/* -Checks the commutative property of addition with a large set of parallel tests. -*/ -public final class AdditionCommutesParallel { - public static void main(final String[] args) { - final ExecutorService pool = Executors.newFixedThreadPool(8); - final Strategy s = Strategy.executorStrategy(pool); - final Property p = propertyP(arbInteger, arbInteger, new F2>() { - public P1 f(final Integer a, final Integer b) { - return s.par(new P1() { - public Property _1() { - return prop(a + b == b + a); - } - }); - } - }); - summary.println(p.check(1000000, 5000000, 0, 100)); // OK, passed 1000000 tests. - pool.shutdown(); - } -} +package fj.demo.test; + +import fj.F2; +import fj.P1; +import fj.control.parallel.Strategy; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.CheckResult.summary; +import fj.test.Property; +import static fj.test.Property.prop; +import static fj.test.Property.propertyP; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/* +Checks the commutative property of addition with a large set of parallel tests. +*/ +public final class AdditionCommutesParallel { + public static void main(final String[] args) { + final ExecutorService pool = Executors.newFixedThreadPool(8); + final Strategy s = Strategy.executorStrategy(pool); + final Property p = propertyP(arbInteger, arbInteger, new F2>() { + public P1 f(final Integer a, final Integer b) { + return s.par(new P1() { + public Property _1() { + return prop(a + b == b + a); + } + }); + } + }); + summary.println(p.check(1000000, 5000000, 0, 100)); // OK, passed 1000000 tests. + pool.shutdown(); + } +} diff --git a/demo/src/main/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java similarity index 100% rename from demo/src/main/fj/demo/test/EqualsHashCode.java rename to demo/src/main/java/fj/demo/test/EqualsHashCode.java diff --git a/demo/src/main/fj/demo/test/IntegerOverflow.java b/demo/src/main/java/fj/demo/test/IntegerOverflow.java similarity index 100% rename from demo/src/main/fj/demo/test/IntegerOverflow.java rename to demo/src/main/java/fj/demo/test/IntegerOverflow.java diff --git a/demo/src/main/fj/demo/test/JavaLinkedList.java b/demo/src/main/java/fj/demo/test/JavaLinkedList.java similarity index 100% rename from demo/src/main/fj/demo/test/JavaLinkedList.java rename to demo/src/main/java/fj/demo/test/JavaLinkedList.java diff --git a/demo/src/main/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java similarity index 100% rename from demo/src/main/fj/demo/test/ListFunctorLaws.java rename to demo/src/main/java/fj/demo/test/ListFunctorLaws.java diff --git a/demo/src/main/fj/demo/test/OptionMonadFunctorLaw.java b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java similarity index 100% rename from demo/src/main/fj/demo/test/OptionMonadFunctorLaw.java rename to demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java diff --git a/demo/src/main/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java similarity index 100% rename from demo/src/main/fj/demo/test/Reflect.java rename to demo/src/main/java/fj/demo/test/Reflect.java diff --git a/demo/src/main/fj/demo/test/StringBuilderReverse.java b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java similarity index 100% rename from demo/src/main/fj/demo/test/StringBuilderReverse.java rename to demo/src/main/java/fj/demo/test/StringBuilderReverse.java diff --git a/demo/src/main/fj/demo/test/Triangulation.java b/demo/src/main/java/fj/demo/test/Triangulation.java similarity index 100% rename from demo/src/main/fj/demo/test/Triangulation.java rename to demo/src/main/java/fj/demo/test/Triangulation.java From b7e6d522c38c01e816de6dd24d1935611109773a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 19 Nov 2013 13:17:45 +1000 Subject: [PATCH 008/811] FJ works with Gradle 1.8, Scala 2.9 and Java 7 --- core/build.gradle | 46 ++++++++++++++++++ ...Test.java => FunctionalJavaJUnitTest.java} | 8 ++-- core/src/test/scala/fj/Tests.scala | 2 +- demo/build.gradle | 47 +++++++++++++++++++ settings.gradle | 2 + 5 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 core/build.gradle rename core/src/test/scala/fj/{JavaTest.java => FunctionalJavaJUnitTest.java} (61%) create mode 100644 demo/build.gradle create mode 100644 settings.gradle diff --git a/core/build.gradle b/core/build.gradle new file mode 100644 index 00000000..aac82a1f --- /dev/null +++ b/core/build.gradle @@ -0,0 +1,46 @@ +/* + * This build file was auto generated by running the Gradle 'buildSetup' task + * by 'MarkPerry' at '19/11/13 10:51 AM' with Gradle 1.8 + * + * This generated file contains a sample Java project to get you started. + * For more details take a look at the Java Quickstart chapter in the Gradle + * user guide available at http://gradle.org/docs/1.8/userguide/tutorial_java_projects.html + */ + +// Apply the java plugin to add support for Java +apply plugin: 'java' +apply plugin: 'scala' + +defaultTasks 'build' + +ext { +// scalaVersion = "2.7.+" +// scalaVersion = "2.8.+" + scalaVersion = "2.9.+" + + scalacheckVersion = "1.10.+" +} + + + +// In this section you declare where to find the dependencies of your project +repositories { + // Use 'maven central' for resolving your dependencies. + // You can declare any Maven/Ivy/file repository here. + mavenCentral() +} + +// In this section you declare the dependencies for your production and test code +dependencies { + // The production code uses the SLF4J logging API at compile time + compile 'org.slf4j:slf4j-api:1.7.5' + testCompile "org.scala-lang:scala-library:$scalaVersion" + testCompile "org.scalacheck:scalacheck_2.9.3:$scalacheckVersion" + + + // Declare the dependency for your favourite test framework you want to use in your tests. + // TestNG is also supported by the Gradle Test task. Just change the + // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add + // 'test.useTestNG()' to your build script. + testCompile "junit:junit:4.11" +} diff --git a/core/src/test/scala/fj/JavaTest.java b/core/src/test/scala/fj/FunctionalJavaJUnitTest.java similarity index 61% rename from core/src/test/scala/fj/JavaTest.java rename to core/src/test/scala/fj/FunctionalJavaJUnitTest.java index 3882de89..d66b2816 100644 --- a/core/src/test/scala/fj/JavaTest.java +++ b/core/src/test/scala/fj/FunctionalJavaJUnitTest.java @@ -10,12 +10,14 @@ * Time: 12:06 PM * To change this template use File | Settings | File Templates. */ -public class JavaTest { +public class FunctionalJavaJUnitTest { @Test - public void test1() { - System.out.println("Hello world"); + public void runScalacheckTests() { +// System.out.println("Hello world"); Assert.assertTrue(true); +// new Tests$().main(null); + Tests.main(null); } } diff --git a/core/src/test/scala/fj/Tests.scala b/core/src/test/scala/fj/Tests.scala index 47418ca1..5c54cd2b 100644 --- a/core/src/test/scala/fj/Tests.scala +++ b/core/src/test/scala/fj/Tests.scala @@ -19,7 +19,7 @@ object Tests { def main(args: Array[String]) { run(tests) - System.exit(0) +// System.exit(0) } import org.scalacheck.Prop diff --git a/demo/build.gradle b/demo/build.gradle new file mode 100644 index 00000000..6d14db7a --- /dev/null +++ b/demo/build.gradle @@ -0,0 +1,47 @@ +/* + * This build file was auto generated by running the Gradle 'buildSetup' task + * by 'MarkPerry' at '19/11/13 10:51 AM' with Gradle 1.8 + * + * This generated file contains a sample Java project to get you started. + * For more details take a look at the Java Quickstart chapter in the Gradle + * user guide available at http://gradle.org/docs/1.8/userguide/tutorial_java_projects.html + */ + +// Apply the java plugin to add support for Java +apply plugin: 'java' +//apply plugin: 'scala' + +defaultTasks 'build' + +ext { +// scalaVersion = "2.7.+" +// scalaVersion = "2.8.+" + scalaVersion = "2.9.+" + + scalacheckVersion = "1.10.+" +} + + + +// In this section you declare where to find the dependencies of your project +repositories { + // Use 'maven central' for resolving your dependencies. + // You can declare any Maven/Ivy/file repository here. + mavenCentral() +} + +// In this section you declare the dependencies for your production and test code +dependencies { + // The production code uses the SLF4J logging API at compile time + compile 'org.slf4j:slf4j-api:1.7.5' + compile project(":core") +// testCompile "org.scala-lang:scala-library:$scalaVersion" +// testCompile "org.scalacheck:scalacheck_2.9.3:$scalacheckVersion" + + + // Declare the dependency for your favourite test framework you want to use in your tests. + // TestNG is also supported by the Gradle Test task. Just change the + // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add + // 'test.useTestNG()' to your build script. + testCompile "junit:junit:4.11" +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..eb5b81aa --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ + +include 'core', 'demo' From fe865b5e55c261d70fd0f459fa056441375c0407 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 19 Nov 2013 13:26:36 +1000 Subject: [PATCH 009/811] Upgraded Scala version used by Gradle to 2.10.3 --- core/build.gradle | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index aac82a1f..b3077e0a 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -14,11 +14,12 @@ apply plugin: 'scala' defaultTasks 'build' ext { -// scalaVersion = "2.7.+" -// scalaVersion = "2.8.+" - scalaVersion = "2.9.+" + scalaVersion = "2.10.+" +// scalaVersion = "2.9.+" scalacheckVersion = "1.10.+" +// scalacheckScalaVersion = "2.9.3" + scalacheckScalaVersion = "2.10" } @@ -35,7 +36,7 @@ dependencies { // The production code uses the SLF4J logging API at compile time compile 'org.slf4j:slf4j-api:1.7.5' testCompile "org.scala-lang:scala-library:$scalaVersion" - testCompile "org.scalacheck:scalacheck_2.9.3:$scalacheckVersion" + testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" // Declare the dependency for your favourite test framework you want to use in your tests. From 69e79293c8108046ac04cde5c81133598874dffd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 19 Nov 2013 15:10:22 +1000 Subject: [PATCH 010/811] Used Java 8 for compilation/test --- core/build.gradle | 8 ++++++++ demo/src/main/java/fj/demo/HList_foldRight.java | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index b3077e0a..1d000dd7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -23,6 +23,14 @@ ext { } +tasks.withType(ScalaCompile) { + scalaCompileOptions.useAnt = false +} + +test { + scanForTestClasses = false + include '**/*Test.*' +} // In this section you declare where to find the dependencies of your project repositories { diff --git a/demo/src/main/java/fj/demo/HList_foldRight.java b/demo/src/main/java/fj/demo/HList_foldRight.java index fa7172cf..4f5ee3e1 100644 --- a/demo/src/main/java/fj/demo/HList_foldRight.java +++ b/demo/src/main/java/fj/demo/HList_foldRight.java @@ -30,13 +30,13 @@ public static void main(final String[] args) { comp0 = Apply.comp(); final HFoldr, HList.HNil, F> fold0 = HFoldr.hFoldr(); - final HFoldr, HList.HCons, - HList.HCons, HList.HCons, HList.HNil>>>, F> - fold2 = HFoldr.hFoldr(comp1, HFoldr.hFoldr(comp0, HFoldr.hFoldr(comp0, fold0))); +// final HFoldr, HList.HCons, +// HList.HCons, HList.HCons, HList.HNil>>>, F> +// fold2 = HFoldr.hFoldr(comp1, HFoldr.hFoldr(comp0, HFoldr.hFoldr(comp0, fold0))); final F id = identity(); // Compose the list and apply the resulting function to a value. // Unit is used because composition has only one possible implementation. - out.println(fold2.foldRight(unit(), id, functions).f("abc")); // 7 +// out.println(fold2.foldRight(unit(), id, functions).f("abc")); // 7 } } From 679f03d338bd6dbe8311b9e1087fc7e47060cdf8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 19 Nov 2013 15:14:49 +1000 Subject: [PATCH 011/811] Setup to run a demo class --- demo/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/demo/build.gradle b/demo/build.gradle index 6d14db7a..76b03edd 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -9,10 +9,14 @@ // Apply the java plugin to add support for Java apply plugin: 'java' +apply plugin: 'application' //apply plugin: 'scala' defaultTasks 'build' +mainClassName = "fj.demo.Array_forall" +//mainClassName = "fj.demo.Primes2" + ext { // scalaVersion = "2.7.+" // scalaVersion = "2.8.+" From 04169066dcabdcff171f77cbb4946a768a99984d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 19 Nov 2013 15:54:25 +1000 Subject: [PATCH 012/811] Got compiling under Intellij --- .idea/.name | 1 + .idea/compiler.xml | 29 ++- .idea/gradle.xml | 9 + .idea/inspectionProfiles/Project_Default.xml | 15 +- .idea/libraries/buildScala.xml | 13 -- .idea/libraries/defScala.xml | 10 -- .idea/libraries/hamcrest_core_1_3.xml | 11 ++ .idea/libraries/junit_4_11.xml | 11 ++ .idea/libraries/scala_2_7_7.xml | 13 -- .idea/libraries/scala_2_7_7__build_.xml | 13 -- .idea/libraries/scala_2_8_1.xml | 13 -- .idea/libraries/scala_actors_2_10_1.xml | 11 ++ .idea/libraries/scala_library_2_10_3.xml | 11 ++ .idea/libraries/scalacheck_1_8.xml | 9 - .idea/libraries/scalacheck_2_10_1_10_1.xml | 11 ++ .idea/libraries/slf4j_api_1_7_5.xml | 11 ++ .idea/libraries/test_interface_0_5.xml | 9 + .idea/misc.xml | 176 ++++++++++++++++--- .idea/modules.xml | 8 +- build.gradle | 0 core/core.iml | 35 ++++ core/functionaljava-core.iml | 13 +- demo/demo.iml | 21 +++ demo/functionaljava-demo.iml | 2 +- functionaljava8.iml | 13 ++ 25 files changed, 338 insertions(+), 130 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/gradle.xml delete mode 100644 .idea/libraries/buildScala.xml delete mode 100644 .idea/libraries/defScala.xml create mode 100644 .idea/libraries/hamcrest_core_1_3.xml create mode 100644 .idea/libraries/junit_4_11.xml delete mode 100644 .idea/libraries/scala_2_7_7.xml delete mode 100644 .idea/libraries/scala_2_7_7__build_.xml delete mode 100644 .idea/libraries/scala_2_8_1.xml create mode 100644 .idea/libraries/scala_actors_2_10_1.xml create mode 100644 .idea/libraries/scala_library_2_10_3.xml delete mode 100644 .idea/libraries/scalacheck_1_8.xml create mode 100644 .idea/libraries/scalacheck_2_10_1_10_1.xml create mode 100644 .idea/libraries/slf4j_api_1_7_5.xml create mode 100644 .idea/libraries/test_interface_0_5.xml create mode 100644 build.gradle create mode 100644 core/core.iml create mode 100644 demo/demo.iml create mode 100644 functionaljava8.iml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..93df1fd0 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +functionaljava8 \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 97c9ca5c..217af471 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -2,23 +2,22 @@ diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..c83159e7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 6dfb3353..12b5d4a8 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -79,7 +79,6 @@ - @@ -146,7 +145,6 @@ - @@ -265,6 +263,7 @@ @@ -311,10 +310,7 @@ - - + p) { return p.map(F.this); @@ -225,7 +225,7 @@ public P1 f(final P1 p) { * * @return This function promoted to return its result in an Option. */ - public final F> optionK() { + default public F> optionK() { return new F>() { public Option f(final A a) { return some(F.this.f(a)); @@ -238,7 +238,7 @@ public Option f(final A a) { * * @return This function promoted to map over an optional value. */ - public final F, Option> mapOption() { + default public F, Option> mapOption() { return new F, Option>() { public Option f(final Option o) { return o.map(F.this); @@ -251,7 +251,7 @@ public Option f(final Option o) { * * @return This function promoted to return its result in a List. */ - public final F> listK() { + default public F> listK() { return new F>() { public List f(final A a) { return List.single(F.this.f(a)); @@ -264,7 +264,7 @@ public List f(final A a) { * * @return This function promoted to map over a List. */ - public final F, List> mapList() { + default public F, List> mapList() { return new F, List>() { public List f(final List x) { return x.map(F.this); @@ -277,7 +277,7 @@ public List f(final List x) { * * @return This function promoted to return its result in a Stream. */ - public final F> streamK() { + default public F> streamK() { return new F>() { public Stream f(final A a) { return Stream.single(F.this.f(a)); @@ -290,7 +290,7 @@ public Stream f(final A a) { * * @return This function promoted to map over a Stream. */ - public final F, Stream> mapStream() { + default public F, Stream> mapStream() { return new F, Stream>() { public Stream f(final Stream x) { return x.map(F.this); @@ -303,7 +303,7 @@ public Stream f(final Stream x) { * * @return This function promoted to return its result in a Array. */ - public final F> arrayK() { + default public F> arrayK() { return new F>() { public Array f(final A a) { return Array.single(F.this.f(a)); @@ -316,7 +316,7 @@ public Array f(final A a) { * * @return This function promoted to map over a Array. */ - public final F, Array> mapArray() { + default public F, Array> mapArray() { return new F, Array>() { public Array f(final Array x) { return x.map(F.this); @@ -329,7 +329,7 @@ public Array f(final Array x) { * * @return A function that comaps over a given actor. */ - public final F, Actor> comapActor() { + default public F, Actor> comapActor() { return new F, Actor>() { public Actor f(final Actor a) { return a.comap(F.this); @@ -343,7 +343,7 @@ public Actor f(final Actor a) { * @param s A parallel strategy for concurrent execution. * @return A concurrent function that returns a Promise of a value. */ - public final F> promiseK(final Strategy s) { + default public F> promiseK(final Strategy s) { return Promise.promise(s, this); } @@ -352,7 +352,7 @@ public final F> promiseK(final Strategy s) { * * @return This function promoted to map over Promises. */ - public final F, Promise> mapPromise() { + default public F, Promise> mapPromise() { return new F, Promise>() { public Promise f(final Promise p) { return p.fmap(F.this); @@ -367,7 +367,7 @@ public Promise f(final Promise p) { * @return This function promoted to return its result on the left side of an Either. */ @SuppressWarnings({"unchecked"}) - public final F> eitherLeftK() { + default public F> eitherLeftK() { return Either.left_().o(F.this); } @@ -378,7 +378,7 @@ public final F> eitherLeftK() { * @return This function promoted to return its result on the right side of an Either. */ @SuppressWarnings({"unchecked"}) - public final F> eitherRightK() { + default public F> eitherRightK() { return Either.right_().o(F.this); } @@ -388,7 +388,7 @@ public final F> eitherRightK() { * @return This function promoted to map over the left side of an Either. */ @SuppressWarnings({"unchecked"}) - public final F, Either> mapLeft() { + default public F, Either> mapLeft() { return Either.leftMap_().f(F.this); } @@ -398,7 +398,7 @@ public final F, Either> mapLeft() { * @return This function promoted to map over the right side of an Either. */ @SuppressWarnings({"unchecked"}) - public final F, Either> mapRight() { + default public F, Either> mapRight() { return Either.rightMap_().f(F.this); } @@ -407,7 +407,7 @@ public final F, Either> mapRight() { * * @return a function that returns the left side of a given Either, or this function applied to the right side. */ - public final F, B> onLeft() { + default public F, B> onLeft() { return new F, B>() { public B f(final Either either) { return either.left().on(F.this); @@ -420,7 +420,7 @@ public B f(final Either either) { * * @return a function that returns the right side of a given Either, or this function applied to the left side. */ - public final F, B> onRight() { + default public F, B> onRight() { return new F, B>() { public B f(final Either either) { return either.right().on(F.this); @@ -434,7 +434,7 @@ public B f(final Either either) { * @return This function promoted to return its value in an Iterable. */ @SuppressWarnings({"unchecked"}) - public final F> iterableK() { + default public F> iterableK() { return IterableW.arrow().f(F.this); } @@ -444,7 +444,7 @@ public final F> iterableK() { * @return This function promoted to map over Iterables. */ @SuppressWarnings({"unchecked"}) - public final F, IterableW> mapIterable() { + default public F, IterableW> mapIterable() { return IterableW.map().f(F.this).o(IterableW.>wrap()); } @@ -454,7 +454,7 @@ public final F, IterableW> mapIterable() { * @return This function promoted to return its value in a NonEmptyList. */ @SuppressWarnings({"unchecked"}) - public final F> nelK() { + default public F> nelK() { return NonEmptyList.nel().o(F.this); } @@ -463,7 +463,7 @@ public final F> nelK() { * * @return This function promoted to map over a NonEmptyList. */ - public final F, NonEmptyList> mapNel() { + default public F, NonEmptyList> mapNel() { return new F, NonEmptyList>() { public NonEmptyList f(final NonEmptyList list) { return list.map(F.this); @@ -477,7 +477,7 @@ public NonEmptyList f(final NonEmptyList list) { * @param o An order for the set. * @return This function promoted to return its value in a Set. */ - public final F> setK(final Ord o) { + default public F> setK(final Ord o) { return new F>() { public Set f(final A a) { return Set.single(o, F.this.f(a)); @@ -491,7 +491,7 @@ public Set f(final A a) { * @param o An order for the resulting set. * @return This function promoted to map over a Set. */ - public final F, Set> mapSet(final Ord o) { + default public F, Set> mapSet(final Ord o) { return new F, Set>() { public Set f(final Set set) { return set.map(o, F.this); @@ -504,7 +504,7 @@ public Set f(final Set set) { * * @return This function promoted to return its value in a Tree. */ - public final F> treeK() { + default public F> treeK() { return new F>() { public Tree f(final A a) { return Tree.leaf(F.this.f(a)); @@ -518,7 +518,7 @@ public Tree f(final A a) { * @return This function promoted to map over a Tree. */ @SuppressWarnings({"unchecked"}) - public final F, Tree> mapTree() { + default public F, Tree> mapTree() { return Tree.fmap_().f(F.this); } @@ -528,7 +528,7 @@ public final F, Tree> mapTree() { * @param m The monoid with which to fold the mapped tree. * @return a function that maps this function over a tree and folds it with the given monoid. */ - public final F, B> foldMapTree(final Monoid m) { + default public F, B> foldMapTree(final Monoid m) { return Tree.foldMap_(F.this, m); } @@ -537,7 +537,7 @@ public final F, B> foldMapTree(final Monoid m) { * * @return This function promoted to return its value in a TreeZipper. */ - public final F> treeZipperK() { + default public F> treeZipperK() { return treeK().andThen(TreeZipper.fromTree()); } @@ -546,7 +546,7 @@ public final F> treeZipperK() { * * @return This function promoted to map over a TreeZipper. */ - public final F, TreeZipper> mapTreeZipper() { + default public F, TreeZipper> mapTreeZipper() { return new F, TreeZipper>() { public TreeZipper f(final TreeZipper zipper) { return zipper.map(F.this); @@ -560,7 +560,7 @@ public TreeZipper f(final TreeZipper zipper) { * * @return This function promoted to return its result on the failure side of a Validation. */ - public final F> failK() { + default public F> failK() { return new F>() { public Validation f(final A a) { return Validation.fail(F.this.f(a)); @@ -574,7 +574,7 @@ public Validation f(final A a) { * * @return This function promoted to return its result on the success side of an Validation. */ - public final F> successK() { + default public F> successK() { return new F>() { public Validation f(final A a) { return Validation.success(F.this.f(a)); @@ -587,7 +587,7 @@ public Validation f(final A a) { * * @return This function promoted to map over the failure side of a Validation. */ - public final F, Validation> mapFail() { + default public F, Validation> mapFail() { return new F, Validation>() { public Validation f(final Validation validation) { return validation.f().map(F.this); @@ -600,7 +600,7 @@ public Validation f(final Validation validation) { * * @return This function promoted to map over the success side of a Validation. */ - public final F, Validation> mapSuccess() { + default public F, Validation> mapSuccess() { return new F, Validation>() { public Validation f(final Validation validation) { return validation.map(F.this); @@ -615,7 +615,7 @@ public Validation f(final Validation validation) { * @return a function that returns the failure side of a given Validation, * or this function applied to the success side. */ - public final F, B> onFail() { + default public F, B> onFail() { return new F, B>() { public B f(final Validation v) { return v.f().on(F.this); @@ -630,7 +630,7 @@ public B f(final Validation v) { * @return a function that returns the success side of a given Validation, * or this function applied to the failure side. */ - public final F, B> onSuccess() { + default public F, B> onSuccess() { return new F, B>() { public B f(final Validation v) { return v.on(F.this); @@ -643,7 +643,7 @@ public B f(final Validation v) { * * @return This function promoted to return its value in a Zipper. */ - public final F> zipperK() { + default public F> zipperK() { return streamK().andThen(new F, Zipper>() { public Zipper f(final Stream stream) { return fromStream(stream).some(); @@ -656,7 +656,7 @@ public Zipper f(final Stream stream) { * * @return This function promoted to map over a Zipper. */ - public final F, Zipper> mapZipper() { + default public F, Zipper> mapZipper() { return new F, Zipper>() { public Zipper f(final Zipper zipper) { return zipper.map(F.this); @@ -669,7 +669,7 @@ public Zipper f(final Zipper zipper) { * * @return This function promoted to map over an Equal as a contravariant functor. */ - public final F, Equal> comapEqual() { + default public F, Equal> comapEqual() { return new F, Equal>() { public Equal f(final Equal equal) { return equal.comap(F.this); @@ -682,7 +682,7 @@ public Equal f(final Equal equal) { * * @return This function promoted to map over a Hash as a contravariant functor. */ - public final F, Hash> comapHash() { + default public F, Hash> comapHash() { return new F, Hash>() { public Hash f(final Hash hash) { return hash.comap(F.this); @@ -695,7 +695,7 @@ public Hash f(final Hash hash) { * * @return This function promoted to map over a Show as a contravariant functor. */ - public final F, Show> comapShow() { + default public F, Show> comapShow() { return new F, Show>() { public Show f(final Show s) { return s.comap(F.this); @@ -708,7 +708,7 @@ public Show f(final Show s) { * * @return This function promoted to map over the first element of a pair. */ - public final F, P2> mapFst() { + default public F, P2> mapFst() { return P2.map1_(F.this); } @@ -717,7 +717,7 @@ public final F, P2> mapFst() { * * @return This function promoted to map over the second element of a pair. */ - public final F, P2> mapSnd() { + default public F, P2> mapSnd() { return P2.map2_(F.this); } @@ -726,7 +726,7 @@ public final F, P2> mapSnd() { * * @return This function promoted to map over both elements of a pair. */ - public final F, P2> mapBoth() { + default public F, P2> mapBoth() { return new F, P2>() { public P2 f(final P2 aap2) { return P2.map(F.this, aap2); @@ -740,7 +740,7 @@ public P2 f(final P2 aap2) { * @param as A SynchronousQueue to map this function over. * @return A new SynchronousQueue with this function applied to each element. */ - public final SynchronousQueue mapJ(final SynchronousQueue as) { + default public SynchronousQueue mapJ(final SynchronousQueue as) { final SynchronousQueue bs = new SynchronousQueue(); bs.addAll(iterableStream(as).map(this).toCollection()); return bs; @@ -753,7 +753,7 @@ public final SynchronousQueue mapJ(final SynchronousQueue as) { * @param as A PriorityBlockingQueue to map this function over. * @return A new PriorityBlockingQueue with this function applied to each element. */ - public final PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { + default public PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { return new PriorityBlockingQueue(iterableStream(as).map(this).toCollection()); } @@ -763,7 +763,7 @@ public final PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { * @param as A LinkedBlockingQueue to map this function over. * @return A new LinkedBlockingQueue with this function applied to each element. */ - public final LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { + default public LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { return new LinkedBlockingQueue(iterableStream(as).map(this).toCollection()); } @@ -773,7 +773,7 @@ public final LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { * @param as A CopyOnWriteArraySet to map this function over. * @return A new CopyOnWriteArraySet with this function applied to each element. */ - public final CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { + default public CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { return new CopyOnWriteArraySet(iterableStream(as).map(this).toCollection()); } @@ -783,7 +783,7 @@ public final CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { * @param as A CopyOnWriteArrayList to map this function over. * @return A new CopyOnWriteArrayList with this function applied to each element. */ - public final CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { + default public CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { return new CopyOnWriteArrayList(iterableStream(as).map(this).toCollection()); } @@ -793,7 +793,7 @@ public final CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { * @param as A ConcurrentLinkedQueue to map this function over. * @return A new ConcurrentLinkedQueue with this function applied to each element. */ - public final ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { + default public ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { return new ConcurrentLinkedQueue(iterableStream(as).map(this).toCollection()); } @@ -803,7 +803,7 @@ public final ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { * @param as An ArrayBlockingQueue to map this function over. * @return A new ArrayBlockingQueue with this function applied to each element. */ - public final ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { + default public ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); bs.addAll(iterableStream(as).map(this).toCollection()); return bs; @@ -816,7 +816,7 @@ public final ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { * @param as A TreeSet to map this function over. * @return A new TreeSet with this function applied to each element. */ - public final TreeSet mapJ(final TreeSet as) { + default public TreeSet mapJ(final TreeSet as) { return new TreeSet(iterableStream(as).map(this).toCollection()); } @@ -826,7 +826,7 @@ public final TreeSet mapJ(final TreeSet as) { * @param as A PriorityQueue to map this function over. * @return A new PriorityQueue with this function applied to each element. */ - public final PriorityQueue mapJ(final PriorityQueue as) { + default public PriorityQueue mapJ(final PriorityQueue as) { return new PriorityQueue(iterableStream(as).map(this).toCollection()); } @@ -836,7 +836,7 @@ public final PriorityQueue mapJ(final PriorityQueue as) { * @param as A LinkedList to map this function over. * @return A new LinkedList with this function applied to each element. */ - public final LinkedList mapJ(final LinkedList as) { + default public LinkedList mapJ(final LinkedList as) { return new LinkedList(iterableStream(as).map(this).toCollection()); } @@ -846,7 +846,7 @@ public final LinkedList mapJ(final LinkedList as) { * @param as An ArrayList to map this function over. * @return A new ArrayList with this function applied to each element. */ - public final ArrayList mapJ(final ArrayList as) { + default public ArrayList mapJ(final ArrayList as) { return new ArrayList(iterableStream(as).map(this).toCollection()); } } diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index 80c248f8..eeb19d12 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -25,7 +25,7 @@ * * @version %build.number% */ -public abstract class F2 { +public interface F2 { /** * Transform A and B to C. * @@ -33,7 +33,7 @@ public abstract class F2 { * @param b The B to transform. * @return The result of the transformation. */ - public abstract C f(A a, B b); + public C f(A a, B b); /** @@ -42,7 +42,7 @@ public abstract class F2 { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - public final F f(final A a) { + default public F f(final A a) { return new F() { public C f(final B b) { return F2.this.f(a, b); @@ -55,7 +55,7 @@ public C f(final B b) { * * @return a wrapped function of arity-1 that returns another wrapped function. */ - public final F> curry() { + default public F> curry() { return new F>() { public F f(final A a) { return new F() { @@ -72,7 +72,7 @@ public C f(final B b) { * * @return A new function with the arguments of this function flipped. */ - public final F2 flip() { + default public F2 flip() { return new F2() { public C f(final B b, final A a) { return F2.this.f(a, b); @@ -85,7 +85,7 @@ public C f(final B b, final A a) { * * @return A new function that calls this function with the elements of a given tuple. */ - public final F, C> tuple() { + default public F, C> tuple() { return new F, C>() { public C f(final P2 p) { return F2.this.f(p._1(), p._2()); @@ -98,7 +98,7 @@ public C f(final P2 p) { * * @return This function promoted to transform Arrays. */ - public final F2, Array, Array> arrayM() { + default public F2, Array, Array> arrayM() { return new F2, Array, Array>() { public Array f(final Array a, final Array b) { return a.bind(b, F2.this.curry()); @@ -111,7 +111,7 @@ public Array f(final Array a, final Array b) { * * @return This function promoted to transform Promises. */ - public final F2, Promise, Promise> promiseM() { + default public F2, Promise, Promise> promiseM() { return new F2, Promise, Promise>() { public Promise f(final Promise a, final Promise b) { return a.bind(b, F2.this.curry()); @@ -124,7 +124,7 @@ public Promise f(final Promise a, final Promise b) { * * @return This function promoted to transform Iterables. */ - public final F2, Iterable, IterableW> iterableM() { + default public F2, Iterable, IterableW> iterableM() { return new F2, Iterable, IterableW>() { public IterableW f(final Iterable a, final Iterable b) { return IterableW.liftM2(F2.this.curry()).f(a).f(b); @@ -137,7 +137,7 @@ public IterableW f(final Iterable a, final Iterable b) { * * @return This function promoted to transform Lists. */ - public final F2, List, List> listM() { + default public F2, List, List> listM() { return new F2, List, List>() { public List f(final List a, final List b) { return List.liftM2(F2.this.curry()).f(a).f(b); @@ -150,7 +150,7 @@ public List f(final List a, final List b) { * * @return This function promoted to transform non-empty lists. */ - public final F2, NonEmptyList, NonEmptyList> nelM() { + default public F2, NonEmptyList, NonEmptyList> nelM() { return new F2, NonEmptyList, NonEmptyList>() { public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { return NonEmptyList.fromList(as.toList().bind(bs.toList(), F2.this)).some(); @@ -163,7 +163,7 @@ public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { * * @return This function promoted to transform Options. */ - public final F2, Option, Option> optionM() { + default public F2, Option, Option> optionM() { return new F2, Option, Option>() { public Option f(final Option a, final Option b) { return Option.liftM2(F2.this.curry()).f(a).f(b); @@ -177,7 +177,7 @@ public Option f(final Option a, final Option b) { * @param o An ordering for the result of the promoted function. * @return This function promoted to transform Sets. */ - public final F2, Set, Set> setM(final Ord o) { + default public F2, Set, Set> setM(final Ord o) { return new F2, Set, Set>() { public Set f(final Set as, final Set bs) { Set cs = Set.empty(o); @@ -194,7 +194,7 @@ public Set f(final Set as, final Set bs) { * * @return This function promoted to transform Streams. */ - public final F2, Stream, Stream> streamM() { + default public F2, Stream, Stream> streamM() { return new F2, Stream, Stream>() { public Stream f(final Stream as, final Stream bs) { return as.bind(bs, F2.this); @@ -207,7 +207,7 @@ public Stream f(final Stream as, final Stream bs) { * * @return This function promoted to transform Trees. */ - public final F2, Tree, Tree> treeM() { + default public F2, Tree, Tree> treeM() { return new F2, Tree, Tree>() { public Tree f(final Tree as, final Tree bs) { final F2, Tree, Tree> self = this; @@ -225,7 +225,7 @@ public Stream> _1() { * * @return A function that zips two arrays with this function. */ - public final F2, Array, Array> zipArrayM() { + default public F2, Array, Array> zipArrayM() { return new F2, Array, Array>() { public Array f(final Array as, final Array bs) { return as.zipWith(bs, F2.this); @@ -238,7 +238,7 @@ public Array f(final Array as, final Array bs) { * * @return A function that zips two iterables with this function. */ - public final F2, Iterable, Iterable> zipIterableM() { + default public F2, Iterable, Iterable> zipIterableM() { return new F2, Iterable, Iterable>() { public Iterable f(final Iterable as, final Iterable bs) { return wrap(as).zipWith(bs, F2.this); @@ -251,7 +251,7 @@ public Iterable f(final Iterable as, final Iterable bs) { * * @return A function that zips two lists with this function. */ - public final F2, List, List> zipListM() { + default public F2, List, List> zipListM() { return new F2, List, List>() { public List f(final List as, final List bs) { return as.zipWith(bs, F2.this); @@ -265,7 +265,7 @@ public List f(final List as, final List bs) { * * @return A function that zips two streams with this function. */ - public final F2, Stream, Stream> zipStreamM() { + default public F2, Stream, Stream> zipStreamM() { return new F2, Stream, Stream>() { public Stream f(final Stream as, final Stream bs) { return as.zipWith(bs, F2.this); @@ -278,7 +278,7 @@ public Stream f(final Stream as, final Stream bs) { * * @return A function that zips two non-empty lists with this function. */ - public final F2, NonEmptyList, NonEmptyList> zipNelM() { + default public F2, NonEmptyList, NonEmptyList> zipNelM() { return new F2, NonEmptyList, NonEmptyList>() { public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { return NonEmptyList.fromList(as.toList().zipWith(bs.toList(), F2.this)).some(); @@ -292,7 +292,7 @@ public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { * @param o An ordering for the resulting set. * @return A function that zips two sets with this function. */ - public final F2, Set, Set> zipSetM(final Ord o) { + default public F2, Set, Set> zipSetM(final Ord o) { return new F2, Set, Set>() { public Set f(final Set as, final Set bs) { return iterableSet(o, as.toStream().zipWith(bs.toStream(), F2.this)); @@ -306,7 +306,7 @@ public Set f(final Set as, final Set bs) { * * @return A function that zips two trees with this function. */ - public final F2, Tree, Tree> zipTreeM() { + default public F2, Tree, Tree> zipTreeM() { return new F2, Tree, Tree>() { public Tree f(final Tree ta, final Tree tb) { final F2, Tree, Tree> self = this; @@ -325,7 +325,7 @@ public Stream> _1() { * * @return A function that zips two zippers with this function. */ - public final F2, Zipper, Zipper> zipZipperM() { + default public F2, Zipper, Zipper> zipZipperM() { return new F2, Zipper, Zipper>() { @SuppressWarnings({"unchecked"}) public Zipper f(final Zipper ta, final Zipper tb) { @@ -341,7 +341,7 @@ public Zipper f(final Zipper ta, final Zipper tb) { * * @return A function that zips two TreeZippers with this function. */ - public final F2, TreeZipper, TreeZipper> zipTreeZipperM() { + default public F2, TreeZipper, TreeZipper> zipTreeZipperM() { return new F2, TreeZipper, TreeZipper>() { @SuppressWarnings({"unchecked"}) public TreeZipper f(final TreeZipper ta, final TreeZipper tb) { diff --git a/core/src/main/java/fj/F3.java b/core/src/main/java/fj/F3.java index d27d3a1f..68e7627a 100644 --- a/core/src/main/java/fj/F3.java +++ b/core/src/main/java/fj/F3.java @@ -6,7 +6,7 @@ * * @version %build.number% */ -public abstract class F3 { +public interface F3 { /** * Transform A, B and C to D. * @@ -15,5 +15,5 @@ public abstract class F3 { * @param c The C to transform. * @return The result of the transformation. */ - public abstract D f(A a, B b, C c); + public D f(A a, B b, C c); } diff --git a/core/src/main/java/fj/F4.java b/core/src/main/java/fj/F4.java index 3b2cae41..9447389a 100644 --- a/core/src/main/java/fj/F4.java +++ b/core/src/main/java/fj/F4.java @@ -6,7 +6,7 @@ * * @version %build.number% */ -public abstract class F4 { +public interface F4 { /** * Transform A, B, C and D to E. * @@ -16,5 +16,5 @@ public abstract class F4 { * @param d The D to transform. * @return The result of the transformation. */ - public abstract E f(A a, B b, C c, D d); + public E f(A a, B b, C c, D d); } diff --git a/core/src/main/java/fj/F5.java b/core/src/main/java/fj/F5.java index b28cf367..ff7184f2 100644 --- a/core/src/main/java/fj/F5.java +++ b/core/src/main/java/fj/F5.java @@ -7,7 +7,7 @@ * * @version %build.number% */ -public abstract class F5 { +public interface F5 { /** * Transform A, B, C, D and E to * F$. @@ -19,5 +19,5 @@ public abstract class F5 { * @param e The E to transform. * @return The result of the transformation. */ - public abstract F$ f(A a, B b, C c, D d, E e); + public F$ f(A a, B b, C c, D d, E e); } diff --git a/core/src/main/java/fj/F6.java b/core/src/main/java/fj/F6.java index 7e24ef22..f403eb0a 100644 --- a/core/src/main/java/fj/F6.java +++ b/core/src/main/java/fj/F6.java @@ -7,7 +7,7 @@ * * @version %build.number% */ -public abstract class F6 { +public interface F6 { /** * Transform A, B, C, D, E and * F$ to G. @@ -20,5 +20,5 @@ public abstract class F6 { * @param f The F$ to transform. * @return The result of the transformation. */ - public abstract G f(A a, B b, C c, D d, E e, F$ f); + public G f(A a, B b, C c, D d, E e, F$ f); } diff --git a/core/src/main/java/fj/F7.java b/core/src/main/java/fj/F7.java index 3ada05e9..be9d87e1 100644 --- a/core/src/main/java/fj/F7.java +++ b/core/src/main/java/fj/F7.java @@ -7,7 +7,7 @@ * * @version %build.number% */ -public abstract class F7 { +public interface F7 { /** * Transform A, B, C, D, E, * F$ and G to H. @@ -21,5 +21,5 @@ public abstract class F7 { * @param g The G to transform. * @return The result of the transformation. */ - public abstract H f(A a, B b, C c, D d, E e, F$ f, G g); + public H f(A a, B b, C c, D d, E e, F$ f, G g); } diff --git a/core/src/main/java/fj/F8.java b/core/src/main/java/fj/F8.java index f3fc4505..5ad75489 100644 --- a/core/src/main/java/fj/F8.java +++ b/core/src/main/java/fj/F8.java @@ -7,7 +7,7 @@ * * @version %build.number% */ -public abstract class F8 { +public interface F8 { /** * Transform A, B, C, D, E, * F$, G and H to I. @@ -22,5 +22,5 @@ public abstract class F8 { * @param h The H to transform. * @return The result of the transformation. */ - public abstract I f(A a, B b, C c, D d, E e, F$ f, G g, H h); + public I f(A a, B b, C c, D d, E e, F$ f, G g, H h); } From ee4c70df88a368d41414ecb4ac03e5aa18469389 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 20 Nov 2013 01:37:03 +1000 Subject: [PATCH 015/811] Added first two Eueler problems in Java 8 --- .idea/.name | 2 +- .idea/modules.xml | 2 +- demo/build.gradle | 3 +- .../src/main/java/fj/demo/euler/Problem1.java | 22 ++++++++++---- .../src/main/java/fj/demo/euler/Problem2.java | 30 ++++++++++++++----- functionaljava8.iml => functionaljava.iml | 0 6 files changed, 43 insertions(+), 16 deletions(-) rename functionaljava8.iml => functionaljava.iml (100%) diff --git a/.idea/.name b/.idea/.name index 93df1fd0..f111a67e 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -functionaljava8 \ No newline at end of file +functionaljava \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 46e669f8..ba1a7031 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -4,7 +4,7 @@ - + diff --git a/demo/build.gradle b/demo/build.gradle index 76b03edd..7ae6fe98 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -14,7 +14,8 @@ apply plugin: 'application' defaultTasks 'build' -mainClassName = "fj.demo.Array_forall" +//mainClassName = "fj.demo.Array_forall" +mainClassName = "fj.demo.euler.Problem2" //mainClassName = "fj.demo.Primes2" ext { diff --git a/demo/src/main/java/fj/demo/euler/Problem1.java b/demo/src/main/java/fj/demo/euler/Problem1.java index 4c70a035..8f7cf5a6 100644 --- a/demo/src/main/java/fj/demo/euler/Problem1.java +++ b/demo/src/main/java/fj/demo/euler/Problem1.java @@ -1,6 +1,8 @@ package fj.demo.euler; import fj.F; +import fj.data.Stream; + import static fj.data.List.range; import static fj.function.Integers.sum; @@ -10,9 +12,19 @@ * Add all the natural numbers below one thousand that are multiples of 3 or 5. */ public class Problem1 { - public static void main(final String[] args) { - out.println(sum(range(0, 1000).filter(new F() { - public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} - }))); - } + public static void main(final String[] args) { + java7(); + java8(); + } + + public static void java7() { + out.println(sum(range(0, 1000).filter(new F() { + public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} + }))); + } + + public static void java8() { + out.println(Stream.range(0, 1000).filter(i -> i % 3 == 0 || i % 5 == 0).foldLeft((acc, i) -> acc + i, 0)); + } + } diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index faf91ddd..45a3be34 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -13,12 +13,26 @@ * Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million. */ public class Problem2 { - public static void main(final String[] args) { - final Stream fibs = new F2>() { - public Stream f(final Integer a, final Integer b) { - return cons(a, curry().f(b).lazy().f(a + b)); - } - }.f(1, 2); - out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); - } + public static void main(final String[] args) { + java7(); + java8(); + } + + static void java7() { + final Stream fibs = new F2>() { + public Stream f(final Integer a, final Integer b) { + return cons(a, curry().f(b).lazy().f(a + b)); + } + }.f(1, 2); + out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); + } + + static F2> fibsJava8 = (a, b) -> { + return cons(a, fibsJava8.curry().f(b).lazy().f(a + b)); + }; + + static void java8() { + out.println(sum(fibsJava8.f(1, 2).filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); + } + } diff --git a/functionaljava8.iml b/functionaljava.iml similarity index 100% rename from functionaljava8.iml rename to functionaljava.iml From 2dcbca8f9c5dc3d718c03ce556ed9260909c907d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 20 Nov 2013 10:34:35 +1000 Subject: [PATCH 016/811] Name and version FJ core artifact --- build.gradle | 5 +++++ core/build.gradle | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index 2ed9c081..1e1b7a99 100644 --- a/build.gradle +++ b/build.gradle @@ -1,2 +1,7 @@ defaultTasks 'build' + +ext { + fjVersion = "4.0-java8" + projectName = "functionaljava" +} \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index 1d000dd7..ce25fbcb 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -32,6 +32,14 @@ test { include '**/*Test.*' } +jar { + baseName project.projectName + version project.fjVersion + manifest { + attributes 'Signature-Version': project.fjVersion + } +} + // In this section you declare where to find the dependencies of your project repositories { // Use 'maven central' for resolving your dependencies. From 8ec4dcd92f6f58b90b43411a7dd1198f5c458bf0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 01:13:53 +1000 Subject: [PATCH 017/811] Set project org and version for local Maven/Gradle install --- build.gradle | 17 ++++++++++++++--- core/build.gradle | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1e1b7a99..2919d37d 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,17 @@ defaultTasks 'build' ext { - fjVersion = "4.0-java8" - projectName = "functionaljava" -} \ No newline at end of file +} + +allprojects { + ext { + fjVersion = "4.0-SNAPSHOT" + projectName = "functionaljava" + } + version = fjVersion + group = "org.functionaljava" +} + +subprojects { + +} diff --git a/core/build.gradle b/core/build.gradle index ce25fbcb..9772c388 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,6 +9,7 @@ // Apply the java plugin to add support for Java apply plugin: 'java' +apply plugin: 'maven' apply plugin: 'scala' defaultTasks 'build' From 706e8280285cebc24c3585a2b226ae2cc044dd19 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 01:15:14 +1000 Subject: [PATCH 018/811] Ignore .gradle and build dir --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 12b582d3..df28fabf 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ lib_managed .idea/ant.xml .idea/workspace.xml +.gradle +build + From 3a67972dcc1d476adaccc3b007f1409ed2fc09d2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 01:19:56 +1000 Subject: [PATCH 019/811] Removed unnecessary Gradle comments --- core/build.gradle | 23 ----------------------- demo/build.gradle | 34 ++-------------------------------- 2 files changed, 2 insertions(+), 55 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 9772c388..4a5b1f9f 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,13 +1,4 @@ -/* - * This build file was auto generated by running the Gradle 'buildSetup' task - * by 'MarkPerry' at '19/11/13 10:51 AM' with Gradle 1.8 - * - * This generated file contains a sample Java project to get you started. - * For more details take a look at the Java Quickstart chapter in the Gradle - * user guide available at http://gradle.org/docs/1.8/userguide/tutorial_java_projects.html - */ -// Apply the java plugin to add support for Java apply plugin: 'java' apply plugin: 'maven' apply plugin: 'scala' @@ -16,14 +7,10 @@ defaultTasks 'build' ext { scalaVersion = "2.10.+" -// scalaVersion = "2.9.+" - scalacheckVersion = "1.10.+" -// scalacheckScalaVersion = "2.9.3" scalacheckScalaVersion = "2.10" } - tasks.withType(ScalaCompile) { scalaCompileOptions.useAnt = false } @@ -41,24 +28,14 @@ jar { } } -// In this section you declare where to find the dependencies of your project repositories { - // Use 'maven central' for resolving your dependencies. - // You can declare any Maven/Ivy/file repository here. mavenCentral() } -// In this section you declare the dependencies for your production and test code dependencies { - // The production code uses the SLF4J logging API at compile time compile 'org.slf4j:slf4j-api:1.7.5' testCompile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - - // Declare the dependency for your favourite test framework you want to use in your tests. - // TestNG is also supported by the Gradle Test task. Just change the - // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add - // 'test.useTestNG()' to your build script. testCompile "junit:junit:4.11" } diff --git a/demo/build.gradle b/demo/build.gradle index 7ae6fe98..5769f739 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,52 +1,22 @@ -/* - * This build file was auto generated by running the Gradle 'buildSetup' task - * by 'MarkPerry' at '19/11/13 10:51 AM' with Gradle 1.8 - * - * This generated file contains a sample Java project to get you started. - * For more details take a look at the Java Quickstart chapter in the Gradle - * user guide available at http://gradle.org/docs/1.8/userguide/tutorial_java_projects.html - */ -// Apply the java plugin to add support for Java apply plugin: 'java' apply plugin: 'application' -//apply plugin: 'scala' defaultTasks 'build' -//mainClassName = "fj.demo.Array_forall" mainClassName = "fj.demo.euler.Problem2" -//mainClassName = "fj.demo.Primes2" ext { -// scalaVersion = "2.7.+" -// scalaVersion = "2.8.+" scalaVersion = "2.9.+" - scalacheckVersion = "1.10.+" } - - -// In this section you declare where to find the dependencies of your project repositories { - // Use 'maven central' for resolving your dependencies. - // You can declare any Maven/Ivy/file repository here. mavenCentral() } -// In this section you declare the dependencies for your production and test code dependencies { - // The production code uses the SLF4J logging API at compile time - compile 'org.slf4j:slf4j-api:1.7.5' + compile 'org.slf4j:slf4j-api:1.7.5' compile project(":core") -// testCompile "org.scala-lang:scala-library:$scalaVersion" -// testCompile "org.scalacheck:scalacheck_2.9.3:$scalacheckVersion" - - - // Declare the dependency for your favourite test framework you want to use in your tests. - // TestNG is also supported by the Gradle Test task. Just change the - // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add - // 'test.useTestNG()' to your build script. - testCompile "junit:junit:4.11" + testCompile "junit:junit:4.11" } From b7ce9571abbc01f74e12a7db587bc04d5eef192c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 09:47:47 +1000 Subject: [PATCH 020/811] Removed .idea dir --- .idea/.name | 1 - .idea/compiler.xml | 23 ---- .idea/copyright/profiles_settings.xml | 5 - .idea/encodings.xml | 5 - .idea/gradle.xml | 9 -- .idea/libraries/hamcrest_core_1_3.xml | 11 -- .idea/libraries/junit_4_11.xml | 11 -- .idea/libraries/scala_actors_2_10_1.xml | 11 -- .idea/libraries/scala_library_2_10_3.xml | 11 -- .idea/libraries/scalacheck_2_10_1_10_1.xml | 11 -- .idea/libraries/slf4j_api_1_7_5.xml | 11 -- .idea/libraries/test_interface_0_5.xml | 9 -- .idea/misc.xml | 11 -- .idea/modules.xml | 11 -- .idea/scopes/scope_settings.xml | 5 - .idea/uiDesigner.xml | 125 --------------------- .idea/vcs.xml | 7 -- 17 files changed, 277 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/compiler.xml delete mode 100644 .idea/copyright/profiles_settings.xml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/libraries/hamcrest_core_1_3.xml delete mode 100644 .idea/libraries/junit_4_11.xml delete mode 100644 .idea/libraries/scala_actors_2_10_1.xml delete mode 100644 .idea/libraries/scala_library_2_10_3.xml delete mode 100644 .idea/libraries/scalacheck_2_10_1_10_1.xml delete mode 100644 .idea/libraries/slf4j_api_1_7_5.xml delete mode 100644 .idea/libraries/test_interface_0_5.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/scopes/scope_settings.xml delete mode 100644 .idea/uiDesigner.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index f111a67e..00000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -functionaljava \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 217af471..00000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index 3572571a..00000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index e206d70d..00000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index c83159e7..00000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/.idea/libraries/hamcrest_core_1_3.xml b/.idea/libraries/hamcrest_core_1_3.xml deleted file mode 100644 index d65a446f..00000000 --- a/.idea/libraries/hamcrest_core_1_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/junit_4_11.xml b/.idea/libraries/junit_4_11.xml deleted file mode 100644 index 6e677320..00000000 --- a/.idea/libraries/junit_4_11.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/scala_actors_2_10_1.xml b/.idea/libraries/scala_actors_2_10_1.xml deleted file mode 100644 index 80b687eb..00000000 --- a/.idea/libraries/scala_actors_2_10_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/scala_library_2_10_3.xml b/.idea/libraries/scala_library_2_10_3.xml deleted file mode 100644 index 6a8811dc..00000000 --- a/.idea/libraries/scala_library_2_10_3.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/scalacheck_2_10_1_10_1.xml b/.idea/libraries/scalacheck_2_10_1_10_1.xml deleted file mode 100644 index 8246da21..00000000 --- a/.idea/libraries/scalacheck_2_10_1_10_1.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/slf4j_api_1_7_5.xml b/.idea/libraries/slf4j_api_1_7_5.xml deleted file mode 100644 index 4400458f..00000000 --- a/.idea/libraries/slf4j_api_1_7_5.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/libraries/test_interface_0_5.xml b/.idea/libraries/test_interface_0_5.xml deleted file mode 100644 index d83760e8..00000000 --- a/.idea/libraries/test_interface_0_5.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 4e5bf88f..00000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index ba1a7031..00000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b8..00000000 --- a/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml deleted file mode 100644 index 3b000203..00000000 --- a/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index def6a6a1..00000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - From 88aa19b1d93dbc97237f51978f87f6cf94330e4e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:00:48 +1000 Subject: [PATCH 021/811] Removed Intellij files --- .gitignore | 3 +-- core/core.iml | 34 ---------------------------------- demo/demo.iml | 21 --------------------- 3 files changed, 1 insertion(+), 57 deletions(-) delete mode 100644 core/core.iml delete mode 100644 demo/demo.iml diff --git a/.gitignore b/.gitignore index df28fabf..ad05cb7f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,7 @@ lib_managed *.iws .deps -.idea/ant.xml -.idea/workspace.xml +.idea .gradle build diff --git a/core/core.iml b/core/core.iml deleted file mode 100644 index f35c0bd8..00000000 --- a/core/core.iml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/demo/demo.iml b/demo/demo.iml deleted file mode 100644 index c4230de2..00000000 --- a/demo/demo.iml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - From bf5e3e98417c60b26dc8fdcc4f2679d747574ac6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:06:24 +1000 Subject: [PATCH 022/811] Basic scala module for testing --- tests/build.gradle | 28 +++++++++++++++++++++++++ tests/settings.gradle | 19 +++++++++++++++++ tests/src/main/scala/Library.scala | 9 ++++++++ tests/src/test/scala/LibrarySuite.scala | 18 ++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 tests/build.gradle create mode 100644 tests/settings.gradle create mode 100644 tests/src/main/scala/Library.scala create mode 100644 tests/src/test/scala/LibrarySuite.scala diff --git a/tests/build.gradle b/tests/build.gradle new file mode 100644 index 00000000..eee40fea --- /dev/null +++ b/tests/build.gradle @@ -0,0 +1,28 @@ +/* + * This build file was auto generated by running the Gradle 'init' task + * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 + * + * This generated file contains a sample Scala library project to get you started. + * For more details take a look at the Scala plugin chapter in the Gradle + * user guide available at http://gradle.org/docs/1.9/userguide/scala_plugin.html + */ + +// Apply the scala plugin to add support for Scala +apply plugin: 'scala' + +// In this section you declare where to find the dependencies of your project +repositories { + // Use 'maven central' for resolving your dependencies. + // You can declare any Maven/Ivy/file repository here. + mavenCentral() +} + +// In this section you declare the dependencies for your production and test code +dependencies { + // We use the latest 2.10 scala version in our library project + compile 'org.scala-lang:scala-library:2.10.3' + + // We use the latest version of the scalatest for testing our library + testCompile 'junit:junit:4.11' + testCompile 'org.scalatest:scalatest_2.10:1.9.2' +} diff --git a/tests/settings.gradle b/tests/settings.gradle new file mode 100644 index 00000000..1c460539 --- /dev/null +++ b/tests/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'tests' diff --git a/tests/src/main/scala/Library.scala b/tests/src/main/scala/Library.scala new file mode 100644 index 00000000..b956351a --- /dev/null +++ b/tests/src/main/scala/Library.scala @@ -0,0 +1,9 @@ +/* + * This Scala source file was auto generated by running 'gradle buildInit --type scala-library' + * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 + * + * @author MarkPerry, @date 12/12/13 10:02 AM + */ +class Library { + def someLibraryMethod(): Boolean = true +} diff --git a/tests/src/test/scala/LibrarySuite.scala b/tests/src/test/scala/LibrarySuite.scala new file mode 100644 index 00000000..ced7f663 --- /dev/null +++ b/tests/src/test/scala/LibrarySuite.scala @@ -0,0 +1,18 @@ +/* + * This Scala Testsuite was auto generated by running 'gradle init --type scala-library' + * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 + * + * @author MarkPerry, @date 12/12/13 10:02 AM + */ + +import org.scalatest.FunSuite +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class LibrarySuite extends FunSuite { + test("someLibraryMethod is always true") { + def library = new Library() + assert(library.someLibraryMethod) + } +} From 4a7802fb459eff7a19480e5f2146a3bdc5646edc Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:19:48 +1000 Subject: [PATCH 023/811] Made tests module compile for scala, disabled scala in core module --- core/build.gradle | 17 ----------------- tests/build.gradle | 32 ++++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 4a5b1f9f..eeb8a392 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,24 +1,9 @@ apply plugin: 'java' apply plugin: 'maven' -apply plugin: 'scala' defaultTasks 'build' -ext { - scalaVersion = "2.10.+" - scalacheckVersion = "1.10.+" - scalacheckScalaVersion = "2.10" -} - -tasks.withType(ScalaCompile) { - scalaCompileOptions.useAnt = false -} - -test { - scanForTestClasses = false - include '**/*Test.*' -} jar { baseName project.projectName @@ -34,8 +19,6 @@ repositories { dependencies { compile 'org.slf4j:slf4j-api:1.7.5' - testCompile "org.scala-lang:scala-library:$scalaVersion" - testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" testCompile "junit:junit:4.11" } diff --git a/tests/build.gradle b/tests/build.gradle index eee40fea..ddc61710 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -10,6 +10,25 @@ // Apply the scala plugin to add support for Scala apply plugin: 'scala' + +ext { + scalaVersion = "2.10.+" + scalacheckVersion = "1.10.+" + scalacheckScalaVersion = "2.10" +} + + + +tasks.withType(ScalaCompile) { + scalaCompileOptions.useAnt = false +} + + +test { + scanForTestClasses = false + include '**/*Test.*' +} + // In this section you declare where to find the dependencies of your project repositories { // Use 'maven central' for resolving your dependencies. @@ -17,12 +36,13 @@ repositories { mavenCentral() } -// In this section you declare the dependencies for your production and test code + dependencies { - // We use the latest 2.10 scala version in our library project - compile 'org.scala-lang:scala-library:2.10.3' + compile 'org.slf4j:slf4j-api:1.7.5' + compile "org.scala-lang:scala-library:$scalaVersion" + testCompile "org.scala-lang:scala-library:$scalaVersion" + testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - // We use the latest version of the scalatest for testing our library - testCompile 'junit:junit:4.11' - testCompile 'org.scalatest:scalatest_2.10:1.9.2' + testCompile "junit:junit:4.11" + testCompile 'org.scalatest:scalatest_2.10:1.9.2' } From 689901ffbd1e8a7031a234b6f2146380fa009407 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:26:30 +1000 Subject: [PATCH 024/811] Moved scala tests out of core into tests --- {core => tests}/src/test/scala/fj/ArbitraryP.scala | 0 {core => tests}/src/test/scala/fj/FunctionalJavaJUnitTest.java | 0 {core => tests}/src/test/scala/fj/Implicit.scala | 0 {core => tests}/src/test/scala/fj/Tests.scala | 0 .../src/test/scala/fj/control/parallel/ArbitraryParModule.scala | 0 .../src/test/scala/fj/control/parallel/ArbitraryStrategy.scala | 0 .../src/test/scala/fj/control/parallel/CheckParModule.scala | 0 .../src/test/scala/fj/control/parallel/CheckStrategy.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryArray.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryHashMap.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryHashSet.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryList.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryOption.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitrarySet.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryStream.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryTree.scala | 0 {core => tests}/src/test/scala/fj/data/ArbitraryTreeMap.scala | 0 {core => tests}/src/test/scala/fj/data/CheckArray.scala | 0 {core => tests}/src/test/scala/fj/data/CheckHashMap.scala | 0 {core => tests}/src/test/scala/fj/data/CheckHashSet.scala | 0 {core => tests}/src/test/scala/fj/data/CheckIO.scala | 0 {core => tests}/src/test/scala/fj/data/CheckIteratee.scala | 0 {core => tests}/src/test/scala/fj/data/CheckList.scala | 0 {core => tests}/src/test/scala/fj/data/CheckOption.scala | 0 {core => tests}/src/test/scala/fj/data/CheckSet.scala | 0 {core => tests}/src/test/scala/fj/data/CheckStream.scala | 0 {core => tests}/src/test/scala/fj/data/CheckTree.scala | 0 {core => tests}/src/test/scala/fj/data/CheckTreeMap.scala | 0 {core => tests}/src/test/scala/fj/package.scala | 0 29 files changed, 0 insertions(+), 0 deletions(-) rename {core => tests}/src/test/scala/fj/ArbitraryP.scala (100%) rename {core => tests}/src/test/scala/fj/FunctionalJavaJUnitTest.java (100%) rename {core => tests}/src/test/scala/fj/Implicit.scala (100%) rename {core => tests}/src/test/scala/fj/Tests.scala (100%) rename {core => tests}/src/test/scala/fj/control/parallel/ArbitraryParModule.scala (100%) rename {core => tests}/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala (100%) rename {core => tests}/src/test/scala/fj/control/parallel/CheckParModule.scala (100%) rename {core => tests}/src/test/scala/fj/control/parallel/CheckStrategy.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryArray.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryHashMap.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryHashSet.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryList.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryOption.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitrarySet.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryStream.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryTree.scala (100%) rename {core => tests}/src/test/scala/fj/data/ArbitraryTreeMap.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckArray.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckHashMap.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckHashSet.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckIO.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckIteratee.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckList.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckOption.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckSet.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckStream.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckTree.scala (100%) rename {core => tests}/src/test/scala/fj/data/CheckTreeMap.scala (100%) rename {core => tests}/src/test/scala/fj/package.scala (100%) diff --git a/core/src/test/scala/fj/ArbitraryP.scala b/tests/src/test/scala/fj/ArbitraryP.scala similarity index 100% rename from core/src/test/scala/fj/ArbitraryP.scala rename to tests/src/test/scala/fj/ArbitraryP.scala diff --git a/core/src/test/scala/fj/FunctionalJavaJUnitTest.java b/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java similarity index 100% rename from core/src/test/scala/fj/FunctionalJavaJUnitTest.java rename to tests/src/test/scala/fj/FunctionalJavaJUnitTest.java diff --git a/core/src/test/scala/fj/Implicit.scala b/tests/src/test/scala/fj/Implicit.scala similarity index 100% rename from core/src/test/scala/fj/Implicit.scala rename to tests/src/test/scala/fj/Implicit.scala diff --git a/core/src/test/scala/fj/Tests.scala b/tests/src/test/scala/fj/Tests.scala similarity index 100% rename from core/src/test/scala/fj/Tests.scala rename to tests/src/test/scala/fj/Tests.scala diff --git a/core/src/test/scala/fj/control/parallel/ArbitraryParModule.scala b/tests/src/test/scala/fj/control/parallel/ArbitraryParModule.scala similarity index 100% rename from core/src/test/scala/fj/control/parallel/ArbitraryParModule.scala rename to tests/src/test/scala/fj/control/parallel/ArbitraryParModule.scala diff --git a/core/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala b/tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala similarity index 100% rename from core/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala rename to tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala diff --git a/core/src/test/scala/fj/control/parallel/CheckParModule.scala b/tests/src/test/scala/fj/control/parallel/CheckParModule.scala similarity index 100% rename from core/src/test/scala/fj/control/parallel/CheckParModule.scala rename to tests/src/test/scala/fj/control/parallel/CheckParModule.scala diff --git a/core/src/test/scala/fj/control/parallel/CheckStrategy.scala b/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala similarity index 100% rename from core/src/test/scala/fj/control/parallel/CheckStrategy.scala rename to tests/src/test/scala/fj/control/parallel/CheckStrategy.scala diff --git a/core/src/test/scala/fj/data/ArbitraryArray.scala b/tests/src/test/scala/fj/data/ArbitraryArray.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryArray.scala rename to tests/src/test/scala/fj/data/ArbitraryArray.scala diff --git a/core/src/test/scala/fj/data/ArbitraryHashMap.scala b/tests/src/test/scala/fj/data/ArbitraryHashMap.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryHashMap.scala rename to tests/src/test/scala/fj/data/ArbitraryHashMap.scala diff --git a/core/src/test/scala/fj/data/ArbitraryHashSet.scala b/tests/src/test/scala/fj/data/ArbitraryHashSet.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryHashSet.scala rename to tests/src/test/scala/fj/data/ArbitraryHashSet.scala diff --git a/core/src/test/scala/fj/data/ArbitraryList.scala b/tests/src/test/scala/fj/data/ArbitraryList.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryList.scala rename to tests/src/test/scala/fj/data/ArbitraryList.scala diff --git a/core/src/test/scala/fj/data/ArbitraryOption.scala b/tests/src/test/scala/fj/data/ArbitraryOption.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryOption.scala rename to tests/src/test/scala/fj/data/ArbitraryOption.scala diff --git a/core/src/test/scala/fj/data/ArbitrarySet.scala b/tests/src/test/scala/fj/data/ArbitrarySet.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitrarySet.scala rename to tests/src/test/scala/fj/data/ArbitrarySet.scala diff --git a/core/src/test/scala/fj/data/ArbitraryStream.scala b/tests/src/test/scala/fj/data/ArbitraryStream.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryStream.scala rename to tests/src/test/scala/fj/data/ArbitraryStream.scala diff --git a/core/src/test/scala/fj/data/ArbitraryTree.scala b/tests/src/test/scala/fj/data/ArbitraryTree.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryTree.scala rename to tests/src/test/scala/fj/data/ArbitraryTree.scala diff --git a/core/src/test/scala/fj/data/ArbitraryTreeMap.scala b/tests/src/test/scala/fj/data/ArbitraryTreeMap.scala similarity index 100% rename from core/src/test/scala/fj/data/ArbitraryTreeMap.scala rename to tests/src/test/scala/fj/data/ArbitraryTreeMap.scala diff --git a/core/src/test/scala/fj/data/CheckArray.scala b/tests/src/test/scala/fj/data/CheckArray.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckArray.scala rename to tests/src/test/scala/fj/data/CheckArray.scala diff --git a/core/src/test/scala/fj/data/CheckHashMap.scala b/tests/src/test/scala/fj/data/CheckHashMap.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckHashMap.scala rename to tests/src/test/scala/fj/data/CheckHashMap.scala diff --git a/core/src/test/scala/fj/data/CheckHashSet.scala b/tests/src/test/scala/fj/data/CheckHashSet.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckHashSet.scala rename to tests/src/test/scala/fj/data/CheckHashSet.scala diff --git a/core/src/test/scala/fj/data/CheckIO.scala b/tests/src/test/scala/fj/data/CheckIO.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckIO.scala rename to tests/src/test/scala/fj/data/CheckIO.scala diff --git a/core/src/test/scala/fj/data/CheckIteratee.scala b/tests/src/test/scala/fj/data/CheckIteratee.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckIteratee.scala rename to tests/src/test/scala/fj/data/CheckIteratee.scala diff --git a/core/src/test/scala/fj/data/CheckList.scala b/tests/src/test/scala/fj/data/CheckList.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckList.scala rename to tests/src/test/scala/fj/data/CheckList.scala diff --git a/core/src/test/scala/fj/data/CheckOption.scala b/tests/src/test/scala/fj/data/CheckOption.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckOption.scala rename to tests/src/test/scala/fj/data/CheckOption.scala diff --git a/core/src/test/scala/fj/data/CheckSet.scala b/tests/src/test/scala/fj/data/CheckSet.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckSet.scala rename to tests/src/test/scala/fj/data/CheckSet.scala diff --git a/core/src/test/scala/fj/data/CheckStream.scala b/tests/src/test/scala/fj/data/CheckStream.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckStream.scala rename to tests/src/test/scala/fj/data/CheckStream.scala diff --git a/core/src/test/scala/fj/data/CheckTree.scala b/tests/src/test/scala/fj/data/CheckTree.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckTree.scala rename to tests/src/test/scala/fj/data/CheckTree.scala diff --git a/core/src/test/scala/fj/data/CheckTreeMap.scala b/tests/src/test/scala/fj/data/CheckTreeMap.scala similarity index 100% rename from core/src/test/scala/fj/data/CheckTreeMap.scala rename to tests/src/test/scala/fj/data/CheckTreeMap.scala diff --git a/core/src/test/scala/fj/package.scala b/tests/src/test/scala/fj/package.scala similarity index 100% rename from core/src/test/scala/fj/package.scala rename to tests/src/test/scala/fj/package.scala From 6925318e4eef77753a45f6743ac455edc32e9c8f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:27:03 +1000 Subject: [PATCH 025/811] Get functional java from local Maven repo --- tests/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/build.gradle b/tests/build.gradle index ddc61710..f32db76e 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -34,11 +34,13 @@ repositories { // Use 'maven central' for resolving your dependencies. // You can declare any Maven/Ivy/file repository here. mavenCentral() + mavenLocal() } dependencies { compile 'org.slf4j:slf4j-api:1.7.5' + compile "org.functionaljava:functionaljava:4.0-SNAPSHOT" compile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" From 41ed4254319d954c7575d41e600db9c730df3a8c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:30:10 +1000 Subject: [PATCH 026/811] Removed settings.gradle from tests module --- tests/settings.gradle | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 tests/settings.gradle diff --git a/tests/settings.gradle b/tests/settings.gradle deleted file mode 100644 index 1c460539..00000000 --- a/tests/settings.gradle +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This settings file was auto generated by the Gradle buildInit task - * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 - * - * The settings file is used to specify which projects to include in your build. - * In a single project build this file can be empty or even removed. - * - * Detailed information about configuring a multi-project build in Gradle can be found - * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html - */ - -/* -// To declare projects as part of a multi-project build use the 'include' method -include 'shared' -include 'api' -include 'services:webservice' -*/ - -rootProject.name = 'tests' From 9e99fd832c7863c896e8ada7058cb86be72c57e1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 12 Dec 2013 10:38:06 +1000 Subject: [PATCH 027/811] Ignore *.iml files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ad05cb7f..81574421 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ lib_managed .gradle build +*.iml + From 673bd368d3e604acd144d32c82776529d5954a5b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 20 Dec 2013 20:40:44 +1000 Subject: [PATCH 028/811] Removed Intellij iml file --- functionaljava.iml | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 functionaljava.iml diff --git a/functionaljava.iml b/functionaljava.iml deleted file mode 100644 index 7e9ac103..00000000 --- a/functionaljava.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - From f88bbe1c77c6d8ddcb4f9d2f2cc3ece3bf1690d8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 3 Feb 2014 15:06:36 +1000 Subject: [PATCH 029/811] Include tests module, fixed inter project dependency --- settings.gradle | 2 +- tests/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/settings.gradle b/settings.gradle index eb5b81aa..59f00f2c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ -include 'core', 'demo' +include 'core', 'demo', 'tests' diff --git a/tests/build.gradle b/tests/build.gradle index f32db76e..7cd4bdbe 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -12,7 +12,7 @@ apply plugin: 'scala' ext { - scalaVersion = "2.10.+" + scalaVersion = "2.10.3" scalacheckVersion = "1.10.+" scalacheckScalaVersion = "2.10" } @@ -39,8 +39,8 @@ repositories { dependencies { + compile project(":core") compile 'org.slf4j:slf4j-api:1.7.5' - compile "org.functionaljava:functionaljava:4.0-SNAPSHOT" compile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" From 63ed4885c8239818a6f24574a29a276da4f8d926 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 4 Apr 2014 01:11:02 +1000 Subject: [PATCH 030/811] Fixed self reference problem introduced since last early access released used --- demo/src/main/java/fj/demo/euler/Problem2.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index 45a3be34..db6bf1c5 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -27,8 +27,8 @@ public Stream f(final Integer a, final Integer b) { out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); } - static F2> fibsJava8 = (a, b) -> { - return cons(a, fibsJava8.curry().f(b).lazy().f(a + b)); + final static F2> fibsJava8 = (a, b) -> { + return cons(a, Problem2.fibsJava8.curry().f(b).lazy().f(a + b)); }; static void java8() { From 049364a2d55b6e3ee1a1c26171b166257e0b93d5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 4 Apr 2014 01:12:03 +1000 Subject: [PATCH 031/811] Workaround since Java 8 release does not work with Gradle for ScalaDoc task --- build.gradle | 2 +- settings.gradle | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2919d37d..a73a6321 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ allprojects { projectName = "functionaljava" } version = fjVersion - group = "org.functionaljava" + group = "com.github.mperry" } subprojects { diff --git a/settings.gradle b/settings.gradle index 59f00f2c..a3dbc7ff 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,6 @@ -include 'core', 'demo', 'tests' +//include 'core', 'demo', 'tests' +include 'core', 'demo' +// The final Java 8 release, (build 1.8.0-b132) does not work with Gradle and the Scala plugin +// see http://issues.gradle.org/browse/GRADLE-3023 + From bf1f9e684b22ed227cadd891c12307d2e9670b7d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 6 Apr 2014 15:39:42 +1000 Subject: [PATCH 032/811] Fixed to work with final Java 8 release --- demo/src/main/java/fj/demo/euler/Problem2.java | 2 +- settings.gradle | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index 45a3be34..479a8088 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -28,7 +28,7 @@ public Stream f(final Integer a, final Integer b) { } static F2> fibsJava8 = (a, b) -> { - return cons(a, fibsJava8.curry().f(b).lazy().f(a + b)); + return cons(a, Problem2.fibsJava8.curry().f(b).lazy().f(a + b)); }; static void java8() { diff --git a/settings.gradle b/settings.gradle index 59f00f2c..f1cf677d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,3 @@ -include 'core', 'demo', 'tests' +//include 'core', 'demo', 'tests' +include 'core', 'demo' From 659f728ef8d1e4f172bd00c897c6559d5b3297a3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 6 Apr 2014 16:40:16 +1000 Subject: [PATCH 033/811] Converted F2 methods to static methods on F2Functions --- core/src/main/java/fj/F1Functions.java | 7 + core/src/main/java/fj/F2.java | 330 ----------------- core/src/main/java/fj/F2Functions.java | 349 ++++++++++++++++++ core/src/main/java/fj/F3Functions.java | 7 + core/src/main/java/fj/F4Functions.java | 7 + core/src/main/java/fj/F5Functions.java | 7 + core/src/main/java/fj/F6Functions.java | 7 + core/src/main/java/fj/F7Functions.java | 7 + core/src/main/java/fj/F8Functions.java | 7 + core/src/main/java/fj/control/Trampoline.java | 9 +- .../java/fj/control/parallel/ParModule.java | 3 +- core/src/main/java/fj/data/List.java | 3 +- core/src/main/java/fj/data/Tree.java | 5 +- core/src/main/java/fj/data/TreeZipper.java | 13 +- core/src/main/java/fj/data/Zipper.java | 4 +- .../src/main/java/fj/demo/euler/Problem2.java | 6 +- 16 files changed, 419 insertions(+), 352 deletions(-) create mode 100644 core/src/main/java/fj/F1Functions.java create mode 100644 core/src/main/java/fj/F2Functions.java create mode 100644 core/src/main/java/fj/F3Functions.java create mode 100644 core/src/main/java/fj/F4Functions.java create mode 100644 core/src/main/java/fj/F5Functions.java create mode 100644 core/src/main/java/fj/F6Functions.java create mode 100644 core/src/main/java/fj/F7Functions.java create mode 100644 core/src/main/java/fj/F8Functions.java diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java new file mode 100644 index 00000000..960162ee --- /dev/null +++ b/core/src/main/java/fj/F1Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F1Functions { +} diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index eeb19d12..0aa82585 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -35,334 +35,4 @@ public interface F2 { */ public C f(A a, B b); - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - default public F f(final A a) { - return new F() { - public C f(final B b) { - return F2.this.f(a, b); - } - }; - } - - /** - * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function. - * - * @return a wrapped function of arity-1 that returns another wrapped function. - */ - default public F> curry() { - return new F>() { - public F f(final A a) { - return new F() { - public C f(final B b) { - return F2.this.f(a, b); - } - }; - } - }; - } - - /** - * Flips the arguments of this function. - * - * @return A new function with the arguments of this function flipped. - */ - default public F2 flip() { - return new F2() { - public C f(final B b, final A a) { - return F2.this.f(a, b); - } - }; - } - - /** - * Uncurries this function to a function on tuples. - * - * @return A new function that calls this function with the elements of a given tuple. - */ - default public F, C> tuple() { - return new F, C>() { - public C f(final P2 p) { - return F2.this.f(p._1(), p._2()); - } - }; - } - - /** - * Promotes this function to a function on Arrays. - * - * @return This function promoted to transform Arrays. - */ - default public F2, Array, Array> arrayM() { - return new F2, Array, Array>() { - public Array f(final Array a, final Array b) { - return a.bind(b, F2.this.curry()); - } - }; - } - - /** - * Promotes this function to a function on Promises. - * - * @return This function promoted to transform Promises. - */ - default public F2, Promise, Promise> promiseM() { - return new F2, Promise, Promise>() { - public Promise f(final Promise a, final Promise b) { - return a.bind(b, F2.this.curry()); - } - }; - } - - /** - * Promotes this function to a function on Iterables. - * - * @return This function promoted to transform Iterables. - */ - default public F2, Iterable, IterableW> iterableM() { - return new F2, Iterable, IterableW>() { - public IterableW f(final Iterable a, final Iterable b) { - return IterableW.liftM2(F2.this.curry()).f(a).f(b); - } - }; - } - - /** - * Promotes this function to a function on Lists. - * - * @return This function promoted to transform Lists. - */ - default public F2, List, List> listM() { - return new F2, List, List>() { - public List f(final List a, final List b) { - return List.liftM2(F2.this.curry()).f(a).f(b); - } - }; - } - - /** - * Promotes this function to a function on non-empty lists. - * - * @return This function promoted to transform non-empty lists. - */ - default public F2, NonEmptyList, NonEmptyList> nelM() { - return new F2, NonEmptyList, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { - return NonEmptyList.fromList(as.toList().bind(bs.toList(), F2.this)).some(); - } - }; - } - - /** - * Promotes this function to a function on Options. - * - * @return This function promoted to transform Options. - */ - default public F2, Option, Option> optionM() { - return new F2, Option, Option>() { - public Option f(final Option a, final Option b) { - return Option.liftM2(F2.this.curry()).f(a).f(b); - } - }; - } - - /** - * Promotes this function to a function on Sets. - * - * @param o An ordering for the result of the promoted function. - * @return This function promoted to transform Sets. - */ - default public F2, Set, Set> setM(final Ord o) { - return new F2, Set, Set>() { - public Set f(final Set as, final Set bs) { - Set cs = Set.empty(o); - for (final A a : as) - for (final B b : bs) - cs = cs.insert(F2.this.f(a, b)); - return cs; - } - }; - } - - /** - * Promotes this function to a function on Streams. - * - * @return This function promoted to transform Streams. - */ - default public F2, Stream, Stream> streamM() { - return new F2, Stream, Stream>() { - public Stream f(final Stream as, final Stream bs) { - return as.bind(bs, F2.this); - } - }; - } - - /** - * Promotes this function to a function on Trees. - * - * @return This function promoted to transform Trees. - */ - default public F2, Tree, Tree> treeM() { - return new F2, Tree, Tree>() { - public Tree f(final Tree as, final Tree bs) { - final F2, Tree, Tree> self = this; - return node(F2.this.f(as.root(), bs.root()), new P1>>() { - public Stream> _1() { - return self.streamM().f(as.subForest()._1(), bs.subForest()._1()); - } - }); - } - }; - } - - /** - * Promotes this function to zip two arrays, applying the function lock-step over both Arrays. - * - * @return A function that zips two arrays with this function. - */ - default public F2, Array, Array> zipArrayM() { - return new F2, Array, Array>() { - public Array f(final Array as, final Array bs) { - return as.zipWith(bs, F2.this); - } - }; - } - - /** - * Promotes this function to zip two iterables, applying the function lock-step over both iterables. - * - * @return A function that zips two iterables with this function. - */ - default public F2, Iterable, Iterable> zipIterableM() { - return new F2, Iterable, Iterable>() { - public Iterable f(final Iterable as, final Iterable bs) { - return wrap(as).zipWith(bs, F2.this); - } - }; - } - - /** - * Promotes this function to zip two lists, applying the function lock-step over both lists. - * - * @return A function that zips two lists with this function. - */ - default public F2, List, List> zipListM() { - return new F2, List, List>() { - public List f(final List as, final List bs) { - return as.zipWith(bs, F2.this); - } - }; - } - - - /** - * Promotes this function to zip two streams, applying the function lock-step over both streams. - * - * @return A function that zips two streams with this function. - */ - default public F2, Stream, Stream> zipStreamM() { - return new F2, Stream, Stream>() { - public Stream f(final Stream as, final Stream bs) { - return as.zipWith(bs, F2.this); - } - }; - } - - /** - * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists. - * - * @return A function that zips two non-empty lists with this function. - */ - default public F2, NonEmptyList, NonEmptyList> zipNelM() { - return new F2, NonEmptyList, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { - return NonEmptyList.fromList(as.toList().zipWith(bs.toList(), F2.this)).some(); - } - }; - } - - /** - * Promotes this function to zip two sets, applying the function lock-step over both sets. - * - * @param o An ordering for the resulting set. - * @return A function that zips two sets with this function. - */ - default public F2, Set, Set> zipSetM(final Ord o) { - return new F2, Set, Set>() { - public Set f(final Set as, final Set bs) { - return iterableSet(o, as.toStream().zipWith(bs.toStream(), F2.this)); - } - }; - } - - /** - * Promotes this function to zip two trees, applying the function lock-step over both trees. - * The structure of the resulting tree is the structural intersection of the two trees. - * - * @return A function that zips two trees with this function. - */ - default public F2, Tree, Tree> zipTreeM() { - return new F2, Tree, Tree>() { - public Tree f(final Tree ta, final Tree tb) { - final F2, Tree, Tree> self = this; - return node(F2.this.f(ta.root(), tb.root()), new P1>>() { - public Stream> _1() { - return self.zipStreamM().f(ta.subForest()._1(), tb.subForest()._1()); - } - }); - } - }; - } - - /** - * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions. - * The structure of the resulting zipper is the structural intersection of the two zippers. - * - * @return A function that zips two zippers with this function. - */ - default public F2, Zipper, Zipper> zipZipperM() { - return new F2, Zipper, Zipper>() { - @SuppressWarnings({"unchecked"}) - public Zipper f(final Zipper ta, final Zipper tb) { - final F2, Stream, Stream> sf = F2.this.zipStreamM(); - return zipper(sf.f(ta.lefts(), tb.lefts()), F2.this.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); - } - }; - } - - /** - * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions. - * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. - * - * @return A function that zips two TreeZippers with this function. - */ - default public F2, TreeZipper, TreeZipper> zipTreeZipperM() { - return new F2, TreeZipper, TreeZipper>() { - @SuppressWarnings({"unchecked"}) - public TreeZipper f(final TreeZipper ta, final TreeZipper tb) { - final F2>, Stream>, Stream>> sf = F2.this.treeM().zipStreamM(); - final - F2>, A, Stream>>>, - Stream>, B, Stream>>>, - Stream>, C, Stream>>>> - pf = - new F2>, A, Stream>>, - P3>, B, Stream>>, - P3>, C, Stream>>>() { - public P3>, C, Stream>> f(final P3>, A, Stream>> pa, - final P3>, B, Stream>> pb) { - return p(F2.this.treeM().zipStreamM().f(pa._1(), pb._1()), F2.this.f(pa._2(), pb._2()), - F2.this.treeM().zipStreamM().f(pa._3(), pb._3())); - } - }.zipStreamM(); - return treeZipper(F2.this.treeM().f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()), - sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4())); - } - }; - } } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java new file mode 100644 index 00000000..f2e0a8b1 --- /dev/null +++ b/core/src/main/java/fj/F2Functions.java @@ -0,0 +1,349 @@ +package fj; + +import fj.control.parallel.Promise; +import fj.data.*; + +import static fj.P.p; +import static fj.data.IterableW.wrap; +import static fj.data.Set.iterableSet; +import static fj.data.Tree.node; +import static fj.data.TreeZipper.treeZipper; +import static fj.data.Zipper.zipper; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F2Functions { + + + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F f(final F2 f, final A a) { + return new F() { + public C f(final B b) { + return f.f(a, b); + } + }; + } + + /** + * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function. + * + * @return a wrapped function of arity-1 that returns another wrapped function. + */ + static public F> curry(final F2 f) { + return new F>() { + public F f(final A a) { + return new F() { + public C f(final B b) { + return f.f(a, b); + } + }; + } + }; + } + + /** + * Flips the arguments of this function. + * + * @return A new function with the arguments of this function flipped. + */ + static public F2 flip(final F2 f) { + return new F2() { + public C f(final B b, final A a) { + return f.f(a, b); + } + }; + } + + /** + * Uncurries this function to a function on tuples. + * + * @return A new function that calls this function with the elements of a given tuple. + */ + static public F, C> tuple(final F2 f) { + return new F, C>() { + public C f(final P2 p) { + return f.f(p._1(), p._2()); + } + }; + } + + /** + * Promotes this function to a function on Arrays. + * + * @return This function promoted to transform Arrays. + */ + static public F2, Array, Array> arrayM(final F2 f) { + return new F2, Array, Array>() { + public Array f(final Array a, final Array b) { + return a.bind(b, curry(f)); + } + }; + } + + /** + * Promotes this function to a function on Promises. + * + * @return This function promoted to transform Promises. + */ + static public F2, Promise, Promise> promiseM(final F2 f) { + return new F2, Promise, Promise>() { + public Promise f(final Promise a, final Promise b) { + return a.bind(b, curry(f)); + } + }; + } + + /** + * Promotes this function to a function on Iterables. + * + * @return This function promoted to transform Iterables. + */ + static public F2, Iterable, IterableW> iterableM(final F2 f) { + return new F2, Iterable, IterableW>() { + public IterableW f(final Iterable a, final Iterable b) { + return IterableW.liftM2(curry(f)).f(a).f(b); + } + }; + } + + /** + * Promotes this function to a function on Lists. + * + * @return This function promoted to transform Lists. + */ + static public F2, List, List> listM(final F2 f) { + return new F2, List, List>() { + public List f(final List a, final List b) { + return List.liftM2(curry(f)).f(a).f(b); + } + }; + } + + /** + * Promotes this function to a function on non-empty lists. + * + * @return This function promoted to transform non-empty lists. + */ + static public F2, NonEmptyList, NonEmptyList> nelM(final F2 f) { + return new F2, NonEmptyList, NonEmptyList>() { + public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { + return NonEmptyList.fromList(as.toList().bind(bs.toList(), f)).some(); + } + }; + } + + /** + * Promotes this function to a function on Options. + * + * @return This function promoted to transform Options. + */ + static public F2, Option, Option> optionM(final F2 f) { + return new F2, Option, Option>() { + public Option f(final Option a, final Option b) { + return Option.liftM2(curry(f)).f(a).f(b); + } + }; + } + + /** + * Promotes this function to a function on Sets. + * + * @param o An ordering for the result of the promoted function. + * @return This function promoted to transform Sets. + */ + static public F2, Set, Set> setM(final F2 f, final Ord o) { + return new F2, Set, Set>() { + public Set f(final Set as, final Set bs) { + Set cs = Set.empty(o); + for (final A a : as) + for (final B b : bs) + cs = cs.insert(f.f(a, b)); + return cs; + } + }; + } + + /** + * Promotes this function to a function on Streams. + * + * @return This function promoted to transform Streams. + */ + static public F2, Stream, Stream> streamM(final F2 f) { + return new F2, Stream, Stream>() { + public Stream f(final Stream as, final Stream bs) { + return as.bind(bs, f); + } + }; + } + + /** + * Promotes this function to a function on Trees. + * + * @return This function promoted to transform Trees. + */ + static public F2, Tree, Tree> treeM(final F2 f) { + return new F2, Tree, Tree>() { + public Tree f(final Tree as, final Tree bs) { + final F2, Tree, Tree> self = this; + return node(f.f(as.root(), bs.root()), new P1>>() { + public Stream> _1() { + return streamM(self).f(as.subForest()._1(), bs.subForest()._1()); + } + }); + } + }; + } + + /** + * Promotes this function to zip two arrays, applying the function lock-step over both Arrays. + * + * @return A function that zips two arrays with this function. + */ + static public F2, Array, Array> zipArrayM(final F2 f) { + return new F2, Array, Array>() { + public Array f(final Array as, final Array bs) { + return as.zipWith(bs, f); + } + }; + } + + /** + * Promotes this function to zip two iterables, applying the function lock-step over both iterables. + * + * @return A function that zips two iterables with this function. + */ + static public F2, Iterable, Iterable> zipIterableM(final F2 f) { + return new F2, Iterable, Iterable>() { + public Iterable f(final Iterable as, final Iterable bs) { + return wrap(as).zipWith(bs, f); + } + }; + } + + /** + * Promotes this function to zip two lists, applying the function lock-step over both lists. + * + * @return A function that zips two lists with this function. + */ + static public F2, List, List> zipListM(final F2 f) { + return new F2, List, List>() { + public List f(final List as, final List bs) { + return as.zipWith(bs, f); + } + }; + } + + + /** + * Promotes this function to zip two streams, applying the function lock-step over both streams. + * + * @return A function that zips two streams with this function. + */ + static public F2, Stream, Stream> zipStreamM(final F2 f) { + return new F2, Stream, Stream>() { + public Stream f(final Stream as, final Stream bs) { + return as.zipWith(bs, f); + } + }; + } + + /** + * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists. + * + * @return A function that zips two non-empty lists with this function. + */ + static public F2, NonEmptyList, NonEmptyList> zipNelM(final F2 f) { + return new F2, NonEmptyList, NonEmptyList>() { + public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { + return NonEmptyList.fromList(as.toList().zipWith(bs.toList(), f)).some(); + } + }; + } + + /** + * Promotes this function to zip two sets, applying the function lock-step over both sets. + * + * @param o An ordering for the resulting set. + * @return A function that zips two sets with this function. + */ + static public F2, Set, Set> zipSetM(final F2 f, final Ord o) { + return new F2, Set, Set>() { + public Set f(final Set as, final Set bs) { + return iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); + } + }; + } + + /** + * Promotes this function to zip two trees, applying the function lock-step over both trees. + * The structure of the resulting tree is the structural intersection of the two trees. + * + * @return A function that zips two trees with this function. + */ + static public F2, Tree, Tree> zipTreeM(final F2 f) { + return new F2, Tree, Tree>() { + public Tree f(final Tree ta, final Tree tb) { + final F2, Tree, Tree> self = this; + return node(f.f(ta.root(), tb.root()), new P1>>() { + public Stream> _1() { + return zipStreamM(self).f(ta.subForest()._1(), tb.subForest()._1()); + } + }); + } + }; + } + + /** + * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions. + * The structure of the resulting zipper is the structural intersection of the two zippers. + * + * @return A function that zips two zippers with this function. + */ + static public F2, Zipper, Zipper> zipZipperM(final F2 f) { + return new F2, Zipper, Zipper>() { + @SuppressWarnings({"unchecked"}) + public Zipper f(final Zipper ta, final Zipper tb) { + final F2, Stream, Stream> sf = zipStreamM(f); + return zipper(sf.f(ta.lefts(), tb.lefts()), f.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); + } + }; + } + + /** + * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions. + * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. + * + * @return A function that zips two TreeZippers with this function. + */ + static public F2, TreeZipper, TreeZipper> zipTreeZipperM(final F2 f) { + return new F2, TreeZipper, TreeZipper>() { + @SuppressWarnings({"unchecked"}) + public TreeZipper f(final TreeZipper ta, final TreeZipper tb) { + final F2>, Stream>, Stream>> sf = zipStreamM(treeM(f)); + final + F2>, A, Stream>>>, + Stream>, B, Stream>>>, + Stream>, C, Stream>>>> + pf = + zipStreamM(new F2>, A, Stream>>, + P3>, B, Stream>>, + P3>, C, Stream>>>() { + public P3>, C, Stream>> f(final P3>, A, Stream>> pa, + final P3>, B, Stream>> pb) { + return p(zipStreamM(treeM(f)).f(pa._1(), pb._1()), f.f(pa._2(), pb._2()), + zipStreamM(treeM(f)).f(pa._3(), pb._3())); + } + }); + return treeZipper(treeM(f).f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()), + sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4())); + } + }; + } + +} diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java new file mode 100644 index 00000000..5700414e --- /dev/null +++ b/core/src/main/java/fj/F3Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F3Functions { +} diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java new file mode 100644 index 00000000..e29eb49c --- /dev/null +++ b/core/src/main/java/fj/F4Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F4Functions { +} diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java new file mode 100644 index 00000000..13600c6f --- /dev/null +++ b/core/src/main/java/fj/F5Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F5Functions { +} diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java new file mode 100644 index 00000000..70d4ed97 --- /dev/null +++ b/core/src/main/java/fj/F6Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F6Functions { +} diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java new file mode 100644 index 00000000..17f3643a --- /dev/null +++ b/core/src/main/java/fj/F7Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F7Functions { +} diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java new file mode 100644 index 00000000..f4d9b07d --- /dev/null +++ b/core/src/main/java/fj/F8Functions.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 6/04/2014. + */ +public class F8Functions { +} diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 46e857fa..e2d6de0d 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -5,6 +5,7 @@ import fj.F2; import fj.P1; import fj.data.Either; +import fj.F2Functions; import static fj.Function.curry; import static fj.data.Either.left; @@ -336,7 +337,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(P1.bind(x, y, new F2, Trampoline, Trampoline>() { + return suspend(P1.bind(x, y, F2Functions.curry(new F2, Trampoline, Trampoline>() { public Trampoline f(final Trampoline ta, final Trampoline tb) { return suspend(new P1>() { public Trampoline _1() { @@ -344,12 +345,12 @@ public Trampoline _1() { } }); } - }.curry())); + }))); } for (final B y : eb.right()) { return suspend(x.map(new F, Trampoline>() { public Trampoline f(final Trampoline ta) { - return ta.map(f.flip().f(y)); + return ta.map(F2Functions.f(F2Functions.flip(f), y)); } })); } @@ -363,7 +364,7 @@ public Trampoline _1() { }); } for (final P1> y : eb.left()) { - return suspend(y.map(liftM2(f.curry()).f(pure(x)))); + return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); } } throw Bottom.error("Match error: Trampoline is neither done nor suspended."); diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index c7c2072b..e3b09b8c 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -3,6 +3,7 @@ import fj.Effect; import fj.F; import fj.F2; +import fj.F2Functions; import fj.Function; import fj.Monoid; import fj.P; @@ -103,7 +104,7 @@ public F> f(final F abf) { * that can be claimed in the future. */ public F2> promise(final F2 f) { - return P2.untuple(f.tuple().promiseK(strategy)); + return P2.untuple(F2Functions.tuple(f).promiseK(strategy)); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 798ac190..42ea0e76 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1,6 +1,7 @@ package fj.data; import static fj.Bottom.error; +import fj.F2Functions; import fj.Effect; import fj.Equal; import fj.F; @@ -637,7 +638,7 @@ public final B foldRight(final F2 f, final B b) { public final Trampoline foldRightC(final F2 f, final B b) { return Trampoline.suspend(new P1>() { public Trampoline _1() { - return isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(f.f(head())); + return isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head())); } }); } diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 13e49dd7..8c3cd8b1 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -2,6 +2,7 @@ import fj.F; import fj.F2; +import fj.F2Functions; import fj.P; import fj.P1; import fj.P2; @@ -144,7 +145,7 @@ public P1>> f(final Tree a) { public Stream flatten() { final F2, P1>, Stream> squish = new F2, P1>, Stream>() { public Stream f(final Tree t, final P1> xs) { - return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(curry()).f(xs._1()))); + return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); } }; return squish.f(this, P.p(Stream.nil())); @@ -331,7 +332,7 @@ public String f(final Tree tree) { * @return A new tree of the results of applying the given function over this tree and the given tree, position-wise. */ public Tree zipWith(final Tree bs, final F2 f) { - return f.zipTreeM().f(this, bs); + return F2Functions.zipTreeM(f).f(this, bs); } /** diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 8d06c296..ed4ceacb 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -1,15 +1,6 @@ package fj.data; -import fj.Equal; -import fj.F; -import fj.F2; -import fj.F4; -import fj.P; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.P4; -import fj.Show; +import fj.*; import fj.function.Booleans; import java.util.Iterator; @@ -730,7 +721,7 @@ public Option> f(final F, Boolean> f, final TreeZipper * @return The result of applying the given function over this TreeZipper and the given TreeZipper, location-wise. */ public TreeZipper zipWith(final TreeZipper bs, final F2 f) { - return f.zipTreeZipperM().f(this, bs); + return F2Functions.zipTreeZipperM(f).f(this, bs); } /** diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index c65acddd..c94a8129 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -3,6 +3,7 @@ import fj.Equal; import fj.F; import fj.F2; +import fj.F2Functions; import fj.F3; import fj.Function; import fj.Ord; @@ -24,6 +25,7 @@ import static fj.data.Option.some; import static fj.data.Stream.nil; import static fj.data.Stream.repeat; +import static fj.F2Functions.*; /** * Provides a pointed stream, which is a non-empty zipper-like stream structure that tracks an index (focus) @@ -592,7 +594,7 @@ public Stream rights() { * @return The result of applying the given function over this Zipper and the given Zipper, location-wise. */ public Zipper zipWith(final Zipper bs, final F2 f) { - return f.zipZipperM().f(this, bs); + return F2Functions.zipZipperM(f).f(this, bs); } diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index 479a8088..2704dffb 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -1,6 +1,7 @@ package fj.demo.euler; import fj.F2; +import fj.F2Functions; import fj.data.Stream; import static fj.data.Stream.cons; import static fj.function.Integers.even; @@ -21,14 +22,15 @@ public static void main(final String[] args) { static void java7() { final Stream fibs = new F2>() { public Stream f(final Integer a, final Integer b) { - return cons(a, curry().f(b).lazy().f(a + b)); + return cons(a, F2Functions.curry(this).f(b).lazy().f(a + b)); } }.f(1, 2); out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); } static F2> fibsJava8 = (a, b) -> { - return cons(a, Problem2.fibsJava8.curry().f(b).lazy().f(a + b)); + + return cons(a, F2Functions.curry(Problem2.fibsJava8).f(b).lazy().f(a + b)); }; static void java8() { From a3a0ae83adb0ef48773669c578aee5d1cc71bf54 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 6 Apr 2014 17:29:02 +1000 Subject: [PATCH 034/811] Converted methods on F to F1Functions --- core/src/main/java/fj/Equal.java | 2 +- core/src/main/java/fj/F.java | 802 ----------------- core/src/main/java/fj/F1Functions.java | 820 ++++++++++++++++++ core/src/main/java/fj/Ord.java | 2 +- core/src/main/java/fj/P2.java | 4 +- core/src/main/java/fj/P3.java | 6 +- core/src/main/java/fj/P4.java | 8 +- core/src/main/java/fj/P5.java | 10 +- core/src/main/java/fj/P6.java | 12 +- core/src/main/java/fj/P7.java | 14 +- core/src/main/java/fj/P8.java | 16 +- core/src/main/java/fj/control/Trampoline.java | 3 +- .../java/fj/control/parallel/ParModule.java | 18 +- core/src/main/java/fj/data/IO.java | 5 +- core/src/main/java/fj/data/Iteratee.java | 3 +- core/src/main/java/fj/data/NonEmptyList.java | 5 +- core/src/main/java/fj/data/TreeMap.java | 9 +- .../main/java/fj/demo/Comonad_example.java | 3 +- demo/src/main/java/fj/demo/Primes2.java | 3 +- .../java/fj/demo/concurrent/MapReduce.java | 57 +- .../src/main/java/fj/demo/euler/Problem2.java | 5 +- 21 files changed, 912 insertions(+), 895 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index ff0362e2..edd9dfb9 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -80,7 +80,7 @@ public Boolean f(final A a1) { * @return A new equal. */ public Equal comap(final F f) { - return equal(f.andThen().o(this.f).o(f)); + return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } /** diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java index 9500e183..1b524fdc 100644 --- a/core/src/main/java/fj/F.java +++ b/core/src/main/java/fj/F.java @@ -47,806 +47,4 @@ public interface F { */ public abstract B f(A a); - - /** - * Function composition - * - * @param g A function to compose with this one. - * @return The composed function such that this function is applied last. - */ - default public F o(final F g) { - return new F() { - public B f(final C c) { - return F.this.f(g.f(c)); - } - }; - } - - /** - * First-class function composition - * - * @return A function that composes this function with another. - */ - default public F, F> o() { - return new F, F>() { - public F f(final F g) { - return F.this.o(g); - } - }; - } - - /** - * Function composition flipped. - * - * @param g A function with which to compose this one. - * @return The composed function such that this function is applied first. - */ - @SuppressWarnings({"unchecked"}) - default public F andThen(final F g) { - return g.o(this); - } - - /** - * First-class composition flipped. - * - * @return A function that invokes this function and then a given function on the result. - */ - default public F, F> andThen() { - return new F, F>() { - public F f(final F g) { - return F.this.andThen(g); - } - }; - } - - /** - * Binds a given function across this function (Reader Monad). - * - * @param g A function that takes the return value of this function as an argument, yielding a new function. - * @return A function that invokes this function on its argument and then the given function on the result. - */ - default public F bind(final F> g) { - return new F() { - @SuppressWarnings({"unchecked"}) - public C f(final A a) { - return g.f(F.this.f(a)).f(a); - } - }; - } - - /** - * First-class function binding. - * - * @return A function that binds another function across this function. - */ - default public F>, F> bind() { - return new F>, F>() { - public F f(final F> g) { - return F.this.bind(g); - } - }; - } - - /** - * Function application in an environment (Applicative Functor). - * - * @param g A function with the same argument type as this function, yielding a function that takes the return - * value of this function. - * @return A new function that invokes the given function on its argument, yielding a new function that is then - * applied to the result of applying this function to the argument. - */ - default public F apply(final F> g) { - return new F() { - @SuppressWarnings({"unchecked"}) - public C f(final A a) { - return g.f(a).f(F.this.f(a)); - } - }; - } - - /** - * First-class function application in an environment. - * - * @return A function that applies a given function within the environment of this function. - */ - default public F>, F> apply() { - return new F>, F>() { - public F f(final F> g) { - return F.this.apply(g); - } - }; - } - - /** - * Applies this function over the arguments of another function. - * - * @param g The function over whose arguments to apply this function. - * @return A new function that invokes this function on its arguments before invoking the given function. - */ - default public F> on(final F> g) { - return new F>() { - public F f(final A a1) { - return new F() { - @SuppressWarnings({"unchecked"}) - public C f(final A a2) { - return g.f(F.this.f(a1)).f(F.this.f(a2)); - } - }; - } - }; - } - - - /** - * Applies this function over the arguments of another function. - * - * @return A function that applies this function over the arguments of another function. - */ - default public F>, F>> on() { - return new F>, F>>() { - public F> f(final F> g) { - return F.this.on(g); - } - }; - } - - /** - * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1. - * - * @return This function promoted to return its result in a product-1. - */ - default public F> lazy() { - return new F>() { - public P1 f(final A a) { - return new P1() { - public B _1() { - return F.this.f(a); - } - }; - } - }; - } - - /** - * Promotes this function to map over a product-1. - * - * @return This function promoted to map over a product-1. - */ - default public F, P1> mapP1() { - return new F, P1>() { - public P1 f(final P1 p) { - return p.map(F.this); - } - }; - } - - /** - * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option. - * - * @return This function promoted to return its result in an Option. - */ - default public F> optionK() { - return new F>() { - public Option f(final A a) { - return some(F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over an optional value. - * - * @return This function promoted to map over an optional value. - */ - default public F, Option> mapOption() { - return new F, Option>() { - public Option f(final Option o) { - return o.map(F.this); - } - }; - } - - /** - * Promotes this function so that it returns its result in a List. Kleisli arrow for List. - * - * @return This function promoted to return its result in a List. - */ - default public F> listK() { - return new F>() { - public List f(final A a) { - return List.single(F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over a List. - * - * @return This function promoted to map over a List. - */ - default public F, List> mapList() { - return new F, List>() { - public List f(final List x) { - return x.map(F.this); - } - }; - } - - /** - * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream. - * - * @return This function promoted to return its result in a Stream. - */ - default public F> streamK() { - return new F>() { - public Stream f(final A a) { - return Stream.single(F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over a Stream. - * - * @return This function promoted to map over a Stream. - */ - default public F, Stream> mapStream() { - return new F, Stream>() { - public Stream f(final Stream x) { - return x.map(F.this); - } - }; - } - - /** - * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array. - * - * @return This function promoted to return its result in a Array. - */ - default public F> arrayK() { - return new F>() { - public Array f(final A a) { - return Array.single(F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over a Array. - * - * @return This function promoted to map over a Array. - */ - default public F, Array> mapArray() { - return new F, Array>() { - public Array f(final Array x) { - return x.map(F.this); - } - }; - } - - /** - * Returns a function that comaps over a given actor. - * - * @return A function that comaps over a given actor. - */ - default public F, Actor> comapActor() { - return new F, Actor>() { - public Actor f(final Actor a) { - return a.comap(F.this); - } - }; - } - - /** - * Promotes this function to a concurrent function that returns a Promise of a value. - * - * @param s A parallel strategy for concurrent execution. - * @return A concurrent function that returns a Promise of a value. - */ - default public F> promiseK(final Strategy s) { - return Promise.promise(s, this); - } - - /** - * Promotes this function to map over a Promise. - * - * @return This function promoted to map over Promises. - */ - default public F, Promise> mapPromise() { - return new F, Promise>() { - public Promise f(final Promise p) { - return p.fmap(F.this); - } - }; - } - - /** - * Promotes this function so that it returns its result on the left side of an Either. - * Kleisli arrow for the Either left projection. - * - * @return This function promoted to return its result on the left side of an Either. - */ - @SuppressWarnings({"unchecked"}) - default public F> eitherLeftK() { - return Either.left_().o(F.this); - } - - /** - * Promotes this function so that it returns its result on the right side of an Either. - * Kleisli arrow for the Either right projection. - * - * @return This function promoted to return its result on the right side of an Either. - */ - @SuppressWarnings({"unchecked"}) - default public F> eitherRightK() { - return Either.right_().o(F.this); - } - - /** - * Promotes this function to map over the left side of an Either. - * - * @return This function promoted to map over the left side of an Either. - */ - @SuppressWarnings({"unchecked"}) - default public F, Either> mapLeft() { - return Either.leftMap_().f(F.this); - } - - /** - * Promotes this function to map over the right side of an Either. - * - * @return This function promoted to map over the right side of an Either. - */ - @SuppressWarnings({"unchecked"}) - default public F, Either> mapRight() { - return Either.rightMap_().f(F.this); - } - - /** - * Returns a function that returns the left side of a given Either, or this function applied to the right side. - * - * @return a function that returns the left side of a given Either, or this function applied to the right side. - */ - default public F, B> onLeft() { - return new F, B>() { - public B f(final Either either) { - return either.left().on(F.this); - } - }; - } - - /** - * Returns a function that returns the right side of a given Either, or this function applied to the left side. - * - * @return a function that returns the right side of a given Either, or this function applied to the left side. - */ - default public F, B> onRight() { - return new F, B>() { - public B f(final Either either) { - return either.right().on(F.this); - } - }; - } - - /** - * Promotes this function to return its value in an Iterable. - * - * @return This function promoted to return its value in an Iterable. - */ - @SuppressWarnings({"unchecked"}) - default public F> iterableK() { - return IterableW.arrow().f(F.this); - } - - /** - * Promotes this function to map over Iterables. - * - * @return This function promoted to map over Iterables. - */ - @SuppressWarnings({"unchecked"}) - default public F, IterableW> mapIterable() { - return IterableW.map().f(F.this).o(IterableW.>wrap()); - } - - /** - * Promotes this function to return its value in a NonEmptyList. - * - * @return This function promoted to return its value in a NonEmptyList. - */ - @SuppressWarnings({"unchecked"}) - default public F> nelK() { - return NonEmptyList.nel().o(F.this); - } - - /** - * Promotes this function to map over a NonEmptyList. - * - * @return This function promoted to map over a NonEmptyList. - */ - default public F, NonEmptyList> mapNel() { - return new F, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList list) { - return list.map(F.this); - } - }; - } - - /** - * Promotes this function to return its value in a Set. - * - * @param o An order for the set. - * @return This function promoted to return its value in a Set. - */ - default public F> setK(final Ord o) { - return new F>() { - public Set f(final A a) { - return Set.single(o, F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over a Set. - * - * @param o An order for the resulting set. - * @return This function promoted to map over a Set. - */ - default public F, Set> mapSet(final Ord o) { - return new F, Set>() { - public Set f(final Set set) { - return set.map(o, F.this); - } - }; - } - - /** - * Promotes this function to return its value in a Tree. - * - * @return This function promoted to return its value in a Tree. - */ - default public F> treeK() { - return new F>() { - public Tree f(final A a) { - return Tree.leaf(F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over a Tree. - * - * @return This function promoted to map over a Tree. - */ - @SuppressWarnings({"unchecked"}) - default public F, Tree> mapTree() { - return Tree.fmap_().f(F.this); - } - - /** - * Returns a function that maps this function over a tree and folds it with the given monoid. - * - * @param m The monoid with which to fold the mapped tree. - * @return a function that maps this function over a tree and folds it with the given monoid. - */ - default public F, B> foldMapTree(final Monoid m) { - return Tree.foldMap_(F.this, m); - } - - /** - * Promotes this function to return its value in a TreeZipper. - * - * @return This function promoted to return its value in a TreeZipper. - */ - default public F> treeZipperK() { - return treeK().andThen(TreeZipper.fromTree()); - } - - /** - * Promotes this function to map over a TreeZipper. - * - * @return This function promoted to map over a TreeZipper. - */ - default public F, TreeZipper> mapTreeZipper() { - return new F, TreeZipper>() { - public TreeZipper f(final TreeZipper zipper) { - return zipper.map(F.this); - } - }; - } - - /** - * Promotes this function so that it returns its result on the failure side of a Validation. - * Kleisli arrow for the Validation failure projection. - * - * @return This function promoted to return its result on the failure side of a Validation. - */ - default public F> failK() { - return new F>() { - public Validation f(final A a) { - return Validation.fail(F.this.f(a)); - } - }; - } - - /** - * Promotes this function so that it returns its result on the success side of an Validation. - * Kleisli arrow for the Validation success projection. - * - * @return This function promoted to return its result on the success side of an Validation. - */ - default public F> successK() { - return new F>() { - public Validation f(final A a) { - return Validation.success(F.this.f(a)); - } - }; - } - - /** - * Promotes this function to map over the failure side of a Validation. - * - * @return This function promoted to map over the failure side of a Validation. - */ - default public F, Validation> mapFail() { - return new F, Validation>() { - public Validation f(final Validation validation) { - return validation.f().map(F.this); - } - }; - } - - /** - * Promotes this function to map over the success side of a Validation. - * - * @return This function promoted to map over the success side of a Validation. - */ - default public F, Validation> mapSuccess() { - return new F, Validation>() { - public Validation f(final Validation validation) { - return validation.map(F.this); - } - }; - } - - /** - * Returns a function that returns the failure side of a given Validation, - * or this function applied to the success side. - * - * @return a function that returns the failure side of a given Validation, - * or this function applied to the success side. - */ - default public F, B> onFail() { - return new F, B>() { - public B f(final Validation v) { - return v.f().on(F.this); - } - }; - } - - /** - * Returns a function that returns the success side of a given Validation, - * or this function applied to the failure side. - * - * @return a function that returns the success side of a given Validation, - * or this function applied to the failure side. - */ - default public F, B> onSuccess() { - return new F, B>() { - public B f(final Validation v) { - return v.on(F.this); - } - }; - } - - /** - * Promotes this function to return its value in a Zipper. - * - * @return This function promoted to return its value in a Zipper. - */ - default public F> zipperK() { - return streamK().andThen(new F, Zipper>() { - public Zipper f(final Stream stream) { - return fromStream(stream).some(); - } - }); - } - - /** - * Promotes this function to map over a Zipper. - * - * @return This function promoted to map over a Zipper. - */ - default public F, Zipper> mapZipper() { - return new F, Zipper>() { - public Zipper f(final Zipper zipper) { - return zipper.map(F.this); - } - }; - } - - /** - * Promotes this function to map over an Equal as a contravariant functor. - * - * @return This function promoted to map over an Equal as a contravariant functor. - */ - default public F, Equal> comapEqual() { - return new F, Equal>() { - public Equal f(final Equal equal) { - return equal.comap(F.this); - } - }; - } - - /** - * Promotes this function to map over a Hash as a contravariant functor. - * - * @return This function promoted to map over a Hash as a contravariant functor. - */ - default public F, Hash> comapHash() { - return new F, Hash>() { - public Hash f(final Hash hash) { - return hash.comap(F.this); - } - }; - } - - /** - * Promotes this function to map over a Show as a contravariant functor. - * - * @return This function promoted to map over a Show as a contravariant functor. - */ - default public F, Show> comapShow() { - return new F, Show>() { - public Show f(final Show s) { - return s.comap(F.this); - } - }; - } - - /** - * Promotes this function to map over the first element of a pair. - * - * @return This function promoted to map over the first element of a pair. - */ - default public F, P2> mapFst() { - return P2.map1_(F.this); - } - - /** - * Promotes this function to map over the second element of a pair. - * - * @return This function promoted to map over the second element of a pair. - */ - default public F, P2> mapSnd() { - return P2.map2_(F.this); - } - - /** - * Promotes this function to map over both elements of a pair. - * - * @return This function promoted to map over both elements of a pair. - */ - default public F, P2> mapBoth() { - return new F, P2>() { - public P2 f(final P2 aap2) { - return P2.map(F.this, aap2); - } - }; - } - - /** - * Maps this function over a SynchronousQueue. - * - * @param as A SynchronousQueue to map this function over. - * @return A new SynchronousQueue with this function applied to each element. - */ - default public SynchronousQueue mapJ(final SynchronousQueue as) { - final SynchronousQueue bs = new SynchronousQueue(); - bs.addAll(iterableStream(as).map(this).toCollection()); - return bs; - } - - - /** - * Maps this function over a PriorityBlockingQueue. - * - * @param as A PriorityBlockingQueue to map this function over. - * @return A new PriorityBlockingQueue with this function applied to each element. - */ - default public PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { - return new PriorityBlockingQueue(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over a LinkedBlockingQueue. - * - * @param as A LinkedBlockingQueue to map this function over. - * @return A new LinkedBlockingQueue with this function applied to each element. - */ - default public LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { - return new LinkedBlockingQueue(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over a CopyOnWriteArraySet. - * - * @param as A CopyOnWriteArraySet to map this function over. - * @return A new CopyOnWriteArraySet with this function applied to each element. - */ - default public CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { - return new CopyOnWriteArraySet(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over a CopyOnWriteArrayList. - * - * @param as A CopyOnWriteArrayList to map this function over. - * @return A new CopyOnWriteArrayList with this function applied to each element. - */ - default public CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { - return new CopyOnWriteArrayList(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over a ConcurrentLinkedQueue. - * - * @param as A ConcurrentLinkedQueue to map this function over. - * @return A new ConcurrentLinkedQueue with this function applied to each element. - */ - default public ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { - return new ConcurrentLinkedQueue(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over an ArrayBlockingQueue. - * - * @param as An ArrayBlockingQueue to map this function over. - * @return A new ArrayBlockingQueue with this function applied to each element. - */ - default public ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { - final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); - bs.addAll(iterableStream(as).map(this).toCollection()); - return bs; - } - - - /** - * Maps this function over a TreeSet. - * - * @param as A TreeSet to map this function over. - * @return A new TreeSet with this function applied to each element. - */ - default public TreeSet mapJ(final TreeSet as) { - return new TreeSet(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over a PriorityQueue. - * - * @param as A PriorityQueue to map this function over. - * @return A new PriorityQueue with this function applied to each element. - */ - default public PriorityQueue mapJ(final PriorityQueue as) { - return new PriorityQueue(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over a LinkedList. - * - * @param as A LinkedList to map this function over. - * @return A new LinkedList with this function applied to each element. - */ - default public LinkedList mapJ(final LinkedList as) { - return new LinkedList(iterableStream(as).map(this).toCollection()); - } - - /** - * Maps this function over an ArrayList. - * - * @param as An ArrayList to map this function over. - * @return A new ArrayList with this function applied to each element. - */ - default public ArrayList mapJ(final ArrayList as) { - return new ArrayList(iterableStream(as).map(this).toCollection()); - } } diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 960162ee..c8626ddd 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -1,7 +1,827 @@ package fj; +import fj.control.parallel.Actor; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.*; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.PriorityQueue; +import java.util.TreeSet; +import java.util.concurrent.*; + +import static fj.data.Option.some; +import static fj.data.Stream.iterableStream; +import static fj.data.Zipper.fromStream; + /** * Created by MarkPerry on 6/04/2014. */ public class F1Functions { + + + /** + * Function composition + * + * @param g A function to compose with this one. + * @return The composed function such that this function is applied last. + */ + static public F o(final F f, final F g) { + return new F() { + public B f(final C c) { + return f.f(g.f(c)); + } + }; + } + + /** + * First-class function composition + * + * @return A function that composes this function with another. + */ + static public F, F> o(final F f) { + return new F, F>() { + public F f(final F g) { + return o(f, g); + } + }; + } + + /** + * Function composition flipped. + * + * @param g A function with which to compose this one. + * @return The composed function such that this function is applied first. + */ + @SuppressWarnings({"unchecked"}) + static public F andThen(final F f, final F g) { + return o(g, f); + } + + /** + * First-class composition flipped. + * + * @return A function that invokes this function and then a given function on the result. + */ + static public F, F> andThen(final F f) { + return new F, F>() { + public F f(final F g) { + return andThen(f, g); + } + }; + } + + /** + * Binds a given function across this function (Reader Monad). + * + * @param g A function that takes the return value of this function as an argument, yielding a new function. + * @return A function that invokes this function on its argument and then the given function on the result. + */ + static public F bind(final F f, final F> g) { + return new F() { + @SuppressWarnings({"unchecked"}) + public C f(final A a) { + return g.f(f.f(a)).f(a); + } + }; + } + + /** + * First-class function binding. + * + * @return A function that binds another function across this function. + */ + static public F>, F> bind(final F f) { + return new F>, F>() { + public F f(final F> g) { + return bind(f, g); + } + }; + } + + /** + * Function application in an environment (Applicative Functor). + * + * @param g A function with the same argument type as this function, yielding a function that takes the return + * value of this function. + * @return A new function that invokes the given function on its argument, yielding a new function that is then + * applied to the result of applying this function to the argument. + */ + static public F apply(final F f, final F> g) { + return new F() { + @SuppressWarnings({"unchecked"}) + public C f(final A a) { + return g.f(a).f(f.f(a)); + } + }; + } + + /** + * First-class function application in an environment. + * + * @return A function that applies a given function within the environment of this function. + */ + static public F>, F> apply(final F f) { + return new F>, F>() { + public F f(final F> g) { + return apply(f, g); + } + }; + } + + /** + * Applies this function over the arguments of another function. + * + * @param g The function over whose arguments to apply this function. + * @return A new function that invokes this function on its arguments before invoking the given function. + */ + static public F> on(final F f, final F> g) { + return new F>() { + public F f(final A a1) { + return new F() { + @SuppressWarnings({"unchecked"}) + public C f(final A a2) { + return g.f(f.f(a1)).f(f.f(a2)); + } + }; + } + }; + } + + + /** + * Applies this function over the arguments of another function. + * + * @return A function that applies this function over the arguments of another function. + */ + static public F>, F>> on(final F f) { + return new F>, F>>() { + public F> f(final F> g) { + return on(f, g); + } + }; + } + + /** + * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1. + * + * @return This function promoted to return its result in a product-1. + */ + static public F> lazy(final F f) { + return new F>() { + public P1 f(final A a) { + return new P1() { + public B _1() { + return f.f(a); + } + }; + } + }; + } + + /** + * Promotes this function to map over a product-1. + * + * @return This function promoted to map over a product-1. + */ + static public F, P1> mapP1(final F f) { + return new F, P1>() { + public P1 f(final P1 p) { + return p.map(f); + } + }; + } + + /** + * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option. + * + * @return This function promoted to return its result in an Option. + */ + static public F> optionK(final F f) { + return new F>() { + public Option f(final A a) { + return some(f.f(a)); + } + }; + } + + /** + * Promotes this function to map over an optional value. + * + * @return This function promoted to map over an optional value. + */ + static public F, Option> mapOption(final F f) { + return new F, Option>() { + public Option f(final Option o) { + return o.map(f); + } + }; + } + + /** + * Promotes this function so that it returns its result in a List. Kleisli arrow for List. + * + * @return This function promoted to return its result in a List. + */ + static public F> listK(final F f) { + return new F>() { + public List f(final A a) { + return List.single(f.f(a)); + } + }; + } + + /** + * Promotes this function to map over a List. + * + * @return This function promoted to map over a List. + */ + static public F, List> mapList(final F f) { + return new F, List>() { + public List f(final List x) { + return x.map(f); + } + }; + } + + /** + * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream. + * + * @return This function promoted to return its result in a Stream. + */ + static public F> streamK(final F f) { + return new F>() { + public Stream f(final A a) { + return Stream.single(f.f(a)); + } + }; + } + + /** + * Promotes this function to map over a Stream. + * + * @return This function promoted to map over a Stream. + */ + static public F, Stream> mapStream(final F f) { + return new F, Stream>() { + public Stream f(final Stream x) { + return x.map(f); + } + }; + } + + /** + * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array. + * + * @return This function promoted to return its result in a Array. + */ + static public F> arrayK(final F f) { + return new F>() { + public Array f(final A a) { + return Array.single(f.f(a)); + } + }; + } + + /** + * Promotes this function to map over a Array. + * + * @return This function promoted to map over a Array. + */ + static public F, Array> mapArray(final F f) { + return new F, Array>() { + public Array f(final Array x) { + return x.map(f); + } + }; + } + + /** + * Returns a function that comaps over a given actor. + * + * @return A function that comaps over a given actor. + */ + static public F, Actor> comapActor(final F f) { + return new F, Actor>() { + public Actor f(final Actor a) { + return a.comap(f); + } + }; + } + + /** + * Promotes this function to a concurrent function that returns a Promise of a value. + * + * @param s A parallel strategy for concurrent execution. + * @return A concurrent function that returns a Promise of a value. + */ + static public F> promiseK(final F f, final Strategy s) { + return Promise.promise(s, f); + } + + /** + * Promotes this function to map over a Promise. + * + * @return This function promoted to map over Promises. + */ + static public F, Promise> mapPromise(final F f) { + return new F, Promise>() { + public Promise f(final Promise p) { + return p.fmap(f); + } + }; + } + + /** + * Promotes this function so that it returns its result on the left side of an Either. + * Kleisli arrow for the Either left projection. + * + * @return This function promoted to return its result on the left side of an Either. + */ + @SuppressWarnings({"unchecked"}) + static public F> eitherLeftK(final F f) { + return o(Either.left_(), f); + } + + /** + * Promotes this function so that it returns its result on the right side of an Either. + * Kleisli arrow for the Either right projection. + * + * @return This function promoted to return its result on the right side of an Either. + */ + @SuppressWarnings({"unchecked"}) + static public F> eitherRightK(final F f) { + return o(Either.right_(), f); + } + + /** + * Promotes this function to map over the left side of an Either. + * + * @return This function promoted to map over the left side of an Either. + */ + @SuppressWarnings({"unchecked"}) + static public F, Either> mapLeft(final F f) { + return Either.leftMap_().f(f); + } + + /** + * Promotes this function to map over the right side of an Either. + * + * @return This function promoted to map over the right side of an Either. + */ + @SuppressWarnings({"unchecked"}) + static public F, Either> mapRight(final F f) { + return Either.rightMap_().f(f); + } + + /** + * Returns a function that returns the left side of a given Either, or this function applied to the right side. + * + * @return a function that returns the left side of a given Either, or this function applied to the right side. + */ + static public F, B> onLeft(final F f) { + return new F, B>() { + public B f(final Either either) { + return either.left().on(f); + } + }; + } + + /** + * Returns a function that returns the right side of a given Either, or this function applied to the left side. + * + * @return a function that returns the right side of a given Either, or this function applied to the left side. + */ + static public F, B> onRight(final F f) { + return new F, B>() { + public B f(final Either either) { + return either.right().on(f); + } + }; + } + + /** + * Promotes this function to return its value in an Iterable. + * + * @return This function promoted to return its value in an Iterable. + */ + @SuppressWarnings({"unchecked"}) + static public F> iterableK(final F f) { + return IterableW.arrow().f(f); + } + + /** + * Promotes this function to map over Iterables. + * + * @return This function promoted to map over Iterables. + */ + @SuppressWarnings({"unchecked"}) + static public F, IterableW> mapIterable(final F f) { + return F1Functions.o(IterableW.map().f(f), IterableW.>wrap()); + } + + /** + * Promotes this function to return its value in a NonEmptyList. + * + * @return This function promoted to return its value in a NonEmptyList. + */ + @SuppressWarnings({"unchecked"}) + static public F> nelK(final F f) { + return o(NonEmptyList.nel(), f); + } + + /** + * Promotes this function to map over a NonEmptyList. + * + * @return This function promoted to map over a NonEmptyList. + */ + static public F, NonEmptyList> mapNel(final F f) { + return new F, NonEmptyList>() { + public NonEmptyList f(final NonEmptyList list) { + return list.map(f); + } + }; + } + + /** + * Promotes this function to return its value in a Set. + * + * @param o An order for the set. + * @return This function promoted to return its value in a Set. + */ + static public F> setK(final F f, final Ord o + ) { + return new F>() { + public Set f(final A a) { + return Set.single(o, f.f(a)); + } + }; + } + + /** + * Promotes this function to map over a Set. + * + * @param o An order for the resulting set. + * @return This function promoted to map over a Set. + */ + static public F, Set> mapSet(final F f, final Ord o) { + return new F, Set>() { + public Set f(final Set set) { + return set.map(o, f); + } + }; + } + + /** + * Promotes this function to return its value in a Tree. + * + * @return This function promoted to return its value in a Tree. + */ + static public F> treeK(final F f) { + return new F>() { + public Tree f(final A a) { + return Tree.leaf(f.f(a)); + } + }; + } + + /** + * Promotes this function to map over a Tree. + * + * @return This function promoted to map over a Tree. + */ + @SuppressWarnings({"unchecked"}) + static public F, Tree> mapTree(final F f) { + return Tree.fmap_().f(f); + } + + /** + * Returns a function that maps this function over a tree and folds it with the given monoid. + * + * @param m The monoid with which to fold the mapped tree. + * @return a function that maps this function over a tree and folds it with the given monoid. + */ + static public F, B> foldMapTree(final F f, final Monoid m) { + return Tree.foldMap_(f, m); + } + + /** + * Promotes this function to return its value in a TreeZipper. + * + * @return This function promoted to return its value in a TreeZipper. + */ + static public F> treeZipperK(final F f) { + return andThen(treeK(f), TreeZipper.fromTree()); + } + + /** + * Promotes this function to map over a TreeZipper. + * + * @return This function promoted to map over a TreeZipper. + */ + static public F, TreeZipper> mapTreeZipper(final F f) { + return new F, TreeZipper>() { + public TreeZipper f(final TreeZipper zipper) { + return zipper.map(f); + } + }; + } + + /** + * Promotes this function so that it returns its result on the failure side of a Validation. + * Kleisli arrow for the Validation failure projection. + * + * @return This function promoted to return its result on the failure side of a Validation. + */ + static public F> failK(final F f) { + return new F>() { + public Validation f(final A a) { + return Validation.fail(f.f(a)); + } + }; + } + + /** + * Promotes this function so that it returns its result on the success side of an Validation. + * Kleisli arrow for the Validation success projection. + * + * @return This function promoted to return its result on the success side of an Validation. + */ + static public F> successK(final F f) { + return new F>() { + public Validation f(final A a) { + return Validation.success(f.f(a)); + } + }; + } + + /** + * Promotes this function to map over the failure side of a Validation. + * + * @return This function promoted to map over the failure side of a Validation. + */ + static public F, Validation> mapFail(final F f) { + return new F, Validation>() { + public Validation f(final Validation validation) { + return validation.f().map(f); + } + }; + } + + /** + * Promotes this function to map over the success side of a Validation. + * + * @return This function promoted to map over the success side of a Validation. + */ + static public F, Validation> mapSuccess(final F f) { + return new F, Validation>() { + public Validation f(final Validation validation) { + return validation.map(f); + } + }; + } + + /** + * Returns a function that returns the failure side of a given Validation, + * or this function applied to the success side. + * + * @return a function that returns the failure side of a given Validation, + * or this function applied to the success side. + */ + static public F, B> onFail(final F f) { + return new F, B>() { + public B f(final Validation v) { + return v.f().on(f); + } + }; + } + + /** + * Returns a function that returns the success side of a given Validation, + * or this function applied to the failure side. + * + * @return a function that returns the success side of a given Validation, + * or this function applied to the failure side. + */ + static public F, B> onSuccess(final F f) { + return new F, B>() { + public B f(final Validation v) { + return v.on(f); + } + }; + } + + /** + * Promotes this function to return its value in a Zipper. + * + * @return This function promoted to return its value in a Zipper. + */ + static public F> zipperK(final F f) { + return andThen(streamK(f), new F, Zipper>() { + public Zipper f(final Stream stream) { + return fromStream(stream).some(); + } + }); + } + + /** + * Promotes this function to map over a Zipper. + * + * @return This function promoted to map over a Zipper. + */ + static public F, Zipper> mapZipper(final F f) { + return new F, Zipper>() { + public Zipper f(final Zipper zipper) { + return zipper.map(f); + } + }; + } + + /** + * Promotes this function to map over an Equal as a contravariant functor. + * + * @return This function promoted to map over an Equal as a contravariant functor. + */ + static public F, Equal> comapEqual(final F f) { + return new F, Equal>() { + public Equal f(final Equal equal) { + return equal.comap(f); + } + }; + } + + /** + * Promotes this function to map over a Hash as a contravariant functor. + * + * @return This function promoted to map over a Hash as a contravariant functor. + */ + static public F, Hash> comapHash(final F f) { + return new F, Hash>() { + public Hash f(final Hash hash) { + return hash.comap(f); + } + }; + } + + /** + * Promotes this function to map over a Show as a contravariant functor. + * + * @return This function promoted to map over a Show as a contravariant functor. + */ + static public F, Show> comapShow(final F f) { + return new F, Show>() { + public Show f(final Show s) { + return s.comap(f); + } + }; + } + + /** + * Promotes this function to map over the first element of a pair. + * + * @return This function promoted to map over the first element of a pair. + */ + static public F, P2> mapFst(final F f) { + return P2.map1_(f); + } + + /** + * Promotes this function to map over the second element of a pair. + * + * @return This function promoted to map over the second element of a pair. + */ + static public F, P2> mapSnd(final F f) { + return P2.map2_(f); + } + + /** + * Promotes this function to map over both elements of a pair. + * + * @return This function promoted to map over both elements of a pair. + */ + static public F, P2> mapBoth(final F f) { + return new F, P2>() { + public P2 f(final P2 aap2) { + return P2.map(f, aap2); + } + }; + } + + /** + * Maps this function over a SynchronousQueue. + * + * @param as A SynchronousQueue to map this function over. + * @return A new SynchronousQueue with this function applied to each element. + */ + static public SynchronousQueue mapJ(final F f, final SynchronousQueue as) { + final SynchronousQueue bs = new SynchronousQueue(); + bs.addAll(iterableStream(as).map(f).toCollection()); + return bs; + } + + + /** + * Maps this function over a PriorityBlockingQueue. + * + * @param as A PriorityBlockingQueue to map this function over. + * @return A new PriorityBlockingQueue with this function applied to each element. + */ + static public PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { + return new PriorityBlockingQueue(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over a LinkedBlockingQueue. + * + * @param as A LinkedBlockingQueue to map this function over. + * @return A new LinkedBlockingQueue with this function applied to each element. + */ + static public LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { + return new LinkedBlockingQueue(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over a CopyOnWriteArraySet. + * + * @param as A CopyOnWriteArraySet to map this function over. + * @return A new CopyOnWriteArraySet with this function applied to each element. + */ + static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { + return new CopyOnWriteArraySet(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over a CopyOnWriteArrayList. + * + * @param as A CopyOnWriteArrayList to map this function over. + * @return A new CopyOnWriteArrayList with this function applied to each element. + */ + static public CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { + return new CopyOnWriteArrayList(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over a ConcurrentLinkedQueue. + * + * @param as A ConcurrentLinkedQueue to map this function over. + * @return A new ConcurrentLinkedQueue with this function applied to each element. + */ + static public ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { + return new ConcurrentLinkedQueue(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over an ArrayBlockingQueue. + * + * @param as An ArrayBlockingQueue to map this function over. + * @return A new ArrayBlockingQueue with this function applied to each element. + */ + static public ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { + final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); + bs.addAll(iterableStream(as).map(f).toCollection()); + return bs; + } + + + /** + * Maps this function over a TreeSet. + * + * @param as A TreeSet to map this function over. + * @return A new TreeSet with this function applied to each element. + */ + static public TreeSet mapJ(final F f, final TreeSet as) { + return new TreeSet(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over a PriorityQueue. + * + * @param as A PriorityQueue to map this function over. + * @return A new PriorityQueue with this function applied to each element. + */ + static public PriorityQueue mapJ(final F f, final PriorityQueue as) { + return new PriorityQueue(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over a LinkedList. + * + * @param as A LinkedList to map this function over. + * @return A new LinkedList with this function applied to each element. + */ + static public LinkedList mapJ(final F f, final LinkedList as) { + return new LinkedList(iterableStream(as).map(f).toCollection()); + } + + /** + * Maps this function over an ArrayList. + * + * @param as An ArrayList to map this function over. + * @return A new ArrayList with this function applied to each element. + */ + static public ArrayList mapJ(final F f, final ArrayList as) { + return new ArrayList(iterableStream(as).map(f).toCollection()); + } + } diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 00e0a51d..248b1f12 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -78,7 +78,7 @@ public Boolean f(final A a1, final A a2) { * @return A new ord. */ public Ord comap(final F f) { - return ord(f.andThen().o(this.f).o(f)); + return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } /** diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index a87a9ef6..91131f57 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -168,7 +168,7 @@ public Stream _1() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P2.__1().lazy().f(this); + return F1Functions.lazy(P2.__1()).f(this); } /** @@ -177,7 +177,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P2.__2().lazy().f(this); + return F1Functions.lazy(P2.__2()).f(this); } /** diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 23b8a78d..d7b990f6 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -99,7 +99,7 @@ public X _3() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P3.__1().lazy().f(this); + return F1Functions.lazy(P3.__1()).f(this); } /** @@ -108,7 +108,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P3.__2().lazy().f(this); + return F1Functions.lazy(P3.__2()).f(this); } /** @@ -117,7 +117,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return P3.__3().lazy().f(this); + return F1Functions.lazy(P3.__3()).f(this); } /** diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 17ba0216..e4c58185 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -144,7 +144,7 @@ public X _4() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P4.__1().lazy().f(this); + return F1Functions.lazy(P4.__1()).f(this); } /** @@ -153,7 +153,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P4.__2().lazy().f(this); + return F1Functions.lazy(P4.__2()).f(this); } /** @@ -162,7 +162,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return P4.__3().lazy().f(this); + return F1Functions.lazy(P4.__3()).f(this); } /** @@ -171,7 +171,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return P4.__4().lazy().f(this); + return F1Functions.lazy(P4.__4()).f(this); } /** diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index d01b79f4..58285ff4 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -197,7 +197,7 @@ public X _5() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P5.__1().lazy().f(this); + return F1Functions.lazy(P5.__1()).f(this); } /** @@ -206,7 +206,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P5.__2().lazy().f(this); + return F1Functions.lazy(P5.__2()).f(this); } /** @@ -215,7 +215,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return P5.__3().lazy().f(this); + return F1Functions.lazy(P5.__3()).f(this); } /** @@ -224,7 +224,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return P5.__4().lazy().f(this); + return F1Functions.lazy(P5.__4()).f(this); } /** @@ -233,7 +233,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return P5.__5().lazy().f(this); + return F1Functions.lazy(P5.__5()).f(this); } /** diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 625f3039..f70ef742 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -259,7 +259,7 @@ public X _6() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P6.__1().lazy().f(this); + return F1Functions.lazy(P6.__1()).f(this); } /** @@ -268,7 +268,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P6.__2().lazy().f(this); + return F1Functions.lazy(P6.__2()).f(this); } /** @@ -277,7 +277,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return P6.__3().lazy().f(this); + return F1Functions.lazy(P6.__3()).f(this); } /** @@ -286,7 +286,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return P6.__4().lazy().f(this); + return F1Functions.lazy(P6.__4()).f(this); } /** @@ -295,7 +295,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return P6.__5().lazy().f(this); + return F1Functions.lazy(P6.__5()).f(this); } /** @@ -304,7 +304,7 @@ public final P1 _5_() { * @return the 1-product projection over the sixth element. */ public final P1 _6_() { - return P6.__6().lazy().f(this); + return F1Functions.lazy(P6.__6()).f(this); } /** diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 923a9624..6b06e86f 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -328,7 +328,7 @@ public X _7() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P7.__1().lazy().f(this); + return F1Functions.lazy(P7.__1()).f(this); } /** @@ -337,7 +337,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P7.__2().lazy().f(this); + return F1Functions.lazy(P7.__2()).f(this); } /** @@ -346,7 +346,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return P7.__3().lazy().f(this); + return F1Functions.lazy(P7.__3()).f(this); } /** @@ -355,7 +355,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return P7.__4().lazy().f(this); + return F1Functions.lazy(P7.__4()).f(this); } /** @@ -364,7 +364,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return P7.__5().lazy().f(this); + return F1Functions.lazy(P7.__5()).f(this); } /** @@ -373,7 +373,7 @@ public final P1 _5_() { * @return the 1-product projection over the sixth element. */ public final P1 _6_() { - return P7.__6().lazy().f(this); + return F1Functions.lazy(P7.__6()).f(this); } /** @@ -382,7 +382,7 @@ public final P1 _6_() { * @return the 1-product projection over the seventh element. */ public final P1 _7_() { - return P7.__7().lazy().f(this); + return F1Functions.lazy(P7.__7()).f(this); } /** diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index 70674c59..e6763d2b 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -406,7 +406,7 @@ public X _8() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return P8.__1().lazy().f(this); + return F1Functions.lazy(P8.__1()).f(this); } /** @@ -415,7 +415,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return P8.__2().lazy().f(this); + return F1Functions.lazy(P8.__2()).f(this); } /** @@ -424,7 +424,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return P8.__3().lazy().f(this); + return F1Functions.lazy(P8.__3()).f(this); } /** @@ -433,7 +433,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return P8.__4().lazy().f(this); + return F1Functions.lazy(P8.__4()).f(this); } /** @@ -442,7 +442,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return P8.__5().lazy().f(this); + return F1Functions.lazy(P8.__5()).f(this); } /** @@ -451,7 +451,7 @@ public final P1 _5_() { * @return the 1-product projection over the sixth element. */ public final P1 _6_() { - return P8.__6().lazy().f(this); + return F1Functions.lazy(P8.__6()).f(this); } /** @@ -460,7 +460,7 @@ public final P1 _6_() { * @return the 1-product projection over the seventh element. */ public final P1 _7_() { - return P8.__7().lazy().f(this); + return F1Functions.lazy(P8.__7()).f(this); } /** @@ -469,7 +469,7 @@ public final P1 _7_() { * @return the 1-product projection over the eighth element. */ public final P1 _8_() { - return P8.__8().lazy().f(this); + return F1Functions.lazy(P8.__8()).f(this); } /** diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index e2d6de0d..a07da3b9 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -2,6 +2,7 @@ import fj.Bottom; import fj.F; +import fj.F1Functions; import fj.F2; import fj.P1; import fj.data.Either; @@ -214,7 +215,7 @@ public Trampoline f(final P1> trampolineP1) { * @return A new trampoline that runs this trampoline, then applies the given function to the result. */ public final Trampoline map(final F f) { - return bind(Trampoline.pure().o(f)); + return bind(F1Functions.o(Trampoline.pure(), f)); } /** diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index e3b09b8c..4bc6580e 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -1,17 +1,7 @@ package fj.control.parallel; -import fj.Effect; -import fj.F; -import fj.F2; -import fj.F2Functions; -import fj.Function; -import fj.Monoid; -import fj.P; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.P4; -import fj.Unit; +import fj.*; + import static fj.P.p; import static fj.Function.curry; import static fj.Function.uncurryF2; @@ -79,7 +69,7 @@ public Promise f(final P1 ap1) { * that can be claimed in the future. */ public F> promise(final F f) { - return f.promiseK(strategy); + return F1Functions.promiseK(f, strategy); } /** @@ -104,7 +94,7 @@ public F> f(final F abf) { * that can be claimed in the future. */ public F2> promise(final F2 f) { - return P2.untuple(F2Functions.tuple(f).promiseK(strategy)); + return P2.untuple(F1Functions.promiseK(F2Functions.tuple(f), strategy)); } diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index 6aecf8e9..cc773c1a 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -14,6 +14,7 @@ import java.util.Arrays; import fj.F; +import fj.F1Functions; import fj.Function; import fj.P; import fj.P1; @@ -171,7 +172,7 @@ public IterV run() throws IOException { final String s = r.readLine(); if (s == null) { return i; } final Input input = Input.el(s); - final F, IterV>, P1>> cont = Function., IterV>apply(input).lazy(); + final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); i = i.fold(done, cont)._1(); } return i; @@ -222,7 +223,7 @@ public IterV run() throws IOException { } final Input input = Input.el(buffer); final F, IterV>, P1>> cont = - Function., IterV>apply(input).lazy(); + F1Functions.lazy(Function., IterV>apply(input)); i = i.fold(done, cont)._1(); } return i; diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index f67a5320..f4047b32 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -1,6 +1,7 @@ package fj.data; import fj.F; +import fj.F1Functions; import fj.Function; import fj.P; import fj.P1; @@ -81,7 +82,7 @@ public Z fold(final F>, Z> done, final F, IterV, Option> runCont = new F, Option>() { - final F>, Option> done = P2.>__1().andThen(Option.some_()); + final F>, Option> done = F1Functions.andThen(P2.>__1(), Option.some_()); final F, IterV>, Option> cont = Function.constant(Option.none()); @Override diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index aabcdb02..9450b918 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -2,6 +2,7 @@ import fj.Effect; import fj.F; +import fj.F1Functions; import static fj.data.Option.some; import static fj.data.Option.somes; @@ -106,11 +107,11 @@ public void e(final A a) { public NonEmptyList> sublists() { return fromList( somes(toList().toStream().substreams() - .map(new F, Option>>() { + .map(F1Functions.o(new F, Option>>() { public Option> f(final List list) { return fromList(list); } - }.o(Conversions.Stream_List())).toList())).some(); + }, Conversions.Stream_List())).toList())).some(); } /** diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 57e9da20..af871cdc 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -1,6 +1,7 @@ package fj.data; import fj.F; +import fj.F1Functions; import fj.P; import fj.P2; import fj.P3; @@ -214,10 +215,10 @@ public TreeMap update(final K k, final F f, final V v) { * and the optional value is the value associated with the given key if present, otherwise None. */ public P3, Option, Set> split(final K k) { - final F>>, Set> getSome = Option.fromSome().o(P2.>__2()) - .mapSet(tree.ord().comap(P.>p2().f(k).o(Option.some_()))); + final F>>, Set> getSome = F1Functions.mapSet(F1Functions.o(Option.fromSome(), P2.>__2()) + , tree.ord().comap(F1Functions.o(P.>p2().f(k), Option.some_()))); return tree.split(p(k, Option.none())).map1(getSome).map3(getSome) - .map2(Option.join().o(P2.>__2().mapOption())); + .map2(F1Functions.o(Option.join(), F1Functions.mapOption(P2.>__2()))); } /** @@ -228,7 +229,7 @@ public P3, Option, Set> split(final K k) { */ @SuppressWarnings({"unchecked"}) public TreeMap map(final F f) { - final F>, P2>> g = P2.map2_(f.mapOption()); + final F>, P2>> g = P2.map2_(F1Functions.mapOption(f)); final F>> coord = flip(P.>p2()).f(Option.none()); final Ord o = tree.ord().comap(coord); return new TreeMap(tree.map(TreeMap.>ord(o), g)); diff --git a/demo/src/main/java/fj/demo/Comonad_example.java b/demo/src/main/java/fj/demo/Comonad_example.java index 169a534f..a52b8957 100644 --- a/demo/src/main/java/fj/demo/Comonad_example.java +++ b/demo/src/main/java/fj/demo/Comonad_example.java @@ -1,6 +1,7 @@ package fj.demo; import fj.F; +import fj.F1Functions; import fj.P; import static fj.data.List.asString; import static fj.data.List.fromString; @@ -27,7 +28,7 @@ public static Stream> perms(final Stream s) { r = join(z.cobind(new F, Stream>>() { public Stream> f(final Zipper zp) { return perms(zp.lefts().reverse().append(zp.rights())) - .map(Stream.cons().f(zp.focus()).o(P.>p1())); + .map(F1Functions.o(Stream.cons().f(zp.focus()), P.>p1())); } }).toStream()); return r; diff --git a/demo/src/main/java/fj/demo/Primes2.java b/demo/src/main/java/fj/demo/Primes2.java index c2d71204..0a79dd75 100644 --- a/demo/src/main/java/fj/demo/Primes2.java +++ b/demo/src/main/java/fj/demo/Primes2.java @@ -1,5 +1,6 @@ package fj.demo; +import fj.F1Functions; import fj.P1; import static fj.data.Enumerator.naturalEnumerator; @@ -22,7 +23,7 @@ public class Primes2 { public static Stream sieve(final Stream xs) { return cons(xs.head(), new P1>() { public Stream _1() { - return sieve(xs.tail()._1().removeAll(naturalOrd.equal().eq(ZERO).o(mod.f(xs.head())))); + return sieve(xs.tail()._1().removeAll(F1Functions.o(naturalOrd.equal().eq(ZERO), mod.f(xs.head())))); } }); } diff --git a/demo/src/main/java/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java index f4f4d8b5..72e68391 100644 --- a/demo/src/main/java/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -1,6 +1,7 @@ package fj.demo.concurrent; import fj.F; +import fj.F1Functions; import fj.P1; import fj.Unit; import fj.control.parallel.ParModule; @@ -40,37 +41,37 @@ public Long f(final Stream document) { // Main program does the requisite IO gymnastics public static void main(final String[] args) { final List> documents = list(args).map( - new F() { - public BufferedReader f(final String fileName) { - try { - return new BufferedReader(new FileReader(new File(fileName))); - } catch (FileNotFoundException e) { - throw new Error(e); - } - } - }.andThen(new F>() { - public Stream f(final BufferedReader reader) { - final Option s; - try { - s = fromNull(reader.readLine()); - } catch (IOException e) { - throw new Error(e); + F1Functions.andThen(new F() { + public BufferedReader f(final String fileName) { + try { + return new BufferedReader(new FileReader(new File(fileName))); + } catch (FileNotFoundException e) { + throw new Error(e); + } } - if (s.isSome()) - return fromString(s.some()).append(new P1>() { - public Stream _1() { - return f(reader); + }, new F>() { + public Stream f(final BufferedReader reader) { + final Option s; + try { + s = fromNull(reader.readLine()); + } catch (IOException e) { + throw new Error(e); + } + if (s.isSome()) + return fromString(s.some()).append(new P1>() { + public Stream _1() { + return f(reader); + } + }); + else { + try { + reader.close(); + } catch (IOException e) { + throw new Error(e); + } + return Stream.nil(); } - }); - else { - try { - reader.close(); - } catch (IOException e) { - throw new Error(e); - } - return Stream.nil(); } - } })); final ExecutorService pool = newFixedThreadPool(16); diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index 2704dffb..321a34b7 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -1,5 +1,6 @@ package fj.demo.euler; +import fj.F1Functions; import fj.F2; import fj.F2Functions; import fj.data.Stream; @@ -22,7 +23,7 @@ public static void main(final String[] args) { static void java7() { final Stream fibs = new F2>() { public Stream f(final Integer a, final Integer b) { - return cons(a, F2Functions.curry(this).f(b).lazy().f(a + b)); + return cons(a, F1Functions.lazy(F2Functions.curry(this).f(b)).f(a + b)); } }.f(1, 2); out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); @@ -30,7 +31,7 @@ public Stream f(final Integer a, final Integer b) { static F2> fibsJava8 = (a, b) -> { - return cons(a, F2Functions.curry(Problem2.fibsJava8).f(b).lazy().f(a + b)); + return cons(a, F1Functions.lazy(F2Functions.curry(Problem2.fibsJava8).f(b)).f(a + b)); }; static void java8() { From 0a9c386f2e83019cad621733fdf29375d1e63ab8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 6 Apr 2014 19:38:16 +1000 Subject: [PATCH 035/811] Removed Scala classes created when initialising with gradle --- tests/src/main/scala/Library.scala | 9 --------- tests/src/test/scala/LibrarySuite.scala | 18 ------------------ 2 files changed, 27 deletions(-) delete mode 100644 tests/src/main/scala/Library.scala delete mode 100644 tests/src/test/scala/LibrarySuite.scala diff --git a/tests/src/main/scala/Library.scala b/tests/src/main/scala/Library.scala deleted file mode 100644 index b956351a..00000000 --- a/tests/src/main/scala/Library.scala +++ /dev/null @@ -1,9 +0,0 @@ -/* - * This Scala source file was auto generated by running 'gradle buildInit --type scala-library' - * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 - * - * @author MarkPerry, @date 12/12/13 10:02 AM - */ -class Library { - def someLibraryMethod(): Boolean = true -} diff --git a/tests/src/test/scala/LibrarySuite.scala b/tests/src/test/scala/LibrarySuite.scala deleted file mode 100644 index ced7f663..00000000 --- a/tests/src/test/scala/LibrarySuite.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This Scala Testsuite was auto generated by running 'gradle init --type scala-library' - * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 - * - * @author MarkPerry, @date 12/12/13 10:02 AM - */ - -import org.scalatest.FunSuite -import org.junit.runner.RunWith -import org.scalatest.junit.JUnitRunner - -@RunWith(classOf[JUnitRunner]) -class LibrarySuite extends FunSuite { - test("someLibraryMethod is always true") { - def library = new Library() - assert(library.someLibraryMethod) - } -} From fb3ba4f14ea10c0dfc3d71d7da0009ac9766f68d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 6 Apr 2014 20:40:44 +1000 Subject: [PATCH 036/811] Use java 7 and run scala tests using retro lambda --- core/src/main/java/fj/Equal.java | 2 +- core/src/main/java/fj/Ord.java | 2 +- demo/build.gradle | 19 +++++++++++++++++++ settings.gradle | 4 ++-- .../test/scala/fj/data/CheckIteratee.scala | 3 ++- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index edd9dfb9..e510671f 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -80,7 +80,7 @@ public Boolean f(final A a1) { * @return A new equal. */ public Equal comap(final F f) { - return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); + return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } /** diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 248b1f12..1fdf05f8 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -78,7 +78,7 @@ public Boolean f(final A a1, final A a2) { * @return A new ord. */ public Ord comap(final F f) { - return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); + return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } /** diff --git a/demo/build.gradle b/demo/build.gradle index 5769f739..6d4288db 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,6 +1,18 @@ + +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'me.tatarka:gradle-retrolambda:1.3.1' + } +} + apply plugin: 'java' apply plugin: 'application' +apply plugin: 'retrolambda' defaultTasks 'build' @@ -15,6 +27,13 @@ repositories { mavenCentral() } + +retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 +} + dependencies { compile 'org.slf4j:slf4j-api:1.7.5' compile project(":core") diff --git a/settings.gradle b/settings.gradle index f1cf677d..95aee2e6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,3 @@ -//include 'core', 'demo', 'tests' -include 'core', 'demo' +include 'core', 'demo', 'tests' +//include 'core', 'demo' diff --git a/tests/src/test/scala/fj/data/CheckIteratee.scala b/tests/src/test/scala/fj/data/CheckIteratee.scala index 2044e21c..76213a5d 100644 --- a/tests/src/test/scala/fj/data/CheckIteratee.scala +++ b/tests/src/test/scala/fj/data/CheckIteratee.scala @@ -7,6 +7,7 @@ import Unit.unit import List.{list, nil} import Option.{some, none} import fj.Function._ +import fj.F1Functions import fj.data.Iteratee._ import org.scalacheck.Prop._ @@ -50,7 +51,7 @@ object CheckIteratee extends Properties("Iteratee") { var tail = l while(!isDone(i) && !tail.isEmpty) { val input = Input.el(tail.head) - val cont: F[F[Input[E], IterV[E, A]], P1[IterV[E, A]]] = Function.apply(input).`lazy`() + val cont: F[F[Input[E], IterV[E, A]], P1[IterV[E, A]]] = F1Functions.`lazy`(Function.apply(input)) i = i.fold(done, cont)._1 tail = tail.tail } From 28c9b595263cf7c7f7fa0176f819336a88dcad9d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 9 Apr 2014 16:32:16 +1000 Subject: [PATCH 037/811] Made this version 4.1-SNAPSHOT using the group com.github.mperry --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 2919d37d..2f442beb 100644 --- a/build.gradle +++ b/build.gradle @@ -6,11 +6,11 @@ ext { allprojects { ext { - fjVersion = "4.0-SNAPSHOT" + fjVersion = "4.1-SNAPSHOT" projectName = "functionaljava" } version = fjVersion - group = "org.functionaljava" + group = "com.github.mperry" } subprojects { From 6c2fda1dbf88242b30376abda3b4c10a2a7c4f44 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Apr 2014 09:01:35 +1000 Subject: [PATCH 038/811] Changed group to official FJ group --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2f442beb..0ccedcfd 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ allprojects { projectName = "functionaljava" } version = fjVersion - group = "com.github.mperry" + group = "org.functionaljava" } subprojects { From a0e487b29ee2ed55f38896be3f9c5ab19333d2d9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Apr 2014 09:03:09 +1000 Subject: [PATCH 039/811] Add group for FJ back to official group --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index a73a6321..2919d37d 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ allprojects { projectName = "functionaljava" } version = fjVersion - group = "com.github.mperry" + group = "org.functionaljava" } subprojects { From dbda2ac113a88248f35b65c10dc434d3e410e7bd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 27 Apr 2014 09:21:17 +1000 Subject: [PATCH 040/811] Setup uploading to sonatype repo --- build.gradle | 23 +++++++++++++++++++++-- core/build.gradle | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 2919d37d..31bf017c 100644 --- a/build.gradle +++ b/build.gradle @@ -6,9 +6,28 @@ ext { allprojects { ext { - fjVersion = "4.0-SNAPSHOT" + isSnapshot = true + fjBaseVersion = "4.0" + + snapshotAppendix = "-SNAPSHOT" + fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") + + projectTitle = "Functional Java" projectName = "functionaljava" - } + pomProjectName = projectTitle + pomOrganisation = projectTitle + projectDescription = "Functional Java is an open source library that supports closures for the Java programming language" + projectUrl = "http://functionaljava.org/" + scmUrl = "git://github.com/functionaljava/functionaljava.git" + scmGitFile = "scm:git@github.com:functionaljava/functionaljava.git" + + sonatypeBaseUrl = "https://oss.sonatype.org" + sonatypeSnapshotUrl = "$sonatypeBaseUrl/content/repositories/snapshots/" + sonatypeRepositoryUrl = "$sonatypeBaseUrl/content/groups/public" + sonatypeReleaseUrl = "$sonatypeBaseUrl/service/local/staging/deploy/maven2/" + sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl + primaryEmail = "functionaljava@googlegroups.com" + } version = fjVersion group = "org.functionaljava" } diff --git a/core/build.gradle b/core/build.gradle index eeb8a392..58ad58f5 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,10 +1,10 @@ apply plugin: 'java' apply plugin: 'maven' +//apply plugin: 'signing' defaultTasks 'build' - jar { baseName project.projectName version project.fjVersion @@ -19,6 +19,48 @@ repositories { dependencies { compile 'org.slf4j:slf4j-api:1.7.5' - testCompile "junit:junit:4.11" } + +uploadArchives { + repositories { + mavenDeployer { + // used for signing the artifacts, no need to sign snapshot, so leave out for now +// beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + + repository(url: sonatypeUploadUrl) { + authentication(userName: sonatypeUsername, password: sonatypePassword) + } + pom { + groupId = project.group + project { + name pomProjectName + packaging 'jar' + description projectDescription + url projectUrl + organization { + name pomOrganisation + url projectUrl + } + scm { + url scmUrl +// connection scmGitFile +// developerConnection scmGitFile + } + licenses { + license { + name "The BSD3 License" + url "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" + distribution 'repo' + } + } + developers { + developer { + email primaryEmail + } + } + } + } + } + } +} From f6cc29fda0bfd004716a9e5c337344a5aa2c0c47 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 9 May 2014 11:14:24 +1000 Subject: [PATCH 041/811] Removed obsolete files including Maven, SBT and ant build files --- build-maven.xml | 93 -------------- fjscala/functionaljava-scala.iml | 24 ---- pom.xml | 109 ----------------- project/.gitignore | 1 - project/build.properties | 9 -- project/build/.gitignore | 1 - project/build/FunctionalJavaProject.scala | 142 ---------------------- project/build/OverridableVersion.scala | 20 --- project/project.iml | 66 ---------- sbt | 3 - sbt-launch-0.7.4.jar | Bin 928236 -> 0 bytes sbt.boot.properties | 37 ------ sbt.cmd | 4 - 13 files changed, 509 deletions(-) delete mode 100644 build-maven.xml delete mode 100644 fjscala/functionaljava-scala.iml delete mode 100755 pom.xml delete mode 100644 project/.gitignore delete mode 100644 project/build.properties delete mode 100644 project/build/.gitignore delete mode 100644 project/build/FunctionalJavaProject.scala delete mode 100644 project/build/OverridableVersion.scala delete mode 100644 project/project.iml delete mode 100755 sbt delete mode 100644 sbt-launch-0.7.4.jar delete mode 100644 sbt.boot.properties delete mode 100644 sbt.cmd diff --git a/build-maven.xml b/build-maven.xml deleted file mode 100644 index 5cf7742b..00000000 --- a/build-maven.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/fjscala/functionaljava-scala.iml b/fjscala/functionaljava-scala.iml deleted file mode 100644 index c5f3d3aa..00000000 --- a/fjscala/functionaljava-scala.iml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml deleted file mode 100755 index 31d43386..00000000 --- a/pom.xml +++ /dev/null @@ -1,109 +0,0 @@ - - - - 4.0.0 - org.functionaljava - functionaljava - jar - Functional Java - Functional Java is an open source library that aims to prepare the Java programming language for the - inclusion of closures. - - 3.1 - http://functionaljava.org/ - - - The BSD3 License - https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE - repo - - - - git://github.com/functionaljava/functionaljava.git - - - - functionaljava@googlegroups.com - - - - Functional Java - http://functionaljava.org/ - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.5 - 1.5 - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.5 - - - generate-sources - - add-source - - - - src/main - src/package-info - resources - - - - - - - - - - ossrh - http://oss.sonatype.org/service/local/staging/deploy/maven2 - - - ossrh - http://oss.sonatype.org/content/repositories/snapshots - - - - - release-sign-artifacts - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.0-alpha-4 - - - sign-artifacts - verify - - sign - - - - - - - - - - UTF-8 - - diff --git a/project/.gitignore b/project/.gitignore deleted file mode 100644 index 36ef4c37..00000000 --- a/project/.gitignore +++ /dev/null @@ -1 +0,0 @@ -boot diff --git a/project/build.properties b/project/build.properties deleted file mode 100644 index 10a7b6cd..00000000 --- a/project/build.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Project properties -#Thu Jul 15 07:36:17 CEST 2010 -project.organization=org.functionaljava -project.name=functionaljava -sbt.version=0.7.7 -project.version=3.2-SNAPSHOT -def.scala.version=2.7.7 -build.scala.versions=2.9.2 -project.initialize=false diff --git a/project/build/.gitignore b/project/build/.gitignore deleted file mode 100644 index 1de56593..00000000 --- a/project/build/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target \ No newline at end of file diff --git a/project/build/FunctionalJavaProject.scala b/project/build/FunctionalJavaProject.scala deleted file mode 100644 index 06f5180b..00000000 --- a/project/build/FunctionalJavaProject.scala +++ /dev/null @@ -1,142 +0,0 @@ -import sbt._ -import java.util.jar.Attributes.Name._ -import Process._ - -abstract class FunctionalJavaDefaults(info: ProjectInfo) extends DefaultProject(info) with OverridableVersion { - private val encodingUtf8 = List("-encoding", "UTF-8") - - override def compileOptions = target(Target.Java1_5) :: (CompileOptions.Unchecked :: encodingUtf8).map(CompileOption) ++ super.compileOptions - - override def javaCompileOptions = List("-target", "1.5", "-source", "1.5", "-encoding", "UTF-8", "-Xlint:unchecked").map(JavaCompileOption) ++ super.javaCompileOptions - - def scalacheckDependency = "org.scalacheck" %% "scalacheck" % "1.10.0" % "test" - - override def testFrameworks = Seq(new TestFramework("org.scalacheck.ScalaCheckFramework")) - - override protected def disableCrossPaths = true - - override def packageSrcJar = defaultJarPath("-sources.jar") - - override def packageTestSrcJar = defaultJarPath("-test-sources.jar") - - override def outputPattern = "[conf]/[type]/[artifact](-[revision])(-[classifier]).[ext]" - - lazy val sourceArtifact = Artifact(artifactID, "src", "jar", Some("sources"), Nil, None) - - override def documentOptions = encodingUtf8.map(SimpleDocOption(_)): List[ScaladocOption] - - override def managedStyle = ManagedStyle.Maven - - val authors = "Tony Morris, Runar Bjarnason, Tom Adams, Brad Clow, Ricky Clarkson, Jason Zaugg" - - val projectNameFull = "Functional Java" - val projectUrl = "http://functionaljava.org/" - - override def packageOptions = - ManifestAttributes( - (IMPLEMENTATION_TITLE, projectNameFull) - , (IMPLEMENTATION_URL, projectUrl) - , (IMPLEMENTATION_VENDOR, authors) - , (SEALED, "true") - ) :: Nil - - override def packageToPublishActions = super.packageToPublishActions ++ Seq(packageSrc, packageTestSrc, packageDocs) - - override def consoleInit = -""" -import fj._ -import fj.data._ -import org.scalacheck._ -import org.scalacheck.Prop._ -""" - - val pubishToRepoName = "Sonatype Nexus Repository Manager" - - val publishTo = { - val repoUrl = "http://nexus.scala-tools.org/content/repositories/" + (if (version.toString.endsWith("-SNAPSHOT")) - "snapshots" - else - "releases") - - pubishToRepoName at repoUrl - } - - lazy val publishUser = system[String]("build.publish.user") - lazy val publishPassword = system[String]("build.publish.password") - - (publishUser.get, publishPassword.get) match { - case (Some(u), Some(p)) => - Credentials.add(pubishToRepoName, "nexus.scala-tools.org", u, p) - case _ => - Credentials(Path.userHome / ".ivy2" / ".credentials", log) - } -} - -final class FunctionalJavaProject(info: ProjectInfo) extends ParentProject(info) with OverridableVersion { - lazy val core = project("core", "functionaljava-core", new Core(_)) - lazy val demo = project("demo", "functionaljava-demo", new Demo(_), core) - lazy val fjscala = project("fjscala", "functionaljava-scala", new FJScala(_), core) - - class Core(info: ProjectInfo) extends FunctionalJavaDefaults(info) with JavaDocProject { - - val scalacheck = scalacheckDependency - - override def testScalaSourcePath = "src" / "test" - - override protected def docAction = javadocAction - - override def javadocOptions = Seq( - WindowTitle(projectNameFull + " " + version.toString) - , DocTitle(.toString) - , Header(

Copyright 2008 - 2011 {authors}

This software is released under an open source BSD licence.
.toString)) - - override def documentOptions = documentTitle("Functional Java") :: super.documentOptions - - override def moduleID = "functionaljava" - } - - class Demo(info: ProjectInfo) extends FunctionalJavaDefaults(info) { - override def documentOptions = documentTitle("Functional Java Demonstration") :: super.documentOptions - } - - class FJScala(info: ProjectInfo) extends FunctionalJavaDefaults(info) { - override def documentOptions = documentTitle("Functional Java for Scala") :: super.documentOptions - } - - private def noAction = task {None} - - override def deliverLocalAction = noAction - - override def publishLocalAction = noAction - - override def publishAction = noAction -} - -trait JavaDocProject { - self: DefaultProject => - - sealed abstract class JavadocOption - - case class WindowTitle(t: String) extends JavadocOption - - case class DocTitle(t: String) extends JavadocOption - - case class Header(html: String) extends JavadocOption - - def javadocOptions = Seq[JavadocOption]() - - def javadocAction = javadocTask(mainLabel, mainSourceRoots, mainSources, mainDocPath, docClasspath, javadocOptions).dependsOn(compile) describedAs "Generate Javadoc" - - def javadocTask(label: String, sourceRoot: PathFinder, sources: PathFinder, outputDirectory: Path, classpath: PathFinder, options: Seq[JavadocOption]): Task = task { - val os = options flatMap { - case WindowTitle(t) => Seq("-windowtitle", t) - case DocTitle(t) => Seq("-doctitle", t) - case Header(html) => Seq("-header", html) - } - val proc = Process(Seq("javadoc", "-quiet", "-sourcepath", sourceRoot.get.toList.head.toString, "-d", outputDirectory.toString) ++ os ++ sources.getPaths) - log.debug(proc.toString) - proc ! - - None - } -} diff --git a/project/build/OverridableVersion.scala b/project/build/OverridableVersion.scala deleted file mode 100644 index 57a9caee..00000000 --- a/project/build/OverridableVersion.scala +++ /dev/null @@ -1,20 +0,0 @@ -import sbt._ - -/** - * Replaces 'SNAPSHOT' in the project version with the contents of the system property 'build.timestamp', - * if provided. - */ -trait OverridableVersion extends Project { - lazy val buildTimestamp = system[String]("build.timestamp") - - override def version = { - val realVersion = super.version - val v = realVersion.toString - val SnapshotVersion = """(.+)-SNAPSHOT""".r - (buildTimestamp.get, realVersion.toString) match { - case (Some(timestamp), SnapshotVersion(base)) => OpaqueVersion(base + "-" + timestamp) - case _ => realVersion - } - } -} - diff --git a/project/project.iml b/project/project.iml deleted file mode 100644 index 6db57662..00000000 --- a/project/project.iml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sbt b/sbt deleted file mode 100755 index 84c41c8e..00000000 --- a/sbt +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -java $SBT_OPTS -Dfile.encoding=UTF-8 -Xss4M -Xmx1024M -XX:MaxPermSize=256M -XX:NewSize=128M -XX:NewRatio=3 -jar `dirname $0`/sbt-launch-0.7.4.jar @sbt.boot.properties "$@" diff --git a/sbt-launch-0.7.4.jar b/sbt-launch-0.7.4.jar deleted file mode 100644 index 2a9fe7fb9f6e89415176f2a3bc373127297e0ce8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 928236 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�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

LTIMS;Hd zU~VKir-~!@tlZ3nQm+Ig4jGANTyzqHDPhDhiWQc@KHOom*$#qLN;QL}9{#;_sTxBK zNe<08iwL~z%8uH(+T;mu@1kxD|5Ckc8XH2u zsneI$2tqU`Y8y`c<;aeLrO3n9m`@MrMK9awqyqeDxzr~ayvtUDO2A<-FFJjWWrISA zcDtk7`0e@wi=Z8`4Y;)9tTUu-n%4Fp>2k1-@?iy&fq5nUhNHS8^4VppD0Ykb)Yb+s zqL%4>2DM-Ul-h;RpRSSvxq@>(4Mz~}Z`dwX zO3b&e9S5I+p&iB^-z10uh^km?{M*;fw0>0??iF>Rc|uyDZjc@$DlnL=*V+xYJeG_h zhHC`iGpX>-`|0k@@`S6$sUsF9=m!vMK1P-&NJ^W5r4AKEG87()@p?*il{g_n(JH?X zZR;B_`f-OQ570o@GKfx6g=h_eno-E3Rp%kp1SGkDQy3|dDOyBcp@h;-@r$6j%Oog- zb`U12NZ~6gTBL9qQM47`tUdo8P;2=9cy<7qwfG+a!T+ua`!~~8F#N}Wl%aeCY{Jmq z=#&&kg-Lv$Ln%zZL-ylo+I%d5rJ$-z+E=KIBa?E|5X~C+dJ*LKxDBL(h&%{P1PR~W zGT6W2`Zn=@ID5zFNZV~)xI4B{v2EM7ZQFK772CG$q?2@PtK*Kpf@eU(Y>8)sGr=KU3Gd<~9B89sJ*)-$8q!ewjLPM2%>5jqav|V!<|HVd&20tRaheZ0k;psh4pNTD zW$(3zF5tE~rS2h2yU6aKjIaW^BCj|v3VNLgL~s!q`>&BGxbThQ_qb}Ex`wGp=oy=N zo~VF$^8U{?<**83zv$3MnSi+%=;8HeQ@=Gs%?dkpT;-~IX(G*b<&iOm%oJ#&<`eH! z-?}v-jZf5wdoUzt(w3B~Q{B*fP#e^v3X4C^i+$_T^Rcuv)X+nd-Zhoac}412QnYpI zZYi?zOaPKQ3v@^Gv;a|XA0`@bFUmBO>Eu|>O-gk1QVZPhN{{{%mcmI3 z!g3STpd7w37RS0(^QZRnQ4QK7W@0P|Le}DSq@%RMN};KWsour~*x;rwg2!Y)gn?>r zS8O{w|M{e+I?+|B-@_t;Ipx+$);q9rcGoRDB_AKdG4p*;rkd;(O(|-1vXs=On-32) z@;|pI7ECxlda5iaZSAk&C^)*^e>2zz$*TD=7A?y}im#TEKvdBOWp?$17rEl-xX!iB ziC|g;9T&>^pLp)UjWNyh6N?}+ULg1jwec+W);3R-~j=<%>@ z2%m?v28dx&h4kqiImDIvyb_cL*)``bG0@0m@`|1v*@|FFaVCBCGn z+9`b6pZ~@2ad}Fg;j!=63Ib| zn7xf6W04Xkjhs*>7kpBBT50*-*NbD#Aw4`c+7rzIKRj}2?u4XI*$TXw`of|>F<^xB zeR_eW)hFgU;YwF$(^@3xxhZ}hZbU|w7yFtFybG?i%F+2l#UaMaXeY33KI8FBKNPzv z-6et_rTF;k$HL=P9@^J38GM&p$9>#vi9sZCVRo9m)Rel&l)c~gzu{n0(3Eca_G7O^ z?=po}@A0PN9bn>mP9L~=JssS1$I<2=VdS=2H%MrZP*{cSi>XV0bRB!w`7q1Lp6<1d zDH1qj7XPU$bX!FX{`u!6aB2&N%8%ZR7w-E3rvq^$_glDN6WYb|FDXy5Wtc$%&C&Q4 zvT!5q5W3UoHb_1VPmAPqG$WtwRX7%nsJU04LE$iq`*8Jph9Q>Z559#r&v;f*5nPWe zxE3dK$)NrTdP$@7=6umI;X{*&^V?ul+J)y&<#DWMOAgeypGorl^YmLqE*XV0&Cgog zZ81xAv(andszvOBawc|Ao0Rp5%!79vvhYp=l%}T11Y%?dARP?QP8qgXT#Zqptza=Q z`w{-Rjb^;X0)r&BJ4{;f;l;T6O3{Psq+l|ZoXt0R zd|aPFV(xECjQ?9@`L7`HuNvduMvBj3<1=+d@)HX&6H`UwdvX&&`%GQI1dK%)?0LWK z=%>Q4ou(!SU0ZlDUvDE`Nnlxc>=*_`D6JP~Wc={*V_0~ITjuxzsp(RmD8>|JhDkMf zxI;KFOYQSuOzKJ4Pw${z)NenvP&y%I@W?l|bR6-rCTVYKfHN@@qvp}y=Jp1F(00Xk z>PU^JoT^hLwBexxdOsOhGLKNJ{z)eCE8s~q>QgD`!s2f(=|DgKMjcuw2PdZRLTm|L zMBEE-V^@p89h*%gzmX$)!W?EFUKQOn3n5w?FnBa_%<{JM#gZ~vd3_Ij8wCqqNC3_H z7UxgsNsT@*me<9c{4B0cFQm}f+3V})B+0kt&&`YSgB>>#zcU6S=kjv#m@KtrtvsVxYS;bSVBvHE551I zeeoBEqNAiDHewqYJ|`p%>E*X%2{{NTn97wl09wGExE#O$mw0&(3N@jW zSBfXvqx>Ku6nfVF4hO{UQ$AveehmihJStE#?L%s-QlKwNuOxl_(;!H|p&#vz0Fe{5 z-;yAdY2T!57$&i#QEV_O(-&v^JeVZCVE?r*OPKpj5-yQe- z@JAz3-ngyk>v0cVgH|)NjvuJ(7Sh60$(wuUfZ?FkKxtqgNAjzGbdutx?DNL`=5Y{_ z7Z$HH@TTtO#g7RMZV2Ogy-!7>5_0a|RgO$uZlf;?JJ{s&?ld8013oRJynv*{^%JLHhlLd50V0ppIet3+4W z`|52=zFW4wrKq9a+*0lL423Kyl)C9b5VtXl;yvD_GU%hgDE>kQ63O1sG5Y_7ePASj zlP7;78-G9a%lmJz4?71_H(N6XQ!^J6XDi1~`7Q<_V;5KFPa^DpU?2Y)k@^=07NJ8n zQGUU3xzMg61tbs-gig&8{Y1?6n{vE*7n2kOb9H<{67&TB6VDam9(2oKdUci87{f}FK>unP*>)!GJx>#h^)S~Mk)iC*gv9$cJKma zK*Ztjm`}^6$c>?(;Gy7+B@IOlRSBsW$r${$zFPUz)Loc+dZW$_cv8p97#%D?3WXPxaDaw;m|JR|F81GTJ?RhV4a!tzlHensP z|5TUhHz^Ja)Jg$@8Fwu_3Z%xVY+a}X@nW#VdK_tjLk_omAydgOK z(_Uc*g~36?!jm3eLFpbr@yC;8Fiola!+G{M_m4vJxCi09 zf?n(Q0;6V9NQx?RcBZ07qe(aWLN$M9< z+!h2Fa~c+zLP+ zfAYZEKgAs|bdvX*C$#F%Dlk?2H{C(hg1muHK$U+%P3~oKUC%|Hp6cBg%r8rL$FhQC z%Wfj2wWBJXvb?nMteS+2RynhKuji(k=aklG9ksfSkG~K#N!q=flFwkq{B|k}d%3YQuD)eEe(-GYZEPEJjv51g@SnO{nggKl zd6ti^px*U)JDdX%VBeW04VlhNICH-B{lLdH9cApw?Ip)G^o-d-8ZZJD!HuA-Odgu! zN*Th6f4|24!<=o(xfDZ+fYTn%0hq>m{NjK$YLd8P2kO#poIm;_3&5e+j|ECk4(DmB z4zOo>1h6O$!GnHP@r(6<_l>9ytn=K)(Pg}%8wMBECd|dpMmv^6l&2eApQn~;vy_AU zv4_C|GO+*WwUCU4S-?T(Q?-uf@~Ktr4@?WnD!9!eVm4O>A~`IY{kw&y`saK0zSNhZ zTyxy6Rz(Zy{PYtX3#|3h9LHQdA_x6g22npweSMcNPpAG?$o#%_*xJPF6WQMg$-gMngweyR`$1an}gB!c_VyLaeqnWNbM>p;=o`Yo0Gf_gR?eHk1^+Q z+)uxVop3KHlEqEYs$0tDr7b;)YYl38MMhb1$J+}%hpKaBtu+ZY%;k|C*mj_a`x(&7 zbE(a5;HYsGm%PdbXzYPek?GqDZQp&=pamA$6lo?L&hgBbRh+b>ruSa7yse`Hv^2AkVxQ>!pVU{E9@qtY~)fc%&BTR`a=cTCiN|7?ESV zoL#jEESpXkC%ekc@s|(;Uz}4|zQ9n7A&LbU__$t=Jl3kx>G?0(=U+#0DsYPY^ou;p zcTb}d$2W<40vlc$S@{FieK<>UmoX3*&rGmal7~J()?af>j7z*Bm-fJ@4CrG&8EZfQ}zq0y>lDq{OYEMLFU&!Bt)g)Hxm$5h^p=6LI2CmJKuVN)rI)aY2+mtZAtq#50KddAEnq;OD0<9hdF~m}T_HJdNm}oyrZNsO-G5piN0}P~vrq z$ViSjdU4@Ev$2agv{&y+u^DHr!L1}istY<)$Iro_I|aS?TPL{`h{;>1OoRM_qsUWR z2W@S_eWwe&nA(ch48j^vvCZ#spU%LTK9`$jcB;Whw$Aef zqAb8nER4m}B6u)atTVCUxsSp49Y}ufLv8&}APFUYqU!LoPWOWSyC&1WYxw^kJnO$E zj{fOKLzVtfoTFvmw1gKzl?Qx9P&VoEVn#+qQ3Q3qR&SkYFsJbZ` z!BWtr7OUB1%+wmFs&dei$a-6HXCmW_a!R`2l*;il1M{Ghe`;!SP)VZc{Ki0s!K_Di zRs2>fzYE&72A@O`dobeuWIBXY5o)vrQ=V|9xCq=jx>E@Rzv{udA4uIaVv2@s!1Y7d z?cVRLIlJ~2$i7c){*$Dv*;%*ohNV7iF5S0w`MC&3j%6#eBI?{70CL0wbS-aoM6+Tu zR`HSHi6sXQgafOi4KQS)a11Bz)f6HcBH35w)!*yGt{N@V1g06o`(zW=&-g%;{3RE` zo_Nj8`kD8m{%zhb`v08%ia6MtTUod{8~tNf5vjVBi1f}qS>L1<7zzkv$doMHdQ%$ikfEAU zNR&IA-r#dNoZOhq>k$a}>KT0i$Q`=k1!BS+qM4#i(r7Bymv389a3{nc0$E9@`vJ&8eq>jSGSQH_x{Hl7C?wVT8MDk&T74*P&1v)T#^Hqai+ zU2N-4*GQug4sT2~!HCl9aO-p)pQGFMH{O8jjq|iwrdohSSf^;K8`*{v&37f1Nxj;r z;UD(g^vhN9t8MN2hi(h#Y%@;x*(R6ak(b!Hj%N{t;;%U(GJZG^V(<8`U+oo30j8E#7CQ3oq9D~gk;$Z!j;^D#Mx`HRTM}HIKm3sx!MAB<8DW&ELMb>u?XA~Ex&a=v&SE9v z2wS8hH32{ez{C)SqNhVSWe5r%Sd!}$5qAsRXWbk_uKpk=pOZiD;)NZT8N7vsbIiT* z>BIQ_rkI21SM6@(mi{@JdVU)OG z9^@uqB#WIJg@Bh*aAtnCywu6|MgmQ^^RR@p`)=vj;VG_IEQUJ3DXudHE2NaUip<@% zS3nN&qk!g0Yr9IB02XRVaDp>IF8+bB-Kdxqh=u)Blz$Z*@DE(7>y-p4@6#Ay|F-Y+ z?^>$=yPNti2Juf{RihE*fu@1=F?B)SWDDfQ0D*=IX&q(mJW-ZLhAIw0T5Bd!Oawys zx;FBx!sSesHZ=u)Yf-N-Zu$9~AM_KlRhh0u&ISq@yb^s{X+|mT=#k>lqP)k)BFQ%O zIy-lpt8=US;pO7NKbt4u`N5$UbR`D#jjpP5CQ)R}LMOT3_Yb5B*3@SMeGY zT|o8vdn7@{V?$(Kd3*6L9eR)A^#obCN!%Aa5LcM1_AlKaxY|KxD@481fWk*rI2o{T zBL_G(eoxtN!AzDbpX&jeM-(aCooq1;+rGSjd5V6M06&f`Kwh_2jAH-lzLbxTxSTJ9 zi!)2o8;DISk@n?GB#h(U~K(iWcaQAZ$J$v&4ISLvK<~z;Q_HeC#^I8&@#5Juq15qp_B)v zQo`(&#Tr8|W0e^vlMTsrV3N#(SM9<68rm5d_vPXIaC!n3)56b3QSKy?2NZ~d&o2y6zz4E}R=OKd-J+rLmQ-EA)YHv>+FF4j>r)r%l ze=e|;2U8IpT}L5MS^gTa$`KYn>>!B?J8GKIieI%o7bLpf{Utl7DPqX$<72FV_4~|S zu}5SrVJXG1uFb~Pq#R7@l_G9q4cx<0C+*118oDU=t(J|VX|#ofJSf&MZm5QUE61x&|cf`-Iq55`15T?TUbhJA-6LR4w0@A zuZ^K~60JN8!2{9t&V%VNEO%plVRNkd?jXv3c*6m@&izkZIvtnIhO0Jphfbqc)3)uM z_6PHNOt4 zt#im!QnH?mCAXIM;>kqyHFD^iy}xQ-rP0I~eSMG3pC3Wb*(Y@QRF>tUO1sLte^ORe zXlBgFhr+LhZd%8KFGIFzW<*^FDWe}_N;J=is%9^-<@;{Z%?o2`+Aa8HHqSz`jXc^r zb}0wu-Iz^Mn`?4<7Im7>MZ6}iW!uh#{mf431fNbUkPJFP+YduH{Vc* zzG_V9?71Z9Nx~n60mdLPl~!TaF71=+OE5T)&}?fAllyLHw4yui_+3^g*Gi~S)9q(W zy_P!<)9p+rNm6sB0JY&p#fCY?x+KQT_1N8AlO$C$6Emg!hbc>XA(GOOQzNLSPtmsf zw{6%&*VcRVq`!Qe4{Q`_eVfNpW;i>3P@c5-_T5lHfe-L@$1oD>67)dWIbuKHLABLM z>Gy=|jj`$28?o%5A8RxS<@FsRO`F(7mSb%Y^d}^fk|$|2SV343Plu$)d^}O!=c>AA zJJPB4>-lnA9>TWaLGwn_tpv;Gc0%74|5ha+dG7=iP_cp;B%4QWra4BMi+kPL07_)V zc!Oks9!l=vr^wPcbP*+O%rOOwJev8063>IuIHaih= zV0i_lp4f;zV+dMQFd+1)nPQgcFw_ca~`be;gRx}+uzcM%b@8vSA4u! zyJ6&3n*CClUKlTm&4VNIA#^L|;KF`_qy*kS%CVUk&=6y-cjlpmojr zx(0}S+p3c?568=(1uUdsTpppd=IcvL^%v7T6-s;vlC=OiO;>ilt&0(Mw46$oN#4qw zoWV6jT~wJ2+<-V)lk=E;IDBQtZS3Ei&HSr4zc8$#!|$5LfP0a)O;9?vZ(h@3$@APX zgJirYh-s+5@6aH_6r_hlJmUFxlCZU9lCgLR&2>ZQeB>SMa{4g9ZLhF+0sV62uMNvb zFKu{kAq#LjYQW<*&9KvzaGbN{tZWN{-7o$#M6ZzUdlH<10yj->>=QQ-`U82Z76A!g z*TxBt&+c8i$haMy>5r2hsdOQ1@T#uC-95t_4f|A5t#qzA1a@b%NZx(O7%u-t*(frNz2k#gJ8HzpG&RABI2 z%2r~weAqNoL~F3~Vd-(6#K@&_oOo)7g*aNkmU-Htki(hcek6w!n16_PrT976#$l@G zGPcRXW=Of28;y4={%mMpYnRj<%%-tmcF1`QC=#*!rl?RPc3cRp$|G2XB3$O)Ebx!? zYPDCju<^5+0Qsyr{yo+3fB5f6I6JsG{tH+8*8~zC#qpKV%Ba285@%B?=FqRu5bEuKd7VL6) zt9A9#0fQ7dhZXT)M%wQ5^jKV3N~UTYu8Vml6$5tVJNst~Q;p&cG|5A)U4)s^*1y}V zqLq(A(>g`4$n#IgTRq3-ZtQ2SY%V0GPPN$Ckk~oe1@lPhoGJ1fZfs>Sk}TjEi5JU9j%Ni1M>k5fs;>BWdqQ_KfLcOZZpR`zZw)R=@9Ml34#Me z)B9r>(Zp-urxnu{CX($+JiJY@gRxoU>?Pngo!SQ!F)+#Vdf`7@;gbaL~brt6|dOq77Vi7Bl~ zzRIINK+4FNRS&wcX~z_kNw2j0vY20A-LyF@FXX5$rX9K5DZ;eziyWatXM$+5zOzhh zwZriX6-t_V^eXzlv+uVvyUo7e_(?U_MCp)SWak{N+=(e6);;EyQLbk|9RJMFw|h%V zXA{}~pobjTHq(#|<=LgHDVg0wTLkWEo3z%T76)i>%x?(M?7KkCmhZEOYkxiQo0a@U zWD}S>1@esO?(Qe9W${3f>`S;1_BF9YzdQqf79+@N2((d~dE^?7$J>U!EeZc8e@~NoLkR{#qYu0}?q$ z^a*y){q3NW*#E5fm$LuVkaRIK`3Dg2A2zxEITeV+hsu~W0irMX6&+Pn4y2KCmkt1h z%!*Bn9o<$&7H#CZI7kO_eVDWCLfPLK)@4(A(#SsG5UsD zyb5C#Vcm9a5EnQ&_$>@R1hQxxTDMThEM^emhzL}^P9&;P^R6lY(os3m65uade4J)X z2nSxKrrTQ|iPK(7Og1E!t-%x=5~%}Fb;8k5+Ypi+@*7m+?bSjT%T~GukWlAtVPl(I66oXGpN{3IJgm%2i*yi z-}o$glt5LHwxgX;M90Lpu6PUCrNgaa#6!;yW`RPn0m@c>}Vea0;^cLl0X)G0uw|{Gy z|BfB=zb6r*X68n2w*RduJ)~jdvS^CtKYv!U-VD1=r>RIwtlhd!uWFAjI^MnZQ`sH^ zee|N#jxdXMwHQ+|V-Cw~7}0+L@g2nCHNU8YnB_SED=-jK3W*sK@)-~;wV4bXLPt7 zK8(vI&c0o^C>I$1VKMMLL&ZKeTxCa43H0*n6vq7gXb*JNN2LKH@FdRR-N+zndFu2L z2^jv7@(|sJ+?}l7(b}x4E|s2r4Q?*K!$ag`%vD?>(}u&wlJ%H7V(rlsDq_Wlr{IT? zTf|%6OqpLu)T)Dp-s<{R&k!;?#1{Ku*L`owZi3Lud6zti^P8*mluv z6XQoUN6n8)mMZ$+XZ338F%y+FO*UH}zwQyA3oJrHl=pc8NW#42fO8+@^O&^D^fnf* z(~5;3=uFbziHS;{zm|VB8(?ms`Od;;sXfiQoKm*C_CPZ!=@@sVdPhZZOb3|=Llwf?C|**1PV|x9(kz8r%pTjY zVZB5`kzOPGxN=>bWvsRmUM6k^HHp#4O?~utAd~q?Y0+xg(YSUD=-fW*G_+bNH8m;= zctc3VRHUr7Bo^~&taa+x#;^j*ZLrY&3ZuDN8oU&<=N-2!%*N3DMInrP1<+{98f|Br zWm>C3J|iv1Y}xM=M-dv5oi&%$@)U2nr9&*5yrsfitwNivZ9hdo1vXA-GUMlISGe^! zy@z&g750jhL%NiAKuke|!Lg*xZklkzd}og4NlM($spf@2D#^!hx$+B9W~e#@1zyBk zNh!w+7&@XObs)^L%tAUsU#F8ccI}4cbU{McCHhF6t-$GLp6S>5(w-na*=Q^dD9buE zIPDO#TOsA^cH1xSI87U5h{6!BGeZO#$j)j!LOH-u0hqtg78!}V=3W{urwX;lnlDh% z2#mwP66<7+sb;??bvsa$$fR!}Ij4n)HHV4(iHg_DZ6e&~7a+BPu#ziARI2FSCSRfu zveEfbHoJ~>8Z9$V?A!yMyFeTW-K_k4_Lkm;3|xV7&2UAkFrJ=NdkLLZ^cyL zC#|hJ$bU5Q9%+1=zK?Bu#DfBBsb@Y*&Z|cPv0Q=00T$(gPj8q2tGN$?(eX{}^LVRO zKMb0Vf3)S$sg0@RH(;MI@R>-l@!7mNOF0+PNY*STtlws#be4>af>wC;Y7f7MEFR(vSg zpD?u8-&T?e|Ig{!zkI z`TVKifK+bTOI@g@y)NS%IN*rMfQe>fQ`2(!XXr=8xkt}qK@OGD?`D&pW|lXG=Q!8z zKF~yir^&H+{SF*2yqz!Wet(>22m;>jV85L|$_wj$Dl}-2b&(6D#3#n5IZE}LL35C9 zq&i9rdLds%cp3~s67!>7Cxpj|`BLw)Am>H3Q|(4^vzicyU=H{L0Rx|W1OfH@tb&<1 zaop=7XdbLTjIPYMHzs7k{jgKVMx4El@darGc}Bf)Y%8ZD+Gmv`)Mw@ZQ_lkYuXm%8 zhRHi-SQzqS^-hU9&Cyt0q=dV{wvEG3o>?>BD5kGSgdt#_BIhC?>S1epD!-$#r^<&#T^CzjO$ucM z7lKx2&yH8FIWyGh({EaHBM_>z8t>z$n#l{T)#c=^mHf=vGg;~Axa~@Bu;?=9ouy=E z)=JT1thA;it;C(#)!E&-NabNH5nAFp8&+^D>+$7et)x09QtU?>+5a3YSj9B4ciIV% z7)C|CUAsOCgwW$-a*@GLq333l})0nRl*O zQm=!1uB}V1lIOSTaJY6#2+H+j%v&lOcfU|-%gR(eMR#io)tQ}Iu~{*wH^zv-T1KA& z*%R~REq_9@B@`e<>L?G{<*KV92ILnu`m-bv8EmqC=aji;DHxn8&g81l=C+_K;cq-k zdRo4r6gv~hYqCkdpzv{jD>DBjZ5_;w**<>%^-pC5+FLr(pDc0hyipzMhZuQ{DQDTQ ziQ2~Gg5=m^E+nOVi8H3h8%g`by(7dD1Uq({xKn`Yc?wLqQ8EQ z{$eaxP1(|ze;@-JZ3WtX%I$b+V{P{mQ<3~`R$r8#G;i76O&7Z>mSW@3!kzk}@VmSQ zn`%i~?a;0=w~egSIBj(E%_10EnJZ**cS!2Ah1QL|_K0%Zx~;GH0t>;ZE+ZXfwxi2M zf4=Y+Y^B&&;CovK`s~BL3XP$jTD?hPCRd>f(J`yD_JT#ag z^o0}i^|m4mDYUCqP{949bR+Fg;Hrl8m@FXcaznuB@5|(>MuhZpv4r1}7(tY8WZki6 zMY<>kvvaLj6)W~ALieeM&IvbU*zEq3&=OUT1KB_jeB5V*D+ugDK)2elkp+z%z5|!o z1L2DuCiBLNiK=#DwGW<|`_;=;Cgd7Hm0~kzA3KMoKIr)MZWUYox0EPuO>DEfMACpj z;XMayz2~Gxw_V2HNM)US^{72HfTE2o4BsH=@%o^5bEEjS z-nKU7X*^##5-O)ukTs0GW$r&F=-DOAN4V3;uO`h|ol|ts;)e~J!75RHS3EWrig8X9 z^7-v;lXAo0+*syU7_n)@;xf^`Xil3CYOd4jv)3snvn`859VKgAJHLIWmb^q-T-KJJ zDywdvt&gZQj%YZQobg@dL#HDo<$Gr=vqumR@e2a^mzZKA)9DVQTeVFXj;H+cXJaJeZ~CvPIC)?1m0)Dh}3_xKyy%Xc*9F1-U!XR z2VqZY`DRf?HKnSE&7d;Q-P!!lx!tMFd+y@T01*%WcVL>t|2#na_rTDN3+VvWr2bc9s(62LhmHSUY}?>Z~-yo-TKL9{8_11-uAP6CuM&0IAX?<J5V^aZAQJo81@arff)9#Eg<6Rl@X5nny5k6u>$e{x>F>vIAwoHctRwgBz#V5JIGIKJNOOGzi(R#A`HMg zwT%Ta!}J*4CjfZO>ca#>0zg5SL#(1}uj2j)lk;5Mw+)IJ|DB&-#HDN{X*BG#SJY?@Fl z9{Dvr#XuCCzVQ_g#3kcnd|%!E%VGJ-H+_gEz#_BeWPWU)GlY%mMu;7?e&kWPC)cMOR0XwuOj(sD{Itq7cXrio zTti5oE4s&a2K74_gX*<=cImEy6EO0@P<1Hpx{+^VEow`tA*%DG{Y6H%e7A^GY>1*k zb;w{x6CKgGB{IyhG*ZDRAyVOXWkIuamxVK|&lf#!h#Ea_00cd6m5Ap<7 zcFC@c>?LDdcQihFK+F?0{>}w*wc<58t?IR!YtMMNPuS4{n zgP)h_<2;;FLt8}(Ll0Wdai6RC^b2-JHl9U67vEUg_?N!8eE>~VjryG`>vv7nC|QLJ zYp88KBdE{XCDGp;v#4=7mC;QkMT~Lf)x`K$MWQM6pgHK3LLq6?cFY(PluEB`p@UVh zWW~~`OLuJ5k`v>NF=|zYY}dllgDn^}OCp_hOCzaqW4_UYwb}UP|JuTUZZE_MM%M5v zFJWpgpgW6$5TUCDDiY2o61ag+!;2S^Afsu>Y~wD=Y6BN1u=MJOo1Q1xz-{>UEHJC7 zC|&EY1pL{jV#E}0^$Nr_T*?b-s05FLZ}jFAv9Eo>RQevRGid<^F0BDkJ>_FtjRnVd z_ZE=9ixw8bP78MoCm^u#QE=>|AhIHk>-!1?9B3@a)g0MN9A@7yR_k!mEj+Lwut8 zC@Uz@v;O;q5gAe1S!?WII>cgA@09SNQ5a7}&2y=t+G#&!PyOYhdbp4Zb_A8|s#{pk z93ohO{Zr0#Sf(8zRij zU?ADSrs<>sR=Pr^6F9jbmrh7*T;uE5IAoi+BzJ1I&6C&o((wUjCEtlx9F*D7aX98P z+9blS<(|GvC@9zZBSH17A@z9BXPJoFcya7i%{PC3g;#f-g?MUZZa%w!+`z&2rRC*7$FpD19sh6cFBHqY+llQs0!IMQ? z{4(?*o3z68(n#3?EB?10_3xj*ra|_w%(u>Q@q9G;oX!tM1&K1Fk|0&~H0$*IWrX53 z^XImHqRDxRBw}V;*7Rp}bRI?f^j-tRWa5fCh)6?ed#snJ{{*FeWPRfvsEQq9Y_Ys7IhQ}ycC-Zt;O8c}9NllxitJU5?xUI$$FLj> zrj5C!nOE~n50yRe&+?H={AmEMVzEiyKh_uVFqu~fB+BgrESEv32{KGHafvs}+lC#B z*H4u@z_fxDH6c~A+(AqiFnh#a;~7j|6T;PAwKazn(g%nHR}o!g`ZjQAgkXatqsJkS z!)RHDRF8*7rPk_dXmlh4)Jg8Dpj*ML*E5$P`(@rvv%}g{&6}x+^Is|a{`A%{2<|k-mtQ>w$!G^7QDwuU^ z>23J%07Uu>f64OQ{d=mr(sUXepF1h(rl65vZUvbuCJ*nk) z1WIUksbD(RsC*PXHC@G)BnIgzvYN8?Tj`o&b8F0!VTA)s3lgw`U$mS5{@Rh=i~7Fc zQ2m7L&|7M$l8@(>+YU$TrV5sP-I<7^$lqDHaAUhH23q|`MPR`ik|nK-?SiU>tM7QY_<*&ZNwa6}01@(0 z?j6vlGLC~o?>3iVIeLYi$eaZpe(EDQpw6A$=e;Hz0tVkIni0(|Uhs|14&K)OmZKp9 z6gsTXKCib!iCCd^o^_6+L;*?!CzuYNs#XnafUqfE{I}E>9}~_++*_0d;FoI;6xt;G zbgFKVtSZ?AQ36?KhtyQaA~fiqZDJ7$dHeKoh-LnTq~$Q73)6xDTzSl_gnr?p`}64q z`2))2^J!19OjUNl$;rhv{#1{)DScEV5#@4ZR5QgoOMsNI(n{xVxCLxdl`f{y$h%0` z)sb2BRGCRuR@CBrOXT!ig&OdIs$20Hfv(#@DBvR zML#5R)XkP-BzpQI6VzMY@ai}+dHL5f0W3#X1ZL==MTO;bK;Sc)SLsrLaBc(Wn4Kg6 zs6y(i$8n4EUke`rq+9T%<#ashvsf7<6&xHGKnQb$#vnLx8sQopvM|wWacx9#>fJyM zXmRQ+ogy8xDrtezK1sF?1y(>x6p6D+pQR)0R0Ls!9fG)5Kx@9f+@~fo>Ap3$1_d}y zK;C7XZS`LL{%99-JTQp?jxGxXKAIjiYA2d>k>fs5Xgc0`Nb+O?Jh-z%A24~G1{=AS z1)_6c?89<&3Bk9_{xU{(KUl>&GI~t6)^2&2G*_L&#Z19<4*W(d0>N&P%Q|1xN9kj0 zobG*i=ol{p^u!9Uj}Iu$_P5uCOBih>F3 z7mW*Gwj=V+Zk(dKL4w9GR%WK^sEV z{XJgkB(+sODqc6vMbR>)L-}y_r)C#ZOY2-m6H4+NNJKart|fv~5C9LMnH@Qby7GDX z<&>iY_nYS+cBRP@cqX<BKhcNxz21K<d|m?OW&$xyd21Obz)FW;js?g0 z_x@HNk^h_`Rv2UGkL(u7QcKFzuT8scP>~(it@?*_$vbX>zU`Tn`~k4*Jqo_Gcos?< zz(1DC^lkRn90{$4q>qM_glIwnfbkws2*It1gXO-SU{Qm{V<&wS4R;dtxe{*wRg z1zMk|hrr6Co*`jRpbz$h2f9&|iynNC@O~N;HT}dVvJAA9?#{gr z6l%S1_t*KK%s>4rt{nF(`w7C?dQW(Zd0yM}w(()66%p*}4pF z3R3}+%JEpeRHb_!LP)K|5Zh0KX$P96V?^qK@Qq)tc;h-@*O0$&3w>?b=n%O~&g}58 zsJ2)|{E>3Z%0tKM&49N}-!9Srg2Y`=u=u}*mM2|e@IkHLw-H5pE<+rRH^}^q(&bC7@Mvu~Mwr+jrAbZeU~7K0*|FtBWgp!a#J>pkUO|L+`~q@?X7q~9-gh(`JwOz4P>;pY zyDHiV&oO{;^T(y6jx{L9a&jmyiDPA3tMSffMU?I)DE(vGYu-jNmQUE9E+3ISs$>6z z8~{8O1#g*T#K(+cw${qWrjWjD?1#and)`jTpRL8Nm%nA{imaCteU$N_pml8e%CiH< z+_v5YNxdmKePQnAiR<^!@6jDA1jn;Y%#A09=lBcZsv-121fPy)lc^pw)siI&kKCGt zyoDz}maq5R3sCt-5Ix|iiN^aukj>-pERgFprxWtHAokj+4OyT z1jMuc42g0D!B5NdLYjeYFXLu0!$*08^#&>mlSnJILLeqBa}S^ z#RfuIuO1_WzjRm!UTHs{>93cuVu3KmGveTL@-xV7W>2JAVAwW{M(!729^|#I{+n zQ*kO4qw{_D_GsMhuW$G0G4_xBd#(3fXT4|7`Aoc&k?3*#;Mj#gx_jj%`Lg}ph0)7f zpNNx8S9-U2w1Ev6f?X8lJrxYLZGn%TCq&oF0 zI{9V3Vbho6Z0@4Ox#wu)8!0k+O~aiV?;k?sopIRh5}&j;>wI zP@{nc#tx0X;zY5}h00HosFx1zzgB>FMSotKB#x>M0rbonMWc^G{k-bJA%&tyd-&VD zC$4@D(R4fOFj!+;=>-jfq1mT{v*1@6npZ-wYmd!iUvyyU@jG+!rh`P~u+3HA-%?Gr zsN`bq+SG?D558I+*~WG>P8FY4w|=FLrqk;dZU=(~gT82wjy@Y_bN7Bk5j3&ZhiUet z*ro}agS|7<44VEq~FZ2i6CO5>F8wA{c{z}-E z0M&`r54qSS$uoyi`a$qE?tz_T8K$RXYQ-Y23n3u80@{ltXcr-e@5Q?}-vI$;VDGY4)r4=U0k z3Xai%?Ev7Y0x&#~d|tx+Y#_QA{Qy8i4Vd7AO94QElIJ@k<2NvhLA@q0M>Cby{Wh5) zrQGP{#Yk4lPLwmFIvpSQCO20YSiUj zCuf)sxC}V9x&mvUD*VVYDbZ>qOoyiY2-~nce~heaZ$&?3BRrTX8D})LBl5|Cq%#cU zFh+;W+qdkYga(PtP!ealwrD=*=Cv>rkqoq3{#CsM^y3FJV15h3e31c_X}E)o9I9qIZgew z=jI1B3&wUusnam;2ze~gUJK;Wjp3rLHN<$wjNyW1#U_3mAlv*RAwm==R=&$-_ge& zr1QgFsa7YLibLh3i59+}R?9s0s5CM5hN?e0V2g5f`BhEG-KwgtTQo#3{Luxn=3P}A zBVSRK>X?8&l{9k4)yJGr8ii;bMj-AnPw(;_vb2!c2jlKFG}(GA$>ce*+G++uXBDL z$nnbrghGM{B7GT(L@D6`KRIKJg<%6Nc=%g?a_BDm^+>4k!Qt|gV?%QLL%(l<(6*dp z2NLDJVrKZ`AnGQ>4rxGF{yRhALAqCs144Ii`jxe}vUv z@4RxhHFI)WQ9L6&4zAl!01@-IGjqlV#bHVsy`XIQ`E3d5ItEvVTzd$C%dI3UBi6W7 z!$6{uH*9YdZ!gI`Q!bIl%+u2ClM4UhQ@8Z0GFgBH%^T(E8{}fITfi(z?}_i2(oO#6 z*&Cvq0vP>+sx7(X>fNmxVd%ovwstgu%6S~sB8ud=o3AbFa#c!bpra{*S7y$E1$Lkm zF_KXs-)%LzzEKFOAA#jTHoDh4}0)oq3`h*vr&L{R3(04rb&){krsWzsa^#UQT%D?lhJEE1~B^ z!Pg2Mj3y2-c#jkcR-92DJ;bC58x_eF0zKa;HID~cpLMoDEp;fj2)sRosaXwOR%V^1 zuHXAbZjMnPEP&dHyJ0a&LIr3EwRzTH8%IFcEj*Q!K~%TW3a89>uh4@?5X>{4AnH#Y z{--vXD9nBXY#ueD2tieHJFJgQH0J(Iv1Iwyur_{m!ZW6F=!cjFD?xFPV>!jBu6$*u zGv4rLF_BQBN;cB5XOE&bZH!BTlJD-Hd6w70K!U{S+G?5pD86@8RqRN9K(v~1Dz=C$ zfegm1bp^87uBnP}>x);1Y{wq&9?9p;K==I?1*}Osb(yU>DnBFTAe$*HkXA9wb4dLu zg*r`AN6g!nbdKgE8pg2zf0$|+R;%B-b|mb8GZP`(ou5@?)0_x4hA>jF#BYS> z_qS!WCSKC!cVwl-E&IX`;}ivp1USe6t;dwONy}b!-zEO6#LC6Ea~13OuJYa zCr)Am$&$$gDP8%27>YBZJy5d+2FMb+C^roxX(RHKDR*uyD*s%=81xtZDE@tRqG0_k zo{H0(8NnpXb9sJC+N`vaTI1%SopH;U6r{p_U$1xf?EJ@DII)1 zzR_>ZRJa8geRq5nL{F-Tu(Q-U7WAXbs}-Z1o)4dpzrml^&@V4KFPb%P@%(%OpU`P?wnJKDcR#<$94`87$-fZr8Le$nJkgJ@3MGKWI-ZJ`yYA3o@ zJ_`GLx@_}Ijui+Jf6?9WK$3aYFm@daMZP$sBu=R+oG(t6A){&aiS!SJd{SXZx-s6j zZZ9I&ULpVQs*nFbp2$`E<+vz}EN~vm4Zb+1jC%X~{?G|IEm+h|c0c(g0LoOJYAUd^yQUqSuH>vM2JC&8S_5ASuN9!BXo>t?j>H2VV zj0TpcEdVeR{YP_ZSvlBhI42^e!&qW)kYUPKTP)Y4-{_h!nyjA;1?ee%o|do$NA}}| za4=lRp9|r8-rrYMwK?D3>{Ae|N@zrKEh!?eMCRxHl@i{-5SJIfN6=!6NLO-b- zBzyFb=GJlL>niP@@o<4kPYI^vheJ2ja7iv0@fNC2Kg9po_)M(* z@F#_TBZ?SM{w2doFs3zusf$Wm(iq8}#)9MSZQpW=?Ne-Mc^GMOJIge>s|byqH@#w4 z&Q-MeWs2f@m79f6`1I6=Pq2g&z)<6aiuS4gQF011NxkT4#VvNemsp0Ry(klPX~I@{rBF zfm(f!l?}=5bBI$Ra}WMKnje~m-UsfH;Nh3sV*g(vy8f^0 z>ED4S|BYnwKh#s|S3Nm&b`>_f2CQ3 zWwwfyqK1MpxvmSaSy_6Vye53PE%-x?hMQtIu(%91U7UYHLRr;t+YO5%PGlk9Nn4i9pQjT`M)tld~$Tkg#^_Y2#?zU)4t3LKJR z^!FV8-X%jqWq78BX^wnL^lVW9L&hFqGx&m3;Ssy6v&SRF_Q`hsw~7qI}11l7>osN@gEbJv0eP^ zx^D2@Dne{7Qw?t?8D@ZTaQNBd^VUTowX0pN=6b{gUrVpI-UCxFcB9j%%%*j%CB0>G z2_pjg)FyLcc+67@N%J(NJ^QXw0#;K9pQ53t+4o4yR3I6=o++`ee)xEIilcEPxnWa>f$Xqql-wu;9XBxO2e_C zffhm+$}E2aK|ga(28IUFm{@`iHQDtWuGCf78AuqwbtNL3^+Q(J>A5d!tQz>PyBoAu z*uBnnUQcH~fXb|Weg^a$0$&|@9&=oky4m*DiHLmAze%oBa^KiPhVoG#8SD3U=W>)#Wt^z>v@K*3HAjdymm+g0c%}6 z_Qm*ZE)pH+EYc`abf%G{;k2fiq#iW;AQJo)kvr6;?W7OXMLH-9(QDO_niBjak(?6z zHIY*2w-uy>YD0n&{B@C3=wJ8uJk_Da=(YOD1oYcRQbCoW^5`ddlzh5BdR$l$Nzn6r$T?3yRe7DVeYmR3 zFs({cPQkipS;9;@pDI(qfXZlEpeP2_{%Dmpy)cHHmoZI1d2||Zl=ez*lx~IXW{<6^ zVq}NeOBw@LuppWjD1-6$sfCtvS5V{WRz<^p=v<=_CSO_N+qDItmv-QZPJ?}SxoR!; zr#ec%o;u3WDt16&w4|fM-nbr4Kd0o}(5^XT`L3cy&V-uc!It7+w#F?RP!2=r1f!e{ z&T2QLiW|*IYglK~lXJT&+SO~=+pCa*2n_4bIfYj{Z9u;o<8Zr%GtP$! zM#i6W4EVZ3hWh=LWv@8ex_&$jXND`yVRx?t+Bz$kt=QVCju4}3WH9x{6g^MY4y<~$ zVGy7Q2GlK{2LGg}UtT#d&{yM@RLL7fNM(5PiBAJa+oW;Zc3K|^y{Zj#UaIx)VGn5l!^o_Lp3r9T zM)>|wl>@e5=|(u(G$+@GMyq#&M5}icmmW<|)rRE09Q?NFO`a{@G?>|~?lNb*+X81^ zKg$y@DDj$sT3Hvei$Ra{l+j6bltejkhrzOLTs=!wrzzf>ik1Sm`boW0?33vSU`zvV zrKoU^C8KScC=Nk%Oo`y+uXmkptq9z*Z6R*&2!Th2koZqGR}OYfs5cH5Qg=T6`Anvj zF*YAW&*iT_6MtYWlB(27I))V>dWN0r_X8Zvgk8sV8UeThgDBDA32quA`r=h>3?r{A zT~*oEUA5-orJ=4UJ{hr@z4PtETE|Ek8sWIOW-(?c(^xs;(g$Q9Mio8wCVwS21d6jQ zU&a0|{J-;?&ws_)lo7NPs&WJ6mGBh|ucplH#m+d{eTM4V%>7^hY$!Nv=; zwrui?p#LlNzWfm=v?4AIjF8-~=kTnlDLpge<9`=-fV)IP9Jja{WUNkR;CW^qV5Ta+ zP~MoAxW_AfHbWFJ(lS#;4N!j;?eU45b#*(g3Kur(7D8u$dof+YpwT;wnSYL`y4TWW zYkKD(F;b3EZP#og-Y$Yb<7?e5iDW{rg_8<)X@*TOlzRhcZrsbEgWUl{}sit8HPCXV%fX*v3+LP^}s( zmLVpUF%!)J@^!Fmf2lPIj2q6s=E3X&zN&vKQF3csIIPRb9S}xq7bwpcign( zo0_@p8lUfR(gP<;FJNnh$bn%4l_j%EEi;vwO#a)-@kRpEE*no~Mcg*|GuHa=Mq5*8 zD@L06M6lTib9De+qc;+pO2$F#NLSaxquw}d=K78Ztg19e{PZ1pH^C3<`(Cm;V3)lOr#~Zi4!p3(gS>w@C<{RLVwyKHCLJYa*UJe?wXqvK6e}#pSXNWK*7#)%ocG( zV1S+Q46JA>j$t*mvs~Np3++I>B&b!mPyRd*P?O__oAonWg?TZWYm8MuW)vh3stnus z(r3vsK~NFJ6E>GLPq}Ein|kwY-n5GJ8KI>pCg4ShI>?ST);ASh&21zCds3V)p#9|2 zG|wN0xAwz6wZI8A*CHN?H8Ffga~*Q)S&*9>B7T2f<*ls3M$C}YbCEdHU*1=VQ6{iP z>5fN|8Hnek#<&YUT3_9l<<{pP{Bo!HW340>KTXVU@HqaQ?US#QlhilMLm#cU_E_le z_R7Xn&1jc_JjpCpVs}}`eXpQwRpq}uYDlW#Y8@3urohN}{90V2K#~53J{MpSCE>g} zT%BfC3vj=Jmeek6C`vrGRC5N}=s zt!OH0m)L#-tsPaM87``8ZrO(wXS>OPRru=nU0QDryJm%y>bVLml%0uVSd6-%Dk;JC zv#dbNm%}9Bc*|4iJp1}>D&;!Q86$7A*eLXItm39(jep2pss9ZS$JDTdb<1`R`B}_+ zeGo5jmwoSS0KBX?o#;9s-IGk;y|1IMlYfy8w`(EuXh}(^aryCgM>?8X({r39)%|6_ zU3Ase%hL+=0@2DVV&3a~YGko8K~B<>1Zp<%!bFJn*5fK9*{ti0W&EiwKze~OY=sD5 z&ZNs~7H}l*a`;8tel_!vc|vg6^RuwT`G94p=all?!*%u35`xQmHyS^zz~>uKQXlbP zI8FHdR!-Bc^;4^!R;Sft0(UlYS*@bc2cdn1IC7Z~9Bk=Z`si-Nh zZyZY+1!`96?!TQampPFA=sGh>Af7FVVP-nYEyJ**kwxWb4IOc535~xeSy6TO^uR~E z)To~~+=5A7P*S2EGVVT6u99npz1L}08@nFKmGLQ~>|VSHJY1bXt|ymGmQMb2ppSDZ zPbmX;Dlm=eTjDw2Vu<6fD#$yHV|jk4Xkc?s5F0A}nH!@Yk=wuZhJzOaIw>~aTprT*e zNU8i1tX3g@{Ijh;i_yU4#C8jK1bl{%dwwA3zWJ3n=nh(Xu7#GL;QGm~$P=Sd{3Sf>D)gu`gl7JnK-Sml$_)mCBTn zK7~%d609CR;{jh~rO4v4gA94WFJ%|gU%CnaCapJT4# zO4&}1oOmp+BB}Pd)0&lL{5Y-YVA6Vjgp_RuQ8>HVXk{}K6 z=v%U)olUOLT*Wq)go)T9GLzwblbn}hU6bx{DNfK0J6@&6{DHwgFdyYsr;4?3FYRxZ z=%Mt3o!JbPs4Sh`OxScJctqG(Mf)y`okU0=Oa5$uO=bb%{7%TdZVBH7t%*)jN|RE7 z%BFch+*wcn^_Jr-OE^H6i9kxJnh!#?ehCi()vM^h%g7Ck02;^im;kKQcAN{oP(inr zXUoN$1*#FaqzAL`lFApA>e*S~yWuYmdzbnPItHb4; z1a)XqE?wssoJZldXr_;OhB7o-mrq(K^CdJ>GV+M~Z(JIZY8olG_fY18F*)_n=(^Q% zgMz-Q5xlK4SggVpwIc?MAp&6Mk2LPwTZ5k$qSR-n8moolO>eR+0}b(8aReJ~42~nn zl5S6i@P#!gMkF)(&K86Ffew%ym%NJq+<3LSbizl5^1zRvkW(Pm%vZbSM= zm$1ydbg2UgBUKXYR$B07YuV?~HCDT>QO_2{#lyG5WQS)8HeDZ|XZ0GMC51z{q-;4xAYy0YxX1wIUG-g?$Z&KpA;V3K zM<%B|n1*T=fo2TCEtm2Eg) z+b_V0Qo?oU{*#L*+XXE(J+*xhpUv7&EJcU#+--2MLE;Ew0XHzA`=B^xY|bDk(B0w_ z$u;dhb2kZ7-4yXv=PV-zMwYZEs}ys!I;x>7%P zDe^4Ww2mCYoKQT3(|t40rRe-53_CDBrup@I3zpObW6Dk zm3Hd1-L6Zl59_dd(o7p@t400wzamdtIu#mYSj7N?`~(@WYXT*iE~rVMu{Lt)Oj1C;Z!V|2ePo)lofKVe7%+2^t0MtWJ zE;s0vDAQ&f+peHK=;HzJT3CSBx8fV(JjmXDR}(Hn@M+Z@+%fxLX6fI0nEX&7!~RPy zbAp3Ix0~Dhm98S%l7>};f6MSO`OkZaZi3NO>L^ZM`WlD*YJ;*p^C#^73|Hit*UuJKJ7E;&W%We-(%yOcf2Gz0 z0XJN~b+z`-VL){262D|}eR!bvc76p2!3R4sq3Oz|?|EE@E4Zvk4**6Kl{-QZO2=ke zF2hD2`$nMTHK0X|f{l`u2}v}(P^0&3RKviOA!mgl_?151B{Jcd22puW|K9K}^=BVa zZ$~iPu;hT`4@exIGltdg^76jn?HK{6{16@oxNeC32u_l7>j4?L!%06I+k>iOch0gTz?ZjEaBUm4P)T$sNkVSgNA~}Ub2{yrigL2J zLKS5EO0fs^`1<@LO}{%Q-$MiU8XWy@OpGW^x@?jBJ2?t2#Ruf7f!JM5S2Hk#UWULv z*(X`VR%x-qcXXON1XyT1YLXa1p&Ut;Ja%rAyt+t!Z7O#MdUohtJ9Z$n!G)QD7ej#V zAFvFMR8~)v*0OEV#D%=Wwc-?+FJ3jf(2Y*B4Kgq_L)&jlbk;qJT73|?Y!+h?AMnX^bnMxvpsHH*7*)O^I19+?KN; z>WUwlT~8(%K58`-5^kLvT4lDVnS-OK_hj$_7;`fMWPPL+nRjZOGUy{G6??B^_|LOe zVT#>7Nyc*8pCt0@vO&2UsZA|?$D^`D5#xNu=4XPL`X)?eLDea)b)o{DcP<-4FpDRA zCcGp%GMhkpW1`f%A7D91GM;)S86m?Sx$CBUDu39=lYO+Xr$fIT3nQ7@z?4GC^+!z_ zGu8#80XXOfIT|omgYy>>s0Fg;pvp}-^dmU{G%Ev$OVkFH<@e@b{NgZRaM$9p{C4(f0NXp1JxJ^9{gbeHT*va}$*(ZqVR7M}#}ba17a%ugl+ zI6Z{&U%GP(noLdl`0_@;b(dR=vO+2*M`@!?>rU>#N4%I5oUnP~l>tq!I92a;FASO? zjg|os!9kGwl=u!Bm|J2rXXNWv$+w^ALxXyI43e7(0ShRfQ>eGkl>6PGnF-dNg(_c| zK0Om5&{e8gfIn+0?kuT;YGXkQPMsfe`VNS9o~jN+!{4j7GXx}>vlvJLCW{5OKn9pu zaHu>8#!W;=e!P)=9%h8u5FD=_9ktFvY26|OpAf0d5Fr^p1IM|mK#4X{PV;?JG(nRk z^^mw9RlO|%gPOEeKq%$E7gACpkKF(koFfYPR|!61WmykTldx{~7$P0X0oA133Ewc) z8tl!4{q&iDuww4&wf=Bl9X9r>z~KE0Qz$Kd#4SkAkNaPonZNPZHH)i+69qp!F=mF9-8)emS2O!7jA9XvOtHAI@cg{&ww zr-|ko$ns*#iEB^f>L92a=G&#*glXS3Q1948@V!|DBsQg;$dvXB8{7~GMk)gF{y1|z zNOZfcE0zKn(#ZX45NQkIQF_bFG>pmBV`vVME|}wGGb)!RikMwVy^+cP3P=xg_(F!c z9ODiycI@)q<}{?Z=)+m5WbGHVdJbCN(&;7*!y-SjuNmP}2`CVHV2z?-Dt`RFwGlHJ z!GUE{=JilThuui%8#18j@d$c!&TIlxyuAvc>8kHZPm`b=$5?N>l}#eeec<-kkoAV! zl%Gi2f^}+`IBYg-892Acn^XAiol@-(HglA<@LqsvmGS$4UAp?CuZ(S;`RL=md6G_S z*vHAGqG7E^$+=A?FkboURwUwqI?mNl77Yn|5Ng^)%|em#6~ZqvSPBm!A%Z4a5cd6+ zrHc45i9!gmcpQ_CS}QY7shR;dy=@BLc>i7^>!4{H{8xS$E$jh*!Q3Ni8G{KeJU~$N4al@+b z;J1}Vy(;1TpMO)6@YZZXT|*)xYHn7#0XAvQoN%n5oCM-Dqt=4Z^;ddL(arEXtl@g$ zP9{h#P274u8s|qfd{JsNRI`XrB!|1Bb6`RwVjt+?swCW~pP-}rMkay*Am=wu=3_>p z$i2akZxN}-x8l!!$;Y_+On4(H?CZqd@9x(n|6sVI|y_U7SK6Db7) zYD>HRlJr?-;FSS60XNqq9I^>YMpVP)0hWFn^6}(oC%7LRrc-WYBk(2pZaF(TdoA7# zS(Yp_%+3=mrLi{-n@D13C>uy%PjT6`H{I~{Bndw;dM1N&bADWhQ7u#ww z7?()bolMB1q(@mi5t$wuC9{i6_^_kwbGXJW!XIOf3izw2&SVz1QAMc0{I+rD~ALZU!P+Nr8WVk_=*bz9ZkP=qf;|vjEU{%425{d+s0VH{eoZ?|c?L?Di z(S_d-nEfO0>0c=y1x1I1SH2?p}#$o;`858SDH&3u@pBm%7^1|g2cZDMkhmYjFr^fn=h1}1Dc1Ro*4#( zl4PUXCbXuByoBhA1!mrfpm_`IF)&?mjF;5hpD*-=N?m@eGgZe@b|{}Q33n3r!tu|* zg&VGksO0bYeTdL!Lb9cYKiEkgysI47Bwuri`TF(x^J2b3R5pkAHRrH_`VlZO#;J(#uGR-fAh95LA1DRVed? zx4q35PHd&U{fh_NRvenvjid4WPxvGXJ+_?QsmmlHFpj|$%#I|#P4AZz;qPnDYI?yF zNy1B!lz_;TehNj9c5V#Gs72%CC!8r%p$N30vxd}dtr#|wTy8lR)--E;G1Nt&a)4N; z%5)qlOkFyRuM_un&G|~U`<4qUZ%-1&+h-&$&x+>2FwaT~p%YsUUu$m%OjWG5j>)x> zx)Fd59qX6Cd-fiFd{D6IF6$Yk5Ph5Pb16c2<|+q7Q~bh#8Jsww>td|lJzSc~_@9@% zR>X)cM}50n#s^)0Ff$UePX6Z&%ZiAf`!35uU~*$=bd6k#b=|`}ZbK)@X#5GHW6yI+ z`ojA>`JwJ8^5|HDsLnJne_3Ta7$f9{GyrKGxQ>{seOvpw)+l_tCO+Rq^_{kd??cZ_ zK?0Npy3-M5>eHm{%XkHBpfmJF$CXf;_E4NtViBqf4GEJ7>WbtoTjk^CS9W+gDwMQL znuwj%_^`g~NZJB2jvPGvHyk)Et~JxUlcMME`PR0O?ZbT+1qQb?JsaM3fVk)7*s+H< zKD<9(7f?1chNR-hrQ&N;vJxCFlU%;@mO(MdbT)MVMJlOxYSaHtxNSo+8g~{$)RuZc zp}1R_4(ru~-W2tOY0weV*~{`Ae7p;t>Z-1{%gwUJ*j7o``_axoW2 zwKpum+fUH_Ke0AE0Q_r?R3ZL!Hjl;Q1HwS?Xs@h+f$CI^ZpqG-Ym+7~f-+TKObXxI z*{c_ks1_l`-^ZDLvnWo928H$t1<@kHEU6pusA3kp6?P(OC zhMM_I-rXY{1M&yBBx&RZ>enhmUPLd^NXD5@i4z40W0n5!Y(wSDdVXJ_J0{|c)gig; zO>--Hym_G5WM*JeHyUM6nmGHe%9k#w#t`Ul`LcNMdB!D#VSW)ZX&Yw@H*CC9i`jc8 zXSnwg3s7NUlrN$zGu*kNEP1*)C|p@>KkONM-1fd(*f175_cnSJis*3}Ufk*iP?LNp zoDHqYq`I@woLjnLKOSuj{aSD;rfwHE+#85?GBK5S!wyh~wNuTwPp1&L`7 z_onL@%?v{;{=F$Vpy@IH6YL){mv)@>2oKV4-};UJl?v}mqW8_o#fr%UU}9!%!DQp% z&1B}}V!`yk0`LJW9L+5p&Ak72(4{n$e~%a4)OZ6G+F!@RZ`oFmR%d1*`4O4JpT=54 zA@`HU0QCEGh)^Gq1wIIg3S-$ga6H@F$#NlKw%zkv26wbdyh@ZaH9)_%71FlGyvm;R zS3h31K1}L&YdH~*JYD(aEEmBfTD6z75*(#ckG#XVzjvwT36dMx^xRB%sY#bf%Znq) z<{>Gzmlj(!%^IJrUlWm=_8DUj1ZZj7WOo@~O0qCTA>iD8hrCm(pPLVr+rn{6KPZxJ zS_V0i$6HzKht=$2?D25C((~@JX~GtW%~kL7b?f(bEbdQ>WT+I`AK>W~jCdRwXZ{5y zZq#C3i_>mh zCZ9jBKE8cVy>+YjsaMevX|qu7Iy1#*was>xkiXLd<`o|vF-oY({{*k}Hlk@-6xiO$ zof!1n4J-*8rzM#=#s(jfXj6;LZ}7%+Z2VVKv1*!iyY-UO1?$vnT)kcda4;nEoO-QM z@+`9H`tAwmN1=R}ibHm$u|ZoYVkzd9hS{t<*x@$n9BAIehbIXHd`I5HNy* zT~G)*igekiR`Kge{J4XRW;gb8O%|n{4lPCrh{EC z{#%jT`%v)EVXXT5RFmxc;aidV`{rBfLXP@->eBvU(Nu8q8>xTBQt%QmbqRPVi`7xk zN=fkp2M4_|>b0!QoD$TgyJo0KToSTw_idr*P`!OBM_m#UBr!8U(bTZ3=ew$=tqTkp zm@lKYfbv3=Uwhw$xtY1Ksj>Mt5J}8}b@(Y_Ofb4cb5moGf5zg?%^0W`eRY`NzwE*P zT|DT2JP!YZ8rffYToH@~-n|Rq)n%7R7lt{9heW+3DO&h`j7DLTM1vB?BB$yN7wR7h zRJE|K`QyAf2BNtkac!yW?nBI3 zw4a@v`WtKz<==nd<T zrAdrBxkKPBW~LO%oyhbDNcf=)Zffw@c(AmH!!A1kF7;70X@Wu{ z!2+4A2AMYSafUq02R4U}HY(Wo&o(AeXTi2LYfRdMR?9McCLz`N3k0e5gHA(RcwXKd zz{5ODubLEEbSa*W+mohN1E&lHUe`?!`UUTPGrHAwTFrX-8to~ZmYxmz+a_^HPlS=e ziMh7l#~(_$+VOyXngb*#Si}Gu*w;X}S@hbx=&Lunnyeo|!HCp62G5I*O7tQ~!T=1& z>kdT!N^0$-pJ2;$|LAPE<43U9|Ks|y{ilCL99{pN#h<2ZAO|XfF0lBL)K;41 zZ=*afW=pi_J1;l4Xo{3RchG^z+jKS20sCGZOnzEOG?x&46|0)qGc?d`H6w76cN7rN z{ry{qFi%`9y9cYb=tk-hJ+>;NzPW)t*>zDUzgVN{UmsKYuaIy=rycRR>ml ztz)Y{u_|SC>J|HT;X?{b>F{;semICnohodH{1_826+6ied#|sq_yLmMM)1wwX6?rQX}s3RH>x* z1z_QCPWJ}YRPUJqd@ae%-zAb5uBu23>`K7!7m{#t1EK`G>LnxZnlHDTy z)xSg--xvp1ymSj5is3k{z)URYl4}ixpU@s8T#4ez+^|;tM$gJJMT%y=A9I*F0{Cs2 zUei6`{h^cBbl78XstC~>2A}=KmFPV#4m(Du)_sNi$1Zx8zph$*bx0uSzq*!j{-<|Q zLHxg7$Nud!?$-2G!_z?jbdYYcSxfiiaHwn%#7&n%PSUigPLhg&h)%_%Y4vE<8Q8bP z;^b=KKG3@HD_dpUc)xiaFXYH#nbx-*!lLnI@=41Ek+YG z4Gs%qPhniGt$te?O+^cj!GrOOwnufZf;vx>Z`<^aGsQC#{_A=U&oa)8BS#u9CqvGh zD4s0C$4KRjJ9x<*#+4PzjN=dyPA9*BD>$M-sV47etvwKdD>zsajv;T?5y69i#8PPj zhK5UMCK3|mjo>ZV3Q!A)@#MJJB}4d0|A(cxfI)z}zJN=hqru?<2WJ!jm*qRqzBP~< zJkzz-Dt`Pi0UFhHUewf(I~7YpkE)nB_XiHgY?QgZCbqjhpG9D20=?UBz0hAUP{TtCVCWYrvBxnHfnHYrsS$|wZ$Lj*a!p}~JNpv-h_k)etw(I~M zeD7-WmxuV9H(h=Y;m0Z*`gR`25+s33GEH9@0sxB>-YkIHkA%3!3MBH4~?yhIsP`7agb{AP9teAJ% z9zU~RcA?$V0hPnOynvQy*F)8!hzUoKB#$t}xUbA;G{r86~n@jbSYk19Q7wZRs^Vbok_9ZUHD_M;5;_@8V+Pi=Ft(D1V5Ehoc_R@8A^;6t8x)7V7rv>{eAb=5*S`Kesd=2=t3QIb@K$ zKv4qVqhfA+saLl)x>WVfXwv8eN?b}$RO;@N7pg=GtsZ&j=`UTBQOqg@+4+;BX(vEb zg`_W)A}MVk>XNVRIwUs5HLwUB!IBTO(Z`+HQO2G59g+_sixzg`s)UYMb1U2^@4=CCEhZAFROh?H~?ujQO_{%)Fl5I;O_ ziICFzAwM^PE%PqrMzmiPd=f{$e`l`Xvs$IgaSgjtY5_ffH;Te3ibALiQ3c&j%`15B zG$bsKnD^VpcuOy}}%TZo7%c-X<1z9f9i! z9v4$MQq2ydalo^1+ze;#7v3wTuY3cyBz7-#!)JPrHMHr_51i`*##G`S!`n<|4|<73 za1-_G-XNx*AzsPkG`H%l07E9(WpWmxe7--OIFIi z|8t~ulZb*|`wHN+fd5x#=YKxw{C{oP$kotOTNFkY1R=*vpEp)P1Ph#)2_W5lVGUGF&G9a1DZW zmUgU`Fm6N>|6k++m6Dx`V*4MiZj@ zF=tGh#d}G4+_nFyS2F#i<6EbOUfO4dIy|s+`BaHxxEDW6(7dt)LT5izpD4g}*+;rQ zSR9w_MJ#{yRM;rG9%^?1N1yUiC&IW+W1(N&dY*Ktc@8PXnq=RLUbVPrPH$8c#pIqA zh45=2b*b}Zj4dKSs$Cyrc~P+`2Cbe(eW!vp$dRxwX-ru$ccW)vzjzv^?D1CZ8!|KEHca>Rjx4pTGO!C5%QI>Uoi#;Zx92R(%iZ zyV~r_mlq+^S~hfDJEtAkLwv3XCr%iGee{Qt?~Vz`pzn)wI4GUBra@( zU_t^3V0c*omik{np_q8%yECfW z*$}z0{3sMj8!a+B4p)~O3|u_kUaye3undq_WN1pX)w=wBh5lu<{HBS=^1#q01mL@x zKdV;B#X{-IX6uD*cvC~9<+FrSZpe0;%5=Vo;h3lLc8Ds9oBSQ&8>fnPBJM6l==>q! zdS_94>ER)wbd1A@4i@fWEA{P3bIF<_s%d(`!Pu>*;g!raClHu;lg{+%*(*^>)nW7P z#;djl=QkIRxvt4*!u)Hi)DlFMZU^ZF6h2}IBhHwtTL;3BgR5Wq4#D8dZk|Nr zL`0mQo&34F!f=P_-1=+?c%nHbG!zUTEk8oJ{Y;L2~Hz9z$ybImY2K zYo(@TSx6|mWhaZ;?j>bRAi|W~{q-H1^Gs5lL`HM%4@b|$(>VTk)eT~cq;|$na(CicEW9Dx?i%trAnB@QMYG46g0LM2qw*0 zrg3}~dVgoUq8{du6ivHj6fE{(UFINBeVH$lw<x@VRZSPh`AlR(d+qsz&EBWm};}}lD@(-VRq~< z;jo@Ulza24#g55{g4EaNaH_|7;;u{_<{+Ww*Tt?2N9t*#+`z!tpKkMSq5Qd?B@gnF z#i#x2m$w)U{T3Y>=^+!9x8@Ihn^y`;CeVj8H9f0i1@Sa1`;Pv&VG6EWv#3lChz90m zHy1Sap( z#P#xX%fW9^fH1R=`nTgmYVk(=%v#LSZRa(%!r#6u+NY9X440B6U6(O`A2MB1Km>}X zhO(bMxlTAw47XW)zVA11e^u|N1?LA-U=%ZX7VTLeSCDtB+y?wK7tHaZ`u;-MLr4+) zkU*>{{^3xR#0s;ki?-QACX|s#M_$wWeI;t`SnSl1HmLfQ9nf8!sUCFVuC;`10K&l`J{*DUzm^I4&3!1kjkxQj z!BnU*ta#3tEsFz!wrSNEt5a3Tw@94~b*tHNZEQMKT!OACIjEUOEX7y;SlmwHQZ%+V z8K`{BkF7tiZ)`M+XaEklaP6!$ zlYi+urNaY`d$pJ=pjbJ!UNBxJJzXVVR%vL!+!;$tztu6QdlX+NR}Kdsu|-1f4S!3z z3I>xubp7^QOy77Se-a4E7^Er@M^vv$-ZC8eDzjpG8nyYpNKk9|bW;WuW23~+jc?Mw zMDPr3Y-&G$g}vwsKWX$Fu>!sQS>PT@YHw0OoqYjUPP*D26RFlE09@PV;k;cp>K0dU zj_J_gV07=XKxp0Ei7)ljaWRETzs8}L_rw54bQA$Q)slrf@DNsytV!o&8Mu$*OmIB1 z-Ul5+Q0s~1;WL?j@zpD^{k27kvzusl^h;p4)!w)78R4DkWb}8!BEgIdWU#I-Fi2!U zC{@m!SRH>2AUw zFYHXOAoTj_Sf}EE2MSF>3JGOpbpykr(Qz>erET7@o~R!mVa%RPa^ui%rhOg?Hyv<9oSesuf7=vRi~VGJIlvXaw+8&y_}l8KL~dIKk+7z`*Vcs_eoB zO!<7@sQ54nzo7^tb@E&SaB+c1{@lnj4%pq4S>G7T*tU_lmSTQ%lDOuPxYlB7o+$i!Yq&M@)d{(k;-Opy5UGvo*N0`mi0;s6Y^?M6egR3FeB@=7=@m~pu79oa zlrK13QBzRX@rR7HoNRjZICMK)X+3>?&e-$-o%X@fQ;)eS3~SJDC)3dw2nj0>lhAj^ z-SQ3(z;T1`{ro}hO~7?S?sjkf%BS51Llpg$YLNi1&M$>Z*@XHsRtJp;;MmI*crkx~H z9aaiHhrGfo!way0v`>|d9WerNp)2eC!4UvEm<8ZfkSgn&hHInkKyvt1Zm5irJYyyh z@c7J&bR_xlmg%VT@R#Z8@~g~mBaNv?Oe`m8Q^1H8tzc2D2oQ4??--Yb4A?B#s*jos z)nhO#&TkE;=MUC2%Tw`rkY!Yx>k5f3Z;_}}aymTaRrT$zxlwgiRHFRj7(l|vQw`KO zAXBw9=MtWFx6_3qBqZ8}3Wx0{Y+n0YyXyU%KV-94?1YJrLU&DCiMEXN;Uynu%gd7?f)=0xyEwI|C` zUZ_yu&`W(&r0XcvXjs<|7B29JS-#@C{w&|RcNQYC7o%b*Q3D;Z2Py}1+jIYxIpYHJ zx$I|X%THRQL9eV8pEz-15Q@S-B736pFw2Bib69}qyEmK%{Ir&vKsvo#x}MXd$}1wW zG@sO;TQ>Wct+ys|Mi|9CC}J|S#Fd12%zjqP41|l4Hd8}TmRN3Vs!S8+YcNyhhlW&&)x@KP{)@#x*1q|5A{iKfnn32%q#oo`5m4pWkecBI(5cC zG!}jgB8A^IytpzvmH>)MBAwIC1VSz}I3@dXZ>c)Y+BSylNKUEZXd_F$J^U$YNS_ZIM_F zg!~|~BdRy|9G%TnI(*V9rqkgv+5v=~^kBKoZ|DuxbZ-ukm8E6Ee4D?HwK+J!1NGM< zP)QI#+90lW2EPq|?F|}AzZ)HPtQ<}`xze{*(iD82)2n}L&}U9EHrt_GaLj#inxs^v zBRiKbN;x4|fhdzKPatYMdVwgj_P`OUBs_DWzZ{=}xDrl{WbAE7q3VyMYx3f=+}X)X ze1O4e$t^%VXk0H`wQj0oROq;(2y(Z8xFR!Hz&Z)Uxj}g|zpAE;ukhLN-txV#aqDv2 zG!OhMe3IWtmJc4inESe@hX%w5^X%|lhakjXP>eAPlA5l-VVFSw7&vIoA5=9c8kirg z2&Q8+g*xv#Fkxtc#h>Pe+l*C`rH3&}DORfG$9^zdxnaLrbW1jZ+_6zux(GE;fPOz) zfIJ=Rq%4@YZXyB6ApDJ4%Bw^CGYy_SJ+rks`WL$`?DZXTIE{k!(|f*1?0f0+7I-fs+I@Sa3Oa_1EexcKlm?w)P z(NK_JuKXwRqxW6^Z~G#V;tWG{`+%HGatUhJsZ*yhdK2nBA|9Tu02+^vCX-v4m)ErV zkB^3zk0tGRsV(@{`VOx z;eaRt_q80~$*)bI@uQ!P77$kV$V-S1p{rd_+ZSdPN(*`qURfj*uXY*!2zd{VET1Gn z?WQQbmncB4$r=b}5L$7^Dwl+tG|tk%UmuleFJJyQ?dt5c{r!9m{qym;rUzg(LdM^f zCiFRgHh>gtuY9z8w2W3!Qz1@8PF7Blu42DEybT82fH#y6U!VU1dEW~EDJVCeClGHN zTn}iU{{nu03XZ=Yg~;K_CwT z!;LYL$NFq4w6XoEjj_s0w6XZCiqu7iF*`QQDZ1IKM*w<9W8JROZ+uVv-Tds<1aZyP z3|3pRxX#8C@r#?IQ(YYb2TNJL8`)(_b)n}_|6_qAF}y7C94xtAnGLo8u-Gk#7-TAg zeED>`Ofj$FLZH%@3NW@W?f_t<3qX{7?m$X6s_4#>g0)9(#5sHn#XQ z+1WRHqnOZAJjdZ`R<#2`xm@P+qk6p~QzOR`Rt38#HW18u=dwzU;le6jWQUoRR=GJT z>i4@~3C;1vdMWZph%UhqT9cB@PHW^7#}-qK!n)iU1_r82;lj5CW#=c* zpYBsO3mBIMM%pr}R%POx=PiVERLOKa=2LC$Nkz*>N|FsKl@C9@ixnBgTsE_7CNqk4##A#x;1Hx*Z^L`8AsOWRNCP(R3|9Ox1N9vemwKPH^_S7NN~; zPpkAnDN2zF_Pgff1GlzrHO(6=jThrp*6A%=d5Jz5*jy)wy)#owc#dqn6B+vrRwIV3 zL4oAFizlo-QCB)dKUcsZ1KFU7K9VkXA7PCLwzu>fFrLy?D02hGAFt86i4cc6_dsi4 z(intGwDmM;u;96YhrjS1a{cJ&H9+^7aRj&KN(A0Bq1@2}b3&Hk)Okkk@LW)#gF2z< zi)W!e@LN4122iKr!>F_9pCECfx#=N_o^~>BniFL?On#29WkGhyb|tk@j8}&Rtr<4^ z+}vSg-J$4dS&`8k^dfW)L=^hOFJ}8623V!W8HsB^0K!+AQVz<1=Gg+svVBRx86CRpy`c3sqz&bkAA)iz7t>GJm*;O6wd5G&Tm<$;N^Gt~ zTYC7`_C`rq{;hy|iNB-prqM~*v2n%rq!19|YQ^aBQt}3Z_R+Z8hz7U5Rfn6@9_|AL zqo{8W$Hl~|#6w3fx3Z4!V^5wHw{GU)(qUxC!>R26;#7l<6};{&59W?K?s8 zl>0d>y&%1-cPsrJ=(FQ*4bXYwZWYjZ5^ftKO$<3H4%pCpl5RQBX(nE}B6&t%4A_nH z()nNl)Ipt~*U0k^dk+kI-cv-M-A$M#z<#sT${o->9@9e*^8yf zzQ<1yAWcF&APtHSDo0X3SG^C_n$`z~=9$??g6eNF*6t31veb&IX5p@#4s+SP(FK3vS9xY zMO(sySod!z#b(*Mo*Q zM!xO{S`0D`TpP1FHXgRI)fO4v5^&9|KyKuT$?-N{qpz?vp)J8jWiKDy2$TYSC`2D4 zgfBxD$#&^v$t!+H<&8qt5_8F>ZR`t3;r{;8jgnIHKjBNs3bjYkE#t}93be+0-u*;j zUvk;XM>5RsVj-J<#Ue;(5-h&KUL#IokS@F_kS}y$q7oKp$r%(xjV|JoK6KP6;(7W^ zb6jg>SeHpy7Kv(rJ@mHQJNf&^0F9IsNYQ=|FN=z582$OpUbU&LEp0idDX&@Irs!Wq zIA56n%~irM9-!AnzdctfV$n1VC#N+QTtlJ8HusN{pZvscd5=enw)V=)B1AYJ#R#`r!J?}toNL}zrH^ISKJ+e zxSrA|gcK}EDJd}=OWipI$);>eSxdRiOmI>TF-#=mA&T!wET6Yv37@r?{uppeV}N>B>+O9E8cN zn<52{la_gfG{ORSbaC;5cURd6pX=Do(vO8jZj0${tkV_Yye;7vt37j&r)lz>S zHI*=Y9Bl@v##pSbgscsnW)y1vbdkJ^?Digg3Mqt6|%iM0RE?Z(l;*!9-R*NAc>&g$3&y8-Yi+HG>=e zi?QS^!l8DDH*aWh(1Wc-q^Asnc@pPkt$o~DoNPQ&bhK$~O08%dL*+FEl*eMxmo1YDu>@R&@PX<4E-ghRf&iKs>X90nvhwj63?QySHu z)OIowxeC*Uv11HK*9H`;=JFhUTnni9Gx5p4Y91{p;peKNIvEb93Yx`9+$azZ_s{vN zF=0zXxYqhbHo|q;h!&7OS7Bc4UQ1qq-RoERTF927MNAfO4S%_|y(=Fc^J;O=V<6*d z;3Nr@bJ2H*TYGhf)$E82dj3cvpjC*$r}!*(b_N+& zu(8C^)5K*TIFnU1uA#XmzcLg~?|CZbeL$ssXp*!0EA6l0j9pX5I6^DkZE!z;TusRT zdX{+Xk~Y3dcUZx?#>9(*2pw{Q>2|5Y3~<`QbxK?yc_OnJhGXiKte^KGAHE@!Hzc)U z78zdH${p_7e<1I`0jvk224Rv7-lF!G^1S%`UWl?7g*X;}b|uOYmx*qIQWvG}syR{!Ln^q>${sgazi6&<(acWv@3{kK+_B(pw*+Tc29_4tGqn)`!&Un# zt?M_!6Zqh*DW>raapGiE?1!Wj`VDe zU41}PZu=YMEG=MYwz)fXMj8rGQ*i5`HKdPy*(HjjB}(|{uxsWS_LwFI++J?jllNf~ zcX1cJz6%jvP@DI53f9FMc49IFOCRrzpB+WzB*a=dJ z%RRRn2E?-nW}b1yMok|q1R}&0$IzE<)0@uHpCa!cgGrW@Rc2!8XzgMC@(O|3#ehg+ z%wZ8{4YcQH7Gs=YFct5xI<}o5ZS1(T44wz-hrHBI$)dE|Se;}9)wjUiUViL!v#iXD zD3iuB5{R=W&23X9obuI4591$;nwqC<6myuRo@&Ag_I9Vv%!St#z*ky04_rHgkd-1R z7Fm=nIV#^tkLSWbAa_&QJVu-dDnve!XGCoqoLug_U`~sf7KRy4380k$ac!+ab%8 zy2=kJkb4*I`-kIJxJnNZAT9DJ%Iul$MNEomcBxF4gAAeAgV|mXP zPT{f@A|#0Q&tNOuHN1X3b`~q~peo1m!Pez!Xa^&bT@RcC26reJlP3Tfj1JPigeYX( z@{Q4?=?l3r6KCYJ#S42e6KD84qbFhs6DO!dXeV5A@cpRiOS0>&6=&`q2frumv-wL{ z>bpYboUL4^7esKd&i(<0H;C2%MXSg_jUM^U1N6nU-0ac{ZqCBVV``DfLf!2d8-W^D zIg<>M6+=d`+W@jdnW=i+T)y7`-Aik}}`&&sNXH{-T&3CqNoyYs% zDwu@G?y!P{r@r~0-81_O>%(czC&pTqv_9;W?7w%!;??7i;ay{z6uRzj=BCvpT&gGZ zOQWOxF^d=nY#i7N_wM$~p=tL}(-G(k`|Kmpqap?v(c9p%15G;{DjZB{4NcOL@nCGHH*e{L?11t7adZ1~yIm!T$a^s*+!yMA1j@ z5>22&@tl;yw8CW0aj8jTig#gdN1QqGMsZV2YmKMV4g zleJaYoWux|H(swLc{Gb~@Q<>GTDC#J(Tb8OorZMSqzpaVTGH~!khBmLtl3bw)s$~3 zcHBT(Yb9gaqJVVPzBVTdWn>BZ4ies8Q6&V~$S?(^SBBRQ(G7%3MU$~@0z_~rTzXU#hrV|skPsqpy_5W-BAG}T5s}?!uh#ya&}KPKSueRRKkP^*)tN{) z0D>BaMxZo)xP}$13iD+SH$N5$Kd-+k&1R`aPXmIjuXwmGlM=3farDyKcO_rO8p^Fg z!TLARI>}VY#pK?XIul?_n(Vmi&I&#}dU6cgwW#icXo zzT8FCkO?`9;ln#OQijT%vsUq7E_4lcLn61XDJwt_j%phy(o-9Epv8CXu1{o3^TiK> zd^L#1wz&zq0@>Mxi?k}6cAM6=>b-@+d^_9u~0UG7^3CSs?M%A*E!|cKh|E0?4|d2Vru)RcKxyjS^XE3w{sT z|EkG!)DgP+qA$gjIY^*?z8`Iq1=A#@!crT&6x84^M6s#{l%gmwGin^U@v9(2sSZ+a z71y8HSD;qh4r1SnUq^>%hF}+RpCfvx!UrWBR|)m3_8*w0H!sP^oyF-3pblw{u$j}S z92yp#r9hn$7{ludyWw@hGMU0L$s|#INcgaK7axY=xSzOXZdU@I3Twe3_nvl!FT5cb zi~7J2A)hLZR6PhtdpzW6U z(QL)ItJWyBV)$+-9hJl(FKY|TRvn*x4 z2|5S0Zol37B?1$QlNm;MJEfBZx!QdeRbd^Vu`av~47nmdj`UM90a-4P=a`g2H z8iP}^uVoMYB3M4Ls_cRA(X#*Y)Fuk)a&PAHW&M1@t0A;P=2sWUVNUm@;+L1?12{e2 z;P(vVeA&4YGb3^S-_rFKX83i%KLgcM_t!qCMj=NZwSMA zvF!S!vce|Gia}?Vu$RjXp$e7~fF;l4AqVOURgYSUQa5xo<|BPRXRi?vu~W-G3u%Tq zusIx0Ru0cl+t8rk?r6J1hi( zg4HS|OcvXnU+`h^#R`ST`ID!kLyzU(UK%!r9`?hT$zcHyi~+%46;NmL_X7SeXU4NrbyNv{;TD z$!);VXKg|UjdG&3Wnn?L&kNnW=6#N~py~?bIm)Xz2T5Lul9Pb+c`3>@!{~osNd>)A z`o7kM<*!Kh^1Yag+O!)JZr;Yh@+PvWWC_hVcVI)rxE4xbGzkfxelJ;iGXeh{KJrSF zu;5!cQAe-s+>R^#MUG;@J2jM?aq4j-^b1-8XnMkNcgw0G(7NPzWfQoZ`^vA*u-W2- zvCQIoM0c(KlTCL7Duby1kgpQ6eOS-P~g-dL$&1veAh_g%RooX}s_fsvOtZ8a6 z!anr)F`A@3_Fu|$CG=;dydDuf5-$a$!q8;;CC;zB6{VLU*jQ5E?|)FPeq*Q1;p zA4VRQ(-IUScmmRBVkp)J^Gu#*(*E$1bf!7a33Ly z4bEl-5M?2wR6V`(2EAYiU6G_M{<{;l_JK}|>XmmQQIO_PBQ!=6Yiz1FE> zvU~vb2>fIKc&vBv>=RnC#U_cV__j8DCo6ryIpZdw^bGcM{mKd3l;fQ({teY=81%Ya z9-^u*-rvaKI_bk#`pAe!F_oDVKO-#v3+0;RDn^x=WGbVIIfPJ^E+U4;zcB>3lOy)`fgeE2`MLA{7FsX9}~Yz~Oc z8{#baF$umnJM<5;{ptXb0st)jnS>19e$*K1zZgNvcITf};bOyW=6p-QB& zV(pf-nzy=x_YekZ7}39^X@Ys?V*g;w;XV+2VoeI{GJ8^i2L6o`1N#PX_#f=k@*(p8p^A(i|N19Gx6! z6#nb>-+O7YQW68aNSRG_O-$?R7N3-2?&jeJz{*P=aQ~g*Hi=gd6S8WJl4yhH>&#B(a24!SS2AkAV))NQLjq=b+V0BTRV87Oub z4po+PA8?!J9p)#un@O^WeEpXLopet~bBtD3HTL%C+QAI#s(lTHj9peeH=OTwJeM`-9x;R*(iazbQ8`#%JFnB9og!Z! zHQ(Kj)V}XGGsh>^JKb4>ON8CogEH|i4hT?Uoi+QYh{L+wY6?3O__%fz1;L;YYPy%F)2MPSsMYZrT5N`6L zrLiS}kr3!I_*C|0aS{h-NX&bIv3mGy*bS)&_F|((_}#G-?A`vnBPw$9w@j0#u4;$f zerDJ^NNqNI4(#1g5&V|eJ3qUR@2Ru5km2m!p<>uP{zV5PuF4}aMvn~mJR;g7=cK1E z6wuf|DHYhQQuE+Bm%i_@`7f0-2hm5jk+YSQ?=+Qc}- z*f^$5T2~u6=D7x+@e*acIqeaMfb>055QiYx07;5&t0y?w1{6TxX=uc>69?P@2kNZV zKRP=vxQt}9WcDiiZ6Np#I||tBn-}OSgbp25Cw*xrRA+=;Jv$RRVqtc2730J1%$mzb z6RF+ZJl$im$tu{aO}dg%8?#?-rAcZa?^%oMWJR(i9AO+r{z@8?XO=bZDgb@pd17JH z#PT`(3@k0)q%9kHlH8QdkWJY(HHzyPMG^!vm}-PmEjydGt6?}$YPuMsLSWDUxXQ5r zV09Di>+;cTtLcf;vXl*jPCSo>#b(tY*hEawPPNNL8wKQ@d+^4zzWO^0-j0Ibf8{q}_BrN*JR@eqUPY*<&+H7c6wzkeX7Rj;(fP|#RbT!`wrzf37B5o|o>BeZaLL??( z{Y8lHgJ$41^aQ;@Zem@3&3+! z0$2fsDc%p0FMy`3{%6~xhBaxe@EV=(txW7`2Qo-k_h&3EC{1hn&Fw%uP2Js~R-A$7=LXCH9R2k@S8Bx$3R+e1)#ydJ7~ zDgD2m0-4Mq2U5caSjElQEOd~E>w6yaxAg{BmBuuA@*7B^b>DFN)ooA#r zu^~7Mbz5!VVIwqgQNfTqW1``4wzqgfx`|BL>|dGaVlE?CHzOTtw!WV0lc?g7zz8Vb z2gj+YxwV_>g(`1)d;l~k-oDkOZ~3<0{S+vt&5B)u@vw)yGmXTu`F|U<`Z|#An-wP; z%pWlNWUrh+>9IXAEDfyoD|>}4ztzIl?7JoJfqcn^x~7bIA?LtC`E;qjoZsyC=Y&D+ zkezM&ljp|$C|NHKPP~pga|0pI*as4ur_ZTb36pqfFnBaUbDv;=rAN?K9tn6xL{Km%gsA+Lz{52Ds2Or?QeX9nF} z^mVJnSkuK)L+#@XnF-eY!f6QA?-Y(Dw~N$jxtYaig?Dyz^u5mN|MMgPh;3O7jj3d# zXmDYu!)sdp!Pgkp6Vg1t@vEYq6F6W=+mmh4{nqDSNb<3tZp_q=Kts&$e`+)T6OwG} zq;F~FU`iwV@4Jw-iJA3()3~$b$Ham7;JmCPhX=#L!rrM}NB=bM&Rycc2MPv-?h2ho zP8ANUA{s*+HgJaS_QBp14F07917Zth>{Kr<-^uv<_Tm2h%Qn;sssd%1vQlGpR3AeP zs0|Cv*z%Ch!T`hwGegx-RH^(KIwq+Yw^j2YXdy`xCV2A}Xzbl?L_sfQ=W8|CIVsr+ zT}ZrR?{*M{EtY*BCV(n0h$6s1AeK!|UC0D_0re}vP?W_H2^#%^qRPm2FN`)3Um#Bm zc;(hX1k@$}Ku)jhjHAB;)sOy`luhjt*gW`c$0xEp=8Fz=p7m)jmju)wf92_*H!fuy zy!nVm30g>@pDRzxd*MusM1Pc|j8z`TCX8FajdB|^s^ZPW?O}OO6d#7`Z#i5?BS<8( zVfgPZul>0{u||$}wGbzy?zx`fmU&O070NzB#m(R04-)gVGOGCzzKHz_hIYbICy7AL z-s`nNAb7XXFcO>shM^HiX;PALI-`blnVanoF#r0bos!g_&Oaqk*FTm(|4Cos|M!zB z7&$tcS)2U#kibe(4ziyXX(FS&T*uo3^!5z@VWm%cHfi1|vAS`ix8ijVfHSd`>?;(4 z5H6lGyM@CSNExur7fuzSSxAR1<8K1X^0~ZA)+6yHCYxw~yXAZ7!y3EPsw6tc8H`T3 za7DDOWq}@gVL8*r-gtRb`oKx-Hx8mRPsZ+BT`cQps^j6l)sDOLC@+CYDz9o}y51My zzh3*un4LHNr>>j$`Tb|Q$$xrndm~#Ld&mEqYa(dlVr^-oXDI()kN;iYC#hH{U>YHL zCkGM+T0xkVH5J7xSMi!IWGIm-DF7yk_aWpqH#JMt2Nq>mrf)r5ZMpX}<2pVBETf;5 zI=ZI;7EH57;~EbCa5Sf{hy#rRK!Q)ao-f)s-!l`u#(2KJp1^#uTXA~3f3*X$BJi^R zV)MQIMGw%4-mBrQ`E(GDd;M}-jjM8A3%P;T%rJ=NOv^cR!#Kd;q#8wnrjEYu53Wx! zARVj)?Sal7PaDo3ZIFBPZvoixr;Y|AM6besf|n* zhWKatMhjU)$nZ8llrtMu5082uYXBrTVwGm!2@CNSM>_n)KdT0x`WK-2pDIAkDl0Ey z90WLXtMi=1X)!vXh{qq%O_|>Gc(Ek=G}RXJGj_EV>U!cR|M-d6wtz`>e8hx1d2{|~ zvJ>iId3C<%qR9!@KH1@-L^@SjdhzH@7bUwH^Rs;Nk@@;;a#A+|ibMf2Q;not|I8Ig zVamL$nX>dmX^eO|!}15i0%9E0+PcSC`E9W9g9Cd%&MwCkO-v0`i{9qwsmez`g1DaWbaTwh)L!j2A-v>7gmqUTgEqA<@0=*766h9?{oAQx=$%HPzx3nCjDP(8Yx|0vmJ< zg6b3-%KDp2Dc3xxW%1*fk118(Ue4@!$JaXw?Z>uZbS4+5Y4OhxmtDidwZ|zE5b#fS zAyiMk_KNhBK^Du9nHuV=CD7M{>cguOObq!{WRz_P7Ke$?3|i{L5NjQV?um0R{Ys(~ z7cZ6<&4+<`)UCR6YhAnjD^ZoM3c4F(^tP(p+9mECpO3@d_Os85q}`k>=!jRTbWM|Q zRwcpgW2aqt%wIwawP14Gj>W-p+vfeusvV)zDYEj9%hOk+9EpGH#oDG;Yya_psmgm| z^D++|P>pUs=vamZGre0_fhOE^7eh_uv)J_E7GI~> zU98!CmQ3&xXz@C8%io5I^LC`&IGH=P7NLOT&@N8n3ZC{Rf@XVuu5MC|bR@1aHWV=3 z#)xG*=UAl>7kMt=6**un$S?iJgjBeS{}2Wt5-Nx4xg=h6R7}u;=&r1zU5^AlOFxoa zP`hDiNoxbkx%st|BF>_y1P&t%bSL9v=A5fChyTH45jSIiK<}H9`Tk<+4?=a_)1F#m z;JGPJ1eHr=sFOmfE=a#$`0V;O1l6k>#Rumyx8MZ*5l(u4uzaHp{<>r8KyeVar4aU> zk^BRsbDX)>L;Xb_v+*sn^)9)0-r5@!uHqz_9gW$fnBQ0&H!DB`sk=p1GFkoH6>S$5tUEYs4lFMqrmZnCH@{XE8r?^K(s*S68)LR+u5X z{B?gS*BnbpZX;#!um3Xs6qM%6c=^GM^kM%gxp4dkSmD2ui-3)_v6+dJy`JL_xk=v0 z!N$_r=>M5uiqs)o6;_hIVu)VX?iyg2Gk$@QSPD1OX#mmz(`x$%SfMlk^NR*PS_0P_ zHKK{G8xu$Xi3w!D)YnLF6hequ+NM!jmHf14(~VLYj8Z9LCdFrs3~61Lj1QUb+1W(+ zZ1pGaA6XvPZ9i%%PafHqE!f(H5igdX>s6~x4vFj9kVgxaTn<6cd7R%)b zgE6v~&f!N@&z-7AaTm>%Fug?zub4S@35zhb3lwlLy=4l!m^n%o%vd~tL|rYP;zV67 zopMKAt(>+BlicO)4SOQ(F}$XRYk+tv_re2+fN)am8UX+Sf`VkC+=z1*AFuD01mM05j@HBQSD#5~!H0PH>#W_#OW#jWX}Qvgm6Lj(-oObyxq>6G*3-z3~+ z2B3j-mFiuAr2Rbu!Ai7S11U@HSi~<+PFTcG58wjfD%Oh*utV7^n3oaw4oQm+3+0;s zgHSg{^X!rUeyNRo%XLS`nE6X9n1xF(7%B_1v1|G2oGSX|K)rxvk>BpHFU2a9fYjH; z+B>NS!aAx;T4zxs$x>ia+(t`R-1M+l4ZpK5?b$e~2V9>k#`w&Y0eqJ#Aac*2$*-wK z_{^WtcNQ(Me`uGWbXF)}dY3K;d#aR3xyqC{e~6b%y_897+yG@Y?_E2!W9`hDbx^v1 zZza9NNq5|EWmO{-t4s`AcUCEYdHR)@Wd5VAWG7CbuKZ7L7~`Ck3$?ah;kPe(>&>TSy-D*E(J(b0nu>-0?j zA(53G1qRsSufUI`6Bs{Nr&4_5(ryGsWM*QZWi*DK4kHqGNIMZ+oWuwT{sv4Rm7XT) zrqaRrqtgYQIiOdFIXk~zL9qZ83woR^EiuC4MElap!8v{4cRut;yTF&~Z0Rj#T(oU& zicwh^ln783cafvja)>%|ai8#w-t}k*koUQ4!*{|^Ll_IXmmj!A$!{eSRwQP3fjv_x zfm2=?+Qa)65wAJbz_SzMLX(0=bfzh?}-nKC;OpkUzF3@+P@j2Rg82Gr7 zEI&8>Hpu3xA9f#Qb*jtIX;TmB0-3~TEAD~uYT>MB?VtNTMUKcC+5;N6ax+NasG~pk znc)ui1XkmUUVwRNf)@H&S>*gA#RMkjloA0m^8SQ!Rhd#5!%AxK#i&fu-Aq8)N~V$_ zxN}Em_jY0!+~^=N?~%J@qB;eFht1F)1R=L?+W6s=G71gUrJ_Sc_~cwEp+4t?V>{NO12S6}M$+wqEW0 zEKfdunhFex+Os9q^wxz%ox0Q3VeKELz7{oe%l;=b|1lf)p(w!k)y& z_-c4W3MrSo=nTurF=0ZAxZ>Cp^>GnK>((~Yu{$<8dSct%v2EM7?R1=u{lvCy+qUhbgUNfoZ>nahzH?@N?ArU+-nH&p zYt>%YeIa{GmcnRR?;eNO2UxTh+Z&?p6oRY{9+*)LpYBy2?+jzR|LSo7txAwh7TO{_ z97BSpEQFG=t$;l;56}I`>biKfqhNS#FDe>FZzu6UvVVj0P_ux&chuW^^fq{@hWYDh zhzuU9{p^t(n#adYKk~>3@4N6vesN+ThQKAD^T*OM;T?p#=pN5`7_3H!VyQ-wVA-_eCnakW0FDGlIXxwz!*49m=OZMMHZh=t`mgyjN0ow$L2UkC7x>5>t6%5>VRzeQB16(!kID-OuF3~2^R zghuxlNS}vtR8L)mKqsJj=4N?^=nl6)j8+4&(8-=;&)4!VDa|Vo_b-_dOT=ZG=GQO% z+y=ZniK&F(LNO!!>$quHDs7mTGI&Q%P(1{0qU)K_&Tg3DlgBDyb!g`;DZBLQd9n3B zj&+9OzUP})K0^>ZXi7BONkyUS>nvI;yVT#zaxzDT@{$a(ASjEJ{k|R(4PgI^K@&Jk z*;TM#M3v4KCC6I|h+?1(-W*3FLD|XKJ5I8tKl$cCdz-h(03}6%v13s@D=hnScnnQ9 zttrL1q&fLaJdt<4#@2CpsRv8cR?30S$|>{}o|TceB6yEpR-a=9?qz4EcT&kaBz_DV zMvElf0IDoMd6=g`gB$1xI@=>8SgK|(92GK7HN+(%D4$(#S3@8Z{j=!Rg()(G+eFoO z$ouq7&l?g02%|3BpRgzzfen2m!y;8-74B zNakgUZvsTtVF5xW>%%PW7}V>bYhbU5a4A-?kmb@VhF5Q=nh96{*oNhqYXSr(`VnPV zQ6-yyDn(_dc+7|t&bVDQKN-_t^;Z&UNt*2lPyDE~sVLuFStr7C%Bk=`l8h#CgJf18 z*=Uf7NnrGeaYVu|swrJ`h8$SqtyEM~Oh0?r_kfz=3wuSK&Um-ulG!6}6yr~t=bGxC zfTyF&{Y7JnhP_HM-xxWmV{5DwCZi@h1q(VSpEG#&L9S)p*fUklTKkyng>O&;H5whs@S zj*mZ>fH(>PzuT%c1#i@Eh&BOpmqJ;dNRkaX^u(Oa2~pBMmViixpY00KYY8^pXEQD# zIqMgU<;HUF&Kwu`rJ6=rNO!6|-U81K-Jx@0gL2)124u}0IH1 z*D0T_TL^BONkyHu=z%VRIXkeS@u>1QX|=#~P8l2dQTLbA6$;>*IdP0cnjY6v~vk z1VE!YEIltV+Xf{17yS*{Y?XumA{ZmO#YSthe!jx3bWwxab^-EujAw;l?C zmovu6mSz`l_xa7LPjGpv8O$xw`z>YGoAzurNFq&ik5dX0=nu*n$P8n%=H6W8Z48Hz=8-T=(#FoD8lArM6;uvT?1(h zl=uc~k<;hiDGw~`r8{*qog|F|GSksiRPjV9zbC8mXPPZG)iIrYSIZ!*Rrl>b^h_5# z8&dOkecth9?5BD-u-5LE1g}tgn;x|S2>B;+uSAIq>yZ%;o zea2Wk9pT%c)V%0{h9U9o!J)tgS3pRJ!m7dp)je8u+dVhJd6|0GJ)~OpG2@MyChG<8 z9y0X(1^<;c^0_St$|zTx0aN3<7>voZmqUr2TIiN$K>1EXm}b7tmsxo2JkLADP6Kr< zC#HIa_=o+lN32PW5=yfxbJr=mefmnEHW`5jawOD_WeHEzf|tB)K+|e`dxJMp@*>yE zwpR?Z%^!{Ap$9;rhP%=klPfRX-N8-sa*6h6$&@D__#Y&qr#A=YxzIC^^ zNr9KtCgwGEQ9amn!ot@>t!P~(rCb}PigQ!wJk+5wIM1ab)?MO|k-=~@q%F717F95f z_dZ;ua^w0C@lkgr?a9`{U~ii$sQ6N8o+3P_{>elGygN@!8CZA|Zww6lyV~L+F|WaN z$Z(;$yh?0{%2!Kl%Ds1BSg_^bfV;p|l>L)0bkYMI5yn80LoEQ8iJ2_~ORwcFp(EblitY6xnbQaR+CogFJK%wPQ5_Go~o_qwYyrH6|sD zx&<+iPK00~&+j=sR7H=tLI|Ov*Fj@Km&1Aam*uqZ!+0SwyMwJmkmhghmjND;v&0#f z+EZ>01;E;YXNux9a8L5pYaA zfxG@uv7PE9cy^;mjfSCV>&WN(n`U<^!I`o}CLMKi--}y^eGNXXT%|P(n+6RsekK{g zQ67O-d&IO#LXq`ZGU!mD<<^_L3j#2;paNtG5A?k&`=0AJ6jjA%Z*I&Ws zKv0FLftoo2CE4NWOaU^pGX6}~_g};j{XxAD_b;wx^_O$Pzi%J>yGGc5BRv08+aOcf zQuZHnI7JK0)dC)2FXFuFg3())>0O`!yvV!|!r-;}GQR%Eta+g({0Eh^l0wwr)Ca|0 z=7s{S71Ecu_bRL9%dp0@u*vts=MzE?PZ+ETejF=>mBDm7+P@7F)|z2DQv_7ooU}na zmpu?8V{9AVqn@)&I-Bhs5Mnpd4=y4lwHpymsl~z=^9}XMZnGaui}?l#6HB9fT`|Om zx~aaWsaYF=XG-Rex}_qTk^Ug(Nx)bj(3$JblYws-W;M9C6{fz22ltYa_=1wxtiLPfKc> zv80#FT=VAdb(fCG?j4@=T$`ynHDg7;9(;*=)jq@%c0AlHIy~>+gF%+yT*DFSaLk1X z<=o9{WnD9)tLf}JCQ4^|@zB3xTJBtV1Z+OHa173+9ixN;Txgj-v}L2nvOL;*_a`gAaz7#}Rvl2S7!CXt!_9zSmlxBVutXh>Sss4gVG@%oQEO-2_c` z+^d*dgp;^Jcvd1vLw7puGeoL0#0qYcU>-*RYQVChlcKY-fEO2-KWK-Wd{#O|A!3R* zU&`vlBqRgXC!24+Efpug;vpH;W|1FL!%Rsb8W@6kflHo7Sd=H3!5quC+ zmRg{qhFD_!ibKyOi(5B7mSm~0z9KwLOPA?1PLW=}Y>}=z{3FpSXhiLrv?il2Usmdp zLp?Y{E?kGNZGT^S(L5UR-os?wpk}AMR90XM-JmDdEWff-^0PnL}NzLdCgE?5FQliAmH?@dETwF|wgbmV5>&t&%ks>5lTWGMSaK z^d)Cn=U)rHPtr3p>K4JI!8GYaFH@eR0}UWztg>_W8WsDg{f7it ziKyCt4X$HNJL-zrb>N|QqXwT@FuJqZrX!GibAv*j&mP{rwiP>%(C>SDVsj`&<-^(& zOM%p^clh|^Xu%AEjbOA!p(Tbvox>Ca^7C88gAr2$$k`&Z*YMv#C#U9nhB0M`d<8{M z;Wu=D$k};Cm^l(lgg+h%{k`Gr^*jnYUqFs*$jl8*@-X;4j_q-F{N_w)GrmrS4(r~zn3Q)jl$@{6pK5Ml1Ls1uOEegGSnf;L zJ3*UHX}erqORApbT%I2reuj ztR1WZ+8>aa%Gk4jBpMC2o2ljpE^rzEwVf+hm5DZQ^b<5{Kb!j~>+edZ>yxj|HyVS+ zuo7avdmxlB`#ppnMG%${)-La6aLOQbpPf?W8wPm*^@MM+QYF)V-Ys9B*u8Ii`%pEW za(#(|JmyW@{^|bjp;fUjaMy&&ofx-9-nk56i$MiHV)?b)tNyC6H?5SiP3G?vR~)<` zx^e=4`ViFYc|>3$abPAX5FJ0#Nfzq>+A4W&jB_tIq6DJhK8+2NeXsN%t1*J&Tq9CDjg08&a%(|q#1rtuFS<@x@PyLTO z1P}TSo0P$BQB$#ZWMDmxZOJtZS$7rSI*A9X1k>OR~74bQjT=p$I!Jbo}z-tf)qiU>ocXQC{T3I0s&yp#2+F)I67t zga1V(DCvjy@BU&?oPC+v{rk!C?-;`W{V(u8GqKY(@LLF6)FVBT)05SSx|zgjFoY1)X0kr+KmP>8&~eG z6}f~P*Pju1@C-YBxP%KSzVZA(@v!hgBg}*i8Lr|$@#*l?W24!D{Pgh2{7~_HXvOMO z@kDX{gu4j2-wX+E$c4F?BPM`;g$T!#d!`e^*{OXJ;gm@O8&V~_ZZfG#6?;@0ReN^6 zqFtzFkpbQ>^NsB7I;lz}dwLuB8)h%%fp?l4$Mw?PUpk&xU{nP9w;Y{?yD(lNU;Z3H z5k>YD5vF#3A~5Y+B9iS=Ba&~#(YpqOsdNSksC4>NmGBNWmToA~Z5dv86Zo0j;RqEW z>}sgM>Ewh75KD;(F-!BH|0**EBVv*@3!u;4&?=ArfD?kaQ{LrLR+_;!pnHVb_rzcq z_Xz2RpV~dt_V4uL#|v|MS>tjs|AMYA9XyE(MO)3>504#~azo#vX6#ayAIyRpM{66? zP&8;_!v@WOES5m^n7R*h^~ejHD%zq3v+^;*V+8Ov)~?N^tM4L)XJ)QFAy z(vGvlIB=k?(foO7Boxi+MvCDqN=PR`!>qbH>E2oGjF}Nzdg)Qx#H-f*?RGCToa^35GoV{M!KSKn z?-&L|moUcAgS>0J zsv-y!ImMCA%!N-c`jWMjaf6}7A|-clwJug>ixN>G8k6Y_ewcKGK1SBt<*-+#GKXS( zMTfQ>2QP?0_Erf;#$A-nW*xek8)ZjQ?6{fGNGz<*$L9m3OUAOg+c=DSZDIYVUot~(a0&NrfiBUoDz}`@B31P9+ z(qz6EFTa7taQ3t)Ur?J`9x(v=E+Q;7p>B*;v#TB`|H@x8z8WEab{ zD6_7Pp z<@mxZFBz8g6UIr+e|68IDo9f)nvxX=jMPf+XnD`=*4hyveu01+l3Gh#HbcM|oE26< z8!NAV!x}0f=qgE8c2v5b+t+bGl|vnD}IHJ4;1D|po-KKl|_B4ii4vG9#RwWVJ#UpJ@(R2T)Z6P zkXDXHHZOzODqtuR#XBm;-MUT^E^sd7x1S$fYig1qN z{UgX$vPm_C?Ev}e%!#RmHo}f~Vx{#?d{Sm=^o=Wh?6B=Gh!$V6bxTvB3zjvTmK7=( zNmY@d3YGRr&N2kd0^)cGAV&9>#O=-?;WfgDd}?p2LNWM{K*jLC*V^U^1=aeo&s{Qx zxEEhOEy7whpe|)F%Y!5-5}a-M?s&_kv#~GGwdkS0;0TBN8vWyryc3bjI31WnXNKb( zr?2!7)AUDQ2_)K}b1?@-j)lP{rE^aTf*7Z1hCtiR^IB${%0Z-`8Eulpo$h^EJ1(20 zW#hkj8@&=RInt+Y$`)p`!_4XS8W)~8_fN^rr|L; z@d$IFd0et=*iN`~Z5}qJf@E})fcbm0tzD+`20blsTWoys+X%`kSmRRkiS>(gR|~1! z7a#Vg5azoP<<45;G!~`J^6|7p@e{1IWqBmGl?Q_Z8<_u;aoz_$=X=)mN7S?sCa3sZ7LY$t**5x4@XfVhcgi1WScFtt>Ft}f28{gEqQ5osLaj%c*ogDXTYO2eP-!S}YY(d~$tY~cs~l}XqcV~S%n%r?{zHq8!Crci3a7hl_e^YlrjQ4cX+eg#o@>emWnhEXxq^$81=nA6SM0Z0g z+F_)M8>&H;-4@^xr+lO+m}drGtwXCmf^IYo@BB%7CJb{e)4HEt%+4>891$2#L$#KZ znU<*=jhFwDlR^dO0AYjSXouP34fn7|D9^Mi|BD_3DEwNB4M3NLPDTdEhtQ|#Ylz`I z7j6y_O|{Qc?kvL9FQyT}eqCuJtn5K^kHCoRqDxV1;f7voU^|cS;_3-FqHV=^f8DC3 z!Sjd5K*c&-k*0oD0m{G;q{w4YT}76S;x@X&o^rq)>*x;fdPaE8k9}Gqc^bpv0E5rCoY|+Q#7t6Ff#Bc}-x~aM-K=QkuE2}x+0ua#iU;JmR=cZeMY!! znT4X8*S+gW?EbfmSF{CE=A~9X$_>cJO*;vk&ka;y61siKI2NQnsq5AH(9UE`wr&^La*qt+lLN)kHYP(LN*{3_N*`07dk7pnCN>>9 zQMH^9BpiW?-AW%Va}PIX2iS{ucnNmE9YmQCW}Pva=DSuVGP{*6Vnn| zFg#c>3AzQtE8u=1W%#o*Tz9(j*t&vHOQ8?KO6Uuy;T6C(ND?)AUNroPe6D|3bRQuj zJF@PeaRS2B@n`|#GO2?ZuDIzMn!GsB4N&w^^Nh949Wh*_#{fb*&$)M>M7^)USJO8pw^#n<)k5Acltwi^GUX43y}ct_UmAHwE; ziy!{T_Q>@9MDmuTTu|`GqIYAsDa6u7jmDzGk&Pl?SZ}(3OqxerNy6bDLk<5YVUtM) zj(jgT)yQOXzazQ*V(JO9o7aOthR4YZngy(W8WBWXuuQpNX zwv`6n_+>-jk3U0jLp@hf z{rqjrgIIU=^yuL0iqdZ6XFbuxqmzF+*f^&gBRePE%=Wl4j1A)CoFPj&<2K@=UFWme zc1qC{?lCajvD05qQ~>j0mAE)nwCf+h3{%|^V*jf^YF{|Wzb_%>|D%NBF77h6M*l4d zn(&74Qd)SpZjoe47?Je*>8Fq2IV=U;h6N2vB=!Slm@1u#G=U*@ygwBN2?@Oi{Rw}4 zsXhV&6NUIvL#}L5#d71cv%$GUqoSe0>uCMya3Y>v-|zA1-FMXeY2#qsaf)}1_leAX z=SY+Q%5UaYf?L<@DDvE^CX>GAPVwBUB$K}G?!cw9cT#orrNqT2EwifDF($LB@y>#~ zs>ZP@Q`hP!d-9oe(4T?UY^?W3jB)Qps{xd%vRnI+6wIkZYAt?t98)6|Wm zvbo1gPu7k&q-R(sI9k>A0;sKPM*&Bx`#kA9D}bZ5eb96*vxG=1hZ-4F6x?A}DsqcBojAda(W_;1V$7j@|a> z-cV8o>G*a${sxUB-x5k#f;Xc4Oi?LF7!tb0!4Eldf?oerQ^RNl`%SrYE4f61$>fBf zE@MDt3|G2zJ0T)c6tpV16oQ$^nFIV2pvQ^jas$(muV=sqk+6>ZB(g;Gg1}0bqoAMd zpvH}3P~29(k=N;R>hY}|`azuILD3l4{@9-VCizSOMPq8pxvjK#=r^~F0B*-v=5+nd zpAgwD3Iyd+KbcF9^-4Ua3yibnPj@i53sQ4RHyJn`i5;iEHuxo3b$Yiq_$B$YL{4V6 z52!4XTS#{uI3m(Bf`2m1TT=HL_$Jxc%jluK1h+LoKS{4`K|g| z`)h&9fOAwO_1+B!H6Y{S%EWOktb zs4!Bl-8e3g{@KuP=OBa=JBFCZ%>msF-~>e19R5ep?PA-8puQy6^x!-RKiNU&pq04v zXxl=%ub{mIwiQ8jQ8dgX;jU+5EeZo+G-yBbx2MAVSxy!PNiQ z)`lJ@ukQY){}=(5w#=K#5S1yr4GPK)v;N!f3BcgjZ4VAWPWh#$0!X}p2NebfmJeY6E;F>b|{$m>q<~KQmfA>f#L+D|q;N4_yjicEpC(8jI4tMC_LOlk{2#P_B0YPC#-^>R$x?me$P; z&PRG}3c5wK&C8^Z@2o!b;qM0r8VCbF5(FYU6*RZ<3zQJ~8Rr}QWYCYRf*bmm7jPTE zHHd#G43EGzC1@Af*LeAn-BkCsU@OCYh^0|q-W))e%nV4k%ECc63t=#~N?_Q#G*N@S zx&R_KylE5yGzKib(x`^dxM^5pS2O)WKCJ#{tc;U{@z0F!Gt7JHO< zfXNMp^!SddMP9(wY(L5ey>y0vBHe*=ni`#lnE~0SI%?4_O25Vj9B9{kKNq7MD#HAf zEJ75qC@QYmxyWW^xXDKlfbHgpwI-EcdYe-^qla*zKlM!kRMmW!MyD#g?kn%q4sk0t z+*)aMlHF`q%cl}Bxz}XA>*WIk&}}za?h15Dqhj9RveX2+RR?aBhDW{xr!@!hmxYf# zpQJTsWEX@}KRc&2$Lk7h(@AR$5H9sEutvA#67VBNy-t(zFu8_$nUfDVcK%Rj5>Ep96> zoZYPgu!*9c_MGw+1}H0r$ai3CvFm8@PW|vV;H$3mCHLrC72#DS_v|0I(q4iEwk2Dx zO0V4hS0@ipRPPCYSyLkuN3-5k)130OMmm>&{6)qZ{wyBhIj4cTp=RMsIfcA)W#JU! zVBt*UFC0OpsBy?YE)d7;(oG0{6PAwN<&(~m*k%DOdyYxdii)Qwdud23|Me%ap%@9e za>fY%G+nDtcQ!xf^zDsA8dA6suyjYx+VU+}m+dYvZCyx@`LhEsl{1SGS2j`?OMh#% z&f|`V+=9SKIkiV$M7KmBp>WM=O9Hd4ts*+a{(RZ-ugI zo1Ga1lE;t}OjE=_sxgS)9NM@C7sOx=gz_Q zSHB|28zzc;5s$mYefL---yc<6+f@^AP)gRJAL=Zk3`o$)2306&V4h6V$H?~~pbuvq z&#RvO#qGCtn~?dm$GjaQm_p|bJwL(N9tH{}bj2znOl}ugA$aw5yLB_z1N?^x)hoBH zAUkeFRmvaApU@UO-<*YwamzZQ=53h*3G8VdRjVFULb;Xbp`q*%%P(qYJQ9!i|6p^9v@E`7aVgf^CYyyc)c&ES zx^I53RCR;#vdE693>C1Mcl$6gJY4Nc;*67>uh`&`d1VbB)Y)VNLwULn<=}oj{q1!>f{#&fD@V8M&)67}b z&1+e@Y096l91dgfKcxVh>bAR{&a^!9p6aSaMSQxdlb|yEwkc6Em>q+KY9p;E#5r-r z%%Q?%PMeUu1bEn85vabKx9qC2MX!Y*LrE?|%@YJq3m$!0BV%Sz+_(JR!)Ijip)z+d zx-wAKO_}D*X-9cz2>7-(#JLSM=+i$?p0Z*UuBlyD~1&e{MhondS`zeCF(7+(L=81X%FKws=vn#yQg zaLB1FUhzSULzGrrHh-z!KCFZ1%fUX8!;Ss{D9Y&s#Qiw^)pF({FCBkjr&APpGsru- z!c``oWq;r%*VSMi#gxMxZ8ed4U&U#~u@hk-Q0Do*aCLS6ZpTNuwpcbUfI|U+PrY_B zQ$aLgo@k_P=((@A?|v5Bh63`DzUkZ-En2FjTgjem`0(CC_Mz27Hw;70xn69P0*NFB zhZ3uhVF`9;m-Jz5I6!k=lgc*Ld1^id^X5mGsmiGvV$r-xzb5_N^Sp-!-MU4LLT?fc z8(tb(F6C;yu}UfW8trd`d@hZP@wiJkM)MorZ?dAG$o3C2B#rlAi^P1N(5B&09r2e7 z@jzi5RG@mK5ry)2c+WiJO6Y|sw>mlFdzJ$+Ln4%GAe!E54By z$Qbd!+t-4 zWMe~7K}5Tt18KoAr0e7C=L!6X1@Q|zTn}%JVt|6fvtta1utiDCfoRN4HHL;TFQoxL z=pD~dSCA5a0WAll)yRac;;EXV>!C#+ELXZS1~NhJfsC@8MGU^9#Y?8WC?E3c+%|HI z#JFFP#h9T?q-BiPED&x(EWfmZT#^<q&X(m`e;ofs ziUta|e97AKIbN|0uNf(&Q77)FQ%)$O7~}Cq7FFX>P|oJE?ZsqX>=HG?y3`IH6%Z2< zyF_a?V%R!!%;`7>%|F(d9Ce^P5EFW2-#w@vvW$kW#3aN_ZT7kdL|qSUVzq7GvWsrb z3_e!s>j&_YOq`9lBi2uaU&cPJ_LV~phSDOxm~v(r!XMM6*~0jNqh4@uiKp&sz1~q% z{JVx67lhQ^zBZ5o-d58^9N(c-tHvx5Ss?cKMf4aL+<~uh0sbl(M;l^A-0xrrUJoz8 zsz=I&2fi+Po^x{&ockd+gYqGxAtA7^BD9|UZ#PP6ZCoN0fGLC`J2)4b=tq+lX|2jIWE z5xA9OC>l3=!k}zX^h!htj(!{)w&8BcliNP12U4LX7;1Yr zdqkV2Bd;^sT?68+(tsJ7SK%mRjl>1%bhSatdzu0a(~yY10me=q)vFBLh`R2LtHKLZ zqhwx^%HF37#nfQDLdSQukyiAdE=;%&4yDYnPA{eODk=tAiEvbO65uE6P*hdG29>21 z7h*0vTgu#q>{)Se9e2(fjANu>!?P%P1Uhfx6!5`&kT*_lY_q2^Ra2q>jPyB2CA_() z7fWXwR#3z_CwB(*o(_JRs=9n$UZo7(lq@LS zdyhowjzsSrb<+o56E|H2cr%lpJj9;98|7f-^%UvciYQEqkKk986+qOBbgMv$IcKS) z15GOlBp9LNbvVCILb;?{xDipZm#%_Ao~yyjt0+9G*PEV`GWbak2gcli^^vQ!Yq`8f zQgf-Yfd=pKz7yODXc|V8^LwmuRbHkIo%KAT|cHL zGQ{4D+Q~81z|tN%Eo874FhJmQur!x#XAM7-sbYl}wyBsRWObtQQ_UKadEkmsM(%T6 z*Qmfapm87xPngEsZ}xT8@j3}-D0PiHMm)mFVL!$>t&+5xUCx#Df=Xj$>5C*5YCkPx zpM3JjqpCP@9@X2m#OO%NC71X$?%7|08<;0BgRVQ#ENj{TRyNN0Iwv_hCH8PraDxHV zG*A{hlJL_0Q{*2u$%wP7R1qnUtqcg&5!?a-+qWZSEZF`SGyo$@!xnd6a_2!9%p)$)=mLeQZ!DD4mkkFR&Z_B?3 zE2G|>c;$(b1$nWa!YrVk;d^{b7JQAQuSeNG?Wog+DrS1E&9vR=2JvEc4?&;+OIb(Coy*PEj%vf<&ofzYbcQ3}PpdZ{$O1rqh^ zV7u$S?NW-0V5~>K(twzPNj(>qd*nI(MHHRt#%~1{92N>O93sTyd}T^J>4t8*3ohrl zCakg|*I8LRF5dmLC}i01p-4TLCC>*=eraHb5HfSx zuJnNz53BSY`%uujq}L8BTp$7eCGh)HK@B78W0dYy?@wXB0BGDsCCahm?s&@Dmgm`T z=nA$&udE(AF)s{{IUH@{OMbP$A(5S*1eH@f0YMCM53hF=a`K@(us{{h8j+_H;O*}O zX&so>z4&Oi-N1Sod&c5w0$H5YrJS+5xLD=_lGbIh6T5l%7(#*<#@aNKuA*;(>p7G& zmGfLUx!g}XvG-x}^?%`g{c*#QLtOW?$`ko~t$*@*=|4d4X(rJdwOXJF|dS?0)!EB4b##h~}Le0ZQW!|R%fkV0Mv9)!`HwyK&y8sV@F z_Pepj=yFt0C@oH7E!Lzuu6gIe0v%iF^V0*eJcvq{;s}~YA>3+nucOq8mU9i*+NOq& z6tW*C1`sU1QOsM)Ujf5|6r7i5=E^o`Z^z*wMJ>l>?iSszht-$n{bYy>=eiLyubVL+ z2k(#5Qp!adh06}vU;4}p%m1E@AQ}Zc$kO*eSr1xUhm{K(8_j%NQdp~Pu1;CDB1Q&}MM0N(9KhN`wdTSZ* zU25-~#K$Jaq%+fz+0Gb{?#rVrxu>IZal_OSu$#x_-GG%NBTp^B-GEAlwtB#NI3S%a zNKSW-&-)%WaH{}b#S@j+hXWv|xNLQbDUYMLEAys9%r%@R=CE>^>UvPMOsN!XJ?d0& zH3f}EM8X|F5K4PA_Y`q2=UE4daSGiH=6-67jodx^AWMF@njrsQh42i@t2 z4u|}Bn0WML&(Y5^DYVGf#pEkZI%0LZ!oi+|=fg7U$dF<6R!lM$ z$%N&Kw!{NpNU-*f5(rarXz-^lJf8b~*)|yqjnJDor6+}?Q(c1C7UM~RIS($=%}G@r z{#LOg>@f&9U%q22 z$pEPLiOPzBKy`sb@`$nfAG=}ECZUVqX{VNjo)1nK z@#weK0=2UOQ4dZ6l5q0t0qMnAL=qO;k3nfFp}zy8;j3f5>_TIM0i8Rv-pZ z2yAS_yy_z<2{PtThu|FxcA>+8aJ-99dCXR=%3sY1t3FtvahCE?)GqwhB$nh=z0FpB zN7|8_ipxv(sNCf*eRMX+@z~1YKf%;1If8r_@A4Ak{enRj9D{mYsTf`xw4pykZ2A5B zKS9{g>w5+u{^mNFkH(#*Zf&<>^c6ZF)F zOX^Vi_^b0}qEb(uPsD?|qaF)kO7cfjA1eb$aa>}^LWyM~*M0n?e{xr78ziMsR=)b3 zY&g5jQKX@_0ixoX-D}^7#BQfcrP+oMH?kr7Dqxd>CtYLZ8Z6d2vHF9NaV8|@yNiH{ z4FCBmF~J~NcM*4Pwtw>Uz8Rnr!yf(7*B29>Z1R&cS64-<%Xxk$l8j?%G0>oe?*JO_ zuLrl~zMPfo>URP6pl3#|8{7I`R?ZG$u|c9E0R2V2B(7FK0GW$uYrcNNoD6>JX{PQ_ zZ4cOdl4>OLW6#47X9l)Jb_8o?G0|WB9)+Tf)SdZNJz45?-JkUHi<4>K5o>I9TV6my z6)Qm{Ui?kAXY{DUX7Jwm&R{~0A-hS!6A4Kc|v7G39ZWSb~ke|u35qW~F@S8Z?IG)@Ht?236ttOr!$ z;SKrC!}~&Q`iQM+JXIsz;$-o`PHj6sEbJ0J!N|G{btpY4{~juZ6Rq?y?c>B2^T~TQ zH(ShnqIfZB6Nw1(`ETpERffanrCb*12J92ZeXlZhuSymz3nXWz&Bd$7h z*NgiMJ-J9rpN#X=mq&0Mw(wE3x|Gmd&LUB6Zhv469fci9rfn|vvjyS$H0)O-{PM7Z zQ9!kf)9TuaNWP}Mqg7BkZLDI(&bV712e3O;e?EUM@kUBB@9ZuI`q7>X*x1w?T>>=@j z<>~RhM(e`LI^f;`>H3zn*S6#SLDAlw9gzGSdClaDsk3v{SN109mg$RN3r*fmDbk~9 z0NGBW(${7{+fEO99k&ch7>R!!-i*eF%Dv-gkNKv~1F9RQx+8gm;YG$5ST&Hn1GPWO zzDxa#q57HmjQBzK0kak9+r!^KbqzGSre8t$Ao1**a^S&>N5xJc`#p9dHOxsPz4CWs z8sWrK403wYl!!IbnD7JDs7~OcxLA-ry=U;2t>w=r2qIhR7CkOQHEJ{4%+OF^NI-7|L-WPkpABP=A6RWl%~g6?PV$Bz3inoVb!hgmLku)bG$)rEubG zrxZY)k!^XMKK%af)0s}#JM5PA^SDD{LMFL7abV1>EczNT`r33D*IY8+Z&*W%sg+{B z(#!T@MEwnS7CUALt_v$VD7?#f>ucK4V!FL$hhNlh#xTxpAPXnL_sxN@^SHurMtX98 zsy(T3v4M*P`12l8rAb1RpT+Z@vSC~=Cw@JYV?qV9Ik;nxg*}Q4ti{7h(*-| z)e#51C*|ZBBOX03<1kCro!3Zb-wCVz{}*fT_?%nxZR@TiE4JU*wr$(CZLZk1ZQHhO z+gQnp&6|CG`_%n(_B|hN)u@_d{sD82K6-EMY0^f4Nq$oc>DcR{)EJv#Bt}^E#@0lW z5!OU2|MiMg%zci`norcq`=;SIm`TUl>ie=z@gtC4jQaY)9;q&F+TrYx*YYn#4x90xyzbXLip6j?KoVR-0sPQy; zl%5|fC>B=8Po{~#H8G4CD1A(Oeh{hv1{SQ-I-qQ%G&Wkv8W4Ll6CiLP^OYSTznYG? z&;cQ&pRG=O7e``$VSce^oN2h_Z?4J2ZB_n?~Q<^oI1D7eeRJH?`xQ4EY8owl=4W7@?acEN7_c< zy%9Ra49cVjWin#C)l<+%CHI-LqLwru=VfJwWhz45YhX~DG3BQu5B{-c)gGhVvt&hg zZTM4%HGMy54a7Z>G62+qt!qfN$I^my{HpwtP#usPCzX&)4_>L7*@44mOo=T&G7%zc z)O&LPwqd~Wp}10*KgmxvPp*0>%C+}P8a1+>1z9)XaENeA7xr#nhy>w$oLSf+u!i6w zDda)Osap|76cIB-v>UU&$UvMgqu2CoSo=~aDL&5Hwf*r>Rk<7oN(0B-T4w4`e-@^5 zGO@;#V&nn2|LR>T?9t-+hu^Gqa96g9y*pBhXe+)BVmIvxcASmj3@g3Un@a~+&+y24 z;*E`S`#P_C8LH1(wqGs7i8gv9T>;CwA#8)@bjg~C<~?R_Uz!nAHqTAE5P=NW70#P^ zrZo@+(y4{wy}5^-5w2`+)oPz}K>eHakaLSvxB+3r$xo_NMv*CIk>eXnzeJqOd6@O2 zLEI72R)))4kZ}-Ihmrq*hWAhaiDqk;kZ$mJq4hy1%gPl&XS#ZlviU+V`mwQi`dzP zG3*uZ%^ceZWxx2cf5HIs%Roz90w_U$8@k!P$*$$+;Fw$_RNZXR>v#Z#=A}8v=6ZO%S|Bq9YOp4^HV7AZ^#eZ>h{=`VQWL@y6wuqQ=?v8;H55!Wi+|);ar0Z>bW`jTSN5(tI1y1dy-K@ zVpzKB-#@5|3@T6?@#rOKft# zG?5ucD$5p6b~R>^Ct#5$sRi&c` zN(DV5^o6cc{9KOU(Oojfr`EpX-2^~1t8U49D1&uPB`aitc2k36A%X;Dc^yWMOKD>r z+Y#jO_IphSGbSJqE86yjEpAjdDE^WJrAAGk^PPvUM8*cg%wz;ib+!dFarRv$) zIo99{&-fh)KrJ_l1nQAFU2LZ+n^NAvKj+7;U!4*4ibtgIq0ZqPcpJ@MAu zucXdfnmt`eJfa+tYA#ZYVho?R024xWi&~0`!nsIDqzTup<&J<2oVo$r4b9-1VOr(c z(QfOs45D23P5?D2Hkarf)jvu`AM6d)xMoHl>TO%&3RSk78q)+9YH*PIu{+VZoM}~s zjtB5*)AcG#nuKF_+$VzYKDfPm>IyCA$HTVCXmqcGuA7Z{NC6&j+{**R%GTn6i{Bz_r%vUH{hRSfPTbn98R=@R|Jq>d4nJD-Fz zz(f?PtIh9AOORXYpILfHv4wkh9?J&Fy(3?xORrv~*flnKZ-9zPareOWQVmuPZjUW7 z0cCVb1-)f?s-S?7`GOpm3=P%Pay9)&I}REYJYP^{;zKET6wB)wPVOfW zRXHX1FO6XF4PaZuv9g<(=RlYpzL4b4>G8Kr0VQ9ehABT>a|t+#dd$IH`k0Y!du&@Y z<~XDW{uy~~AQMAFOTd&9G7vO#%X(2-lDqg!S6AH@lo!6!E_ zNXji^*{~T;ZgEN%aH=!#+OS6xA}b(tvQk(=BGi^%q`i@O38PeD05qe@LcViIdEDM? z4&M^AJQCJ&c}F~{735<8uwAI@&4A|KI&l0~S^FV79o*vM2;jN1n#K$3QK8c(pZqlu z%+Q}5ay3o=yQ845m=U7N7yM6+GuGXuv)EC4MW0HUn+?Z9J(YreYW^N=D6SW1#g1g! zn4CyS4%p%=rIIbFV2EM3A3>WPahvchOrRlG1C!uwF{zYk!egHq-(WL~n>=V_iX<1g!*v`DJ~xM!1uUF-jTHL&_WF6>aSTcZnNbfiINO*9e(iGS;SYBNcoMUu0~J z|KW{^;06_Z(vL^^ie0cVuO2yvkC$)}GF*$up(IeLoTnZL3LK{c6B^wU8ZnU@(kcrC zRauxdvZvj;?&CTEf)~Pia6+5@1vLq7IWuEBOe&27d>CwpNb+u_=J~b#MPDS#_SE`C zeQ2x?RtH&okZX=Q_bh!1$DOtF#zQh;Smn0?hY2^N?MOoKieFYL%2W(18~u9G?X<+$ zkAKf1zPA8epPk>bE;C)fFrEoDX9S!b`FUK*iF-I{-kp7(O0@*lur6w>EC2FSl?-ye z;Tt&v9q=@w_T-x}@#2ZA-+#spKj%?-|GIn8Md?sQ>0nJ8dF~(oKvbW>3$^_E4Yiec zk}*0U&Y{gw*rqR3tpSQva$cFL8?`)6Wi8advU$4D>Arp?c$IbBf2W z_eB6RO74mD4KTfxGl2Vs;rM7DU)~3lge+N*fd?l00%&_?j_k72h~LQ3eKA8CJ%U_t zdu8+r$on1OvL>ZcQ+un2_-C$syiyr;p`XuK?GQwC5MeP9yQx&(S`Nd-(H4IQ&mFzC zWo zo{v-X4wAuBux4|@pdU)NHD*j%=-$&k3{DD**$Um+u@!nDS2zySVnqxg6mFL{Qo$-O zQf-b}D42QhzQNW}FAtiR1^h6`_>=w3OYtsa(kdO8o1z4uqgXvqg%gVZ>bAqfj?>dQ zK|`Kx^AO-0!fnfqxYQHu zNpV8G9Lfg`UlU}1|I&Gh1wefS1$@z==z}c=1#tjamZ7jl_+8cMu*q#HJ&?haT!kjr&e5u#) z$u8niVKns*diZTPmeK5AfGfc13|l{}IO*q<1%bNbhNlJg&Z%m{pNF zLAkjqQ)0{siU@r|y*uheqq>N5wC1!QQ(6 zSyBBnUI0QgKPl>Kw9>``qN?TocW&)#;@N z2T{um$Hz^0b+cj-d{XWi#=*l-`n#og6b$h(cRM+VH(_#9`wWg3gPs)t_X@zewEun0 zA^ebSD5^E{u$NU0f$J3`Jjt#l>jQkU|C9udchd33Ev0KSBg$=)`cG>(pB+9012E=e zKTO5K+|c877^E_zH0Vs6Epx!qms?_v#K?H4BiMecof~5Buzj_JWc@E;ZRe^;reY}2R;v;9tielnlssNy93U;@C$>qHpItA zQYEr<_o1S$34N2Ec1gWz|IqMN})f<;fyuv@11cr4g2FN z;hHU*@np|Gjlp5L!DQh>x6kSkFS6X#E?Hhy2Yc@{WW8CrCJgRM2YcW&;MXUo>M%Pg z>}|`A_Efb}?BUPyxo#BoTPqVkjlbw;lP$9Y#aDq_h^s4~F~r#6y-S0GuE`+{)4j`@ zi!6uOo)iJGByhxIr#YD}gusT*@H+=5tIrY4pM0P9b8@UPcpk$Uzgo`+6Jtz0x=RAc z$Ohr(F*+f+TdgtV+CGR|E^?&Wktv>?EKgFtU1be#+t8e{v?=`k9OW)pjDu_dbxas! zAAr~~zIAwP4z}Rt^H`FhnGdv@XX|scWx)4ljMB{x9T4n;XaxNukkIt{eSToX?dJ>J zJyg0kbjN>d#`JDDswoLM_m01K2g7*hb`EftMi){!tAmbJ#hLzTgPrJw3*Hwub1=d6 zMtv#UASv^a6ugm!n=G9hJ&-xlpx7HxeWZn*drE7uCD9M>od0uM2FhgyKqH2i9-OBgwrYR z6RHXVP6snllrxxJHDi8dT%78hK_SC@4NeEFRoLm)xn%pOg}5ZyODmCd_{fDC&_fgl z@ah;oj7Cl`75X^jSX7mxe#P%u7NI5nx^nl7B5}x?>;0NWDK2X0JCE(cMDEH%!u!>z z{WpnPjR&lfobO~IHgFz!^4I;4qE41>8dZ2>?S(|68#FXtDvPa$To-7ZjzHpeUgVTO z{1seq1Gx0i9m+a#`uyaFbr}MvWz^e4DLN+}RBaebaWIL_(U)*#2%Xt#}Nzp{|zvY8l*1x|K1Z#2}~_EP22{XXB6; z&bzAZRFlpyg9fVWpE0dJ!G1+aiw+cA4in_Sq zttrjZ^k%pgd>6?z?5cU+@t&VnB|}^fBdc7raB^@PU|0a$n*?Exeup!e7Dk49;nIid zrP~|q$jAuuCGM;8rOs#Ahf}f{o~>Xr39vZ@*pB?RVDEP|3iwglf=bx~y(1U9M3PA1 z9zByP32G54(Q#%WQIe49HIyS;jL9a2Oxo`qi{U#$N5d;iz2HSjT(OGR(#-klkGyzs z+$phgct>~Uj=7D?PKH3f=L1_^mpK!GYo*Ame`a^W!eNeE9QuueiJhzEW{hnzWVM0Z z9qXKx`1l(P(d7&7fJ7eIs#9Ep)OPWany^Q<0+@ZP7o2}lDZpF_#+OkR(f6oVL|Q(+ zT5AA#cSO&B%vRrY`E>ttEm@oupO2-UgO_NhIBR!8KdJzZmwq4|=zPrl_Y{PZ<^|#Q zWkBpk2W3T-uoZ$h$D2mIX%OP|`(*6XzQGFx&FCHKwFm?Dc<{#oT2e?k#cEflma*Bi zkmQ$anDOgJHcD6wi~_4t4gw+~l&h7YdhoAL*x>V@!N-=KG*$2R+B@)P;05y|2(xbm z0?DVg^QPY3Up7^pG5tZ;8e8Q;r*r@D%(8Vmf-AQlRP}G3;*k4SI?TZxx>*Q@>lR5V%#ECf9bLF9{8(25Ug=W4QGbujVfPmj16HeXk8yx z%H1sTqrLs7hU&y%djc)JgwOBa|BJ7W2XG-oXa4o8E9!r88!`Uhxs3#^e==`>a*3S( zliSj*Y$LZQkK)7mq}XEH=RW@mEF#hZOcjvFh|O3KJ}yiYG6djr-rgo(Npapr`U>?O zu*+Zn*k-#=`fa-3RRcfa4>U%366EDLL+HPjr6g3uUh2;+iG zLRypF+oun42oIg)K5}mx7+fYsN)s1+7$k;Q;?_>2kIh6PpV(Ao^MSc~0l)o^q zDA$m2nRS7w)Ig$_GugDL*oZH|qhCJ5uI%_nzidFWc}f3haq7NW!(<3|4E+v_b`PSH zvkI4fl`_Lt(}V?kk_7y)GuJ!EcS2`;;+r_r3+x^KQeuE%o6h?J7yn!O=`6YNABAJO zUwnl@{r1y4rjxD(OJdr3UG$i$jSkZ@%jjMauG3Y3r&1S0tzFdbah}e9XP4pqr4V*! z&nY|NT%3lg+0^jZ^*Yzbj2$*C(wydW%%K`Jeo1bZGbxQSC#nG%43t;DjWH^CaFrbw zq&8i1*B@KP*|SHKY+}^qf`p>h#>~Vp_!cz8QG-yEC)oW~-24ccJ`!pc98mhVEM?7^c<2{?F^ zzx60%$3U?Qiolz*%|R~>Ja8;?@1(mz$gEZA74Y(on76+Ct#Nhm+eo8-6zK<8WyX$s z=MZri7Q2|#-~dGifcGeaaW8w~DZ{P2f&MQap7*#4VaJcLGxL8$xBZ`Ejs9b0{BIwg zkb$+eiK7$of1dyOJc`vcoKRFyzC2n+(nBuAqo@P+j1%Yys0qX8>GOmW>x2dPNwU*f zEz+b%b8`6khe4mc(T9Fuli;{b6Mpjx3+T9BH?c2xOV>MB&ZLPc0qV(|&pS?69H(4b zr!#oI-w#xNu3m+NwFf4swPo%q!&a2KYPTT~Y$`utmLRBj6))n$qm;bukWzEB;-UCh zpywz>QgK)8g64?EiTG~Ahyt83WqZSOn4>aln4zRa8F7|B*cO{^{7q!}dW|@nfUWF4 z!X`+^So~*Fgi$boD`|WJS4ivm8wd~3^-2SncV?72vB2O@%$y+xSP||#1K^I3LwaWE z0=+?r2Mc%1PL`|@TG-hG0a&xR`5QD>OLr_eb9ZneOx|I?ko$oNbip@NIP*3?9L$~( zT+n@Er`muwW2apOZ$Y`!#{qGVx%%k=@zQ_{4A*gn`*VRog4#^(NnDAGLl4&_@l52z z^C}apa|SB439R!hg{h5`Hly`(oRKz#F^u5LBe+}%kj?yBJ2* zeMqMw;|sXL;%Z~RYCk^_LCi#x;c4|(?s*8J)g*=myF}>f-RP97Z{`gG#F2gdvKED= zJ7iIh+|H{xoX-tN_^V2BMNW-O?vLEyl-CQU$QWvwx$a*%0qUt5^x3wyjGRt(i)tei z7*Hs1l`C5009Vpl^hi+!0iEliqhG;S(+3^~vH~i(8uVb2MuQ=ralBcjmNs#P8+jUK zl!H69v1;~Pv-~!>$;RxL|ghFe!POHj78 zd7{b)cukV7D{ZqV94hP%F8;YyX*rXRNB2+_?dge%1XK|Ur78sUV6=&m_qCsGBm z2e^@%cl1=@#w2tEDcNM$Cz(8GsAM(y+A-5{_mgoB>kNnE2|1^v+=g>zJQi}dY4MrW zYIKjbq+ExckNt|(n&Ky5__W~3or;WFm?Hw=@a-|769K7Clc+?69uCU=g!S%Drj9dH z2fRYFv(ox5$1hU`?JDU8;{xaPHr@&1mZln=XMV^mv25fEE$%Z*(;QNNF4Gt&*zy_t z|4gyA6GM$Sm=012uVL~|!0Gg%+%bFdCQD_vKiT&LoyR7(uiiWA00+m82rLM3dk4_#mGM)$fWnsN zBJ#L{Mk|%cij>IbTBZxyRJcI7l($eU6=9B5z3FavWI40smh_qOI%z2c!z~#>V>*zj z>Qk-k(J~uhHFVXFKl;%zK#gVdSB+)&VJC3;vr@YO+XXrDn)4*_DIy(iBwJc^2dI?e z$!{`7D?@jJNOz9%{%E=fRgg=&te6=8Y1@?2p3Qo<2;95SzOw{ZnAxe@rEw*q6 zfc|vGS6Ni4+&~X3sw-9XR=k3d(~+jx)jbol7i-?XZWcU42(57zcLD zvl^kP^&&O#0G7%6SJ0qnd)iu>;zvU4AQ zmsK-3aMgLf+#i$NJSVKmwO!z321b}OP@nXZBmcpH-bT%+7y`@)f)7(a$S3`m)I@I`f5jo-Cf5iz z(u@eS94m}_U;ZzoBd8$WVDrzZxQg&U)r|E2cQxaGpN#)G5}Vbb{ghQOzGh|)XJ)ir z4GjFH(kk<4I|HG^_zUB?h2_yujUk!O8J#r1%*~7s6HcU-{0w&ia1c^YwaO@4W72x&fyZi3ZpGNKHXz zG2D0hpuu#RZxZ}dVY>|XR6uGm+_(FDVJ{g_V2WW>OvrQdKSH1Yl;-4xm_+soaVCOL z1~2x403U2T(LNHX;3h~8CKw@i0)i4LRR|5TBP9cv;R^Z?0~3G?J5AKSI_(h(K?{PI zcxPNuTvMEM+H(%!5wakX!P22HfmD!}wz&3~C4p6NQBW4Gu@Hc09#H^6g8(Zy3sHcD zGx&%I;?S5N7bO9?L3gZ_C``XTE?Ust5Mo7GK2V9M%tc~iD7lS)j4jA(bg23zBV2E9 zlhh~tLV7Ev7V5Plywms(8!gJ64011O`z~ZVdZx@)=w#4G-wn&?bdPN2k>Pa$XK%|UHB$YG^idniPdyicO;!9My=m9pU-eC|Z z6cHvFwYF7lqn4s;NB8lIidDAzSD61L$*VQvw(Qdxt}8*Vbo11Bks^wm>B1J~x}BB4 z&iKZwbPCqsn+>&t@Tc@0E~?SzF)knC!Q>+rm4yO__8Z^FTTKSIcg-G>k5ezOepWlL(Zu7 zV$)3$RPg(@{TLVa1ZTUnW%go&{&t8+dXUig$#b0cWsK9mF7Ke4C{`IY@+CG|_I7O& zX=ESJ)Y*CsqV+9zx1;_*tmm561`>cbyufPGdhl{(^Uj;&fwR6S#+N?z4R`HQ0Pbyz z+umZs>+wq<^xyd(ROcEVPjjV=<@>LP2b-rZ96lMUo)*Pn5UbXy`fhd;sE5zI$fK(I zsBV)Q#Cb7H@JQirH#y$8B^@63?eJS)$|cwS>=lM`mPiI zfPgy`&9D+;nNOdnOKt>Ou@B^NN6j z%FuTFY}W=SMOWI>Bb1Qm=R^5+&3sn_#(&h5&Q*>LWb2iR+?r}v4$K7~onkh4u9e#y zeuq7gFq@Tsk7J~_WSiI5i?+^nxGnTHCHBXjpHrBOZm!u;-3B~gRKBJU^PnO>>I8VE z3*Hs4p!P}91zE4Aq$CqiDsA1@*;2{_J)2}3u(srxiJf52rF;5mk5-Kv#-n8m2y!jN z&!$+67huP|W+bX(SZ=1rWrbMYPiiZie;D4~`~7-eUe+KY$@rxqyBvUKZ|k{)YkOgYaiJB8##6J{v? zY%2L0)_2yg)q4st2)mO|D*%Qcvl8x$=@l8ZH}(hi1a%F!L5@2nRJPr8$S#ai(oQSV z$)<_uhUuPXNSU{@xZ1`y>MCX%mn5|Bu+#gE zcfsTrfm=X{oOf^1_2L7?%zS`g;WER?-`^O1s69iEQ%HVsw09-i@7Iz_5nI!sB7-{GiluB& zi?N@^=_R57lJb?6MR}R1GMgd8^1ViEZ~|oWnG8;||6uL}TwJ2m4gvvy_j7HKr%Di42EX34666Q!m=4SUpp%+-OJS3&SClpb0PsP zNV!i2mkkdC0__ZZtw&%zIs(gZju&>93q zm|3?WD#L_0s1D+$0lhdq$D4?G7)BS$hjYKlH?)U>Y|f3Zdn*jHBH$}Dc-j58`lrE>(&r-*(Wd!MYayLp1G?q4%C-S9!KmM8h>jC z;}aPkSepLBoDxNs9cnf=YEeBH6=x{Gx<$^4&Sm@&M>?WVyfR(69=dKtdDh{?9-wi@ z;J9OOxqPrOG(6ut>$O1&kvl=;I-mP*e0$mGaf!|hMi{^>1! z^2^y4!V38K#{QC!f*ITWwOhnPpxFiLwoqcZ(Sh4(p_f+KPANQ%xO0atWzS=fnq_mBVc5oUqG>)%2X7M_xGWe=8ExH7754IOB$Y^EFdc30wkCq0y#)hU+t zBZ*k4XUvLz0Be23J>MbWY!+KPoa0s-4guN}5cDwhwIgXe%irRcw6fIwn}YD}O@`j% z=byQ$wA9ilup+&fb;!CkXa_^Dx zE!7WDsat^TFml~3apoh%zjJBLod|=qVS8};?7LaUX`h(I=2G5~B9&6zgwFX$aR`mA zk%0u)uH19`Lwc23NNC0CZFbH4)tbDW*Up|r=VFh7%D?IEt@))lJ#i>{Ohf>hW+I{{ zXfxKwLk3=NP3Al{62*?)5AOl2rT|@cBgXpyD|Mhra>A8p4wa$A`gffO%gGy5hoV*k z44!E>ExX2H<}GfqI*%NiXW)^25#|FDY17TAp-Stv)jFu!L+37kVCWB+53JKent@H< zrqjstZOWXu1J=5@^!PEbaD6%L|c~j%{Zu{pDXR@klRCJtt=_>5#WRLQ*%_ zIrQ^IChv#jzI?D=!WU(W>CA5F(=%Td4lUA@Johcr-(EW17lA1(h%)erm)Bh=EIk(f z;UZCbs(5DyO}zY9sO*Nj0kyO*8qvJkV|V3i(#26^Rig!{R;8BJtCZjOVVe174&J!0^zz__M6#sxPnndd z!g~W!e`;FAmigr-OYA%9I2_D@mZX86Vw5ME;ySy2yS0cr=N|afKjq#Tr$x&fMXe+1 zU*QYfqZEWcHURarLNOp;H77pX%25|46ccZngzVUc^eCOOdKlI`RO*8A$yF^vaH$Lx zCSb}421~+12FS!EV`&AY@PDDmlO_AaEQL$BO=U+?nNJ!Px^f^*^~JXH#VaMbBtAUI zav&b0IbaN_9Bad;A^l9N?sk-q*6Wq#)6*L*cwg}U)tvHA2`D1@Vcq#-|4$`2@Bdv1 zF5+ro^k1MY;{Ux7{z0w(ryw6z(Xzu5LHQcFHThSSz0@u5WYIdOINEM41x+IZSuCpr zETJi`5*`Aa_&Ahq*=e<6CG}@7|A4H|_Y4{ye_t3lT#WLz5W&opO>0$0egj>1hJ)$e z+pNdQ+4ZTm*Y_QykHgD!FUg+`w##I%323tq9LyHozR@ohTAg+;k#OWTgRz$CK7^4h zi9;j6Urmx+w4`LJazdSilgC!^j>6iiY%!|Ow83&>X8p_znj zgKRpIN-|h&M&GQq%c#5iS30=j!!b%(9DBcYIUsEHZqE1b!o0pnLRy=yo`J=vC5jWa zOL6aH#oTHB2HsPr#b^>9Efgbd5?aUPpjkLEfR(+l!Uv%134EdGU1d@GI1)d#-58qj{Utj zIk@m4md@!~UK`9GdH97Koeo49y$&=bO2gG>T$qBD_n|xpi88iR$c;t(DWzhrJfq0Eaezf)GJ(N&kq>>=((jL{SLb4iqN~vuTbq| z*PgyQfEY%N7*EdaD{B}n8!odX<)lsA99C#pt~Vc5KGH^!EBo~N{rV?YL!3h@LwaQTHI8dc~Goulw|F%TdAqw_B*qLt{pEn;VF_MvYFCYvcg?!`4N^oS1>n+ zDx$nPIU95_V#8DUT14>KPe^8e4@fsCE8i?xY_@qfi9|L1p*t*j-7 ztbp(ZM|0Uiy^skfcI79x=n zOG~yL1xB&ja(>?AEyL4kew2xEv59?{@9Ba(8)Ki82npbIv_n$KBdX8`;DVO^vj+l(zNQgmfgrMvYxpAhJV=D3YEMywf98MiVuCkU<0?JhbKRSX1~ zVrn$*GprnqL4EcT>7)L2F0;P!n_b;unhvUU&; zOFQ&Bk=!-G8ZZ7=Y}gsYA31~prKUrS0rwbWcYlEH0!RcXD6J6!!j6bX+Ks!C3&fp6 zZBx<0#P0Ga@8EO2-<0FJ_eyI%FB*spppiDxQcS2o;60e9~e9OQDT0V4`D+s`reD7-rj;{f$P`J72dqAMfP$8(-qa|sVa_Wp+=vHiZZJP# zh!xp}$H=K6tp4!A@Pip-&lZUiS%?+XRUM;(`XfT%jL~`X2MxWxEogXE-AiZW`Gy3; z^Hu~+FW!M`_MIShdz>)%daNyS_*bNWm%vCjd+cyA)n0G?zmDHV-)<1=`bx^UK2<>jdgIW+^9S^j;c3*B9A<% zz>R#UaEb2rrm2TZHl+n{G?FD;E);N9hq;P2J^dzN!J3v-K3Bv*{bLtMzy_J5GP|BN ztEI9`q?5V2$r74oZplrszHV`;lVZoY?jW6W3vcKTy7#Rp>V}f8}+E&je zPSO^)2*wh{ASfvZfEDNt0!s#ws5!$H6O!E;`9Xk_KHb#%4Ge?TccCN^ZGOU@6t$8HuS^YaJd}!QX?V z#fu3ld516cnHK&hmbY|ao?uU<;9rGo4w)f2507Qi$k9_+g)r^z zvwzuMv8!Ny0Kwj#8}4IN5mJ6mQAz20b&3R8XX(>fI_@?|8Cm6E+UcbtGO$>jb(pZU z`Fu^5qi`iDd~To5oLZSNN+x1nDu)!rFW3yGFsY@MxLa;b#WW0te`6VjUscy{h~V&S3u5rSsJG-@w2JH!Zb&91(F4WqC>zuli*grRYc=k3PrJo zkVcC*xAmp2Ve?eB468H-Lx~Fs#qLzIwNU27pYi>~7D|su4^j&xOpWUENuzBZM3#Kf zH^!(r=gxog&Q6DnGJ1Gw1sy4K9*tz3O~1kWD>W!&31;f*Nif2*0E-0=w#VuJEa5YS z+ngp>>If41mDTTdy~o5}q2T_IGIeRrw<_9TFszKgz(i3?p=20{Sg7x+A93jXW5WEh zCGqKi-C3`8NO0L?j_V9PF30cGRv6r_DeL!V^ig&tdlWWdPAS_eP!$~)0~U+E_MxFS zf&mrA=Z;|%T3vsX zook`bNu)--RbUz}uS9{YwIz$pvduWQ5$v!cv5My{NH}|~;IHQ;oYm=Q$@XhU(qfUl z7Oo<|ReLkP7p9)}m8(UPsNjq#lCy{B|Hk=9mY@Om)xexxtv=ORaq9CZi8Ax+VRGAt zN>Ed*#gp{_se=ADm^6p)h4q|&C;OXeIzqaUdXajTS!xiR-T>h$8t9Z)x`z&>2RYG} zjkPPq7=kweeozGOMC3u@r`6bRHt+VV%^gJYknYXxZNj$j>;mnryUWisDdQ9b!WQ^l z#k8leaI@NG@_=kFRB-w>hXVm;crao=&5OmH*PXUvrzkI-tqReo^(GY)HCto=f@k*^aUEx}j;Y#`e=Jeq@elst; zq1BMVLw?ow54?l~D@?}LKmGbZo9V{rYFD=sHO%Jm^BA!F@tl|Xp3PhDnU3X?LN$$(Sm^_GAP{Jxb5I5PyaP%&?!X8em_ zokR@?={4Zc=d#czQ~eQZ>Rd+VMc%Gl4L$%-yB!?CEJI0v+)#eFM`yit7;FkEg?4+A z7|^@bHo2arw0Gi}1YMC5A;53=kCAGvi%GYzjiG-NZvNOex<#7YGs7O?;{WXmx47{+ zH+-&*xYJtfkq1K>z2=XP%*>|Y(x<@XXSrrcBWBTNg_IL072Bw;u~J!Qs)&k=LvZg% zf$O@D0bE7B-1jCOL2{qEHt#yf&gw0$>$_<|w*@GKJPQ-^c@B%~+MLRbi~Mc|=%DCj zUgT*$%Fr2A!y(O)gV|+J@^w%SVH6DYZAc>3G$`;DY?ze%pq;ly@LJ2!|7+d6&zmUJ zVp^5yUlZU#d^yZR%>^=tHa9D#=SYdlN#?h#d(Frim`cgmum@w_A@iIpcUrwH!=|A+ zUyGT{naC0^Nns!1_|9byFm&R#zwJBjSQ_O_afK1b>2 zny@I&xJY-ckgXtzWd%&4CF{V1jHN!PmUZxKnC?D-_cYw8^VqU0!5G{woqMi3mMyWC zjJ&y8;t1c z9&!Yo021WYs}P2&%zOm)@I^pXC)3&wbZ)&YO}m;#eCtcb??R7lzsUsztQw*vlHw>C>XTQ3D=4aV} zj70n52N1bsV^K=d7b+~xr7OE|CmAV6Yt79q*bkG2ozM84`v{aP?y}P;I>tz}6v&vV z5jMk;5GUenFHsmSk$Bv-iEoO;H$rcuFPq8H3E6tAMISa=X&RIo#u<{&j$s13L^W7+W3ev_t>rxgVcb0J@=7NKyHlKZ9 z$r)JF592^HY|e%`giGnYx=-xz$zCI5VSF-d-gGfHmtT{E8rtR&k$Ki*&$RA2$zGGg zH`eaKY2U1{u=Y*T7QBX;cdFvNkbb(uat-od*YjoBo5Ay+Zk_7?m`w41DJ4^JGB7hC z7B;aru{Abv{LgKoSouFuw~OGN)zC>$W%$4mnwt8NFSg!5mg2vRbQOx9FBCLG{}C2p&l&YgHk`jPZw%ByF~}8hh8(~j8(_swCYT#=0Z_095rVQU zQ0upGrb_G60Mpx*0`s-DkI3g?W$!LYW?`vK*KnyZ$1-I-ww+;u8Mb`Nsj715PUCd< z>T2qku%Y~G?))Kw6D4*FpH^CLF*#GADX{3I%`$%3C^wF*^hJXiX|q*8A2FR(qw=+ z+zI0kIba&+=8pmJ7BZP&Zs&<##SZ0yv1xV#AR+-YOJNgdQ&!a4KBcwBkwqW&S~qgH zl(4f~oN4%K*F(x4CKgAPm|cG(V+=T{j<38D32osst1(1!=rTJy8pN}*=$ytd#YvNX z(~1rkNKipQcsyf3NsfSI)lI2v9AS~r$hCkvW+W2X4a+xkC|=L?C@KSlF3xxM#jcvQuGY<}nq$p5#xutAOK?nu=lelS zNH7$RHNtc)>GB(;>nu0&YLD>0qK$mB-yY^)F>LYwM&ssxN85j)6#jP=ELBzOUlk1P zlYu_B5WfT;j5DE03bSPeo!YKOU1pw$;=Ksa*#el5&6SV*_~sw-31;9iCn{YOIhh|1mt4)fxOHV84-q7XVnqQ zjNr~xw9g>Uz6ELs^VD5!h(P|XK$c~87AMMzJDQeAg`+Oec*Rqes=yqhwC45zQ*3es z%V%h3OX<`GL`7uW9HGyXw6`_CX3tBq&0~HNMRe8D-rnQpME4zJBH-TmOSR`>>YK}3 zS;q0_e94bxVSx>V*-RB|KhYxlf*9-`hC(eavAU2plABqi#PG-hsMs+rwK;ktpN}l0 zHP+_SS=T+DQ88|n41J$>{=~IWtT4aIQSve4DyyhTk8d0M*V*)NR6;tG)mZCVrTk(W z7U#=4v}e#pD<3zTZ3LdLMB`{3n=v*ns#kGmR(cgipY4}wl$i8-8Kp#~oWkdBjS!le zy5$Kc-YN7;WO{A%j*{uu{Mf0W|gOE zd~eqv(-ycMe4@IPspKc;7h9PQQzYwhtM%dHHqxBh_l>i{XiEC7%o5*%?m(>Z=%e1y zZ~`KNO@PJ+CQpCS-_DzDVC3!LpF9bV##aU&pi@F^mbi!) zMctU)s3SVAYTWLKyFmCwK}qfmYrXG~c)k4x3-b})1!DLYl7atYNdA9wUH@Ob)c*;| z|33F>H9cKa&C$PlwO9;K5<|!!!{k<&#$~bGHiZIz!iq{-1d32o`A+dAK?7woGKZC4 ztXiXLaT)Y#bkH}Iq397TwKs}_7Sz97xu5a)%dZ`|F9o zo$P&i>3->U-_iZtT|5P&8)fwI*a}w>;M)hj_`LQZmHToX0+D>Mp7t#X!+bnO!_6s) z0xm^cqSlCviX-IwEHsb8;clORq@?!pqJQs8uUQH9cm!pTJa(7TGgRWhZe|Pj4wtS zT)ZSWY{|R1x0(31(_2yI<7zTFnkv~aDbVS!n8ZLLGo=gLO2w-Y&lyV9Uz%)b(%JJZ znNsBM(-sn6jdiM9NAm6!mg!0DmKN}_Pvtey$&2$dh&s z|Fo>f*0USQQ50WCXWsHkD^qN>;`zFYOExbJsRZL=M1A@$a8=Wv^U_SJzq_OzcRW{iCJOXm72`D%#aoZgurgyZ4OgjJx+KvoD|W2Nr|bGip{JhY z4~2qGttV42Hk^7mV$%GckGs`f$4%+-#?}68)K+FBu9=q5-;cUkKDUk-4PyN{D5}1u znH){jz{vvTVaJs9w3H`7v%k8Rye}|27n7%Ky>hTu9v@mu`jKL=vSz+TV=~V4(PeGP1aA1s`5ZLCOO0Yo4}I{vc4mTz|}Il z2!Q}jS^wZNP9E)HCMX;ImaherHfzfOdEg(2=Oi;Ymb2LXZad{z9+CJtw7&6CgTR)| zYr0zk0|dxx@E*pQ%-C*c8lo&d47yzW$UI9+$C0Kq=b$1>?viMlALvXhJP>L42x4Jt zwXj`tY*n2u4N6c-jAzxW5{a0&KA9JwwH=iZ6A_k^~U zKd~_1kTk2QS++l!Oqi5r$xD-45v6VJWAf@!bBH+7(&ARJTz3tIPg^P8r&ioBX>|GywYPgEYQ1MxgtI>36tv*Mzu}X^6I-{^rka?psLT<7tE6S-kgKCYP#FwRZth9u*W^r zOJ$lGx;%n(dd_vtx>+xZOrx5!;PPzZ$;pYbjYLdUe0yuiLUdAb$4s{>?5g+&vFv#( zNVE+22H#7hquOWdZYEASgMir!NP>zf~B6bOa~c@8GunxPv9MrO5N zEJ6CAB7dby-Q8|Nirc|<)xAug@Jl?0f}@#i;rLtj_MOEOLy0|JTHt?85MgvR^2Sfr z`}AQhI_5Vm=kQ*xWd%OA)na?duP4oyCl)FY@CE4DR9|+ISgW;Y%-sx;%lXpeauYpbiBi8+zIHJX2%6#!uwO)4VwQ4}q9?*&d(sd+ftSFNN zKx2~V#Hxc(g*&4hS*c)o5$}mfXi;9@^H~-qOhPFbgp~^v=uyMW-1}ws!w%N zW~Wv=70;aLYYZ}TE0#+`=u!mqA#$8kCJsC?81~!zaI`}9kTV=PC(44$upDCsXb&Y8 zgs&**d-kTJ6U&aWW<;8gk9&^Zafhd8RtzJd3*>6OS4_(!A8MkqHYjkfgycJs#r1}4 z+Ja`30Z{q2`)T_j*3Xdqn2l^n`FG!YF_loCzVioLI2pc3ElFsTk&kR5uhMF8FbI8C zWrYwf4(2muU?P{kxgLq)832k|nUMsI!C`wiK->SdHubP!ggDvj3hMksT*v*bIYLm~ zhUl$eFhx2-zW-Ti@zNeT=;|0B#uXh?JG*5Q8(^&btMT-*>hpzga){ot_s@}j>BggD ztWSuAN1|WX$|bEYD%{x?iQNa>+ZO3%F~~$o&)MV0d)|-e1=;ZyFi4r|h1(2=e#Q!E z*SK{akPW^-Fz?b0k6L~S4gZm9;%Wy8*cv597`CGf`n^@Tt#}v7g&nM%8=|;rNnJU^ zzCgHpLO+U42_PGu%;0vlJzQvB%@TIX@HQ_GxLLTnK7xBbbzV>1W)3aM|sTVO{C3OMF z!x{62fZOb1ntm*g(Hm@W*@CXG-M-I7n>vB&>wwF(~XW;U%OSUHn z`Tm{w6Z7M0v^ERQaXQv+T17~-86cX#c?^t-a0~x2Nj&5fv3B`$K5}+b)CU&YmV{%o zwm(c%H8g){$zlDZ{Jdg?0)wp#2c(REdzV|qoNKb@q`kTk%TUmQXw(`?PTt|t!HE4KQ9)3*LzBK7N~vd&0Hs)B(qU``|I&I&3XIkf9rkwHEomUcUdU$Z3-1% zUiWmkJ=bG2@|Npfqnye;3RX%sY1l+cHc_;dj4vsJCK5+VHhEYoDT5(WTgroco+vVa z42K*!WtdMYha~bXiAxOyj;yf(etB)2WT+^9L?0vH%&`_uK17!a2(9aYEn?ajJR*R( z#dj*+4tIEmjY;$BhGN7ZJ9?^@5rh_v)cD#E{Sm5_GfOgP6fk0kf!X{D8BMF@vjT;b zM8{xq&x~0nVp!O?20UQF(CAbQCcx;WYinK`IY7b4cQ(X1pi`!EYkVz$quj^gG_f(h zN9LSxq>iT5^jV0#=i?;EH*##nMg3_yKYQSWL1=yt#Yy7`79G7+VH6$tS`lM@uZCfX zfz;>`G=hwwFyVo2kbIAmmv+xXkaF+61v&u3w%;?w{x|Py@`2xhG8y!|7NY^R^*2`oOO#Ju(n>JCT zw@D);b16FNoSlTZB@0G54fC>O7}XL*y;!kx zrQ-&P+QJZ#)N7Ws_fftVpFIS zbX!qw+~vJwbnlZoIj?MMQs{|bG zYP^Y$%_w+rbynYV?k3MfQ7uw2b1OJ^|NXX;Ur^_iaoLPwKO(ax+VF=MJ;OxNU5bg! z?pYcTjzY8FHRiP40MS_@pjHnMU}i&th2-$M0~=%xGU zJ%+^o9e;M|q1Mokuv>D{i02TJY>}*q2w6>;T>@gx+*jPQp2mKE27&$d*>y1j2r;!3 zsmo91-cpX3T6N5vwd|9eBBW9hw&|RhSsgc0%+vsD0A1xXRkbPuu`nZFX`w?#R)EQh z@-N*_diGG#rCBjD#T9&*=c^b+FgQtmDY@cXoWSI%#OH$_;ctA5LG-d2kkVYQTMlia zy`2+}c1R<=+fgXbzo`vV1;&S_mkv$K>P9Qje4{H;(Th`a-%|z9Uf18o6+=>_z28=3 zoQ}_ks-0*&xyZAQZ-pmd;+xKXz-+f?exvcod5M)suqex2IVrfrF&%I)>2S#`{>?P# zoW<#AyhBF{@YSPg+>S7I2@WI<&hPC$7kJb&dEG#ZBBKtQ0?JNfxxM|NRR)A)Rs}pq=HyF2U2_p;%`)kssZ=cqKn|iK26iG(jS-oT)r9O4m@i|nPM_f5;B~=xJ_^hU~TwtCOi8P{CgWvn-CZc%k*D$xj>6wZ5si>qe>=<bWJ`Zn?KloC&!NnSvNS zh7lqLam2_g%(MqWe-U~=@E>vk^;0 z!XPpd;W+V8##39`#3!6-Lu~=*>Vv_o=j&GZL*PJD3=vxlky@BQi5}e2_lOtJcVe{|b)SSz=o^-Q&md`K5IS$fPx-O5#{n=en4d zTJrSEhXwW25nXcm(b@4rh{GSd_1v~YVYpL2|D5Hyx4#i>wUG894skpGxJAYq;t8Ay zBhI0BK(MlC(BD&9a(RP5^Z#Kj)8P3vpZ>v3rb7L_0a+gWW`yFkA(Q4rm(4IbZb~B2 z$06EHL@A0ogShGr!gx`xMScoXpl5&^wNxtxZVImp-bM!!7S&Tzv10`Ca1XqezUGT8 zRhI@Sf)sAJu${ZSjQY|Vio8iw0YPmH=iOhsupf-(X4~^qSIeJ)ne+0Nd2#poD1Nd~ zs=lLc0C|cpB8y(t5kJ`C8g{NgZr1SE4;`7xZ%lcoJPQ`9`Nu`8^Jd_fC>PN`#z)Zp zqAcwx(**Em#7{f>8BPa7{b z^0ecHM8m!vNlV~7KUv6^#(uY)!XK^y2n=z>FJBYCSS1n^{i~n6b~ZzEbFm~ z-_~pc5!|g+AgGr&M&WKMd>`D}@NF^Lqan$tu0;G@7>HwmTt}|ojo7QY0<$H$-jT_5 ziNOy|KPuhCy_P*as6R2t_~g4uD-U{1fq?OTvRNBD6lV?=ciR{|_SmZGx`3@V6tvv6 z)6?ULb=2yQ#FaC6oMv%fz%egrtZ7*2PtrJ_vDs8Ru(SSy?vB2;YiucKNcQJA^!JO- z#-?MrSoRDRq@aaVpJ@k>q=Ped5$+mE8|t*5PkWP*zD3Z)@(aUuwsEgFbTnSa5&koP zQuZ)>YSAHAI5RtQW;b2pbQ+td{;Eh`K!MWjhSI=0`YS)6Uj@L3dBM=EwHl%!81p#A;iu;D@vRn5Q0S$2yzM^Uwn@eLn6s!nF~me9FkqP_)Y`y-HT`mISjqZ=;0IH%;FK6;e$T=r_;5*EgH zbZ2PLJV%tGIbslSc$S9VWOn|3ThN?acfj)g(DUI?{+JPd<(4AY{P~Zy`uFEdAz;qf z`zHclyHY^pi0nNc!8v!{%GKRZ+}ve4&k|q)KT599Eu%2#vzQU`qrHd$Anaz8{cSOh zsWQ6aRM-VMA=D2gdeLHhSs2a~`KimWd^v63++i`R%Cgq^ytO1zA0l0)j5kt{^8lU4 z&p+C(2NtT{5L%yd#}hC+@1<=?NfF6ia!NGq#GK40H9Q?_L~5#ZLfllf$Z=(&C{^cKG9A_JT4s}gr z675Dc`0}jy6dMimnpYf?G|*iC@gG?V!(Zhw6#m;cR+9fIzhV48%WuT&%q{KyAG-I* zf789cI#2sdc4YN2P{3n|;Im=0eq;+v2r&hSs%t?(;j<(&F=a-wCJSw0Zq=$=*Ot&& zrJ}XcFrb3FR?{z)s$D9#OINqvSlj+p(|OB(Ow&rj&JgnN?r~8eOB(qbjPr zvO{}>ohGmD0Gq~3RkzwGI7%PgmxiNit>l0Q{Vz?O#=S4PpyE9MT~PVn7+p~5UIkrH z<=z>+U-h0A{j2U^mF5#L;$P*|Lql2Z)J3D9dMu*GpnN=DrCTiBPotySDV4ff#ZoqL zs`_TG)>l2zUnN~vRZ(T6fgWCUR4E-;^`w&OrKVLwQ(iGqS%spSI%(6iL1At40FnJM zMQ{Pk}&joaHk@MeFs z%YA~%p4zEPIZOlOuq{-+ucMXAaSxTjw^0LZCK5SJE99`vRCGB^JLIqpRm3+^lsHUV zDdYrEBFfZB*hK zsX-h2Y>uV)+9PW4f(<~=1BNhf>>JVnOL*2RhschNe}i$J@H+SoO!(y#}ZiVfl`;BcT^xR{O-?!Nif6vZ$M}GKlne9(^)ZU^@KQuUEpbTdYq&05?3xci!OOLP7vDfEt(xpNwUNUB;3# z#smU0k8H$VFt`sh8}tQNbrozJrj4|ft&EREFY=+zF|n%0!FV% z`}y!+Mz3k#5{biwO~;I>jIainG7PDJOku{@CrnGczgYA30w#x#5j&JWV)hBb`jLMz z0A<6Hu})3~D-UqOtg-DV2SmP80u-2`HG~Ax4iOHIt z1B~wnt7LsfuigZZ!?d11(b`!)()KOGc29*RU6^}D?%2V=fmeK723z9|(fbf#@z?^C zLW4{KNDLzrd>y(jD8D=jbOWJq`~uUNb*CNZf%NdX@VrGKg!E?K1#@>3vwU@=CgA{eHD%K z_{b%*Vw)wZI≦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ೕ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

<({ng!s5%5UjpP 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�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 WtvvW8BBIq%E0-TwxpfAJ=>Gu5zcXt9 diff --git a/sbt.boot.properties b/sbt.boot.properties deleted file mode 100644 index b120c5db..00000000 --- a/sbt.boot.properties +++ /dev/null @@ -1,37 +0,0 @@ -[scala] - version: 2.7.7 - -[app] - org: org.scala-tools.sbt - name: sbt - version: read(sbt.version) - class: sbt.xMain - components: xsbti - cross-versioned: true - -[repositories] - local - maven-local - sbt-db: http://databinder.net/repo/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext] - maven-central - scala-tools-releases - scala-tools-snapshots - -[boot] - directory: project/boot - properties: project/build.properties - prompt-create: Project does not exist, create new project? - prompt-fill: true - quick-option: true - -[log] - level: info - -[app-properties] - project.name: quick=set(test), new=prompt(Name), fill=prompt(Name) - project.organization: new=prompt(Organization) - project.version: quick=set(1.0), new=prompt(Version)[1.0], fill=prompt(Version)[1.0] - build.scala.versions: quick=set(2.7.7), new=prompt(Scala version)[2.7.7], fill=prompt(Scala version)[2.7.7] - sbt.version: quick=set(0.7.3), new=prompt(sbt version)[0.7.3], fill=prompt(sbt version)[0.7.3] - project.scratch: quick=set(true) - project.initialize: quick=set(true), new=set(true) diff --git a/sbt.cmd b/sbt.cmd deleted file mode 100644 index ed4ce6fe..00000000 --- a/sbt.cmd +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -set SCRIPT_DIR=%~dp0 -if defined PROXY_HOST set PROXY_OPTS=-Dhttp.proxyHost=%PROXY_HOST% -Dhttp.proxyPort=%PROXY_PORT% -Dhttp.proxyUser=%PROXY_USER% -Dhttp.proxyPassword=%PROXY_PASSWORD% -java %SBT_OPTS% %PROXY_OPTS% -Dfile.encoding=UTF-8 -Xss4M -Xmx1024M -XX:MaxPermSize=256M -XX:NewSize=128M -XX:NewRatio=3 -jar "%SCRIPT_DIR%sbt-launch-0.7.4.jar" @sbt.boot.properties %* From c8e70958e806fbc0cd8b3d8b46451910f1b68863 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 9 May 2014 11:35:20 +1000 Subject: [PATCH 042/811] Added module to consume the snapshot from Sonatype --- build.gradle | 1 + consume/build.gradle | 15 +++++++++ .../main/java/fj/consume/euler/Problem1.java | 31 +++++++++++++++++++ settings.gradle | 2 +- 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 consume/build.gradle create mode 100644 consume/src/main/java/fj/consume/euler/Problem1.java diff --git a/build.gradle b/build.gradle index 31bf017c..7eb35e27 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") + fjConsumeVersion = fjVersion projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/consume/build.gradle b/consume/build.gradle new file mode 100644 index 00000000..d6621b36 --- /dev/null +++ b/consume/build.gradle @@ -0,0 +1,15 @@ + +apply plugin: 'java' + +defaultTasks 'build' + +repositories { + mavenCentral() + maven { + url sonatypeRepositoryUrl + } +} + +dependencies { + compile("org.functionaljava:functionaljava:$fjConsumeVersion") +} diff --git a/consume/src/main/java/fj/consume/euler/Problem1.java b/consume/src/main/java/fj/consume/euler/Problem1.java new file mode 100644 index 00000000..51e7dfac --- /dev/null +++ b/consume/src/main/java/fj/consume/euler/Problem1.java @@ -0,0 +1,31 @@ +package fj.consume.euler; + +import fj.F; +import fj.data.Stream; + +import static fj.data.List.range; +import static fj.function.Integers.sum; + +import static java.lang.System.out; + +/** + * Add all the natural numbers below one thousand that are multiples of 3 or 5. + */ +public class Problem1 { + + public static void main(final String[] args) { + java7(); + java8(); + } + + public static void java7() { + out.println(sum(range(0, 1000).filter(new F() { + public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} + }))); + } + + public static void java8() { + out.println(Stream.range(0, 1000).filter(i -> i % 3 == 0 || i % 5 == 0).foldLeft((acc, i) -> acc + i, 0)); + } + +} diff --git a/settings.gradle b/settings.gradle index a3dbc7ff..1f0b3e4d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,6 +1,6 @@ //include 'core', 'demo', 'tests' -include 'core', 'demo' +include 'core', 'demo', "consume" // The final Java 8 release, (build 1.8.0-b132) does not work with Gradle and the Scala plugin // see http://issues.gradle.org/browse/GRADLE-3023 From b638cf925c18067edee8d35b573b24d420b1ffa7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 11 May 2014 17:52:47 +1000 Subject: [PATCH 043/811] Added incorrect values for username and pwd so the build can happen --- gradle.properties | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 gradle.properties diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..ee5193b3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ + +sonatypeUsername = incorrectUser +sonatypePassword = incorrectPwd From 479a83cd0efde02b2796e5ca0e8f255365b7c7ef Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 12 May 2014 20:02:50 +1000 Subject: [PATCH 044/811] Added incorrect sonatype username and pwd to allow build to work --- gradle.properties | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 gradle.properties diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..ee5193b3 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ + +sonatypeUsername = incorrectUser +sonatypePassword = incorrectPwd From cbccef4f4fb4ea163ebec1dc5ab010070b73c3c1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 12 May 2014 23:34:41 +1000 Subject: [PATCH 045/811] Turn off strict javadoc for Java 8 --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index 7eb35e27..f9df4b20 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,14 @@ defaultTasks 'build' ext { } +if (JavaVersion.current().isJava8Compatible()) { + allprojects { + tasks.withType(Javadoc) { + options.addStringOption('Xdoclint:none', '-quiet') + } + } +} + allprojects { ext { isSnapshot = true From 744b51aff49f9de1a730320d550234358ad714e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Fri, 23 May 2014 13:50:10 +0200 Subject: [PATCH 046/811] P1 as a 'functional interface'. P1's methods as static methods on P1Functions. --- .gitignore | 5 +- core/src/main/java/fj/F1Functions.java | 2 +- core/src/main/java/fj/Hash.java | 2 +- core/src/main/java/fj/Ord.java | 2 +- core/src/main/java/fj/P1.java | 216 +---------------- core/src/main/java/fj/P1Functions.java | 220 ++++++++++++++++++ core/src/main/java/fj/P2.java | 4 +- core/src/main/java/fj/P3.java | 6 +- core/src/main/java/fj/P4.java | 8 +- core/src/main/java/fj/P5.java | 10 +- core/src/main/java/fj/P6.java | 12 +- core/src/main/java/fj/P7.java | 14 +- core/src/main/java/fj/P8.java | 16 +- core/src/main/java/fj/control/Trampoline.java | 10 +- .../main/java/fj/control/parallel/Actor.java | 4 +- .../java/fj/control/parallel/ParModule.java | 2 +- .../java/fj/control/parallel/Promise.java | 5 +- .../java/fj/control/parallel/Strategy.java | 15 +- core/src/main/java/fj/data/$.java | 2 +- core/src/main/java/fj/data/IterableW.java | 5 +- core/src/main/java/fj/data/Iteratee.java | 5 +- core/src/main/java/fj/data/Stream.java | 11 +- core/src/main/java/fj/data/Tree.java | 9 +- core/src/main/java/fj/data/Zipper.java | 3 +- core/src/main/java/fj/data/vector/V3.java | 5 +- core/src/main/java/fj/data/vector/V4.java | 5 +- core/src/main/java/fj/data/vector/V5.java | 5 +- core/src/main/java/fj/data/vector/V6.java | 5 +- core/src/main/java/fj/data/vector/V7.java | 5 +- core/src/main/java/fj/data/vector/V8.java | 5 +- core/src/main/java/fj/test/Property.java | 6 +- .../main/java/fj/demo/concurrent/Fibs.java | 3 +- 32 files changed, 324 insertions(+), 303 deletions(-) create mode 100644 core/src/main/java/fj/P1Functions.java diff --git a/.gitignore b/.gitignore index 81574421..b0110db5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,12 @@ out lib_managed *.iws .deps - .idea - .gradle build *.iml +.settings +.project +.classpath diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index c8626ddd..255f1798 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -188,7 +188,7 @@ public B _1() { static public F, P1> mapP1(final F f) { return new F, P1>() { public P1 f(final P1 p) { - return p.map(f); + return P1Functions.map(p, f); } }; } diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index d5e80951..74a7de79 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -282,7 +282,7 @@ public static Hash> treeHash(final Hash ha) { * @return A hash instance for a product-1. */ public static Hash> p1Hash(final Hash ha) { - return ha.comap(P1.__1()); + return ha.comap(P1Functions.__1()); } /** diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 1fdf05f8..d1e59868 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -577,7 +577,7 @@ public Ordering f(final Unit u1, final Unit u2) { * @return An order instance for a product-1. */ public static Ord> p1Ord(final Ord oa) { - return oa.comap(P1.__1()); + return oa.comap(P1Functions.__1()); } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index baed70af..af88979b 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -1,230 +1,16 @@ package fj; -import fj.data.List; -import fj.data.Stream; -import fj.data.Array; -import java.lang.ref.SoftReference; /** * A product-1. Also, the identity monad. * * @version %build.number% */ -public abstract class P1 { +public interface P1 { /** * Access the first element of the product. * * @return The first element of the product. */ public abstract A _1(); - - /** - * Map the element of the product. - * - * @param f The function to map with. - * @return A product with the given function applied. - */ - public final P1 map(final F f) { - return new P1() { - public X _1() { - return f.f(P1.this._1()); - } - }; - } - - /** - * Returns a function that returns the first element of a product. - * - * @return A function that returns the first element of a product. - */ - public static F, A> __1() { - return new F, A>() { - public A f(final P1 p) { - return p._1(); - } - }; - } - - /** - * Promote any function to a transformation between P1s. - * - * @param f A function to promote to a transformation between P1s. - * @return A function promoted to operate on P1s. - */ - public static F, P1> fmap(final F f) { - return new F, P1>() { - public P1 f(final P1 a) { - return a.map(f); - } - }; - } - - /** - * Binds the given function to the value in a product-1 with a final join. - * - * @param a A value in a product-1 to which to apply a function. - * @param f A function to apply to the value in a product-1. - * @return The result of applying the given function to the value of given product-1. - */ - public static P1 bind(final P1 a, final F> f) { - return new P1() { - public B _1() { - return f.f(a._1())._1(); - } - }; - } - - /** - * Promotes the given function so that it returns its value in a P1. - * - * @param f A function to have its result wrapped in a P1. - * @return A function whose result is wrapped in a P1. - */ - public static F> curry(final F f) { - return new F>() { - public P1 f(final A a) { - return new P1() { - public B _1() { - return f.f(a); - } - }; - } - }; - } - - /** - * Performs function application within a P1 (applicative functor pattern). - * - * @param ca The P1 to which to apply a function. - * @param cf The P1 function to apply. - * @return A new P1 after applying the given P1 function to the first argument. - */ - public static P1 apply(final P1 ca, final P1> cf) { - return bind(cf, new F, P1>() { - public P1 f(final F f) { - return fmap(f).f(ca); - } - }); - } - - /** - * Binds the given function to the values in the given P1s with a final join. - * - * @param ca A given P1 to bind the given function with. - * @param cb A given P1 to bind the given function with. - * @param f The function to apply to the values in the given P1s. - * @return A new P1 after performing the map, then final join. - */ - public static P1 bind(final P1 ca, final P1 cb, final F> f) { - return apply(cb, fmap(f).f(ca)); - } - - /** - * Joins a P1 of a P1 with a bind operation. - * - * @param a The P1 of a P1 to join. - * @return A new P1 that is the join of the given P1. - */ - public static P1 join(final P1> a) { - return bind(a, Function.>identity()); - } - - /** - * Promotes a function of arity-2 to a function on P1s. - * - * @param f The function to promote. - * @return A function of arity-2 promoted to map over P1s. - */ - public static F, F, P1>> liftM2(final F> f) { - return Function.curry(new F2, P1, P1>() { - public P1 f(final P1 pa, final P1 pb) { - return bind(pa, pb, f); - } - }); - } - - /** - * Turns a List of P1s into a single P1 of a List. - * - * @param as The list of P1s to transform. - * @return A single P1 for the given List. - */ - public static P1> sequence(final List> as) { - return as.foldRight(liftM2(List.cons()), P.p(List.nil())); - } - - /** - * A first-class version of the sequence method for lists of P1s. - * - * @return A function from a List of P1s to a single P1 of a List. - */ - public static F>, P1>> sequenceList() { - return new F>, P1>>() { - public P1> f(final List> as) { - return sequence(as); - } - }; - } - - /** - * Turns a stream of P1s into a single P1 of a stream. - * - * @param as The stream of P1s to transform. - * @return A single P1 for the given stream. - */ - public static P1> sequence(final Stream> as) { - return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); - } - - /** - * Turns an array of P1s into a single P1 of an array. - * - * @param as The array of P1s to transform. - * @return A single P1 for the given array. - */ - public static P1> sequence(final Array> as) { - return new P1>() { - public Array _1() { - return as.map(P1.__1()); - } - }; - } - - /** - * Provides a memoising P1 that remembers its value. - * - * @return A P1 that calls this P1 once and remembers the value for subsequent calls. - */ - public final P1 memo() { - final P1 self = this; - return new P1() { - private final Object latch = new Object(); - @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) - private volatile SoftReference v; - - public A _1() { - A a = v != null ? v.get() : null; - if (a == null) - synchronized (latch) { - if (v == null || v.get() == null) - a = self._1(); - v = new SoftReference(a); - } - return a; - } - }; - } - - /** - * Returns a constant function that always uses this value. - * - * @return A constant function that always uses this value. - */ - public final F constant() { - return new F() { - public A f(final B b) { - return _1(); - } - }; - } } diff --git a/core/src/main/java/fj/P1Functions.java b/core/src/main/java/fj/P1Functions.java new file mode 100644 index 00000000..b0f6bfb3 --- /dev/null +++ b/core/src/main/java/fj/P1Functions.java @@ -0,0 +1,220 @@ +package fj; + +import java.lang.ref.SoftReference; + +import fj.data.Array; +import fj.data.List; +import fj.data.Stream; + +public final class P1Functions { + + /** + * Returns a function that returns the first element of a product. + * + * @return A function that returns the first element of a product. + */ + public static F, A> __1() { + return new F, A>() { + public A f(final P1 p) { + return p._1(); + } + }; + } + + /** + * Promote any function to a transformation between P1s. + * + * @param f A function to promote to a transformation between P1s. + * @return A function promoted to operate on P1s. + */ + public static F, P1> fmap(final F f) { + return new F, P1>() { + public P1 f(final P1 a) { + return map(a, f); + } + }; + } + + /** + * Binds the given function to the value in a product-1 with a final join. + * + * @param a A value in a product-1 to which to apply a function. + * @param f A function to apply to the value in a product-1. + * @return The result of applying the given function to the value of given product-1. + */ + public static P1 bind(final P1 a, final F> f) { + return new P1() { + public B _1() { + return f.f(a._1())._1(); + } + }; + } + + /** + * Promotes the given function so that it returns its value in a P1. + * + * @param f A function to have its result wrapped in a P1. + * @return A function whose result is wrapped in a P1. + */ + public static F> curry(final F f) { + return new F>() { + public P1 f(final A a) { + return new P1() { + public B _1() { + return f.f(a); + } + }; + } + }; + } + + /** + * Performs function application within a P1 (applicative functor pattern). + * + * @param ca The P1 to which to apply a function. + * @param cf The P1 function to apply. + * @return A new P1 after applying the given P1 function to the first argument. + */ + public static P1 apply(final P1 ca, final P1> cf) { + return bind(cf, new F, P1>() { + public P1 f(final F f) { + return fmap(f).f(ca); + } + }); + } + + /** + * Binds the given function to the values in the given P1s with a final join. + * + * @param ca A given P1 to bind the given function with. + * @param cb A given P1 to bind the given function with. + * @param f The function to apply to the values in the given P1s. + * @return A new P1 after performing the map, then final join. + */ + public static P1 bind(final P1 ca, final P1 cb, final F> f) { + return apply(cb, fmap(f).f(ca)); + } + + /** + * Joins a P1 of a P1 with a bind operation. + * + * @param a The P1 of a P1 to join. + * @return A new P1 that is the join of the given P1. + */ + public static P1 join(final P1> a) { + return bind(a, Function.>identity()); + } + + /** + * Promotes a function of arity-2 to a function on P1s. + * + * @param f The function to promote. + * @return A function of arity-2 promoted to map over P1s. + */ + public static F, F, P1>> liftM2(final F> f) { + return Function.curry(new F2, P1, P1>() { + public P1 f(final P1 pa, final P1 pb) { + return bind(pa, pb, f); + } + }); + } + + /** + * Turns a List of P1s into a single P1 of a List. + * + * @param as The list of P1s to transform. + * @return A single P1 for the given List. + */ + public static P1> sequence(final List> as) { + return as.foldRight(liftM2(List.cons()), P.p(List.nil())); + } + + /** + * A first-class version of the sequence method for lists of P1s. + * + * @return A function from a List of P1s to a single P1 of a List. + */ + public static F>, P1>> sequenceList() { + return new F>, P1>>() { + public P1> f(final List> as) { + return sequence(as); + } + }; + } + + /** + * Turns a stream of P1s into a single P1 of a stream. + * + * @param as The stream of P1s to transform. + * @return A single P1 for the given stream. + */ + public static P1> sequence(final Stream> as) { + return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); + } + + /** + * Turns an array of P1s into a single P1 of an array. + * + * @param as The array of P1s to transform. + * @return A single P1 for the given array. + */ + public static P1> sequence(final Array> as) { + return new P1>() { + public Array _1() { + return as.map(P1Functions.__1()); + } + }; + } + + /** + * Map the element of the product. + * + * @param f The function to map with. + * @return A product with the given function applied. + */ + public static P1 map(final P1 a, final F f) { + return new P1() { + public X _1() { + return f.f(a._1()); + } + }; + } + + /** + * Provides a memoising P1 that remembers its value. + * + * @return A P1 that calls this P1 once and remembers the value for subsequent calls. + */ + public static P1 memo(final P1 self) { + return new P1() { + private final Object latch = new Object(); + @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) + private volatile SoftReference v; + + public A _1() { + A a = v != null ? v.get() : null; + if (a == null) + synchronized (latch) { + if (v == null || v.get() == null) + a = self._1(); + v = new SoftReference(a); + } + return a; + } + }; + } + + /** + * Returns a constant function that always uses this value. + * + * @return A constant function that always uses this value. + */ + public static F constant(final P1 a) { + return new F() { + public A f(final B b) { + return a._1(); + } + }; + } + +} diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 91131f57..795ce8db 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -187,8 +187,8 @@ public final P1 _2_() { */ public final P2 memo() { return new P2() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index d7b990f6..4e7587dc 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -127,9 +127,9 @@ public final P1 _3_() { */ public final P3 memo() { return new P3() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); - private final P1 c = _3_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); + private final P1 c = P1Functions.memo(_3_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index e4c58185..1711e9e6 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -181,10 +181,10 @@ public final P1 _4_() { */ public final P4 memo() { return new P4() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); - private final P1 c = _3_().memo(); - private final P1 d = _4_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); + private final P1 c = P1Functions.memo(_3_()); + private final P1 d = P1Functions.memo(_4_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 58285ff4..c5d19ea2 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -243,11 +243,11 @@ public final P1 _5_() { */ public final P5 memo() { return new P5() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); - private final P1 c = _3_().memo(); - private final P1 d = _4_().memo(); - private final P1 e = _5_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); + private final P1 c = P1Functions.memo(_3_()); + private final P1 d = P1Functions.memo(_4_()); + private final P1 e = P1Functions.memo(_5_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index f70ef742..6f557c8e 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -314,12 +314,12 @@ public final P1 _6_() { */ public final P6 memo() { return new P6() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); - private final P1 c = _3_().memo(); - private final P1 d = _4_().memo(); - private final P1 e = _5_().memo(); - private final P1 f = _6_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); + private final P1 c = P1Functions.memo(_3_()); + private final P1 d = P1Functions.memo(_4_()); + private final P1 e = P1Functions.memo(_5_()); + private final P1 f = P1Functions.memo(_6_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 6b06e86f..d1dc7b99 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -392,13 +392,13 @@ public final P1 _7_() { */ public final P7 memo() { return new P7() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); - private final P1 c = _3_().memo(); - private final P1 d = _4_().memo(); - private final P1 e = _5_().memo(); - private final P1 f = _6_().memo(); - private final P1 g = _7_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); + private final P1 c = P1Functions.memo(_3_()); + private final P1 d = P1Functions.memo(_4_()); + private final P1 e = P1Functions.memo(_5_()); + private final P1 f = P1Functions.memo(_6_()); + private final P1 g = P1Functions.memo(_7_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index e6763d2b..ffa60f51 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -479,14 +479,14 @@ public final P1 _8_() { */ public final P8 memo() { return new P8() { - private final P1 a = _1_().memo(); - private final P1 b = _2_().memo(); - private final P1 c = _3_().memo(); - private final P1 d = _4_().memo(); - private final P1 e = _5_().memo(); - private final P1 f = _6_().memo(); - private final P1 g = _7_().memo(); - private final P1 h = _8_().memo(); + private final P1 a = P1Functions.memo(_1_()); + private final P1 b = P1Functions.memo(_2_()); + private final P1 c = P1Functions.memo(_3_()); + private final P1 d = P1Functions.memo(_4_()); + private final P1 e = P1Functions.memo(_5_()); + private final P1 f = P1Functions.memo(_6_()); + private final P1 g = P1Functions.memo(_7_()); + private final P1 h = P1Functions.memo(_8_()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index a07da3b9..47a35b1a 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -5,9 +5,9 @@ import fj.F1Functions; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.data.Either; import fj.F2Functions; - import static fj.Function.curry; import static fj.data.Either.left; import static fj.data.Either.right; @@ -67,7 +67,7 @@ public Trampoline _1() { public Either>, A> resume() { return left(sub.resume().either(new F>, P1>>() { public P1> f(final P1> p) { - return p.map(new F, Trampoline>() { + return P1Functions.map(p, new F, Trampoline>() { public Trampoline f(final Trampoline ot) { return ot.fold(new F, Trampoline>() { public Trampoline f(final Normal o) { @@ -338,7 +338,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(P1.bind(x, y, F2Functions.curry(new F2, Trampoline, Trampoline>() { + return suspend(P1Functions.bind(x, y, F2Functions.curry(new F2, Trampoline, Trampoline>() { public Trampoline f(final Trampoline ta, final Trampoline tb) { return suspend(new P1>() { public Trampoline _1() { @@ -349,7 +349,7 @@ public Trampoline _1() { }))); } for (final B y : eb.right()) { - return suspend(x.map(new F, Trampoline>() { + return suspend(P1Functions.map(x, new F, Trampoline>() { public Trampoline f(final Trampoline ta) { return ta.map(F2Functions.f(F2Functions.flip(f), y)); } @@ -365,7 +365,7 @@ public Trampoline _1() { }); } for (final P1> y : eb.left()) { - return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); + return suspend(P1Functions.map(y, liftM2(F2Functions.curry(f)).f(pure(x)))); } } throw Bottom.error("Match error: Trampoline is neither done nor suspended."); diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 49912199..76ba6657 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -2,8 +2,10 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; + import fj.Effect; import fj.F; +import fj.P1Functions; import fj.Unit; import fj.P1; @@ -92,7 +94,7 @@ public P1 f(final A a) { * @return A new actor that uses the given parallelization strategy and has the given side-effect. */ public static Actor actor(final Strategy s, final Effect e) { - return new Actor(s, P1.curry(e.e())); + return new Actor(s, P1Functions.curry(e.e())); } /** diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 4bc6580e..4e984af5 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -260,7 +260,7 @@ public Promise> f(final F> f, final Stream stream) { * @return A promised product of the result of mapping the given function over the given product. */ public Promise> mapM(final P1 a, final F> f) { - return sequence(a.map(f)); + return sequence(P1Functions.map(a, f)); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index ce78d6b9..522bf8a3 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -5,6 +5,7 @@ import fj.F2; import fj.P; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.Unit; import static fj.P.p; @@ -123,7 +124,7 @@ public Callable _1() { public static F> promise(final Strategy s, final F f) { return new F>() { public Promise f(final A a) { - return promise(s, P1.curry(f).f(a)); + return promise(s, P1Functions.curry(f).f(a)); } }; } @@ -334,7 +335,7 @@ public static F, Promise> foldRight(final Strategy s, fi return new F, Promise>() { public Promise f(final List as) { return as.isEmpty() ? promise(s, p(b)) : liftM2(f).f(promise(s, P.p(as.head()))).f( - join(s, P1.curry(this).f(as.tail()))); + join(s, P1Functions.curry(this).f(as.tail()))); } }; } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index a0b972a5..af850908 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -6,10 +6,11 @@ import fj.Function; import fj.P; import fj.P1; +import fj.P1Functions; import static fj.Function.compose; import static fj.Function.curry; -import static fj.P1.fmap; -import static fj.P1.sequence; +import static fj.P1Functions.fmap; +import static fj.P1Functions.sequence; import fj.data.Java; import fj.data.List; import fj.data.Array; @@ -73,7 +74,7 @@ public P1 par(final P1 a) { * @return A function that executes concurrently when called, yielding a Future value. */ public F> concurry(final F f) { - return compose(f(), P1.curry(f)); + return compose(f(), P1Functions.curry(f)); } /** @@ -142,7 +143,7 @@ public P1> parMap(final F f, final Array bs) { * @return A list with all of its elements transformed by the given function. */ public List parMap1(final F f, final List bs) { - return compose(P1.>__1(), parMapList(f)).f(bs); + return compose(P1Functions.>__1(), parMapList(f)).f(bs); } /** @@ -155,7 +156,7 @@ public List parMap1(final F f, final List bs) { * @return An array with all of its elements transformed by the given function. */ public Array parMap1(final F f, final Array bs) { - return compose(P1.>__1(), parMapArray(f)).f(bs); + return compose(P1Functions.>__1(), parMapArray(f)).f(bs); } /** @@ -286,7 +287,7 @@ public static P1> parFlatMap(final Strategy> s, public static P1> parListChunk(final Strategy> s, final int chunkLength, final List> as) { - return fmap(List.join()).f(s.parList(as.partition(chunkLength).map(P1.sequenceList()))); + return fmap(List.join()).f(s.parList(as.partition(chunkLength).map(P1Functions.sequenceList()))); } /** @@ -546,7 +547,7 @@ public A _1() { public static Strategy> callableStrategy(final Strategy> s) { return s.comap(new F>, P1>>() { public P1> f(final P1> a) { - return P1.curry(Callables.normalise()).f(a._1()); + return P1Functions.curry(Callables.normalise()).f(a._1()); } }); } diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 9dbfc5ff..a12e3689 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -7,7 +7,7 @@ * is the identity morphism from B to B. */ @SuppressWarnings({"UnusedDeclaration"}) -public final class $ extends P1 { +public final class $ implements P1 { private final B b; diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 494de370..f12f1a58 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -2,14 +2,13 @@ import static fj.data.Option.some; import static fj.data.Stream.iterableStream; - import fj.Equal; import fj.F; import fj.F2; import fj.F3; import fj.P1; +import fj.P1Functions; import fj.P2; - import static fj.Function.curry; import static fj.Function.identity; @@ -157,7 +156,7 @@ public static > IterableW> sequence(final final Stream ts = iterableStream(as); return ts.isEmpty() ? iterable(wrap(Option.none())) : wrap(ts.head()).bind(new F>>() { public Iterable> f(final A a) { - return sequence(ts.tail().map(IterableW.>wrap())._1()) + return sequence(P1Functions.map(ts.tail(), IterableW.>wrap())._1()) .bind(new F, Iterable>>() { public Iterable> f(final IterableW as) { return iterable(wrap(Stream.cons(a, new P1>() { diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index f4047b32..affcfbed 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -5,6 +5,7 @@ import fj.Function; import fj.P; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.Unit; @@ -161,7 +162,7 @@ public IterV _1() { new P1>>() { @Override public F> _1() { - return P.p(cont(step.f(acc + 1))).constant(); + return P1Functions.constant(P.p(cont(step.f(acc + 1)))); } }; final P1> eof = @@ -199,7 +200,7 @@ public IterV _1() { new P1>>() { @Override public F> _1() { - return P.p(IterV.drop(n - 1)).constant(); + return P1Functions.constant(P.p(IterV.drop(n - 1))); } }; final P1> eof = diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index c903c514..c11bc5f9 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -10,6 +10,7 @@ import fj.Ord; import fj.P; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.Unit; import fj.control.parallel.Promise; @@ -135,7 +136,7 @@ public final B foldRight(final F2, B> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight1(final F> f, final B b) { - return foldRight(compose(Function., B, B>andThen().f(P1.__1()), f), b); + return foldRight(compose(Function., B, B>andThen().f(P1Functions.__1()), f), b); } /** @@ -654,8 +655,8 @@ private Promise> qs(final Ord o, final Strategy s) { final F id = identity(); final A x = head(); final P1> xs = tail(); - final Promise> left = Promise.join(s, xs.map(flt(o, s, x, id))); - final Promise> right = xs.map(flt(o, s, x, not))._1(); + final Promise> left = Promise.join(s, P1Functions.map(xs, flt(o, s, x, id))); + final Promise> right = P1Functions.map(xs, flt(o, s, x, not))._1(); final Monoid> m = Monoid.streamMonoid(); return right.fmap(m.sum(single(x))).apply(left.fmap(m.sum())); } @@ -1169,7 +1170,7 @@ else if (p.f(head())) { }; return new P2, Stream>() { @Override public Stream _1() { - return cons(head(), yszs.map(P2., Stream>__1())); + return cons(head(), P1Functions.map(yszs, P2., Stream>__1())); } @Override public Stream _2() { @@ -1498,7 +1499,7 @@ private static final class Cons extends Stream { Cons(final A head, final P1> tail) { this.head = head; - this.tail = tail.memo(); + this.tail = P1Functions.memo(tail); } public A head() { diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 8c3cd8b1..28bd3012 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -5,6 +5,7 @@ import fj.F2Functions; import fj.P; import fj.P1; +import fj.P1Functions; import fj.P2; import static fj.Function.*; import static fj.data.Stream.*; @@ -145,7 +146,7 @@ public P1>> f(final Tree a) { public Stream flatten() { final F2, P1>, Stream> squish = new F2, P1>, Stream>() { public Stream f(final Tree t, final P1> xs) { - return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); + return cons(t.root(), P1Functions.map(t.subForest(), Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); } }; return squish.f(this, P.p(Stream.nil())); @@ -174,7 +175,7 @@ public Stream f(final Tree t) { */ public Stream> levels() { final F>, Stream>> flatSubForests = - Stream., Tree>bind_().f(compose(P1.>>__1(), Tree.subForest_())); + Stream., Tree>bind_().f(compose(P1Functions.>>__1(), Tree.subForest_())); final F>, Stream> roots = Stream., A>map_().f(Tree.root_()); return iterateWhile(flatSubForests, Stream.>isNotEmpty_(), single(this)).map(roots); } @@ -186,7 +187,7 @@ public Stream> levels() { * @return The new Tree after the function has been applied to each element in this Tree. */ public Tree fmap(final F f) { - return node(f.f(root()), subForest().map(Stream., Tree>map_().f(Tree.fmap_().f(f)))); + return node(f.f(root()), P1Functions.map(subForest(), Stream., Tree>map_().f(Tree.fmap_().f(f)))); } /** @@ -251,7 +252,7 @@ public static F> unfoldTree(final F>>> f return new F>() { public Tree f(final B b) { final P2>> p = f.f(b); - return node(p._1(), p._2().map(Stream.>map_().f(unfoldTree(f)))); + return node(p._1(), P1Functions.map(p._2(), Stream.>map_().f(unfoldTree(f)))); } }; } diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index c94a8129..293d94f4 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -9,6 +9,7 @@ import fj.Ord; import fj.P; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P3; import fj.Show; @@ -157,7 +158,7 @@ public Zipper map(final F f) { public B foldRight(final F> f, final B z) { return left.foldLeft(flip(f), right.cons(focus).foldRight(compose( - Function., B, B>andThen().f(P1.__1()), f), z)); + Function., B, B>andThen().f(P1Functions.__1()), f), z)); } /** diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index bc72e702..b7d7a962 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -3,6 +3,7 @@ import fj.F; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P3; import static fj.Function.curry; @@ -143,7 +144,7 @@ public Array toArray() { * @return A new vector after zipping the given vector of functions over this vector. */ public V3 apply(final V3> vf) { - return new V3(P1.apply(head, vf.head()), tail.apply(vf.tail())); + return new V3(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); } /** @@ -218,7 +219,7 @@ public Stream _1() { * @return A new vector after the given function has been applied to each element. */ public V3 map(final F f) { - return new V3(head().map(f), tail().map(f)); + return new V3(P1Functions.map(head(), f), tail().map(f)); } /** diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 17096ba9..d139fd9f 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -3,6 +3,7 @@ import fj.F; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P3; import fj.P4; @@ -191,7 +192,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V4 map(final F f) { - return new V4(head.map(f), tail.map(f)); + return new V4(P1Functions.map(head, f), tail.map(f)); } /** @@ -201,7 +202,7 @@ public V4 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V4 apply(final V4> vf) { - return new V4(P1.apply(head, vf.head()), tail.apply(vf.tail())); + return new V4(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 74eca29d..3e6be00d 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -3,6 +3,7 @@ import fj.F; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P4; import fj.P5; @@ -208,7 +209,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V5 map(final F f) { - return new V5(head.map(f), tail.map(f)); + return new V5(P1Functions.map(head, f), tail.map(f)); } /** @@ -218,7 +219,7 @@ public V5 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V5 apply(final V5> vf) { - return new V5(P1.apply(head, vf.head()), tail.apply(vf.tail())); + return new V5(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index eb0bc325..66fb8102 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -3,6 +3,7 @@ import fj.F; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P5; import fj.P6; @@ -225,7 +226,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V6 map(final F f) { - return new V6(head.map(f), tail.map(f)); + return new V6(P1Functions.map(head, f), tail.map(f)); } /** @@ -235,7 +236,7 @@ public V6 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V6 apply(final V6> vf) { - return new V6(P1.apply(head, vf.head()), tail.apply(vf.tail())); + return new V6(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index f593ddf9..552f8ee9 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -3,6 +3,7 @@ import fj.F; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P6; import fj.P7; @@ -242,7 +243,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V7 map(final F f) { - return new V7(head.map(f), tail.map(f)); + return new V7(P1Functions.map(head, f), tail.map(f)); } /** @@ -252,7 +253,7 @@ public V7 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V7 apply(final V7> vf) { - return new V7(P1.apply(head, vf.head()), tail.apply(vf.tail())); + return new V7(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index 4ed66206..aa33b27e 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -3,6 +3,7 @@ import fj.F; import fj.F2; import fj.P1; +import fj.P1Functions; import fj.P2; import fj.P7; import fj.P8; @@ -259,7 +260,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V8 map(final F f) { - return new V8(head.map(f), tail.map(f)); + return new V8(P1Functions.map(head, f), tail.map(f)); } /** @@ -269,7 +270,7 @@ public V8 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V8 apply(final V8> vf) { - return new V8(P1.apply(head, vf.head()), tail.apply(vf.tail())); + return new V8(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/test/Property.java b/core/src/main/java/fj/test/Property.java index 72ea7dd4..6848d083 100644 --- a/core/src/main/java/fj/test/Property.java +++ b/core/src/main/java/fj/test/Property.java @@ -13,6 +13,7 @@ import fj.F8; import fj.P; import fj.P1; +import fj.P1Functions; import fj.P2; import static fj.P2.__2; import fj.data.List; @@ -27,7 +28,6 @@ import static fj.test.CheckResult.propException; import static fj.test.CheckResult.proven; import static fj.test.Result.noResult; - import static java.lang.Math.round; /** @@ -526,7 +526,7 @@ public static Property propertyP(final Arbitrary aa, final Shrink sa, * application of its arguments. */ public static Property property(final Arbitrary aa, final Shrink sa, final F f) { - return propertyP(aa, sa, P1.curry(f)); + return propertyP(aa, sa, P1Functions.curry(f)); } /** @@ -552,7 +552,7 @@ public static Property propertyP(final Arbitrary aa, final F Property property(final Arbitrary aa, final F f) { - return propertyP(aa, P1.curry(f)); + return propertyP(aa, P1Functions.curry(f)); } diff --git a/demo/src/main/java/fj/demo/concurrent/Fibs.java b/demo/src/main/java/fj/demo/concurrent/Fibs.java index 018f92a5..6bb324ba 100644 --- a/demo/src/main/java/fj/demo/concurrent/Fibs.java +++ b/demo/src/main/java/fj/demo/concurrent/Fibs.java @@ -4,6 +4,7 @@ import fj.Effect; import fj.F; import fj.P; +import fj.P1Functions; import fj.P2; import fj.Unit; import fj.data.List; @@ -50,7 +51,7 @@ public static void main(final String[] args) {return n < CUTOFF ? promise(su, P.p(seqFib(n))) : f(n - 1).bind(f(n - 2), add);}}; System.out.println("Calculating Fibonacci sequence in parallel..."); - join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} + join(su, P1Functions.map(spi.parMap(fib, range(0, 46)), Promise.sequence(su))).to(out);} // The sequential version of the recursive Fibonacci function public static int seqFib(final int n) From 3b69b24801d007073473f3318cc9852402224ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Fri, 23 May 2014 14:13:54 +0200 Subject: [PATCH 047/811] Ignore eclipse's conf. --- .gitignore | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 81574421..60f45788 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,12 @@ out lib_managed *.iws .deps - .idea - .gradle build *.iml +.settings +.classpath +.project From 89b16468672f51ae550930afbd4ec5f643a440b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Fri, 23 May 2014 14:19:37 +0200 Subject: [PATCH 048/811] Ignore eclipse's conf. --- .gitignore | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 81574421..81301985 100644 --- a/.gitignore +++ b/.gitignore @@ -3,11 +3,11 @@ out lib_managed *.iws .deps - .idea - .gradle build *.iml - +.settings +.classpath +.project From d9314d7e662fce66c536b5e2af8428766c503cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Fri, 23 May 2014 15:42:24 +0200 Subject: [PATCH 049/811] P1 as a 'functional interface'. --- core/src/main/java/fj/P1.java | 78 +++++++------------------------ core/src/main/java/fj/data/$.java | 2 +- 2 files changed, 18 insertions(+), 62 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index baed70af..efb19f5f 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -10,7 +10,7 @@ * * @version %build.number% */ -public abstract class P1 { +public interface P1 { /** * Access the first element of the product. * @@ -24,12 +24,8 @@ public abstract class P1 { * @param f The function to map with. * @return A product with the given function applied. */ - public final P1 map(final F f) { - return new P1() { - public X _1() { - return f.f(P1.this._1()); - } - }; + public default P1 map(final F f) { + return () -> f.f(_1()); } /** @@ -38,11 +34,7 @@ public X _1() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return new F, A>() { - public A f(final P1 p) { - return p._1(); - } - }; + return P1::_1; } /** @@ -52,11 +44,7 @@ public A f(final P1 p) { * @return A function promoted to operate on P1s. */ public static F, P1> fmap(final F f) { - return new F, P1>() { - public P1 f(final P1 a) { - return a.map(f); - } - }; + return a -> a.map(f); } /** @@ -67,11 +55,7 @@ public P1 f(final P1 a) { * @return The result of applying the given function to the value of given product-1. */ public static P1 bind(final P1 a, final F> f) { - return new P1() { - public B _1() { - return f.f(a._1())._1(); - } - }; + return () -> f.f(a._1())._1(); } /** @@ -81,15 +65,7 @@ public B _1() { * @return A function whose result is wrapped in a P1. */ public static F> curry(final F f) { - return new F>() { - public P1 f(final A a) { - return new P1() { - public B _1() { - return f.f(a); - } - }; - } - }; + return a -> () -> f.f(a); } /** @@ -100,11 +76,7 @@ public B _1() { * @return A new P1 after applying the given P1 function to the first argument. */ public static P1 apply(final P1 ca, final P1> cf) { - return bind(cf, new F, P1>() { - public P1 f(final F f) { - return fmap(f).f(ca); - } - }); + return bind(cf, f -> fmap(f).f(ca)); } /** @@ -126,7 +98,7 @@ public static P1 bind(final P1 ca, final P1 cb, final F P1 join(final P1> a) { - return bind(a, Function.>identity()); + return bind(a, Function.identity()); } /** @@ -136,11 +108,7 @@ public static P1 join(final P1> a) { * @return A function of arity-2 promoted to map over P1s. */ public static F, F, P1>> liftM2(final F> f) { - return Function.curry(new F2, P1, P1>() { - public P1 f(final P1 pa, final P1 pb) { - return bind(pa, pb, f); - } - }); + return pa -> pb -> bind(pa, pb, f); } /** @@ -150,7 +118,7 @@ public P1 f(final P1 pa, final P1 pb) { * @return A single P1 for the given List. */ public static P1> sequence(final List> as) { - return as.foldRight(liftM2(List.cons()), P.p(List.nil())); + return as.foldRight(liftM2(List.cons()), () -> List.nil()); } /** @@ -159,11 +127,7 @@ public static P1> sequence(final List> as) { * @return A function from a List of P1s to a single P1 of a List. */ public static F>, P1>> sequenceList() { - return new F>, P1>>() { - public P1> f(final List> as) { - return sequence(as); - } - }; + return as -> sequence(as); } /** @@ -173,7 +137,7 @@ public P1> f(final List> as) { * @return A single P1 for the given stream. */ public static P1> sequence(final Stream> as) { - return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); + return as.foldRight(liftM2(Stream.cons()), () -> Stream.nil()); } /** @@ -183,11 +147,7 @@ public static P1> sequence(final Stream> as) { * @return A single P1 for the given array. */ public static P1> sequence(final Array> as) { - return new P1>() { - public Array _1() { - return as.map(P1.__1()); - } - }; + return () -> as.map(P1::_1); } /** @@ -195,7 +155,7 @@ public Array _1() { * * @return A P1 that calls this P1 once and remembers the value for subsequent calls. */ - public final P1 memo() { + public default P1 memo() { final P1 self = this; return new P1() { private final Object latch = new Object(); @@ -220,11 +180,7 @@ public A _1() { * * @return A constant function that always uses this value. */ - public final F constant() { - return new F() { - public A f(final B b) { - return _1(); - } - }; + public default F constant() { + return b -> _1(); } } diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 9dbfc5ff..a12e3689 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -7,7 +7,7 @@ * is the identity morphism from B to B. */ @SuppressWarnings({"UnusedDeclaration"}) -public final class $ extends P1 { +public final class $ implements P1 { private final B b; From 458f4f80fadde0a5082927e92616383ff0d5a1a3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 27 May 2014 13:40:09 +1000 Subject: [PATCH 050/811] Fixed Scala tests --- .../test/scala/fj/control/parallel/CheckStrategy.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala b/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala index 3014e2f7..6a3409f3 100644 --- a/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala +++ b/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala @@ -24,19 +24,19 @@ object CheckStrategy extends Properties("Strategy") { property("par") = forAll((a: P1[Int], s: Strategy[Int]) => a._1 == s.par(a)._1) property("parMapList") = forAll((a: List[String], s: Strategy[String]) => - listEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1.__1[String], s.concurry[String](rev))))) + listEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1Functions.__1[String], s.concurry[String](rev))))) property("parMapArray") = forAll((a: Array[String], s: Strategy[String]) => - arrayEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1.__1[String], s.concurry[String](rev))))) + arrayEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1Functions.__1[String], s.concurry[String](rev))))) property("parFlatMapList") = forAll((a: List[String], st: Strategy[List[String]]) => { def f = (x: String) => single[String](x) - listEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1.__1[List[String]], st.concurry[String](f)))) + listEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1Functions.__1[List[String]], st.concurry[String](f)))) }) property("parFlatMapArray") = forAll((a: Array[String], st: Strategy[Array[String]]) => { def f = (x: String) => array[String](scala.Array(x): _*) - arrayEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1.__1[Array[String]], st.concurry[String](f)))) + arrayEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1Functions.__1[Array[String]], st.concurry[String](f)))) }) property("xmapID") = forAll((s: Strategy[Int], n: P1[Int]) => From 3403d479f7d98e7c0972696f170788679c788d68 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 29 May 2014 22:50:54 +1000 Subject: [PATCH 051/811] Changes to do final release 4.0 --- build.gradle | 4 ++-- core/build.gradle | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index f9df4b20..111adc83 100644 --- a/build.gradle +++ b/build.gradle @@ -14,12 +14,12 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.0" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = fjVersion + fjConsumeVersion = "$fjBaseVersion$snapshotAppendix" projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/core/build.gradle b/core/build.gradle index 58ad58f5..76cf561c 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -22,11 +22,41 @@ dependencies { testCompile "junit:junit:4.11" } + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from "build/docs/javadoc" +} + +task sourcesJar(type: Jar) { + from sourceSets.main.allSource + classifier = 'sources' +} + +artifacts { + archives jar + archives javadocJar + archives sourcesJar +} + +Boolean doSigning() { + signingEnabled.trim() == "true" +} + +if (doSigning()) { + apply plugin: "signing" + signing { + sign configurations.archives + } +} + uploadArchives { repositories { mavenDeployer { - // used for signing the artifacts, no need to sign snapshot, so leave out for now -// beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + if (doSigning()) { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + } repository(url: sonatypeUploadUrl) { authentication(userName: sonatypeUsername, password: sonatypePassword) From b0abad965d5a6acee43ec43de11fbe4af09f7d34 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 29 May 2014 23:28:08 +1000 Subject: [PATCH 052/811] Convert from snapshot to final 4.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8eee8e71..10984283 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.1" snapshotAppendix = "-SNAPSHOT" From d34c011ccaac464a2f3f754df4b205c6fc61172d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 30 May 2014 00:00:17 +1000 Subject: [PATCH 053/811] Changed version to 4.2-SNAPSHOT --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 10984283..8cc575cb 100644 --- a/build.gradle +++ b/build.gradle @@ -14,8 +14,8 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = false - fjBaseVersion = "4.1" + isSnapshot = true + fjBaseVersion = "4.2" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") From 9afbb8479583cf0bace42b5bc59e2711676772ba Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 30 May 2014 01:05:24 +1000 Subject: [PATCH 054/811] Disable signing by default. Fixed missing property --- gradle.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle.properties b/gradle.properties index ee5193b3..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,5 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd + +signingEnabled = false From 76b93776206af721afd19c26cb26b8d02861b8a7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 2 Jun 2014 00:18:33 +1000 Subject: [PATCH 055/811] Added java 8 examples --- demo/src/main/java/fj/demo/Array_exists.java | 1 + demo/src/main/java/fj/demo/Array_filter.java | 1 + demo/src/main/java/fj/demo/Array_foldLeft.java | 1 + demo/src/main/java/fj/demo/Array_forall.java | 1 + demo/src/main/java/fj/demo/Array_map.java | 13 ++++++++----- demo/src/main/java/fj/demo/List_map.java | 12 +++++++----- demo/src/main/java/fj/demo/Option_bind.java | 5 +++++ demo/src/main/java/fj/demo/Option_filter.java | 5 +++++ demo/src/main/java/fj/demo/Option_map.java | 4 ++++ 9 files changed, 33 insertions(+), 10 deletions(-) diff --git a/demo/src/main/java/fj/demo/Array_exists.java b/demo/src/main/java/fj/demo/Array_exists.java index 7d6e05d4..0089b475 100644 --- a/demo/src/main/java/fj/demo/Array_exists.java +++ b/demo/src/main/java/fj/demo/Array_exists.java @@ -14,6 +14,7 @@ public Boolean f(final String s) { return fromString(s).forall(isLowerCase); } }); + final boolean b2 = a.exists(s -> fromString(s).forall(isLowerCase)); System.out.println(b); // true ("what" provides the only example; try removing it) } } diff --git a/demo/src/main/java/fj/demo/Array_filter.java b/demo/src/main/java/fj/demo/Array_filter.java index 768e7032..9b5a9330 100644 --- a/demo/src/main/java/fj/demo/Array_filter.java +++ b/demo/src/main/java/fj/demo/Array_filter.java @@ -10,6 +10,7 @@ public final class Array_filter { public static void main(final String[] args) { final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); final Array b = a.filter(even); + final Array c = a.filter(i -> i % 2 == 0); arrayShow(intShow).println(b); // {44,22,90,98,1078,6,64,6,42} } } diff --git a/demo/src/main/java/fj/demo/Array_foldLeft.java b/demo/src/main/java/fj/demo/Array_foldLeft.java index 7e2010a2..1082a07b 100644 --- a/demo/src/main/java/fj/demo/Array_foldLeft.java +++ b/demo/src/main/java/fj/demo/Array_foldLeft.java @@ -8,6 +8,7 @@ public final class Array_foldLeft { public static void main(final String[] args) { final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); final int b = a.foldLeft(add, 0); + final int c = a.foldLeft(i -> (j -> i + j), 0); System.out.println(b); // 1774 } } diff --git a/demo/src/main/java/fj/demo/Array_forall.java b/demo/src/main/java/fj/demo/Array_forall.java index 9ff88456..c9888823 100644 --- a/demo/src/main/java/fj/demo/Array_forall.java +++ b/demo/src/main/java/fj/demo/Array_forall.java @@ -14,6 +14,7 @@ public Boolean f(final String s) { return fromString(s).forall(isLowerCase); } }); + final boolean b2 = a.forall(s -> fromString(s).forall(isLowerCase)); System.out.println(b); // false ("There" is a counter-example; try removing it) } } diff --git a/demo/src/main/java/fj/demo/Array_map.java b/demo/src/main/java/fj/demo/Array_map.java index 31af96a7..cc638c5c 100644 --- a/demo/src/main/java/fj/demo/Array_map.java +++ b/demo/src/main/java/fj/demo/Array_map.java @@ -1,15 +1,18 @@ package fj.demo; import fj.data.Array; + import static fj.data.Array.array; import static fj.function.Integers.add; import static fj.Show.arrayShow; import static fj.Show.intShow; public final class Array_map { - public static void main(final String[] args) { - final Array a = array(1, 2, 3); - final Array b = a.map(add.f(42)); - arrayShow(intShow).println(b); // {43,44,45} - } + public static void main(final String[] args) { + final Array a = array(1, 2, 3); + final Array b = a.map(add.f(42)); + final Array c = a.map(i -> i + 42); + arrayShow(intShow).println(b); // {43,44,45} + arrayShow(intShow).println(c); // {43,44,45} + } } diff --git a/demo/src/main/java/fj/demo/List_map.java b/demo/src/main/java/fj/demo/List_map.java index 9f5018f0..83f89ead 100644 --- a/demo/src/main/java/fj/demo/List_map.java +++ b/demo/src/main/java/fj/demo/List_map.java @@ -1,15 +1,17 @@ package fj.demo; import fj.data.List; + import static fj.data.List.list; import static fj.function.Integers.add; import static fj.Show.intShow; import static fj.Show.listShow; public final class List_map { - public static void main(final String[] args) { - final List a = list(1, 2, 3); - final List b = a.map(add.f(42)); - listShow(intShow).println(b); // [43,44,45] - } + public static void main(final String[] args) { + final List a = list(1, 2, 3); + final List b = a.map(add.f(42)); + final List c = a.map(i -> i = 42); + listShow(intShow).println(b); // [43,44,45] + } } diff --git a/demo/src/main/java/fj/demo/Option_bind.java b/demo/src/main/java/fj/demo/Option_bind.java index 7a2dea37..4a478a22 100644 --- a/demo/src/main/java/fj/demo/Option_bind.java +++ b/demo/src/main/java/fj/demo/Option_bind.java @@ -27,6 +27,11 @@ public Option f(final Integer i) { return i % 2 == 0 ? some(i * 3) : Option.none(); } }); + + final Option p4 = o1.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p5 = o2.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p6 = o3.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + optionShow(intShow).println(p1); // None optionShow(intShow).println(p2); // Some(24) optionShow(intShow).println(p3); // None diff --git a/demo/src/main/java/fj/demo/Option_filter.java b/demo/src/main/java/fj/demo/Option_filter.java index f7cc4a89..ee7fa1ca 100644 --- a/demo/src/main/java/fj/demo/Option_filter.java +++ b/demo/src/main/java/fj/demo/Option_filter.java @@ -15,6 +15,11 @@ public static void main(final String[] args) { final Option p1 = o1.filter(even); final Option p2 = o2.filter(even); final Option p3 = o3.filter(even); + + final Option p4 = o1.filter(i -> i % 2 == 0); + final Option p5 = o1.filter(i -> i % 2 == 0); + final Option p6 = o1.filter(i -> i % 2 == 0); + optionShow(intShow).println(p1); // None optionShow(intShow).println(p2); // None optionShow(intShow).println(p3); // Some(8) diff --git a/demo/src/main/java/fj/demo/Option_map.java b/demo/src/main/java/fj/demo/Option_map.java index e883427f..5f947b04 100644 --- a/demo/src/main/java/fj/demo/Option_map.java +++ b/demo/src/main/java/fj/demo/Option_map.java @@ -13,6 +13,10 @@ public static void main(final String[] args) { final Option o2 = none(); final Option p1 = o1.map(add.f(42)); final Option p2 = o2.map(add.f(42)); + + final Option p3 = o1.map(i -> i + 42); + final Option p4 = o2.map(i -> i + 42); + optionShow(intShow).println(p1); // Some(49) optionShow(intShow).println(p2); // None } From c9d082037b6d7d8a40ba3996f2570f402e4bb4eb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 2 Jun 2014 01:48:51 +1000 Subject: [PATCH 056/811] Added old and new website URLs to readme --- README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README b/README index e5c7f631..ac0e5fb3 100644 --- a/README +++ b/README @@ -2,6 +2,10 @@ Functional Java is an open source library that seeks to improve the experience o Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. +Note that the website is in the midst of being updated. The URLs are: +* [functionaljava.org] (old site) +* [functionaljava.github.io] (new site) + Functional Java includes the following features: * Fully operational Actors for parallel computations (fj.control.parallel) and layered abstractions such as parallel-map, map-reduce, parallel-zip. From 970c7427afdbb5528fb5054c4b406cc4365c5685 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 2 Jun 2014 01:51:08 +1000 Subject: [PATCH 057/811] Fixed site URLs --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index ac0e5fb3..694119ef 100644 --- a/README +++ b/README @@ -3,8 +3,8 @@ Functional Java is an open source library that seeks to improve the experience o Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Note that the website is in the midst of being updated. The URLs are: -* [functionaljava.org] (old site) -* [functionaljava.github.io] (new site) +* http://functionaljava.org (old site) +* http://functionaljava.github.io (new site) Functional Java includes the following features: From c6b1fa45879d3017907d3da6c9e591ff5a0dbe6f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 2 Jun 2014 02:01:16 +1000 Subject: [PATCH 058/811] Added github new website url --- README | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README b/README index 694119ef..a56eda18 100644 --- a/README +++ b/README @@ -3,8 +3,9 @@ Functional Java is an open source library that seeks to improve the experience o Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Note that the website is in the midst of being updated. The URLs are: -* http://functionaljava.org (old site) -* http://functionaljava.github.io (new site) +* Old site, http://functionaljava.org +* New site, http://functionaljava.github.io +* New website on Github, https://github.com/functionaljava/functionaljava.github.io Functional Java includes the following features: From d0dc441bd94439a7126896c2dd157fece204865f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 2 Jun 2014 21:59:55 +1000 Subject: [PATCH 059/811] Merged github issue #13 --- core/src/main/java/fj/data/TreeMap.java | 4 +--- core/src/test/java/fj/data/TestTreeMap.java | 26 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 core/src/test/java/fj/data/TestTreeMap.java diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index af871cdc..636dce7b 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -60,9 +60,7 @@ public Option get(final K k) { * @return A new tree map with the given value mapped to the given key. */ public TreeMap set(final K k, final V v) { - final P3>>, Option>>, Set>>> x - = tree.split(P.p(k, Option.none())); - return new TreeMap(x._1().union(x._3().insert(P.p(k, Option.some(v))))); + return new TreeMap(tree.insert(P.p(k, Option.some(v)))); } /** diff --git a/core/src/test/java/fj/data/TestTreeMap.java b/core/src/test/java/fj/data/TestTreeMap.java new file mode 100644 index 00000000..d4dcf5ba --- /dev/null +++ b/core/src/test/java/fj/data/TestTreeMap.java @@ -0,0 +1,26 @@ +package fj.data; + +import fj.Ord; +import fj.P2; +import org.junit.Test; + +import java.util.ArrayList; + +/** + * Created by MarkPerry on 2/06/2014. + */ +public class TestTreeMap { + + @Test + public void testLargeInserts() { + // check that inserting a large number of items performs ok + // taken from https://code.google.com/p/functionaljava/issues/detail?id=31 and + // https://github.com/functionaljava/functionaljava/pull/13/files + final int n = 10000; + TreeMap m = TreeMap.empty(Ord.intOrd); + for (int i = 0; i < n; i++) { + m = m.set(i, "abc " + i); + } + } + +} From 9c1b4468bce6b1567e847c04d469a8344e855f68 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 07:09:21 +1000 Subject: [PATCH 060/811] First attempt at functions that throw exceptions --- core/src/main/java/fj/F1Functions.java | 10 +++++++ core/src/main/java/fj/F2Functions.java | 11 ++++++++ core/src/main/java/fj/F3Functions.java | 13 +++++++++ core/src/main/java/fj/F4Functions.java | 12 ++++++++ core/src/main/java/fj/Try.java | 32 ++++++++++++++++++++++ core/src/main/java/fj/Try1.java | 10 +++++++ core/src/main/java/fj/Try2.java | 10 +++++++ core/src/main/java/fj/Try3.java | 10 +++++++ core/src/main/java/fj/Try4.java | 10 +++++++ core/src/main/java/fj/data/Validation.java | 4 +-- 10 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/fj/Try.java create mode 100644 core/src/main/java/fj/Try1.java create mode 100644 core/src/main/java/fj/Try2.java create mode 100644 core/src/main/java/fj/Try3.java create mode 100644 core/src/main/java/fj/Try4.java diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 255f1798..ca09cac2 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -824,4 +824,14 @@ static public ArrayList mapJ(final F f, final ArrayList as) { return new ArrayList(iterableStream(as).map(f).toCollection()); } + static public F> toF1(final Try1 t) { + return a -> { + try { + return Try.trySuccess(t.f(a)); + } catch (Exception e) { + return Try.tryFail(e); + } + }; + } + } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index f2e0a8b1..b23d4c6e 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -346,4 +346,15 @@ public P3>, C, Stream>> f(final P3>, A, St }; } + + static public F2> toF2(final Try2 t) { + return (a, b) -> { + try { + return Try.trySuccess(t.f(a, b)); + } catch (Exception e) { + return Try.tryFail(e); + } + }; + } + } diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 5700414e..59dbf3d0 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -4,4 +4,17 @@ * Created by MarkPerry on 6/04/2014. */ public class F3Functions { + + + + static public F3> toF3(final Try3 t) { + return (a, b, c) -> { + try { + return Try.trySuccess(t.f(a, b, c)); + } catch (Exception e) { + return Try.tryFail(e); + } + }; + } + } diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index e29eb49c..9387c1cf 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -4,4 +4,16 @@ * Created by MarkPerry on 6/04/2014. */ public class F4Functions { + + + static public F4> toF4(final Try4 t) { + return (a, b, c, d) -> { + try { + return Try.trySuccess(t.f(a, b, c, d)); + } catch (Exception e) { + return Try.tryFail(e); + } + }; + } + } diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java new file mode 100644 index 00000000..00c62132 --- /dev/null +++ b/core/src/main/java/fj/Try.java @@ -0,0 +1,32 @@ +package fj; + +import fj.data.Either; +import fj.data.Validation; + +/** + * Created by MarkPerry on 2/06/2014. + */ +public class Try extends Validation { + + public static Try toTry(Validation v) { + return toTry(v.toEither()); + } + + public static Try toTry(Either e) { + return new Try(e); + } + + public Try(Either e) { + super(e); + } + + public static Try trySuccess(B b) { + return toTry(Validation.success(b)); + } + + public static Try tryFail(Exception e) { + return toTry(Validation.fail(e)); + } + + +} diff --git a/core/src/main/java/fj/Try1.java b/core/src/main/java/fj/Try1.java new file mode 100644 index 00000000..0ccded46 --- /dev/null +++ b/core/src/main/java/fj/Try1.java @@ -0,0 +1,10 @@ +package fj; + +/** + * Created by MarkPerry on 2/06/2014. + */ +public interface Try1 { + + B f(A a) throws Exception; + +} diff --git a/core/src/main/java/fj/Try2.java b/core/src/main/java/fj/Try2.java new file mode 100644 index 00000000..6fae10ed --- /dev/null +++ b/core/src/main/java/fj/Try2.java @@ -0,0 +1,10 @@ +package fj; + +/** + * Created by MarkPerry on 2/06/2014. + */ +public interface Try2 { + + C f(A a, B b) throws Exception; + +} diff --git a/core/src/main/java/fj/Try3.java b/core/src/main/java/fj/Try3.java new file mode 100644 index 00000000..e2a5b800 --- /dev/null +++ b/core/src/main/java/fj/Try3.java @@ -0,0 +1,10 @@ +package fj; + +/** + * Created by MarkPerry on 2/06/2014. + */ +public interface Try3 { + + D f(A a, B b, C c) throws Exception; + +} diff --git a/core/src/main/java/fj/Try4.java b/core/src/main/java/fj/Try4.java new file mode 100644 index 00000000..029a0446 --- /dev/null +++ b/core/src/main/java/fj/Try4.java @@ -0,0 +1,10 @@ +package fj; + +/** + * Created by MarkPerry on 2/06/2014. + */ +public interface Try4 { + + E f(A a, B b, C c, D d) throws Exception; + +} diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 3b5edcd0..2b8af875 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -30,10 +30,10 @@ * * @version %build.number% */ -public final class Validation implements Iterable { +public class Validation implements Iterable { private final Either e; - private Validation(final Either e) { + protected Validation(final Either e) { this.e = e; } From 710c80f235b089755f0cb61fc2d0b63827a33077 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 11:17:19 +1000 Subject: [PATCH 061/811] Added support for lambdas that throw exceptions --- core/build.gradle | 26 +++++++++++++++++---- core/src/main/java/fj/F1Functions.java | 12 +++++++--- core/src/main/java/fj/F2Functions.java | 12 +++++++--- core/src/main/java/fj/F3Functions.java | 19 +++++++++++---- core/src/main/java/fj/F4Functions.java | 16 +++++++++---- core/src/main/java/fj/F5Functions.java | 19 +++++++++++++++ core/src/main/java/fj/F6Functions.java | 19 +++++++++++++++ core/src/main/java/fj/F7Functions.java | 19 +++++++++++++++ core/src/main/java/fj/F8Functions.java | 19 +++++++++++++++ core/src/main/java/fj/P1Functions.java | 17 ++++++++++++++ core/src/main/java/fj/Try.java | 32 -------------------------- core/src/main/java/fj/Try1.java | 10 -------- core/src/main/java/fj/Try2.java | 10 -------- core/src/main/java/fj/Try3.java | 10 -------- core/src/main/java/fj/Try4.java | 10 -------- core/src/main/java/fj/TryCatch0.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch1.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch2.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch3.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch4.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch5.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch6.java | 16 +++++++++++++ core/src/main/java/fj/TryCatch7.java | 17 ++++++++++++++ core/src/main/java/fj/TryCatch8.java | 16 +++++++++++++ 24 files changed, 304 insertions(+), 91 deletions(-) delete mode 100644 core/src/main/java/fj/Try.java delete mode 100644 core/src/main/java/fj/Try1.java delete mode 100644 core/src/main/java/fj/Try2.java delete mode 100644 core/src/main/java/fj/Try3.java delete mode 100644 core/src/main/java/fj/Try4.java create mode 100644 core/src/main/java/fj/TryCatch0.java create mode 100644 core/src/main/java/fj/TryCatch1.java create mode 100644 core/src/main/java/fj/TryCatch2.java create mode 100644 core/src/main/java/fj/TryCatch3.java create mode 100644 core/src/main/java/fj/TryCatch4.java create mode 100644 core/src/main/java/fj/TryCatch5.java create mode 100644 core/src/main/java/fj/TryCatch6.java create mode 100644 core/src/main/java/fj/TryCatch7.java create mode 100644 core/src/main/java/fj/TryCatch8.java diff --git a/core/build.gradle b/core/build.gradle index e05888a6..7448af0f 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,7 +1,19 @@ + +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'me.tatarka:gradle-retrolambda:1.3.1' + } +} + apply plugin: 'java' apply plugin: 'maven' //apply plugin: 'signing' +apply plugin: 'retrolambda' defaultTasks 'build' @@ -23,11 +35,17 @@ dependencies { } -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from "build/docs/javadoc" +retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 } +//task javadocJar(type: Jar, dependsOn: javadoc) { +// classifier = 'javadoc' +// from "build/docs/javadoc" +//} + task sourcesJar(type: Jar) { from sourceSets.main.allSource classifier = 'sources' @@ -35,7 +53,7 @@ task sourcesJar(type: Jar) { artifacts { archives jar - archives javadocJar +// archives javadocJar archives sourcesJar } diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index ca09cac2..fada67ff 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -824,12 +824,18 @@ static public ArrayList mapJ(final F f, final ArrayList as) { return new ArrayList(iterableStream(as).map(f).toCollection()); } - static public F> toF1(final Try1 t) { + /** + * Promotes the TryCatch1 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch1 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F> toF1(final TryCatch1 t) { return a -> { try { - return Try.trySuccess(t.f(a)); + return Validation.success(t.f(a)); } catch (Exception e) { - return Try.tryFail(e); + return Validation.fail(e); } }; } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index b23d4c6e..a71179c5 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -347,12 +347,18 @@ public P3>, C, Stream>> f(final P3>, A, St } - static public F2> toF2(final Try2 t) { + /** + * Promotes the TryCatch2 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch2 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F2> toF2(final TryCatch2 t) { return (a, b) -> { try { - return Try.trySuccess(t.f(a, b)); + return Validation.success(t.f(a, b)); } catch (Exception e) { - return Try.tryFail(e); + return Validation.fail(e); } }; } diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 59dbf3d0..394f9eb4 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -1,18 +1,27 @@ package fj; +import fj.data.Validation; + +import static fj.data.Validation.fail; +import static fj.data.Validation.success; + /** * Created by MarkPerry on 6/04/2014. */ public class F3Functions { - - - static public F3> toF3(final Try3 t) { + /** + * Promotes the TryCatch3 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch3 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F3> toF3(final TryCatch3 t) { return (a, b, c) -> { try { - return Try.trySuccess(t.f(a, b, c)); + return success(t.f(a, b, c)); } catch (Exception e) { - return Try.tryFail(e); + return fail(e); } }; } diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index 9387c1cf..07bd6e9a 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -1,17 +1,25 @@ package fj; +import fj.data.Validation; + /** * Created by MarkPerry on 6/04/2014. */ public class F4Functions { - static public F4> toF4(final Try4 t) { + /** + * Promotes the TryCatch4 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch4 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F4> toF4(final TryCatch4 t) { return (a, b, c, d) -> { try { - return Try.trySuccess(t.f(a, b, c, d)); - } catch (Exception e) { - return Try.tryFail(e); + return Validation.success(t.f(a, b, c, d)); + } catch (Exception ex) { + return Validation.fail(ex); } }; } diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index 13600c6f..fa67911e 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -1,7 +1,26 @@ package fj; +import fj.data.Validation; + /** * Created by MarkPerry on 6/04/2014. */ public class F5Functions { + + /** + * Promotes the TryCatch5 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch5 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F5> toF5(final TryCatch5 t) { + return (a, b, c, d, e) -> { + try { + return Validation.success(t.f(a, b, c, d, e)); + } catch (Exception ex) { + return Validation.fail(ex); + } + }; + } + } diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 70d4ed97..66764079 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -1,7 +1,26 @@ package fj; +import fj.data.Validation; + /** * Created by MarkPerry on 6/04/2014. */ public class F6Functions { + + /** + * Promotes the TryCatch6 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch6 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F6> toF6(final TryCatch6 t) { + return (a, b, c, d, e, f) -> { + try { + return Validation.success(t.f(a, b, c, d, e, f)); + } catch (Exception ex) { + return Validation.fail(ex); + } + }; + } + } diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 17f3643a..9450b31c 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -1,7 +1,26 @@ package fj; +import fj.data.Validation; + /** * Created by MarkPerry on 6/04/2014. */ public class F7Functions { + + /** + * Promotes the TryCatch7 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch7 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F7> toF7(final TryCatch7 t) { + return (a, b, c, d, e, f, g) -> { + try { + return Validation.success(t.f(a, b, c, d, e, f, g)); + } catch (Exception ex) { + return Validation.fail(ex); + } + }; + } + } diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index f4d9b07d..2be7f58d 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -1,7 +1,26 @@ package fj; +import fj.data.Validation; + /** * Created by MarkPerry on 6/04/2014. */ public class F8Functions { + + /** + * Promotes the TryCatch8 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch8 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F8> toF8(final TryCatch8 t) { + return (a, b, c, d, e, f, g, h) -> { + try { + return Validation.success(t.f(a, b, c, d, e, f, g, h)); + } catch (Exception ex) { + return Validation.fail(ex); + } + }; + } + } diff --git a/core/src/main/java/fj/P1Functions.java b/core/src/main/java/fj/P1Functions.java index b0f6bfb3..672e0368 100644 --- a/core/src/main/java/fj/P1Functions.java +++ b/core/src/main/java/fj/P1Functions.java @@ -5,6 +5,7 @@ import fj.data.Array; import fj.data.List; import fj.data.Stream; +import fj.data.Validation; public final class P1Functions { @@ -217,4 +218,20 @@ public A f(final B b) { }; } + /** + * Promotes the TryCatch0 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch0 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public P1> toP1(final TryCatch0 t) { + return () -> { + try { + return Validation.success(t.f()); + } catch (Exception e) { + return Validation.fail(e); + } + }; + } + } diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java deleted file mode 100644 index 00c62132..00000000 --- a/core/src/main/java/fj/Try.java +++ /dev/null @@ -1,32 +0,0 @@ -package fj; - -import fj.data.Either; -import fj.data.Validation; - -/** - * Created by MarkPerry on 2/06/2014. - */ -public class Try extends Validation { - - public static Try toTry(Validation v) { - return toTry(v.toEither()); - } - - public static Try toTry(Either e) { - return new Try(e); - } - - public Try(Either e) { - super(e); - } - - public static Try trySuccess(B b) { - return toTry(Validation.success(b)); - } - - public static Try tryFail(Exception e) { - return toTry(Validation.fail(e)); - } - - -} diff --git a/core/src/main/java/fj/Try1.java b/core/src/main/java/fj/Try1.java deleted file mode 100644 index 0ccded46..00000000 --- a/core/src/main/java/fj/Try1.java +++ /dev/null @@ -1,10 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 2/06/2014. - */ -public interface Try1 { - - B f(A a) throws Exception; - -} diff --git a/core/src/main/java/fj/Try2.java b/core/src/main/java/fj/Try2.java deleted file mode 100644 index 6fae10ed..00000000 --- a/core/src/main/java/fj/Try2.java +++ /dev/null @@ -1,10 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 2/06/2014. - */ -public interface Try2 { - - C f(A a, B b) throws Exception; - -} diff --git a/core/src/main/java/fj/Try3.java b/core/src/main/java/fj/Try3.java deleted file mode 100644 index e2a5b800..00000000 --- a/core/src/main/java/fj/Try3.java +++ /dev/null @@ -1,10 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 2/06/2014. - */ -public interface Try3 { - - D f(A a, B b, C c) throws Exception; - -} diff --git a/core/src/main/java/fj/Try4.java b/core/src/main/java/fj/Try4.java deleted file mode 100644 index 029a0446..00000000 --- a/core/src/main/java/fj/Try4.java +++ /dev/null @@ -1,10 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 2/06/2014. - */ -public interface Try4 { - - E f(A a, B b, C c, D d) throws Exception; - -} diff --git a/core/src/main/java/fj/TryCatch0.java b/core/src/main/java/fj/TryCatch0.java new file mode 100644 index 00000000..9e0b9aaf --- /dev/null +++ b/core/src/main/java/fj/TryCatch0.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A product of A which may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to a P1. + * + * @see P1Functions#toP1 + * @version %build.number% + */ + +public interface TryCatch0 { + + A f() throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch1.java b/core/src/main/java/fj/TryCatch1.java new file mode 100644 index 00000000..28e83664 --- /dev/null +++ b/core/src/main/java/fj/TryCatch1.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function from A to B that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F. + * + * @see F1Functions#toF1 + * @version %build.number% + */ + +public interface TryCatch1 { + + B f(A a) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch2.java b/core/src/main/java/fj/TryCatch2.java new file mode 100644 index 00000000..3ac3145a --- /dev/null +++ b/core/src/main/java/fj/TryCatch2.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function of arity-2 from A and B to C that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F2. + * + * @see F2Functions#toF2 + * @version %build.number% + */ + +public interface TryCatch2 { + + C f(A a, B b) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch3.java b/core/src/main/java/fj/TryCatch3.java new file mode 100644 index 00000000..35f26d5f --- /dev/null +++ b/core/src/main/java/fj/TryCatch3.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function of arity-3 from A, B and C to D that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F3. + * + * @see F3Functions#toF3 + * @version %build.number% + */ + +public interface TryCatch3 { + + D f(A a, B b, C c) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch4.java b/core/src/main/java/fj/TryCatch4.java new file mode 100644 index 00000000..b07edf3c --- /dev/null +++ b/core/src/main/java/fj/TryCatch4.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function of arity-4 from A, B, C and D to E that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F4. + * + * @see F4Functions#toF4 + * @version %build.number% + */ + +public interface TryCatch4 { + + E f(A a, B b, C c, D d) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch5.java b/core/src/main/java/fj/TryCatch5.java new file mode 100644 index 00000000..b47f339e --- /dev/null +++ b/core/src/main/java/fj/TryCatch5.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function of arity-5 from A, B, C, D and E to F that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F5. + * + * @see F5Functions#toF5 + * @version %build.number% + */ + +public interface TryCatch5 { + + F f(A a, B b, C c, D d, E e) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch6.java b/core/src/main/java/fj/TryCatch6.java new file mode 100644 index 00000000..5453a747 --- /dev/null +++ b/core/src/main/java/fj/TryCatch6.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function of arity-6 from A, B, C, D, E and F to G that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F6. + * + * @see F6Functions#toF6 + * @version %build.number% + */ + +public interface TryCatch6 { + + G f(A a, B b, C c, D d, E e, F f) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch7.java b/core/src/main/java/fj/TryCatch7.java new file mode 100644 index 00000000..f38ea0cd --- /dev/null +++ b/core/src/main/java/fj/TryCatch7.java @@ -0,0 +1,17 @@ +package fj; + + +/** + * A transformation function of arity-7 from A, B, C, D, E, F and G to H that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F7. + * + * @see F7Functions#toF7 + * @version %build.number% + */ + +public interface TryCatch7 { + + H f(A a, B b, C c, D d, E e, F f, G g) throws Exception; + +} diff --git a/core/src/main/java/fj/TryCatch8.java b/core/src/main/java/fj/TryCatch8.java new file mode 100644 index 00000000..db8661b5 --- /dev/null +++ b/core/src/main/java/fj/TryCatch8.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A transformation function of arity-8 from A, B, C, D, E, F, G and H to I that may throw an Exception. + * + * Used to instantiate a lambda that may throw an Exception before converting to an F8. + * + * @see F8Functions#toF8 + * @version %build.number% + */ + +public interface TryCatch8 { + + I f(A a, B b, C c, D d, E e, F f, G g, H h) throws Exception; + +} From 8c88a73727c6f57ab62f63b5ea79264aac7f2fd8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 11:47:15 +1000 Subject: [PATCH 062/811] Added conversion from fj to the base Java 8 function types --- .gitignore | 3 +- java8/build.gradle | 32 +++++++++++++++++++ java8/src/main/java/fj/data/Java8.java | 44 ++++++++++++++++++++++++++ settings.gradle | 2 +- 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 java8/build.gradle create mode 100644 java8/src/main/java/fj/data/Java8.java diff --git a/.gitignore b/.gitignore index a7414e46..28b13f3f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,5 @@ build .settings .classpath .project - - +.DS_Store diff --git a/java8/build.gradle b/java8/build.gradle new file mode 100644 index 00000000..0e9c8ab5 --- /dev/null +++ b/java8/build.gradle @@ -0,0 +1,32 @@ + +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'me.tatarka:gradle-retrolambda:1.3.1' + } +} + +apply plugin: 'java' +apply plugin: 'retrolambda' + +defaultTasks 'build' + +repositories { + mavenCentral() +} + +retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 +} + +dependencies { +// compile 'org.slf4j:slf4j-api:1.7.5' + compile project(":core") + + testCompile "junit:junit:4.11" +} diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java new file mode 100644 index 00000000..78333be1 --- /dev/null +++ b/java8/src/main/java/fj/data/Java8.java @@ -0,0 +1,44 @@ +package fj.data; + +import fj.F; +import fj.F2; +import fj.P1; + +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * Created by mperry on 3/06/2014. + */ +public final class Java8 { + + private Java8() { + throw new UnsupportedOperationException(); + } + + public static P1 toP1(Supplier f) { + return () -> f.get(); + } + + public static Supplier toSupplier(P1 p) { + return () -> p._1(); + } + + public static F toF(Function f) { + return a -> f.apply(a); + } + + public static F toFunction(F f) { + return a -> f.f(a); + } + + public static F2 toF2(BiFunction f) { + return (a, b) -> f.apply(a, b); + } + + public static BiFunction toBiFunction(F2 f) { + return (a, b) -> f.f(a, b); + } + +} diff --git a/settings.gradle b/settings.gradle index 754f592d..0ffcbb50 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ -include 'core', 'demo', "tests", "consume" +include 'core', 'demo', "tests", "consume", "java8" // The final Java 8 release, (build 1.8.0-b132) does not work with Gradle and the Scala plugin // see http://issues.gradle.org/browse/GRADLE-3023 From 7993ede4e93010c7b38f80a1eb3fb0c0b0347d3a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 12:00:13 +1000 Subject: [PATCH 063/811] Added conversion from lambdas with exceptions to Java 8 base function types --- java8/src/main/java/fj/data/Java8.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 78333be1..dc6a8722 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -1,8 +1,6 @@ package fj.data; -import fj.F; -import fj.F2; -import fj.P1; +import fj.*; import java.util.function.BiFunction; import java.util.function.Function; @@ -29,7 +27,7 @@ public static F toF(Function f) { return a -> f.apply(a); } - public static F toFunction(F f) { + public static Function toFunction(F f) { return a -> f.f(a); } @@ -41,4 +39,16 @@ public static BiFunction toBiFunction(F2 f) { return (a, b) -> f.f(a, b); } + static public Supplier> toSupplier(final TryCatch0 t) { + return toSupplier(P1Functions.toP1(t)); + } + + static public Function> toFunction(final TryCatch1 t) { + return toFunction(F1Functions.toF1(t)); + } + + static public BiFunction> toBiFunction(final TryCatch2 t) { + return toBiFunction(F2Functions.toF2(t)); + } + } From 33af6436c363312ca41e8dbcd92001993f8a4df0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 12:04:52 +1000 Subject: [PATCH 064/811] Consume for demo version 4.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8cc575cb..76cd0e1d 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "$fjBaseVersion$snapshotAppendix" + fjConsumeVersion = "4.1" projectTitle = "Functional Java" projectName = "functionaljava" From 6c86d4fafc604ff2fd29ad14e0b6884847bc24ae Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 16:07:09 +1000 Subject: [PATCH 065/811] Got Java 8 Javadoc working --- build.gradle | 8 ++++++++ core/build.gradle | 14 ++++++++----- demo/build.gradle | 6 ++++++ java8/build.gradle | 11 +++++++++++ lib.gradle | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 lib.gradle diff --git a/build.gradle b/build.gradle index 76cd0e1d..0b3ee955 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,6 @@ +import org.apache.tools.ant.taskdefs.condition.Os + defaultTasks 'build' ext { @@ -12,7 +14,10 @@ if (JavaVersion.current().isJava8Compatible()) { } } + allprojects { + + ext { isSnapshot = true fjBaseVersion = "4.2" @@ -43,4 +48,7 @@ allprojects { subprojects { + + + } diff --git a/core/build.gradle b/core/build.gradle index 7448af0f..422ceab6 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -15,6 +15,8 @@ apply plugin: 'maven' //apply plugin: 'signing' apply plugin: 'retrolambda' +apply from: "$rootDir/lib.gradle" + defaultTasks 'build' jar { @@ -34,6 +36,8 @@ dependencies { testCompile "junit:junit:4.11" } +task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { +} retrolambda { jdk System.getenv("JAVA8_HOME") @@ -41,10 +45,10 @@ retrolambda { javaVersion JavaVersion.VERSION_1_7 } -//task javadocJar(type: Jar, dependsOn: javadoc) { -// classifier = 'javadoc' -// from "build/docs/javadoc" -//} +task javadocJar(type: Jar, dependsOn: java8Javadoc) { + classifier = 'javadoc' + from "build/docs/javadoc" +} task sourcesJar(type: Jar) { from sourceSets.main.allSource @@ -53,7 +57,7 @@ task sourcesJar(type: Jar) { artifacts { archives jar -// archives javadocJar + archives javadocJar archives sourcesJar } diff --git a/demo/build.gradle b/demo/build.gradle index 6d4288db..4991116f 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -13,6 +13,7 @@ buildscript { apply plugin: 'java' apply plugin: 'application' apply plugin: 'retrolambda' +apply from: "$rootDir/lib.gradle" defaultTasks 'build' @@ -27,6 +28,11 @@ repositories { mavenCentral() } +//task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { +task javadoc(type: Javadoc, overwrite: true) { + def t = createDynamicJavadoc("$projectDir", ["core"]) + dependsOn(t) +} retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/java8/build.gradle b/java8/build.gradle index 0e9c8ab5..b0846e89 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -12,12 +12,23 @@ buildscript { apply plugin: 'java' apply plugin: 'retrolambda' +apply from: "$rootDir/lib.gradle" + defaultTasks 'build' repositories { mavenCentral() } +//task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { +//} + +task javadoc(type: Javadoc, overwrite: true) { + def t = createDynamicJavadoc("$projectDir", ["core"]) +// dependsOn(":$t.name") + dependsOn(t) +} + retrolambda { jdk System.getenv("JAVA8_HOME") oldJdk System.getenv("JAVA7_HOME") diff --git a/lib.gradle b/lib.gradle new file mode 100644 index 00000000..477f7c2b --- /dev/null +++ b/lib.gradle @@ -0,0 +1,49 @@ + +import org.apache.tools.ant.taskdefs.condition.Os + + +String findCommand(String dir, String command) { + def extension = Os.isFamily(Os.FAMILY_WINDOWS) ? ".exe" : "" + def cmd = "$dir/$command$extension" + if (! new File(cmd).exists()) { + throw new Exception("Command $command not found in dir $dir") + } + cmd + +} + +String findJavaCommand(String s) { + def jh = System.getenv("JAVA8_HOME") + if (jh == null) { + throw new Exception("Environment variable JAVA8_HOME not set") + } + findCommand("$jh/bin", "javadoc") +} + +List projectClasses(List list) { + list.collect { +// "$projectDir/../$it/src/main/java" + "$projectDir/../$it/build/classes/main" + } + +} + +def createDynamicJavadoc(String mainPath, List paths) { + def taskName = "dynamicJava8Javadoc" + task "$taskName"(type: Exec) { + def cp = projectClasses(paths).join(";") + def c = findJavaCommand("javadoc") + commandLine c, "-sourcepath", "$mainPath/src/main/java", "-d", "$mainPath/build/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet", "-classpath", cp + } + project.tasks[taskName] +} + +ext { + createDynamicJavadoc = this.&createDynamicJavadoc +} + +task java8Javadoc(type: Exec) { + def c = findJavaCommand("javadoc") + commandLine c, "-sourcepath", "$projectDir/src/main/java", "-d", "$buildDir/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet" +} + From e7a895305cfd1838f3dd20ddffac4649d7c19941 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Jun 2014 16:09:53 +1000 Subject: [PATCH 066/811] Clean up javadoc related production --- demo/build.gradle | 1 - java8/build.gradle | 5 ----- lib.gradle | 3 --- 3 files changed, 9 deletions(-) diff --git a/demo/build.gradle b/demo/build.gradle index 4991116f..89bdfd15 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -28,7 +28,6 @@ repositories { mavenCentral() } -//task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { task javadoc(type: Javadoc, overwrite: true) { def t = createDynamicJavadoc("$projectDir", ["core"]) dependsOn(t) diff --git a/java8/build.gradle b/java8/build.gradle index b0846e89..16e0fbe1 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -20,12 +20,8 @@ repositories { mavenCentral() } -//task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { -//} - task javadoc(type: Javadoc, overwrite: true) { def t = createDynamicJavadoc("$projectDir", ["core"]) -// dependsOn(":$t.name") dependsOn(t) } @@ -36,7 +32,6 @@ retrolambda { } dependencies { -// compile 'org.slf4j:slf4j-api:1.7.5' compile project(":core") testCompile "junit:junit:4.11" diff --git a/lib.gradle b/lib.gradle index 477f7c2b..a2329f09 100644 --- a/lib.gradle +++ b/lib.gradle @@ -1,7 +1,6 @@ import org.apache.tools.ant.taskdefs.condition.Os - String findCommand(String dir, String command) { def extension = Os.isFamily(Os.FAMILY_WINDOWS) ? ".exe" : "" def cmd = "$dir/$command$extension" @@ -9,7 +8,6 @@ String findCommand(String dir, String command) { throw new Exception("Command $command not found in dir $dir") } cmd - } String findJavaCommand(String s) { @@ -22,7 +20,6 @@ String findJavaCommand(String s) { List projectClasses(List list) { list.collect { -// "$projectDir/../$it/src/main/java" "$projectDir/../$it/build/classes/main" } From 9a0f847c19fb7edb020f25a2f859a33853296b23 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 4 Jun 2014 12:20:23 +1000 Subject: [PATCH 067/811] Compile java8 with separate jvm --- java8/build.gradle | 28 +++----- java8/src/main/java/fj/data/Java8.java | 89 ++++++++++++++++++++------ 2 files changed, 81 insertions(+), 36 deletions(-) diff --git a/java8/build.gradle b/java8/build.gradle index 16e0fbe1..c0cc500d 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -1,16 +1,5 @@ -buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath 'me.tatarka:gradle-retrolambda:1.3.1' - } -} - apply plugin: 'java' -apply plugin: 'retrolambda' apply from: "$rootDir/lib.gradle" @@ -25,14 +14,17 @@ task javadoc(type: Javadoc, overwrite: true) { dependsOn(t) } -retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 -} - dependencies { compile project(":core") - testCompile "junit:junit:4.11" } + +compileJava { + def jh = System.getenv("JAVA8_HOME") + if (jh == null) { + throw new Exception("JAVA8_HOME environment variable not set") + } + options.fork = true + options.forkOptions.executable = "$jh/bin/javac" +} + diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index dc6a8722..983fd107 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -2,6 +2,7 @@ import fj.*; +import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; @@ -15,40 +16,92 @@ private Java8() { throw new UnsupportedOperationException(); } - public static P1 toP1(Supplier f) { - return () -> f.get(); + public static P1 Supplier_P1(final Supplier s) { + return Java8.Supplier_P1().f(s); } - public static Supplier toSupplier(P1 p) { - return () -> p._1(); + public static F, P1> Supplier_P1() { + return s -> () -> s.get(); } - public static F toF(Function f) { - return a -> f.apply(a); + public static Supplier P1_Supplier(final P1 p) { + return Java8.P1_Supplier().f(p); } - public static Function toFunction(F f) { - return a -> f.f(a); + public static F, Supplier> P1_Supplier() { + return (p) -> () -> p._1(); } - public static F2 toF2(BiFunction f) { - return (a, b) -> f.apply(a, b); + public static F Function_F(final Function f) { + return Java8.Function_F().f(f); } - public static BiFunction toBiFunction(F2 f) { - return (a, b) -> f.f(a, b); + public static F, F> Function_F() { + return f -> a -> f.apply(a); } - static public Supplier> toSupplier(final TryCatch0 t) { - return toSupplier(P1Functions.toP1(t)); + public static Function F_Function(final F f) { + return Java8.F_Function().f(f); } - static public Function> toFunction(final TryCatch1 t) { - return toFunction(F1Functions.toF1(t)); + public static F, Function> F_Function() { + return f -> a -> f.f(a); } - static public BiFunction> toBiFunction(final TryCatch2 t) { - return toBiFunction(F2Functions.toF2(t)); + public static F2 BiFunction_F2(final BiFunction f) { + return Java8.BiFunction_F2().f(f); + } + + public static F, F2> BiFunction_F2() { + return f -> (a, b) -> f.apply(a, b); + } + + public static BiFunction F2_BiFunction(final F2 f) { + return Java8.F2_BiFunction().f(f); + } + + public static F, BiFunction> F2_BiFunction() { + return f -> (a, b) -> f.f(a, b); + } + + static public Supplier> TryCatch0_Supplier(final TryCatch0 t) { + return Java8.TryCatch0_Supplier().f(t); + } + + static public F, Supplier>> TryCatch0_Supplier() { + return t -> () -> P1Functions.toP1(t)._1(); + } + + static public Function> TryCatch1_Function(final TryCatch1 t) { + return Java8.TryCatch1_Function().f(t); + } + + static public F, Function>> TryCatch1_Function() { + return t -> a -> F1Functions.toF1(t).f(a); + } + + static public BiFunction> TryCatch2_BiFunction(final TryCatch2 t) { + return Java8.TryCatch2_BiFunction().f(t); + } + + static public F, BiFunction>> TryCatch2_BiFunction() { + return t -> (a, b) -> F2Functions.toF2(t).f(a, b); + } + + static public Option Optional_Option(final Optional o) { + return Java8.Optional_Option().f(o); + } + + static public F, Option> Optional_Option() { + return o -> o.isPresent() ? Option.fromNull(o.get()) : Option.none(); + } + + static public Optional Option_Optional(final Option o) { + return Java8.Option_Optional().f(o); + } + + static public F, Optional> Option_Optional() { + return o -> o.isSome() ? Optional.ofNullable(o.some()) : Optional.empty(); } } From 53a7a3eba24b6295ad836b2e1acbef1998f04519 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 4 Jun 2014 13:26:14 +1000 Subject: [PATCH 068/811] Add .exe to external javac 8 under windows --- java8/build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java8/build.gradle b/java8/build.gradle index c0cc500d..6fc5d95f 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -1,4 +1,6 @@ +import org.apache.tools.ant.taskdefs.condition.Os + apply plugin: 'java' apply from: "$rootDir/lib.gradle" @@ -24,7 +26,8 @@ compileJava { if (jh == null) { throw new Exception("JAVA8_HOME environment variable not set") } + def extension = Os.isFamily(Os.FAMILY_WINDOWS) ? ".exe" : "" options.fork = true - options.forkOptions.executable = "$jh/bin/javac" + options.forkOptions.executable = "$jh$extension/bin/javac" } From 263d2edfb3e9e6a808f78ac454d5bdc87cdfa507 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 13:12:12 +1000 Subject: [PATCH 069/811] Added java8 module to be published --- build.gradle | 57 +++++++++++++++++++++++++++++++++++++++++++++- core/build.gradle | 45 ++---------------------------------- java8/build.gradle | 6 +++++ 3 files changed, 64 insertions(+), 44 deletions(-) diff --git a/build.gradle b/build.gradle index 0b3ee955..db2e2c0b 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,11 @@ import org.apache.tools.ant.taskdefs.condition.Os defaultTasks 'build' +Boolean doSigning() { + signingEnabled.trim() == "true" +} + + ext { } @@ -47,8 +52,58 @@ allprojects { } subprojects { + apply plugin: "maven" + if (doSigning()) { + apply plugin: "signing" + signing { + sign configurations.archives + } + } - + uploadArchives { + enabled = false + repositories { + mavenDeployer { + if (doSigning()) { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + } + + repository(url: sonatypeUploadUrl) { + authentication(userName: sonatypeUsername, password: sonatypePassword) + } + pom { + groupId = project.group + project { + name pomProjectName + packaging 'jar' + description projectDescription + url projectUrl + organization { + name pomOrganisation + url projectUrl + } + scm { + url scmUrl +// connection scmGitFile +// developerConnection scmGitFile + } + licenses { + license { + name "The BSD3 License" + url "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" + distribution 'repo' + } + } + developers { + developer { + email primaryEmail + } + } + } + } + } + } + } } diff --git a/core/build.gradle b/core/build.gradle index 422ceab6..a026c655 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -72,46 +72,5 @@ if (doSigning()) { } } -uploadArchives { - repositories { - mavenDeployer { - if (doSigning()) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - } - - repository(url: sonatypeUploadUrl) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - pom { - groupId = project.group - project { - name pomProjectName - packaging 'jar' - description projectDescription - url projectUrl - organization { - name pomOrganisation - url projectUrl - } - scm { - url scmUrl -// connection scmGitFile -// developerConnection scmGitFile - } - licenses { - license { - name "The BSD3 License" - url "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" - distribution 'repo' - } - } - developers { - developer { - email primaryEmail - } - } - } - } - } - } -} +uploadArchives.enabled = true + diff --git a/java8/build.gradle b/java8/build.gradle index 6fc5d95f..2db6f71d 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -11,6 +11,11 @@ repositories { mavenCentral() } +jar { + baseName "${project.projectName}-${project.name}" + version project.fjVersion +} + task javadoc(type: Javadoc, overwrite: true) { def t = createDynamicJavadoc("$projectDir", ["core"]) dependsOn(t) @@ -31,3 +36,4 @@ compileJava { options.forkOptions.executable = "$jh$extension/bin/javac" } +uploadArchives.enabled = true From cc2b403434e4c92256660678dc8bc890004cf6f6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 14:26:22 +1000 Subject: [PATCH 070/811] Publish java8 module --- build.gradle | 43 +++++++++++++++++++++++++++++++ core/build.gradle | 63 ++++++++++++---------------------------------- java8/build.gradle | 1 - 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/build.gradle b/build.gradle index db2e2c0b..c4ce57b1 100644 --- a/build.gradle +++ b/build.gradle @@ -52,7 +52,26 @@ allprojects { } subprojects { + + defaultTasks "build" + + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'me.tatarka:gradle-retrolambda:1.3.1' + } + } + + repositories { + mavenCentral() + } + + apply plugin: "maven" + apply plugin: "java" if (doSigning()) { apply plugin: "signing" @@ -61,6 +80,30 @@ subprojects { } } + task javadocJar(type: Jar, dependsOn: "javadoc") { + classifier = 'javadoc' + from "build/docs/javadoc" + } + + task sourcesJar(type: Jar) { + from sourceSets.main.allSource + classifier = 'sources' + } + + artifacts { + archives jar + archives javadocJar + archives sourcesJar + } + + jar { + version project.fjVersion + manifest { + attributes 'Signature-Version': project.fjVersion + } + } + + uploadArchives { enabled = false repositories { diff --git a/core/build.gradle b/core/build.gradle index a026c655..18c1e014 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,34 +1,10 @@ - -buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath 'me.tatarka:gradle-retrolambda:1.3.1' - } -} - -apply plugin: 'java' -apply plugin: 'maven' -//apply plugin: 'signing' apply plugin: 'retrolambda' apply from: "$rootDir/lib.gradle" -defaultTasks 'build' - jar { baseName project.projectName - version project.fjVersion - manifest { - attributes 'Signature-Version': project.fjVersion - } -} - -repositories { - mavenCentral() } dependencies { @@ -36,6 +12,7 @@ dependencies { testCompile "junit:junit:4.11" } +//tasks["javadoc"].dependsOn("java8Javadoc") task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { } @@ -45,32 +22,24 @@ retrolambda { javaVersion JavaVersion.VERSION_1_7 } -task javadocJar(type: Jar, dependsOn: java8Javadoc) { - classifier = 'javadoc' - from "build/docs/javadoc" -} - -task sourcesJar(type: Jar) { - from sourceSets.main.allSource - classifier = 'sources' -} +//project.tasks['javadocJar'].dependsOn(javadoc) -artifacts { - archives jar - archives javadocJar - archives sourcesJar -} +//task javadocJar(type: Jar, dependsOn: java8Javadoc) { +// classifier = 'javadoc' +// from "build/docs/javadoc" +//} -Boolean doSigning() { - signingEnabled.trim() == "true" -} -if (doSigning()) { - apply plugin: "signing" - signing { - sign configurations.archives - } -} +//Boolean doSigning() { +// signingEnabled.trim() == "true" +//} +// +//if (doSigning()) { +// apply plugin: "signing" +// signing { +// sign configurations.archives +// } +//} uploadArchives.enabled = true diff --git a/java8/build.gradle b/java8/build.gradle index 2db6f71d..6fb7750f 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -13,7 +13,6 @@ repositories { jar { baseName "${project.projectName}-${project.name}" - version project.fjVersion } task javadoc(type: Javadoc, overwrite: true) { From 2334a95c1c24f20de86892ae5e1f0ab8db02cd38 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 14:33:33 +1000 Subject: [PATCH 071/811] Simplify build scripts --- consume/build.gradle | 5 ----- core/build.gradle | 20 -------------------- demo/build.gradle | 15 +-------------- java8/build.gradle | 8 -------- 4 files changed, 1 insertion(+), 47 deletions(-) diff --git a/consume/build.gradle b/consume/build.gradle index d6621b36..6ec0a36d 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -1,10 +1,5 @@ -apply plugin: 'java' - -defaultTasks 'build' - repositories { - mavenCentral() maven { url sonatypeRepositoryUrl } diff --git a/core/build.gradle b/core/build.gradle index 18c1e014..c491739b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -12,7 +12,6 @@ dependencies { testCompile "junit:junit:4.11" } -//tasks["javadoc"].dependsOn("java8Javadoc") task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { } @@ -22,24 +21,5 @@ retrolambda { javaVersion JavaVersion.VERSION_1_7 } -//project.tasks['javadocJar'].dependsOn(javadoc) - -//task javadocJar(type: Jar, dependsOn: java8Javadoc) { -// classifier = 'javadoc' -// from "build/docs/javadoc" -//} - - -//Boolean doSigning() { -// signingEnabled.trim() == "true" -//} -// -//if (doSigning()) { -// apply plugin: "signing" -// signing { -// sign configurations.archives -// } -//} - uploadArchives.enabled = true diff --git a/demo/build.gradle b/demo/build.gradle index 89bdfd15..93a76109 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,21 +1,8 @@ - -buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath 'me.tatarka:gradle-retrolambda:1.3.1' - } -} - -apply plugin: 'java' apply plugin: 'application' apply plugin: 'retrolambda' -apply from: "$rootDir/lib.gradle" -defaultTasks 'build' +apply from: "$rootDir/lib.gradle" mainClassName = "fj.demo.euler.Problem2" diff --git a/java8/build.gradle b/java8/build.gradle index 6fb7750f..ff0789ca 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -1,16 +1,8 @@ import org.apache.tools.ant.taskdefs.condition.Os -apply plugin: 'java' - apply from: "$rootDir/lib.gradle" -defaultTasks 'build' - -repositories { - mavenCentral() -} - jar { baseName "${project.projectName}-${project.name}" } From de54cf76bc0ec7b201a69c306b4364464e7f89bc Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 14:55:52 +1000 Subject: [PATCH 072/811] Simplified build scripts --- demo/build.gradle | 5 ----- tests/build.gradle | 38 ++++++-------------------------------- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/demo/build.gradle b/demo/build.gradle index 93a76109..4144ec48 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -6,11 +6,6 @@ apply from: "$rootDir/lib.gradle" mainClassName = "fj.demo.euler.Problem2" -ext { - scalaVersion = "2.9.+" - scalacheckVersion = "1.10.+" -} - repositories { mavenCentral() } diff --git a/tests/build.gradle b/tests/build.gradle index 7cd4bdbe..2fc74611 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -1,50 +1,24 @@ -/* - * This build file was auto generated by running the Gradle 'init' task - * by 'MarkPerry' at '12/12/13 10:02 AM' with Gradle 1.9 - * - * This generated file contains a sample Scala library project to get you started. - * For more details take a look at the Scala plugin chapter in the Gradle - * user guide available at http://gradle.org/docs/1.9/userguide/scala_plugin.html - */ -// Apply the scala plugin to add support for Scala apply plugin: 'scala' - ext { scalaVersion = "2.10.3" - scalacheckVersion = "1.10.+" - scalacheckScalaVersion = "2.10" + scalacheckScalaVersion = "2.10" + scalacheckVersion = "1.10.1" + scalatestScalaVersion= "2.10" + scalatestVersion = "1.9.2" } - - tasks.withType(ScalaCompile) { scalaCompileOptions.useAnt = false } - -test { - scanForTestClasses = false - include '**/*Test.*' -} - -// In this section you declare where to find the dependencies of your project -repositories { - // Use 'maven central' for resolving your dependencies. - // You can declare any Maven/Ivy/file repository here. - mavenCentral() - mavenLocal() -} - - dependencies { compile project(":core") - compile 'org.slf4j:slf4j-api:1.7.5' + compile "org.slf4j:slf4j-api:1.7.5" compile "org.scala-lang:scala-library:$scalaVersion" + testCompile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - testCompile "junit:junit:4.11" - testCompile 'org.scalatest:scalatest_2.10:1.9.2' } From 55b01979cec8da709a0b45e5ef0d44f3ba8769cf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 15:06:55 +1000 Subject: [PATCH 073/811] Unifiy library versions --- build.gradle | 5 +++++ core/build.gradle | 4 ++-- demo/build.gradle | 8 ++------ java8/build.gradle | 2 +- tests/build.gradle | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index c4ce57b1..d963a234 100644 --- a/build.gradle +++ b/build.gradle @@ -46,6 +46,11 @@ allprojects { sonatypeReleaseUrl = "$sonatypeBaseUrl/service/local/staging/deploy/maven2/" sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" + + dependencySlf4jApi = "org.slf4j:slf4j-api:1.7.5" + dependencyJunit = "junit:junit:4.11" + + } version = fjVersion group = "org.functionaljava" diff --git a/core/build.gradle b/core/build.gradle index c491739b..455349f3 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,8 +8,8 @@ jar { } dependencies { - compile 'org.slf4j:slf4j-api:1.7.5' - testCompile "junit:junit:4.11" + compile dependencySlf4jApi + testCompile dependencyJunit } task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { diff --git a/demo/build.gradle b/demo/build.gradle index 4144ec48..3941a488 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -6,10 +6,6 @@ apply from: "$rootDir/lib.gradle" mainClassName = "fj.demo.euler.Problem2" -repositories { - mavenCentral() -} - task javadoc(type: Javadoc, overwrite: true) { def t = createDynamicJavadoc("$projectDir", ["core"]) dependsOn(t) @@ -22,7 +18,7 @@ retrolambda { } dependencies { - compile 'org.slf4j:slf4j-api:1.7.5' + compile dependencySlf4jApi compile project(":core") - testCompile "junit:junit:4.11" + testCompile dependencyJunit } diff --git a/java8/build.gradle b/java8/build.gradle index ff0789ca..5147d852 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -14,7 +14,7 @@ task javadoc(type: Javadoc, overwrite: true) { dependencies { compile project(":core") - testCompile "junit:junit:4.11" + testCompile dependencyJunit } compileJava { diff --git a/tests/build.gradle b/tests/build.gradle index 2fc74611..e6b52632 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -15,10 +15,10 @@ tasks.withType(ScalaCompile) { dependencies { compile project(":core") - compile "org.slf4j:slf4j-api:1.7.5" + compile dependencySlf4jApi compile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - testCompile "junit:junit:4.11" + testCompile dependencyJunit } From 5444dfaf655df5bffcae86bc5480688d81f89a13 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 15:12:25 +1000 Subject: [PATCH 074/811] Tidy up gradle scripts --- build.gradle | 10 +--------- consume/build.gradle | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index d963a234..d21e4da8 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,6 @@ Boolean doSigning() { signingEnabled.trim() == "true" } - ext { } @@ -19,10 +18,8 @@ if (JavaVersion.current().isJava8Compatible()) { } } - allprojects { - ext { isSnapshot = true fjBaseVersion = "4.2" @@ -49,9 +46,8 @@ allprojects { dependencySlf4jApi = "org.slf4j:slf4j-api:1.7.5" dependencyJunit = "junit:junit:4.11" - - } + version = fjVersion group = "org.functionaljava" } @@ -74,7 +70,6 @@ subprojects { mavenCentral() } - apply plugin: "maven" apply plugin: "java" @@ -108,7 +103,6 @@ subprojects { } } - uploadArchives { enabled = false repositories { @@ -133,8 +127,6 @@ subprojects { } scm { url scmUrl -// connection scmGitFile -// developerConnection scmGitFile } licenses { license { diff --git a/consume/build.gradle b/consume/build.gradle index 6ec0a36d..e2f10f68 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -6,5 +6,5 @@ repositories { } dependencies { - compile("org.functionaljava:functionaljava:$fjConsumeVersion") + compile("$group:$projectName:$fjConsumeVersion") } From 4d2fd9a0cd4a427ab5b28bf26fd0d767dd6eb927 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 15:27:38 +1000 Subject: [PATCH 075/811] Cleanup common code in lib.gradle --- lib.gradle | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib.gradle b/lib.gradle index a2329f09..a8d78165 100644 --- a/lib.gradle +++ b/lib.gradle @@ -15,20 +15,19 @@ String findJavaCommand(String s) { if (jh == null) { throw new Exception("Environment variable JAVA8_HOME not set") } - findCommand("$jh/bin", "javadoc") + findCommand("$jh/bin", s) } -List projectClasses(List list) { +List projectClasses(List list, String base) { list.collect { - "$projectDir/../$it/build/classes/main" + "$base/$it/build/classes/main" } - } def createDynamicJavadoc(String mainPath, List paths) { def taskName = "dynamicJava8Javadoc" task "$taskName"(type: Exec) { - def cp = projectClasses(paths).join(";") + def cp = projectClasses(paths, projectDir).join(";") def c = findJavaCommand("javadoc") commandLine c, "-sourcepath", "$mainPath/src/main/java", "-d", "$mainPath/build/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet", "-classpath", cp } From 10f434dfcad190a94f3ec92837a659418a8d9e1c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 15:35:09 +1000 Subject: [PATCH 076/811] Clean common gradle functionality --- build.gradle | 1 + lib.gradle | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index d21e4da8..638579ba 100644 --- a/build.gradle +++ b/build.gradle @@ -70,6 +70,7 @@ subprojects { mavenCentral() } +// apply from: "$rootDir/lib.gradle" apply plugin: "maven" apply plugin: "java" diff --git a/lib.gradle b/lib.gradle index a8d78165..c2a0c618 100644 --- a/lib.gradle +++ b/lib.gradle @@ -24,12 +24,12 @@ List projectClasses(List list, String base) { } } -def createDynamicJavadoc(String mainPath, List paths) { +def createDynamicJavadoc(String module, List paths) { def taskName = "dynamicJava8Javadoc" task "$taskName"(type: Exec) { - def cp = projectClasses(paths, projectDir).join(";") + def cp = projectClasses(paths, "$module/..").join(";") def c = findJavaCommand("javadoc") - commandLine c, "-sourcepath", "$mainPath/src/main/java", "-d", "$mainPath/build/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet", "-classpath", cp + commandLine c, "-sourcepath", "$module/src/main/java", "-d", "$module/build/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet", "-classpath", cp } project.tasks[taskName] } From c502854bc6c5def2ae910882aeaaaf89167fa671 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 16:49:12 +1000 Subject: [PATCH 077/811] Consolidate common gradle code --- build.gradle | 2 +- core/build.gradle | 2 -- demo/build.gradle | 5 +---- java8/build.gradle | 5 +---- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/build.gradle b/build.gradle index 638579ba..ffd77e06 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ subprojects { mavenCentral() } -// apply from: "$rootDir/lib.gradle" + apply from: "$rootDir/lib.gradle" apply plugin: "maven" apply plugin: "java" diff --git a/core/build.gradle b/core/build.gradle index 455349f3..9bf429d8 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,8 +1,6 @@ apply plugin: 'retrolambda' -apply from: "$rootDir/lib.gradle" - jar { baseName project.projectName } diff --git a/demo/build.gradle b/demo/build.gradle index 3941a488..c73b29d1 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -2,13 +2,10 @@ apply plugin: 'application' apply plugin: 'retrolambda' -apply from: "$rootDir/lib.gradle" - mainClassName = "fj.demo.euler.Problem2" task javadoc(type: Javadoc, overwrite: true) { - def t = createDynamicJavadoc("$projectDir", ["core"]) - dependsOn(t) + dependsOn(createDynamicJavadoc("$projectDir", ["core"])) } retrolambda { diff --git a/java8/build.gradle b/java8/build.gradle index 5147d852..e1a26c0a 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -1,15 +1,12 @@ import org.apache.tools.ant.taskdefs.condition.Os -apply from: "$rootDir/lib.gradle" - jar { baseName "${project.projectName}-${project.name}" } task javadoc(type: Javadoc, overwrite: true) { - def t = createDynamicJavadoc("$projectDir", ["core"]) - dependsOn(t) + dependsOn(createDynamicJavadoc("$projectDir", ["core"])) } dependencies { From 79f2905722d656d97ac15d0394433895ebacf8e7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 5 Jun 2014 17:44:21 +1000 Subject: [PATCH 078/811] Fixed javadoc warnings for core submodule --- core/src/main/java/fj/Ord.java | 6 +++--- core/src/main/java/fj/data/$.java | 1 + core/src/main/java/fj/data/IO.java | 6 +++--- core/src/main/java/fj/test/package-info.java | 2 +- .../java/fj/test/reflect/package-info.java | 20 +++++++++---------- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index d1e59868..ed234ff9 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -662,11 +662,11 @@ public Ordering f(final A a2) { } /** - * An order instance that uses {@link Object#hashCode()} and {@link Object#equals()} for computing + * An order instance that uses {@link Object#hashCode()} and {@link Object#equals} for computing * the order and equality. First the hashCode is compared, if this is equal, objects are compared - * using {@link Object#equals()}. + * using {@link Object#equals}. * - * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals()}. + * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. */ public static Ord hashEqualsOrd() { return Ord. ord(new F>() { diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index a12e3689..0eeb5af0 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -7,6 +7,7 @@ * is the identity morphism from B to B. */ @SuppressWarnings({"UnusedDeclaration"}) +@Deprecated public final class $ implements P1 { private final B b; diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index cc773c1a..487f2b34 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -24,8 +24,8 @@ import fj.data.Iteratee.IterV; /** - * IO monad for processing files, with main methods {@link #enumFileLines(File, Option, IterV)}, - * {@link #enumFileChars(File, Option, IterV)} and {@link #enumFileCharChunks(File, Option, IterV)} + * IO monad for processing files, with main methods {@link #enumFileLines }, + * {@link #enumFileChars} and {@link #enumFileCharChunks} * (the latter one is the fastest as char chunks read from the file are directly passed to the iteratee * without indirection in between). * @@ -58,7 +58,7 @@ public Unit run() throws IOException { /** * An IO monad that reads lines from the given file (using a {@link BufferedReader}) and passes * lines to the provided iteratee. May not be suitable for files with very long - * lines, consider to use {@link #enumFileCharChunks(File, IterV)} or {@link #enumFileChars(File, IterV)} + * lines, consider to use {@link #enumFileCharChunks} or {@link #enumFileChars} * as an alternative. * * @param f the file to read, must not be null diff --git a/core/src/main/java/fj/test/package-info.java b/core/src/main/java/fj/test/package-info.java index 6544a744..258c2ddb 100644 --- a/core/src/main/java/fj/test/package-info.java +++ b/core/src/main/java/fj/test/package-info.java @@ -5,7 +5,7 @@ * the testing and reporting of the status of those properties occurs by automating various aspects. * For example, if a property is found to be false (i.e. a test fails), then the counter-example may * be reduced while still falsifying the property so that the reported counter-example is the - * simplest found (this is called {@link Shrink shrinking}). The expression of the property also + * simplest found (this is called {@link fj.test.Shrink}). The expression of the property also * serves as very rigorous documentation for the code under test; far surpassing that provided by * traditional testing techniques. * diff --git a/core/src/main/java/fj/test/reflect/package-info.java b/core/src/main/java/fj/test/reflect/package-info.java index ef43e3a4..39ce19ad 100644 --- a/core/src/main/java/fj/test/reflect/package-info.java +++ b/core/src/main/java/fj/test/reflect/package-info.java @@ -1,33 +1,33 @@ /** * A wrapper around the fj.test package that uses annotations for configuring properties to - * check. The properties are found using {@link java.lang.reflect Java Reflection}. All annotations + * check. The properties are found using reflection. All annotations * are optional and a property is eligible for checking by default. A property is any of the * following member descriptions, unless the member or enclosing class is annotated with - * {@link NoCheck}. + * {@link fj.test.reflect.NoCheck}. *
    -
  • a static field of type {@link Property}.
  • -
  • a static zero argument method that returns {@link Property}.
  • -
  • a non-static field of type {@link Property} in a class with a zero-argument constructor.
  • -
  • a non-static no-argument method that returns {@link Property} in a class with a no-argument +
  • a static field of type {@link fj.test.Property}.
  • +
  • a static zero argument method that returns {@link fj.test.Property}.
  • +
  • a non-static field of type {@link fj.test.Property} in a class with a zero-argument constructor.
  • +
  • a non-static no-argument method that returns {@link fj.test.Property} in a class with a no-argument constructor.
* *

* A property may be in zero or more categories by annotating the member or enclosing class with - * {@link Category}. The property is in the set of categories that make up the + * {@link fj.test.reflect.Category}. The property is in the set of categories that make up the * union of its member and enclosing class category annotation. *

*

* When a property is checked, it uses default configuration values, which may be overridden by - * annotating the member or the enclosing class with the {@link CheckParams} + * annotating the member or the enclosing class with the {@link fj.test.reflect.CheckParams} * annotation. The values used are first those specified on the member; or if the annotation does * not exist, then the enclosing class (default values otherwise). *

*

* A property can have a name associated with it by annotating the member with the - * {@link Name} annotation. The name is a {@link String} that is used - * only for reporting in check results. If the {@link Name} annotation does not + * {@link fj.test.reflect.Name} annotation. The name is a {@link java.lang.String} that is used + * only for reporting in check results. If the {@link fj.test.reflect.Name} annotation does not * appear on a property member, then the field or method name is used by default. *

* From bc2b8fba91e4c2f27649a9fb5d88c64da89ffe18 Mon Sep 17 00:00:00 2001 From: Andrea Richiardi Date: Sat, 7 Jun 2014 17:12:11 +0200 Subject: [PATCH 079/811] Now findJavaCommand in lib.gradle is exposed and it is used by the other .gradle files. --- build.gradle | 2 -- java8/build.gradle | 9 +-------- lib.gradle | 8 ++++---- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index ffd77e06..508a321e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,4 @@ -import org.apache.tools.ant.taskdefs.condition.Os - defaultTasks 'build' Boolean doSigning() { diff --git a/java8/build.gradle b/java8/build.gradle index e1a26c0a..cfb2bbaf 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -1,6 +1,4 @@ -import org.apache.tools.ant.taskdefs.condition.Os - jar { baseName "${project.projectName}-${project.name}" } @@ -15,13 +13,8 @@ dependencies { } compileJava { - def jh = System.getenv("JAVA8_HOME") - if (jh == null) { - throw new Exception("JAVA8_HOME environment variable not set") - } - def extension = Os.isFamily(Os.FAMILY_WINDOWS) ? ".exe" : "" options.fork = true - options.forkOptions.executable = "$jh$extension/bin/javac" + options.forkOptions.executable = findJavaCommand("javac") } uploadArchives.enabled = true diff --git a/lib.gradle b/lib.gradle index c2a0c618..c50dfb6e 100644 --- a/lib.gradle +++ b/lib.gradle @@ -10,12 +10,12 @@ String findCommand(String dir, String command) { cmd } -String findJavaCommand(String s) { +String findJavaCommand(String command) { def jh = System.getenv("JAVA8_HOME") if (jh == null) { throw new Exception("Environment variable JAVA8_HOME not set") } - findCommand("$jh/bin", s) + findCommand("$jh/bin", command) } List projectClasses(List list, String base) { @@ -36,10 +36,10 @@ def createDynamicJavadoc(String module, List paths) { ext { createDynamicJavadoc = this.&createDynamicJavadoc + findJavaCommand = this.&findJavaCommand } task java8Javadoc(type: Exec) { def c = findJavaCommand("javadoc") commandLine c, "-sourcepath", "$projectDir/src/main/java", "-d", "$buildDir/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet" -} - +} \ No newline at end of file From bed9499768b868ac0df07353ed24a37c317a4102 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 8 Jun 2014 00:44:58 +0900 Subject: [PATCH 080/811] remove slf4j dependency --- build.gradle | 1 - core/build.gradle | 1 - demo/build.gradle | 1 - tests/build.gradle | 1 - 4 files changed, 4 deletions(-) diff --git a/build.gradle b/build.gradle index ffd77e06..90334bc2 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,6 @@ allprojects { sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" - dependencySlf4jApi = "org.slf4j:slf4j-api:1.7.5" dependencyJunit = "junit:junit:4.11" } diff --git a/core/build.gradle b/core/build.gradle index 9bf429d8..080da5d4 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -6,7 +6,6 @@ jar { } dependencies { - compile dependencySlf4jApi testCompile dependencyJunit } diff --git a/demo/build.gradle b/demo/build.gradle index c73b29d1..4c84c1ef 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -15,7 +15,6 @@ retrolambda { } dependencies { - compile dependencySlf4jApi compile project(":core") testCompile dependencyJunit } diff --git a/tests/build.gradle b/tests/build.gradle index e6b52632..d39a3bf6 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -15,7 +15,6 @@ tasks.withType(ScalaCompile) { dependencies { compile project(":core") - compile dependencySlf4jApi compile "org.scala-lang:scala-library:$scalaVersion" testCompile "org.scala-lang:scala-library:$scalaVersion" From 1e11acb072615fb9e5b7fc3fdef67be2a4afbb0d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 10 Jun 2014 12:04:03 +1000 Subject: [PATCH 081/811] Added gradle wrapper --- build.gradle | 4 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 51106 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++++++++++++++++++++++ gradlew.bat | 90 +++++++++++++ 5 files changed, 264 insertions(+) create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat diff --git a/build.gradle b/build.gradle index 99d494e0..c5348cd3 100644 --- a/build.gradle +++ b/build.gradle @@ -145,3 +145,7 @@ subprojects { } } + +task wrapper(type: Wrapper) { + gradleVersion = '1.11' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..3c7abdf12790879c06b07176de29647f77aa4129 GIT binary patch literal 51106 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

CflOl1i4(-2^1KXo)&I5QlgjRKFQgM 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 z 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%0DvTus6fLI&f~`9YxjD=W5pR41LBYQt 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 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..199fcbcd --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Jun 10 12:02:45 EST 2014 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..91a7e269 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From 7384ad71824ad774af3db8947b54ed753489a871 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 10 Jun 2014 12:16:03 +1000 Subject: [PATCH 082/811] Upgraded to Gradle 2.0-rc-1 --- core/build.gradle | 2 -- demo/build.gradle | 3 --- gradle/wrapper/gradle-wrapper.properties | 3 ++- java8/build.gradle | 7 ------- 4 files changed, 2 insertions(+), 13 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index 080da5d4..40a5ce59 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,8 +9,6 @@ dependencies { testCompile dependencyJunit } -task javadoc(type: Javadoc, overwrite: true, dependsOn: "java8Javadoc") { -} retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/demo/build.gradle b/demo/build.gradle index 4c84c1ef..df833911 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -4,9 +4,6 @@ apply plugin: 'retrolambda' mainClassName = "fj.demo.euler.Problem2" -task javadoc(type: Javadoc, overwrite: true) { - dependsOn(createDynamicJavadoc("$projectDir", ["core"])) -} retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 199fcbcd..4fcfdf1f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip +#distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-rc-1-bin.zip diff --git a/java8/build.gradle b/java8/build.gradle index cfb2bbaf..6dc23320 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -3,18 +3,11 @@ jar { baseName "${project.projectName}-${project.name}" } -task javadoc(type: Javadoc, overwrite: true) { - dependsOn(createDynamicJavadoc("$projectDir", ["core"])) -} dependencies { compile project(":core") testCompile dependencyJunit } -compileJava { - options.fork = true - options.forkOptions.executable = findJavaCommand("javac") -} uploadArchives.enabled = true From 3d4e0f8f714a18a9a5ea3168e2c5ab1e63df579e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 10 Jun 2014 12:19:11 +1000 Subject: [PATCH 083/811] Removed gradle 1.x / java 8 warning from settings.gradle --- settings.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/settings.gradle b/settings.gradle index 0ffcbb50..3dc55f5b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,3 @@ include 'core', 'demo', "tests", "consume", "java8" -// The final Java 8 release, (build 1.8.0-b132) does not work with Gradle and the Scala plugin -// see http://issues.gradle.org/browse/GRADLE-3023 From 365cb6f17274e9564f55c0b1681106e2bc8a3870 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 10 Jun 2014 12:36:57 +1000 Subject: [PATCH 084/811] Set source compatibility 1.7 for default and 1.8 for each module that overrides the default --- build.gradle | 2 ++ core/build.gradle | 1 + demo/build.gradle | 1 + java8/build.gradle | 1 + 4 files changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index c5348cd3..0530f83c 100644 --- a/build.gradle +++ b/build.gradle @@ -71,6 +71,8 @@ subprojects { apply plugin: "maven" apply plugin: "java" + sourceCompatibility = "1.7" + if (doSigning()) { apply plugin: "signing" signing { diff --git a/core/build.gradle b/core/build.gradle index 40a5ce59..749a7ae7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,6 +9,7 @@ dependencies { testCompile dependencyJunit } +sourceCompatibility = "1.8" retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/demo/build.gradle b/demo/build.gradle index df833911..f108aa44 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -4,6 +4,7 @@ apply plugin: 'retrolambda' mainClassName = "fj.demo.euler.Problem2" +sourceCompatibility = "1.8" retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/java8/build.gradle b/java8/build.gradle index 6dc23320..7ecff839 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -3,6 +3,7 @@ jar { baseName "${project.projectName}-${project.name}" } +sourceCompatibility = "1.8" dependencies { compile project(":core") From a94790b239920fe66e3e6e5017f5f880f0a67ea4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 10 Jun 2014 12:43:08 +1000 Subject: [PATCH 085/811] Fixed javadoc link for Java 8/Gradle 2.0-rc-1 --- demo/src/main/java/fj/demo/concurrent/WordCount.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 00f6846a..8c58f2a8 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -37,8 +37,8 @@ import fj.data.Option; /** - * Reads words and their counts from files ({@link #getWordsAndCountsFromFiles(List)} in a single thread - * and {@link #getWordsAndCountsFromFilesInParallel(List, int)} in multiple threads). The files are created + * Reads words and their counts from files ({@link #getWordsAndCountsFromFiles} in a single thread + * and {@link #getWordsAndCountsFromFilesInParallel} in multiple threads). The files are created * initially and populated with some sample content. * * @author Martin Grotzke From 478e2513c70ab446415f55a731d45e7834355011 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 10 Jun 2014 15:54:03 +1000 Subject: [PATCH 086/811] Set Gradle root project name --- settings.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle b/settings.gradle index 0ffcbb50..fd23a9de 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,6 @@ +rootProject.name = "functionaljava" + include 'core', 'demo', "tests", "consume", "java8" // The final Java 8 release, (build 1.8.0-b132) does not work with Gradle and the Scala plugin // see http://issues.gradle.org/browse/GRADLE-3023 From ce53b9fa8463812be0f6eaf6b16d80ca64cd402c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 19 Jun 2014 19:32:10 +1000 Subject: [PATCH 087/811] Made IO compatible with lambdas, moved methods to IOFunctions --- core/src/main/java/fj/data/IO.java | 330 ++---------------- core/src/main/java/fj/data/IOFunctions.java | 312 +++++++++++++++++ .../java/fj/demo/concurrent/WordCount.java | 8 +- 3 files changed, 335 insertions(+), 315 deletions(-) create mode 100644 core/src/main/java/fj/data/IOFunctions.java diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index 487f2b34..eefd11b9 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -1,310 +1,20 @@ -package fj.data; - -import static fj.Bottom.errorF; -import static fj.Function.constant; -import static fj.Function.partialApply2; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.Charset; -import java.util.Arrays; - -import fj.F; -import fj.F1Functions; -import fj.Function; -import fj.P; -import fj.P1; -import fj.P2; -import fj.Unit; -import fj.data.Iteratee.Input; -import fj.data.Iteratee.IterV; - -/** - * IO monad for processing files, with main methods {@link #enumFileLines }, - * {@link #enumFileChars} and {@link #enumFileCharChunks} - * (the latter one is the fastest as char chunks read from the file are directly passed to the iteratee - * without indirection in between). - * - * @author Martin Grotzke - * - * @param the type of the result produced by the wrapped iteratee - */ -public abstract class IO { - - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - - public static final F> closeReader = - new F>() { - @Override - public IO f(final Reader r) { - return closeReader(r); - } - }; - - public static IO closeReader(final Reader r) { - return new IO() { - @Override - public Unit run() throws IOException { - r.close(); - return Unit.unit(); - } - }; - } - - /** - * An IO monad that reads lines from the given file (using a {@link BufferedReader}) and passes - * lines to the provided iteratee. May not be suitable for files with very long - * lines, consider to use {@link #enumFileCharChunks} or {@link #enumFileChars} - * as an alternative. - * - * @param f the file to read, must not be null - * @param encoding the encoding to use, {@link Option#none()} means platform default - * @param i the iteratee that is fed with lines read from the file - */ - public static IO> enumFileLines(final File f, final Option encoding, final IterV i) { - return bracket(bufferedReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IO.lineReader(), i)); - } - - /** - * An IO monad that reads char chunks from the given file and passes them to the given iteratee. - * - * @param f the file to read, must not be null - * @param encoding the encoding to use, {@link Option#none()} means platform default - * @param i the iteratee that is fed with char chunks read from the file - */ - public static IO> enumFileCharChunks(final File f, final Option encoding, final IterV i) { - return bracket(fileReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IO.charChunkReader(), i)); - } - - /** - * An IO monad that reads char chunks from the given file and passes single chars to the given iteratee. - * - * @param f the file to read, must not be null - * @param encoding the encoding to use, {@link Option#none()} means platform default - * @param i the iteratee that is fed with chars read from the file - */ - public static IO> enumFileChars(final File f, final Option encoding, final IterV i) { - return bracket(fileReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IO.charChunkReader2(), i)); - } - - public static IO bufferedReader(final File f, final Option encoding) { - return fileReader(f, encoding).map(new F() { - @Override - public BufferedReader f(final Reader a) { - return new BufferedReader(a); - }}); - } - - public static IO fileReader(final File f, final Option encoding) { - return new IO() { - @Override - public Reader run() throws IOException { - final FileInputStream fis = new FileInputStream(f); - return encoding.isNone() ? new InputStreamReader(fis) : new InputStreamReader(fis, encoding.some()); - } - }; - } - - public static final IO bracket(final IO init, final F> fin, final F> body) { - return new IO() { - @Override - public C run() throws IOException { - final A a = init.run(); - try { - return body.f(a).run(); - } catch (final IOException e) { - throw e; - } finally { - fin.f(a); - } - } - }; - } - - public static final IO unit(final A a) { - return new IO() { - @Override - public A run() throws IOException { - return a; - } - }; - } - - /** - * A function that feeds an iteratee with lines read from a {@link BufferedReader}. - */ - public static F, IO>>> lineReader() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return new F, IO>>>() { - @Override - public F, IO>> f(final BufferedReader r) { - return new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - IterV i = it; - while (!isDone.f(i)) { - final String s = r.readLine(); - if (s == null) { return i; } - final Input input = Input.el(s); - final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); - i = i.fold(done, cont)._1(); - } - return i; - } - }; - } - }; - } - }; - } - - /** - * A function that feeds an iteratee with character chunks read from a {@link Reader} - * (char[] of size {@link #DEFAULT_BUFFER_SIZE}). - */ - public static F, IO>>> charChunkReader() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return new F, IO>>>() { - @Override - public F, IO>> f(final Reader r) { - return new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { return i; } - if(numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - final Input input = Input.el(buffer); - final F, IterV>, P1>> cont = - F1Functions.lazy(Function., IterV>apply(input)); - i = i.fold(done, cont)._1(); - } - return i; - } - }; - } - }; - } - }; - } - - /** - * A function that feeds an iteratee with characters read from a {@link Reader} - * (chars are read in chunks of size {@link #DEFAULT_BUFFER_SIZE}). - */ - public static F, IO>>> charChunkReader2() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return new F, IO>>>() { - @Override - public F, IO>> f(final Reader r) { - return new F, IO>>() { - final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { return i; } - if(numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - for(int c = 0; c < buffer.length; c++) { - final Input input = Input.el(buffer[c]); - final F, IterV>, IterV> cont = - Function., IterV>apply(input); - i = i.fold(done, cont); - } - } - return i; - } - }; - } - }; - } - }; - } - - public abstract A run() throws IOException; - - public final IO map(final F f) { - return new IO() { - @Override - public B run() throws IOException { - return f.f(IO.this.run()); - } - }; - } - - public final IO bind(final F> f) { - return new IO() { - @Override - public B run() throws IOException { - return f.f(IO.this.run()).run(); - } - }; - } -} +package fj.data; + +/** + * Created by MarkPerry on 19/06/2014. + */ + +import java.io.IOException; + +/** + * IO monad for processing files + * + * @author Martin Grotzke + * + * @param the type of the result produced by the IO + */ +public interface IO { + + public A run() throws IOException; + +} diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java new file mode 100644 index 00000000..ac6d1ddc --- /dev/null +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -0,0 +1,312 @@ +package fj.data; + +import static fj.Bottom.errorF; +import static fj.Function.constant; +import static fj.Function.partialApply2; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import java.util.Arrays; + +import fj.F; +import fj.F1Functions; +import fj.Function; +import fj.P; +import fj.P1; +import fj.P2; +import fj.Unit; +import fj.data.Iteratee.Input; +import fj.data.Iteratee.IterV; + +/** + * IO monad for processing files, with main methods {@link #enumFileLines }, + * {@link #enumFileChars} and {@link #enumFileCharChunks} + * (the latter one is the fastest as char chunks read from the file are directly passed to the iteratee + * without indirection in between). + * + * @author Martin Grotzke + * + */ +public abstract class IOFunctions { + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + public static final F> closeReader = + new F>() { + @Override + public IO f(final Reader r) { + return closeReader(r); + } + }; + + public static IO closeReader(final Reader r) { + return new IO() { + @Override + public Unit run() throws IOException { + r.close(); + return Unit.unit(); + } + }; + } + + /** + * An IO monad that reads lines from the given file (using a {@link BufferedReader}) and passes + * lines to the provided iteratee. May not be suitable for files with very long + * lines, consider to use {@link #enumFileCharChunks} or {@link #enumFileChars} + * as an alternative. + * + * @param f the file to read, must not be null + * @param encoding the encoding to use, {@link Option#none()} means platform default + * @param i the iteratee that is fed with lines read from the file + */ + public static IO> enumFileLines(final File f, final Option encoding, final IterV i) { + return bracket(bufferedReader(f, encoding) + , Function.>vary(closeReader) + , partialApply2(IOFunctions.lineReader(), i)); + } + + /** + * An IO monad that reads char chunks from the given file and passes them to the given iteratee. + * + * @param f the file to read, must not be null + * @param encoding the encoding to use, {@link Option#none()} means platform default + * @param i the iteratee that is fed with char chunks read from the file + */ + public static IO> enumFileCharChunks(final File f, final Option encoding, final IterV i) { + return bracket(fileReader(f, encoding) + , Function.>vary(closeReader) + , partialApply2(IOFunctions.charChunkReader(), i)); + } + + /** + * An IO monad that reads char chunks from the given file and passes single chars to the given iteratee. + * + * @param f the file to read, must not be null + * @param encoding the encoding to use, {@link Option#none()} means platform default + * @param i the iteratee that is fed with chars read from the file + */ + public static IO> enumFileChars(final File f, final Option encoding, final IterV i) { + return bracket(fileReader(f, encoding) + , Function.>vary(closeReader) + , partialApply2(IOFunctions.charChunkReader2(), i)); + } + + public static IO bufferedReader(final File f, final Option encoding) { + return IOFunctions.map(fileReader(f, encoding), new F() { + @Override + public BufferedReader f(final Reader a) { + return new BufferedReader(a); + }}); + } + + public static IO fileReader(final File f, final Option encoding) { + return new IO() { + @Override + public Reader run() throws IOException { + final FileInputStream fis = new FileInputStream(f); + return encoding.isNone() ? new InputStreamReader(fis) : new InputStreamReader(fis, encoding.some()); + } + }; + } + + public static final IO bracket(final IO init, final F> fin, final F> body) { + return new IO() { + @Override + public C run() throws IOException { + final A a = init.run(); + try { + return body.f(a).run(); + } catch (final IOException e) { + throw e; + } finally { + fin.f(a); + } + } + }; + } + + public static final IO unit(final A a) { + return new IO() { + @Override + public A run() throws IOException { + return a; + } + }; + } + + public static final IO unit(final P1 p) { + return () -> p._1(); + } + + + /** + * A function that feeds an iteratee with lines read from a {@link BufferedReader}. + */ + public static F, IO>>> lineReader() { + final F, Boolean> isDone = + new F, Boolean>() { + final F>, P1> done = constant(P.p(true)); + final F, IterV>, P1> cont = constant(P.p(false)); + + @Override + public Boolean f(final IterV i) { + return i.fold(done, cont)._1(); + } + }; + + return new F, IO>>>() { + @Override + public F, IO>> f(final BufferedReader r) { + return new F, IO>>() { + final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return new IO>() { + @Override + public IterV run() throws IOException { + IterV i = it; + while (!isDone.f(i)) { + final String s = r.readLine(); + if (s == null) { return i; } + final Input input = Input.el(s); + final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); + i = i.fold(done, cont)._1(); + } + return i; + } + }; + } + }; + } + }; + } + + /** + * A function that feeds an iteratee with character chunks read from a {@link Reader} + * (char[] of size {@link #DEFAULT_BUFFER_SIZE}). + */ + public static F, IO>>> charChunkReader() { + final F, Boolean> isDone = + new F, Boolean>() { + final F>, P1> done = constant(P.p(true)); + final F, IterV>, P1> cont = constant(P.p(false)); + + @Override + public Boolean f(final IterV i) { + return i.fold(done, cont)._1(); + } + }; + + return new F, IO>>>() { + @Override + public F, IO>> f(final Reader r) { + return new F, IO>>() { + final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return new IO>() { + @Override + public IterV run() throws IOException { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { return i; } + if(numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); + } + final Input input = Input.el(buffer); + final F, IterV>, P1>> cont = + F1Functions.lazy(Function., IterV>apply(input)); + i = i.fold(done, cont)._1(); + } + return i; + } + }; + } + }; + } + }; + } + + /** + * A function that feeds an iteratee with characters read from a {@link Reader} + * (chars are read in chunks of size {@link #DEFAULT_BUFFER_SIZE}). + */ + public static F, IO>>> charChunkReader2() { + final F, Boolean> isDone = + new F, Boolean>() { + final F>, P1> done = constant(P.p(true)); + final F, IterV>, P1> cont = constant(P.p(false)); + + @Override + public Boolean f(final IterV i) { + return i.fold(done, cont)._1(); + } + }; + + return new F, IO>>>() { + @Override + public F, IO>> f(final Reader r) { + return new F, IO>>() { + final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ + + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return new IO>() { + @Override + public IterV run() throws IOException { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { return i; } + if(numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); + } + for(int c = 0; c < buffer.length; c++) { + final Input input = Input.el(buffer[c]); + final F, IterV>, IterV> cont = + Function., IterV>apply(input); + i = i.fold(done, cont); + } + } + return i; + } + }; + } + }; + } + }; + } + + public static final IO map(final IO io, final F f) { + return new IO() { + @Override + public B run() throws IOException { + return f.f(io.run()); + } + }; + } + + public static final IO bind(final IO io, final F> f) { + return new IO() { + @Override + public B run() throws IOException { + return f.f(io.run()).run(); + } + }; + } +} diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 00f6846a..d557bdfe 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -33,8 +33,6 @@ import fj.data.Iteratee; import fj.data.Iteratee.Input; import fj.data.Iteratee.IterV; -import fj.data.List; -import fj.data.Option; /** * Reads words and their counts from files ({@link #getWordsAndCountsFromFiles(List)} in a single thread @@ -67,7 +65,7 @@ private static Map update(Map map, K key, F valueFuncti @Override public Map f(final String fileName) { try { - return IO.enumFileCharChunks(new File(fileName), Option. none(), wordCountsFromCharChunks()).run().run(); + return IOFunctions.enumFileCharChunks(new File(fileName), Option.none(), wordCountsFromCharChunks()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } @@ -78,7 +76,7 @@ public Map f(final String fileName) { @Override public Map f(final String fileName) { try { - return IO.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); + return IOFunctions.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } @@ -89,7 +87,7 @@ public Map f(final String fileName) { @Override public Map f(final String fileName) { try { - return IO.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); + return IOFunctions.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } From b13842707c58d1f7638ce39b885516a54fdce201 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 19 Jun 2014 19:51:34 +1000 Subject: [PATCH 088/811] Fixed broken imports --- demo/src/main/java/fj/demo/concurrent/WordCount.java | 3 +-- tests/src/test/scala/fj/data/CheckIO.scala | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index d557bdfe..461803f8 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -29,8 +29,7 @@ import fj.control.parallel.ParModule; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; -import fj.data.IO; -import fj.data.Iteratee; +import fj.data.*; import fj.data.Iteratee.Input; import fj.data.Iteratee.IterV; diff --git a/tests/src/test/scala/fj/data/CheckIO.scala b/tests/src/test/scala/fj/data/CheckIO.scala index 10302b75..6b700aa6 100644 --- a/tests/src/test/scala/fj/data/CheckIO.scala +++ b/tests/src/test/scala/fj/data/CheckIO.scala @@ -4,7 +4,7 @@ package data import Equal.{listEqual, anyEqual} import Unit.unit import fj.Show.{listShow, anyShow} -import fj.data.IO._ +import fj.data.IOFunctions._ import fj.data.Iteratee.IterV import java.io.{File, BufferedWriter, OutputStreamWriter, FileOutputStream} import java.nio.charset.Charset From 212198dfe0ed0b293d4b8d2ae2d00ebff758b988 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 22 Jun 2014 23:32:23 +1000 Subject: [PATCH 089/811] Added sequence, traverse and join to IOFunctions --- build.gradle | 6 +++- consume/build.gradle | 6 ---- core/src/main/java/fj/data/IOFunctions.java | 40 +++++++++++++++++---- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 99d494e0..1ecff14b 100644 --- a/build.gradle +++ b/build.gradle @@ -65,7 +65,11 @@ subprojects { repositories { mavenCentral() - } + maven { + url sonatypeRepositoryUrl + } + + } apply from: "$rootDir/lib.gradle" apply plugin: "maven" diff --git a/consume/build.gradle b/consume/build.gradle index e2f10f68..57c82333 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -1,10 +1,4 @@ -repositories { - maven { - url sonatypeRepositoryUrl - } -} - dependencies { compile("$group:$projectName:$fjConsumeVersion") } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index ac6d1ddc..45e12cc8 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -13,13 +13,7 @@ import java.nio.charset.Charset; import java.util.Arrays; -import fj.F; -import fj.F1Functions; -import fj.Function; -import fj.P; -import fj.P1; -import fj.P2; -import fj.Unit; +import fj.*; import fj.data.Iteratee.Input; import fj.data.Iteratee.IterV; @@ -309,4 +303,36 @@ public B run() throws IOException { } }; } + + /** + * Evaluate each action in the sequence from left to right, and collect the results. + * + * @param list + * @return + */ + public static IO> sequence(List> list) { + F2, IO>, IO>> f2 = (io, ioList) -> + IOFunctions.bind(ioList, (xs) -> map(io, x -> List.cons(x, xs))); + return list.foldRight(f2, IOFunctions.unit(List.nil())); + } + + /** + * Map each element of a structure to an action, evaluate these actions from left to right + * and collect the results. + * + * @param list + * @param f + * @return + */ + public static IO> traverse(List list, F> f) { + F2>, IO>> f2 = (a, acc) -> + bind(acc, (bs) -> map(f.f(a), b -> bs.append(List.list(b)))); + return list.foldRight(f2, IOFunctions.unit(List.nil())); + } + + public static IO join(IO> io1) { + return bind(io1, io2 -> io2); + } + + } From aa5d16aa0092020279ffda4dab4a8450c2f025d6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 1 Jul 2014 21:43:55 +1000 Subject: [PATCH 090/811] Upgrade to gradle 2.0 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0530f83c..e10f415d 100644 --- a/build.gradle +++ b/build.gradle @@ -149,5 +149,5 @@ subprojects { } task wrapper(type: Wrapper) { - gradleVersion = '1.11' + gradleVersion = '2.0' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4fcfdf1f..e7244adc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -4,4 +4,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip -distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-rc-1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip From 5df56fcd18afecf8851602139e87cd175d6ce82d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 1 Jul 2014 22:43:37 +1000 Subject: [PATCH 091/811] Removed javadoc commands to get around Java 8 issues --- lib.gradle | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/lib.gradle b/lib.gradle index c50dfb6e..33dff1cb 100644 --- a/lib.gradle +++ b/lib.gradle @@ -18,28 +18,6 @@ String findJavaCommand(String command) { findCommand("$jh/bin", command) } -List projectClasses(List list, String base) { - list.collect { - "$base/$it/build/classes/main" - } -} - -def createDynamicJavadoc(String module, List paths) { - def taskName = "dynamicJava8Javadoc" - task "$taskName"(type: Exec) { - def cp = projectClasses(paths, "$module/..").join(";") - def c = findJavaCommand("javadoc") - commandLine c, "-sourcepath", "$module/src/main/java", "-d", "$module/build/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet", "-classpath", cp - } - project.tasks[taskName] -} - ext { - createDynamicJavadoc = this.&createDynamicJavadoc findJavaCommand = this.&findJavaCommand } - -task java8Javadoc(type: Exec) { - def c = findJavaCommand("javadoc") - commandLine c, "-sourcepath", "$projectDir/src/main/java", "-d", "$buildDir/docs/javadoc", "-subpackages", "fj", "-Xdoclint:none", "-quiet" -} \ No newline at end of file From 5d7a9d1ced86b00771e99307dc2b496e12bd2f7e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 2 Jul 2014 16:24:01 +1000 Subject: [PATCH 092/811] Added first class cons_ --- core/src/main/java/fj/data/List.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 42ea0e76..17593919 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1383,6 +1383,10 @@ public List f(final List tail) { }; } + public static F2, List> cons_() { + return (a, listA) -> cons(a, listA); + } + /** * Returns a function that prepends a value to the given list. * From 28f099f867b81e5490e25b2910912cce751e46db Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 2 Jul 2014 16:24:17 +1000 Subject: [PATCH 093/811] Partial application for F3 and F4 --- core/src/main/java/fj/F3Functions.java | 10 ++++++++++ core/src/main/java/fj/F4Functions.java | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 394f9eb4..19d74550 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -26,4 +26,14 @@ static public F3> toF3(final TryC }; } + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F2 f(final F3 f, final A a) { + return (b, c) -> f.f(a, b, c); + } + } diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index 07bd6e9a..cb2a83ad 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -24,4 +24,14 @@ static public F4> toF4(fina }; } + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F3 f(final F4 f, final A a) { + return (b, c, d) -> f.f(a, b, c, d); + } + } From d4d1dd47b64ddcb0938006f03dd6d3fe4b296003 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 3 Jul 2014 00:06:53 +1000 Subject: [PATCH 094/811] Added env to debug cloud build --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index a21d11c8..1d52e117 100644 --- a/build.gradle +++ b/build.gradle @@ -155,3 +155,7 @@ subprojects { task wrapper(type: Wrapper) { gradleVersion = '2.0' } + +task env << { + println System.getenv() +} \ No newline at end of file From 28c0e288f0237fddea269ad49c9497b58dd7d36c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 3 Jul 2014 00:30:28 +1000 Subject: [PATCH 095/811] Added partial application of first parameter for uncurried functions for F5-F8 --- core/src/main/java/fj/F5Functions.java | 10 ++++++++++ core/src/main/java/fj/F6Functions.java | 12 ++++++++++++ core/src/main/java/fj/F7Functions.java | 11 +++++++++++ core/src/main/java/fj/F8Functions.java | 10 ++++++++++ 4 files changed, 43 insertions(+) diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index fa67911e..0f065934 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -23,4 +23,14 @@ static public F5> toF }; } + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F4 f(final F5 f, final A a) { + return (b, c, d, e) -> f.f(a, b, c, d, e); + } + } diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 66764079..524c82c5 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -23,4 +23,16 @@ static public F6A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F5 f(final F6 func, final A a) { + return (b, c, d, e, f) -> func.f(a, b, c, d, e, f); + } + + } diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 9450b31c..74907b7e 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -23,4 +23,15 @@ static public F7A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F6 f(final F7 func, final A a) { + return (b, c, d, e, f, g) -> func.f(a, b, c, d, e, f, g); + } + + } diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index 2be7f58d..8ba079da 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -23,4 +23,14 @@ static public F8A to which to apply this function. + * @return The function partially applied to the given argument. + */ + static public F7 f(final F8 func, final A a) { + return (b, c, d, e, f, g, h) -> func.f(a, b, c, d, e, f, g, h); + } + } From 1b63285fafddaea736fe4127bf331d93f09b57bb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 3 Jul 2014 15:49:36 +1000 Subject: [PATCH 096/811] Made TryCatchN family take a generic exception type parameter --- core/src/main/java/fj/F1Functions.java | 4 ++-- core/src/main/java/fj/F2Functions.java | 4 ++-- core/src/main/java/fj/F3Functions.java | 4 ++-- core/src/main/java/fj/F4Functions.java | 4 ++-- core/src/main/java/fj/F5Functions.java | 4 ++-- core/src/main/java/fj/F6Functions.java | 4 ++-- core/src/main/java/fj/F7Functions.java | 4 ++-- core/src/main/java/fj/F8Functions.java | 4 ++-- core/src/main/java/fj/P1Functions.java | 4 ++-- core/src/main/java/fj/TryCatch0.java | 4 ++-- core/src/main/java/fj/TryCatch1.java | 4 ++-- core/src/main/java/fj/TryCatch2.java | 4 ++-- core/src/main/java/fj/TryCatch3.java | 4 ++-- core/src/main/java/fj/TryCatch4.java | 4 ++-- core/src/main/java/fj/TryCatch5.java | 4 ++-- core/src/main/java/fj/TryCatch6.java | 4 ++-- core/src/main/java/fj/TryCatch7.java | 4 ++-- core/src/main/java/fj/TryCatch8.java | 4 ++-- core/src/main/java/fj/data/IOFunctions.java | 5 ++++- java8/src/main/java/fj/data/Java8.java | 18 +++++++++--------- 20 files changed, 49 insertions(+), 46 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index fada67ff..ca7bc02b 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -830,12 +830,12 @@ static public ArrayList mapJ(final F f, final ArrayList as) { * @param t A TryCatch1 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F> toF1(final TryCatch1 t) { + static public F> toF1(final TryCatch1 t) { return a -> { try { return Validation.success(t.f(a)); } catch (Exception e) { - return Validation.fail(e); + return Validation.fail((E) e); } }; } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index a71179c5..3b11d7cd 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -353,12 +353,12 @@ public P3>, C, Stream>> f(final P3>, A, St * @param t A TryCatch2 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F2> toF2(final TryCatch2 t) { + static public F2> toF2(final TryCatch2 t) { return (a, b) -> { try { return Validation.success(t.f(a, b)); } catch (Exception e) { - return Validation.fail(e); + return Validation.fail((E) e); } }; } diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 19d74550..bdc4b35c 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -16,12 +16,12 @@ public class F3Functions { * @param t A TryCatch3 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F3> toF3(final TryCatch3 t) { + static public F3> toF3(final TryCatch3 t) { return (a, b, c) -> { try { return success(t.f(a, b, c)); } catch (Exception e) { - return fail(e); + return fail((E) e); } }; } diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index cb2a83ad..3f605598 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -14,12 +14,12 @@ public class F4Functions { * @param t A TryCatch4 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F4> toF4(final TryCatch4 t) { + static public F4> toF4(final TryCatch4 t) { return (a, b, c, d) -> { try { return Validation.success(t.f(a, b, c, d)); } catch (Exception ex) { - return Validation.fail(ex); + return Validation.fail((Z) ex); } }; } diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index 0f065934..bf951868 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -13,12 +13,12 @@ public class F5Functions { * @param t A TryCatch5 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F5> toF5(final TryCatch5 t) { + static public F5> toF5(final TryCatch5 t) { return (a, b, c, d, e) -> { try { return Validation.success(t.f(a, b, c, d, e)); } catch (Exception ex) { - return Validation.fail(ex); + return Validation.fail((Z) ex); } }; } diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 524c82c5..9f1f881f 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -13,12 +13,12 @@ public class F6Functions { * @param t A TryCatch6 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F6> toF6(final TryCatch6 t) { + static public F6> toF6(final TryCatch6 t) { return (a, b, c, d, e, f) -> { try { return Validation.success(t.f(a, b, c, d, e, f)); } catch (Exception ex) { - return Validation.fail(ex); + return Validation.fail((Z) ex); } }; } diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 74907b7e..c453297e 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -13,12 +13,12 @@ public class F7Functions { * @param t A TryCatch7 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F7> toF7(final TryCatch7 t) { + static public F7> toF7(final TryCatch7 t) { return (a, b, c, d, e, f, g) -> { try { return Validation.success(t.f(a, b, c, d, e, f, g)); } catch (Exception ex) { - return Validation.fail(ex); + return Validation.fail((Z) ex); } }; } diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index 8ba079da..aa4b6391 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -13,12 +13,12 @@ public class F8Functions { * @param t A TryCatch8 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F8> toF8(final TryCatch8 t) { + static public F8> toF8(final TryCatch8 t) { return (a, b, c, d, e, f, g, h) -> { try { return Validation.success(t.f(a, b, c, d, e, f, g, h)); } catch (Exception ex) { - return Validation.fail(ex); + return Validation.fail((Z) ex); } }; } diff --git a/core/src/main/java/fj/P1Functions.java b/core/src/main/java/fj/P1Functions.java index 672e0368..0119c468 100644 --- a/core/src/main/java/fj/P1Functions.java +++ b/core/src/main/java/fj/P1Functions.java @@ -224,12 +224,12 @@ public A f(final B b) { * @param t A TryCatch0 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public P1> toP1(final TryCatch0 t) { + static public P1> toP1(final TryCatch0 t) { return () -> { try { return Validation.success(t.f()); } catch (Exception e) { - return Validation.fail(e); + return Validation.fail((E) e); } }; } diff --git a/core/src/main/java/fj/TryCatch0.java b/core/src/main/java/fj/TryCatch0.java index 9e0b9aaf..cdaf8b5d 100644 --- a/core/src/main/java/fj/TryCatch0.java +++ b/core/src/main/java/fj/TryCatch0.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch0 { +public interface TryCatch0 { - A f() throws Exception; + A f() throws E; } diff --git a/core/src/main/java/fj/TryCatch1.java b/core/src/main/java/fj/TryCatch1.java index 28e83664..02a17afa 100644 --- a/core/src/main/java/fj/TryCatch1.java +++ b/core/src/main/java/fj/TryCatch1.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch1 { +public interface TryCatch1 { - B f(A a) throws Exception; + B f(A a) throws E; } diff --git a/core/src/main/java/fj/TryCatch2.java b/core/src/main/java/fj/TryCatch2.java index 3ac3145a..a92ab00c 100644 --- a/core/src/main/java/fj/TryCatch2.java +++ b/core/src/main/java/fj/TryCatch2.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch2 { +public interface TryCatch2 { - C f(A a, B b) throws Exception; + C f(A a, B b) throws E; } diff --git a/core/src/main/java/fj/TryCatch3.java b/core/src/main/java/fj/TryCatch3.java index 35f26d5f..970f7044 100644 --- a/core/src/main/java/fj/TryCatch3.java +++ b/core/src/main/java/fj/TryCatch3.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch3 { +public interface TryCatch3 { - D f(A a, B b, C c) throws Exception; + D f(A a, B b, C c) throws E; } diff --git a/core/src/main/java/fj/TryCatch4.java b/core/src/main/java/fj/TryCatch4.java index b07edf3c..f15cafdc 100644 --- a/core/src/main/java/fj/TryCatch4.java +++ b/core/src/main/java/fj/TryCatch4.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch4 { +public interface TryCatch4 { - E f(A a, B b, C c, D d) throws Exception; + E f(A a, B b, C c, D d) throws Z; } diff --git a/core/src/main/java/fj/TryCatch5.java b/core/src/main/java/fj/TryCatch5.java index b47f339e..ace1b537 100644 --- a/core/src/main/java/fj/TryCatch5.java +++ b/core/src/main/java/fj/TryCatch5.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch5 { +public interface TryCatch5 { - F f(A a, B b, C c, D d, E e) throws Exception; + F f(A a, B b, C c, D d, E e) throws Z; } diff --git a/core/src/main/java/fj/TryCatch6.java b/core/src/main/java/fj/TryCatch6.java index 5453a747..82dc5fad 100644 --- a/core/src/main/java/fj/TryCatch6.java +++ b/core/src/main/java/fj/TryCatch6.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch6 { +public interface TryCatch6 { - G f(A a, B b, C c, D d, E e, F f) throws Exception; + G f(A a, B b, C c, D d, E e, F f) throws Z; } diff --git a/core/src/main/java/fj/TryCatch7.java b/core/src/main/java/fj/TryCatch7.java index f38ea0cd..97f90cfc 100644 --- a/core/src/main/java/fj/TryCatch7.java +++ b/core/src/main/java/fj/TryCatch7.java @@ -10,8 +10,8 @@ * @version %build.number% */ -public interface TryCatch7 { +public interface TryCatch7 { - H f(A a, B b, C c, D d, E e, F f, G g) throws Exception; + H f(A a, B b, C c, D d, E e, F f, G g) throws Z; } diff --git a/core/src/main/java/fj/TryCatch8.java b/core/src/main/java/fj/TryCatch8.java index db8661b5..f90f2c6e 100644 --- a/core/src/main/java/fj/TryCatch8.java +++ b/core/src/main/java/fj/TryCatch8.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface TryCatch8 { +public interface TryCatch8 { - I f(A a, B b, C c, D d, E e, F f, G g, H h) throws Exception; + I f(A a, B b, C c, D d, E e, F f, G g, H h) throws Z; } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 45e12cc8..120555f7 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -26,7 +26,7 @@ * @author Martin Grotzke * */ -public abstract class IOFunctions { +public class IOFunctions { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; @@ -334,5 +334,8 @@ public static IO join(IO> io1) { return bind(io1, io2 -> io2); } + public static SafeIO toSafeIO(IO io) { + return () -> P1Functions.toP1(() -> io.run())._1(); + } } diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 983fd107..b66bf157 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -64,27 +64,27 @@ public static F, BiFunction> F2_BiFunction() { return f -> (a, b) -> f.f(a, b); } - static public Supplier> TryCatch0_Supplier(final TryCatch0 t) { - return Java8.TryCatch0_Supplier().f(t); + static public Supplier> TryCatch0_Supplier(final TryCatch0 t) { + return Java8.TryCatch0_Supplier().f(t); } - static public F, Supplier>> TryCatch0_Supplier() { + static public F, Supplier>> TryCatch0_Supplier() { return t -> () -> P1Functions.toP1(t)._1(); } - static public Function> TryCatch1_Function(final TryCatch1 t) { - return Java8.TryCatch1_Function().f(t); + static public Function> TryCatch1_Function(final TryCatch1 t) { + return Java8.TryCatch1_Function().f(t); } - static public F, Function>> TryCatch1_Function() { + static public F, Function>> TryCatch1_Function() { return t -> a -> F1Functions.toF1(t).f(a); } - static public BiFunction> TryCatch2_BiFunction(final TryCatch2 t) { - return Java8.TryCatch2_BiFunction().f(t); + static public BiFunction> TryCatch2_BiFunction(final TryCatch2 t) { + return Java8.TryCatch2_BiFunction().f(t); } - static public F, BiFunction>> TryCatch2_BiFunction() { + static public F, BiFunction>> TryCatch2_BiFunction() { return t -> (a, b) -> F2Functions.toF2(t).f(a, b); } From 31061330f7a2fc030b03284ee6129728eae95700 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 3 Jul 2014 15:49:57 +1000 Subject: [PATCH 097/811] Added type safe SafeIO type --- core/src/main/java/fj/data/SafeIO.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 core/src/main/java/fj/data/SafeIO.java diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java new file mode 100644 index 00000000..6dfa64a5 --- /dev/null +++ b/core/src/main/java/fj/data/SafeIO.java @@ -0,0 +1,14 @@ +package fj.data; + +import java.io.IOException; + +/** + * Created by MarkPerry on 3/07/2014. + */ +public interface SafeIO extends IO> { + + @Override + public Validation run(); + +} + From 255beaa4980a83f72aefaf0c468a4e511d778c35 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 3 Jul 2014 17:08:41 +1000 Subject: [PATCH 098/811] Fixed #49 - show null for null parameter in show --- core/src/main/java/fj/Show.java | 2 +- core/src/test/java/fj/data/test/TestNull.java | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/fj/data/test/TestNull.java diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 9540dc1a..7351d918 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -179,7 +179,7 @@ public Stream f(final A a) { public static Show anyShow() { return new Show(new F>() { public Stream f(final A a) { - return Stream.fromString(a.toString()); + return Stream.fromString((a == null) ? "null" : a.toString()); } }); } diff --git a/core/src/test/java/fj/data/test/TestNull.java b/core/src/test/java/fj/data/test/TestNull.java new file mode 100644 index 00000000..6f7795aa --- /dev/null +++ b/core/src/test/java/fj/data/test/TestNull.java @@ -0,0 +1,33 @@ +package fj.data.test; + +import fj.F2; +import fj.F3; +import fj.data.List; +import fj.test.Arbitrary; +import fj.test.CheckResult; +import fj.test.Gen; +import fj.test.Property; +import org.junit.Test; + +import static fj.Function.compose; +import static fj.test.Arbitrary.*; +import static fj.test.Arbitrary.arbLong; +import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Coarbitrary.coarbLong; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by MarkPerry on 3/07/2014. + */ +public class TestNull { + + @Test + public void testShowNullParameters() { + Property p = property(arbitrary(Gen.value(null)), (Integer i) -> { + return prop(i != null); + }); + CheckResult.summary.println(p.check()); + } + +} From 785d1555b8b4cc2f18f6ba8f2e33e91fa56dd7f6 Mon Sep 17 00:00:00 2001 From: Steven Ruppert Date: Thu, 3 Jul 2014 10:11:35 -0600 Subject: [PATCH 099/811] Test: test exception propagation from generators failing. --- .../src/test/java/fj/data/test/TestCheck.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 core/src/test/java/fj/data/test/TestCheck.java diff --git a/core/src/test/java/fj/data/test/TestCheck.java b/core/src/test/java/fj/data/test/TestCheck.java new file mode 100644 index 00000000..8292ff61 --- /dev/null +++ b/core/src/test/java/fj/data/test/TestCheck.java @@ -0,0 +1,41 @@ +package fj.data.test; + +import fj.F2; +import fj.F3; +import fj.data.List; +import fj.test.Arbitrary; +import fj.test.CheckResult; +import fj.test.Gen; +import fj.test.Property; +import org.junit.*; + +import static fj.Function.compose; +import static fj.test.Arbitrary.*; +import static fj.test.Arbitrary.arbLong; +import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Coarbitrary.coarbLong; +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static org.junit.Assert.*; + +public class TestCheck { + + @Test(timeout=1000 /*ms*/) + public void testExceptionsThrownFromGeneratorsArePropagated() { + Gen failingGen = Gen.value(0).map((i) -> { + throw new RuntimeException("test failure"); + }); + + Property p = property(arbitrary(failingGen), (Integer i) -> { + return prop(i == 0); + }); + + CheckResult res = p.check( + 1, /*minSuccessful*/ + 0, /*maxDiscarded*/ + 0, /*minSize*/ + 1 /*maxSize*/ + ); + assertTrue("Exception not propagated!", res.isGenException()); + } +} From d79cd1754946147193f206acfca0ec7ad4a55634 Mon Sep 17 00:00:00 2001 From: Steven Ruppert Date: Thu, 3 Jul 2014 10:21:01 -0600 Subject: [PATCH 100/811] Test: propagate exception in `check()`, fix #43 --- core/src/main/java/fj/test/Property.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/test/Property.java b/core/src/main/java/fj/test/Property.java index 6848d083..e7fc857a 100644 --- a/core/src/main/java/fj/test/Property.java +++ b/core/src/main/java/fj/test/Property.java @@ -184,7 +184,8 @@ else if (x.isFalsified()) { break; } } catch (final Throwable t) { - genException(t, s, d); + res = genException(t, s, d); + break; } } From ac716550b5cdb74af607638ea845949648007db6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 7 Jul 2014 22:40:50 +1000 Subject: [PATCH 101/811] Added functions to IOFunctions --- core/src/main/java/fj/data/IOFunctions.java | 43 +++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 120555f7..a3f69ee3 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -338,4 +338,47 @@ public static SafeIO toSafeIO(IO io) { return () -> P1Functions.toP1(() -> io.run())._1(); } + public static IO append(final IO io1, final IO io2) { + return () -> { + io1.run(); + return io2.run(); + }; + } + + public static IO left(final IO io1, final IO io2) { + return () -> { + A a = io1.run(); + io2.run(); + return a; + }; + } + + public static IO flatMap(final IO io, final F> f) { + return bind(io, f); + } + + static IO> sequenceWhile(final Stream> stream, final F f) { + return new IO>() { + @Override + public Stream run() throws IOException { + boolean loop = true; + Stream> input = stream; + Stream result = Stream.nil(); + while (loop) { + if (input.isEmpty()) { + loop = false; + } else { + A a = input.head().run(); + if (!f.f(a)) { + loop = false; + } else { + input = input.tail()._1(); + result = result.cons(a); + } + } + } + return result.reverse(); + } + }; + } } From 0be0d6ab13127975667b65fae47e8dd77ba7a069 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 7 Jul 2014 22:41:25 +1000 Subject: [PATCH 102/811] Added simple functional RNG --- core/src/main/java/fj/RNG.java | 12 ++++++++++++ core/src/main/java/fj/SimpleRNG.java | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 core/src/main/java/fj/RNG.java create mode 100644 core/src/main/java/fj/SimpleRNG.java diff --git a/core/src/main/java/fj/RNG.java b/core/src/main/java/fj/RNG.java new file mode 100644 index 00000000..64399696 --- /dev/null +++ b/core/src/main/java/fj/RNG.java @@ -0,0 +1,12 @@ +package fj; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public abstract class RNG { + + public abstract P2 nextInt(); + + + +} diff --git a/core/src/main/java/fj/SimpleRNG.java b/core/src/main/java/fj/SimpleRNG.java new file mode 100644 index 00000000..e97568d8 --- /dev/null +++ b/core/src/main/java/fj/SimpleRNG.java @@ -0,0 +1,22 @@ +package fj; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public class SimpleRNG extends RNG { + + private Long seed; + + public SimpleRNG(long s) { + seed = s; + } + + public P2 nextInt() { + long newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL; + SimpleRNG nextRng = new SimpleRNG(newSeed); + long n = (Long) (newSeed >>> 16); + Integer i = (int) n; + return P.p(i, nextRng); + } + +} From be82de64a0f63194443a9cee710f358101f07661 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 7 Jul 2014 22:41:49 +1000 Subject: [PATCH 103/811] Added first attempt at Reader/Writer/State --- core/src/main/java/fj/data/Reader.java | 41 ++++++++++ core/src/main/java/fj/data/State.java | 100 +++++++++++++++++++++++++ core/src/main/java/fj/data/Writer.java | 54 +++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 core/src/main/java/fj/data/Reader.java create mode 100644 core/src/main/java/fj/data/State.java create mode 100644 core/src/main/java/fj/data/Writer.java diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java new file mode 100644 index 00000000..badaae5a --- /dev/null +++ b/core/src/main/java/fj/data/Reader.java @@ -0,0 +1,41 @@ +package fj.data; + +import fj.F; +import fj.F1Functions; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public class Reader { + + private F function; + + public Reader(F f) { + function = f; + } + + public static Reader unit(F f) { + return new Reader(f); + } + + public B f(A a) { + return function.f(a); + } + + public Reader map(F f) { + return unit(F1Functions.andThen(function, f)); + } + + public Reader andThen(F f) { + return map(f); + } + + public Reader flatMap(F> f) { + return unit(a -> f.f(function.f(a)).f(a)); + } + + public Reader bind(F> f) { + return flatMap(f); + } + +} diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java new file mode 100644 index 00000000..24835bc0 --- /dev/null +++ b/core/src/main/java/fj/data/State.java @@ -0,0 +1,100 @@ +package fj.data; + +import fj.*; + +import static fj.P.p; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public class State { + + private F> run; + + private State(F> f) { + run = f; + } + + public P2 run(S s) { + return run.f(s); + } + + public static State unitF(F> f) { + return new State(f); + } + + public static State unitS(F f) { + return unitF((S1 s) -> { + S1 s2 = f.f(s); + return p(s2, s2); + }); + } + + public static State unit(A1 a) { + return unitF(s -> p(s, a)); + } + + public State map(F f) { + return unitF((S s) -> { + P2 p2 = run(s); + B b = f.f(p2._2()); + return p(p2._1(), b); + }); + } + + public static State modify(F f) { + return State.get().flatMap(s -> unitF(s2 -> p(f.f(s), Unit.unit()))); + } + + public State mapState(F, P2> f) { + return unitF(s -> f.f(run(s))); + } + + public static State flatMap(State mb, F> f) { + return mb.flatMap(f); + } + + public State flatMap(F> f) { + return unitF((S s) -> { + P2 p = run(s); + A a = p._2(); + S s2 = p._1(); + State smb = f.f(a); + return smb.run(s2); + }); + } + + + public static State get() { + return unitF(s -> p(s, s)); + } + + public State gets() { + return unitF(s -> { + P2 p = run(s); + S s2 = p._1(); + return p(s2, s2); + }); + } + + public static State put(S1 s) { + return State.unitF((S1 z) -> p(s, Unit.unit())); + } + + public A eval(S s) { + return run(s)._2(); + } + + public S exec(S s) { + return run(s)._1(); + } + + public State withs(F f) { + return unitF(F1Functions.andThen(f, run)); + } + + public static State gets(F f) { + return State.get().map(s -> f.f(s)); + } + +} diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java new file mode 100644 index 00000000..839cd888 --- /dev/null +++ b/core/src/main/java/fj/data/Writer.java @@ -0,0 +1,54 @@ +package fj.data; + +import fj.F; +import fj.F2; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public class Writer { + + private A value; + private W log; + private F2 plus; + + public static final F LOG_FUNCTION = o -> "Added " + o + " to the log\n"; + public static final F2 STRING_CONCAT = (String a, String b) -> a + b; + public static final String STRING_EMPTY = ""; + + private Writer(A a, W w, F2 f) { + value = a; + log = w; + plus = f; + } + + public static Writer unit(B a, W w, F2 f) { + return new Writer(a, w, f); + } + + public Writer tell(W w) { + return unit(value, plus.f(log, w), plus); + } + + public Writer map(F f) { + return unit(f.f(value), log, plus); + } + + public Writer flatMap(F> f) { + Writer writer = f.f(value); + return unit(writer.value, plus.f(log, writer.log), plus); + } + + public static Writer unit(B b) { + return unit(b, STRING_EMPTY, STRING_CONCAT); + } + + public static Writer log(B b) { + return unit(b, LOG_FUNCTION.f(b), STRING_CONCAT); + } + + public static F> log() { + return a -> Writer.unit(a, LOG_FUNCTION.f(a), STRING_CONCAT); + } + +} From e2d35c0f5aa5816323ab5bac5e4c388f0d63a948 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 8 Jul 2014 00:22:02 +1000 Subject: [PATCH 104/811] Added run method to Writer --- core/src/main/java/fj/data/Writer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index 839cd888..b16b77fb 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -2,6 +2,8 @@ import fj.F; import fj.F2; +import fj.P; +import fj.P2; /** * Created by MarkPerry on 7/07/2014. @@ -22,6 +24,10 @@ private Writer(A a, W w, F2 f) { plus = f; } + public P2 run() { + return P.p(log, value); + } + public static Writer unit(B a, W w, F2 f) { return new Writer(a, w, f); } From 393900763b62806851fa7f1d4bf346b889f6fca7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 00:52:55 +1000 Subject: [PATCH 105/811] #52: Reviewed source compatibility --- build.gradle | 2 +- core/build.gradle | 1 - demo/build.gradle | 1 - java8/build.gradle | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 1d52e117..f05c160f 100644 --- a/build.gradle +++ b/build.gradle @@ -75,7 +75,7 @@ subprojects { apply plugin: "maven" apply plugin: "java" - sourceCompatibility = "1.7" + sourceCompatibility = "1.8" if (doSigning()) { apply plugin: "signing" diff --git a/core/build.gradle b/core/build.gradle index 749a7ae7..40a5ce59 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,7 +9,6 @@ dependencies { testCompile dependencyJunit } -sourceCompatibility = "1.8" retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/demo/build.gradle b/demo/build.gradle index f108aa44..df833911 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -4,7 +4,6 @@ apply plugin: 'retrolambda' mainClassName = "fj.demo.euler.Problem2" -sourceCompatibility = "1.8" retrolambda { jdk System.getenv("JAVA8_HOME") diff --git a/java8/build.gradle b/java8/build.gradle index 7ecff839..6dc23320 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -3,7 +3,6 @@ jar { baseName "${project.projectName}-${project.name}" } -sourceCompatibility = "1.8" dependencies { compile project(":core") From c0033d20a5c2f8ce063b4b893a319cc807e4f23b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 00:58:04 +1000 Subject: [PATCH 106/811] #53: git status --- core/src/main/java/fj/data/$.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 0eeb5af0..abdcb507 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -7,7 +7,6 @@ * is the identity morphism from B to B. */ @SuppressWarnings({"UnusedDeclaration"}) -@Deprecated public final class $ implements P1 { private final B b; @@ -16,11 +15,24 @@ public final class $ implements P1 { this.b = b; } + /** + * @deprecated JDK 8 warns '_' may not be supported after SE 8. Replaced by {@link #constant} and synonym {@link #__} (prefer constant). + */ + @Deprecated public static $ _(final B b) { - return new $(b); + return constant(b); } - public B _1() { + public static $ __(final B b) { + return constant(b); + } + + public static $ constant(final B b) { + return new $(b); + } + + + public B _1() { return b; } } From 520f412d303aa5e9b0ccd7278ca34f1e14bcadec Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 00:59:00 +1000 Subject: [PATCH 107/811] #51: Fixed javadoc warnings --- core/src/main/java/fj/data/IOFunctions.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index a3f69ee3..86aac967 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -306,9 +306,6 @@ public B run() throws IOException { /** * Evaluate each action in the sequence from left to right, and collect the results. - * - * @param list - * @return */ public static IO> sequence(List> list) { F2, IO>, IO>> f2 = (io, ioList) -> @@ -319,10 +316,6 @@ public static IO> sequence(List> list) { /** * Map each element of a structure to an action, evaluate these actions from left to right * and collect the results. - * - * @param list - * @param f - * @return */ public static IO> traverse(List list, F> f) { F2>, IO>> f2 = (a, acc) -> From c34d3b42c769881ad9f228753174356801885fef Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 16:09:56 +1000 Subject: [PATCH 108/811] #35: Fixed memo function in for artiy 2..8 in Px (e.g. P3) --- core/src/main/java/fj/P.java | 197 ++++++++++++++++++++- core/src/main/java/fj/P2.java | 39 ++-- core/src/main/java/fj/P3.java | 7 +- core/src/main/java/fj/P4.java | 9 +- core/src/main/java/fj/P5.java | 11 +- core/src/main/java/fj/P6.java | 13 +- core/src/main/java/fj/P7.java | 15 +- core/src/main/java/fj/P8.java | 17 +- core/src/test/java/fj/MemoisationTest.java | 91 ++++++++++ 9 files changed, 346 insertions(+), 53 deletions(-) create mode 100644 core/src/test/java/fj/MemoisationTest.java diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 52bee3dd..e20bb45e 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -37,7 +37,202 @@ public A _1() { }; } - /** + + public static P1 lazy(final P1 pa) { + return pa; + } + + public static P2 lazy(final P1 pa, final P1 pb) { + return new P2() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + }; + } + + public static P3 lazy(final P1 pa, final P1 pb, final P1 pc) { + return new P3() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + @Override + public C _3() { + return pc._1(); + } + }; + } + + public static P4 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd) { + return new P4() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + @Override + public C _3() { + return pc._1(); + } + + @Override + public D _4() { + return pd._1(); + } + }; + } + + public static P5 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe) { + return new P5() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + @Override + public C _3() { + return pc._1(); + } + + @Override + public D _4() { + return pd._1(); + } + + @Override + public E _5() { + return pe._1(); + } + }; + } + + public static P6 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe, P1 pf) { + return new P6() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + @Override + public C _3() { + return pc._1(); + } + + @Override + public D _4() { + return pd._1(); + } + + @Override + public E _5() { + return pe._1(); + } + + @Override + public F _6() { + return pf._1(); + } + }; + } + + public static P7 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe, P1 pf, P1 pg) { + return new P7() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + @Override + public C _3() { + return pc._1(); + } + + @Override + public D _4() { + return pd._1(); + } + + @Override + public E _5() { + return pe._1(); + } + + @Override + public F _6() { + return pf._1(); + } + + @Override + public G _7() { + return pg._1(); + } + }; + } + + public static P8 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe, P1 pf, P1 pg, P1 ph) { + return new P8() { + @Override + public A _1() { + return pa._1(); + } + @Override + public B _2() { + return pb._1(); + } + @Override + public C _3() { + return pc._1(); + } + + @Override + public D _4() { + return pd._1(); + } + + @Override + public E _5() { + return pe._1(); + } + + @Override + public F _6() { + return pf._1(); + } + + @Override + public G _7() { + return pg._1(); + } + + @Override + public H _8() { + return ph._1(); + } + }; + } + + /** * A function that puts an element in a product-2. * * @return A function that puts an element in a product-2. diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 795ce8db..2860eab9 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -180,25 +180,26 @@ public final P1 _2_() { return F1Functions.lazy(P2.__2()).f(this); } - /** - * Provides a memoising P2 that remembers its values. - * - * @return A P2 that calls this P2 once for any given element and remembers the value for subsequent calls. - */ - public final P2 memo() { - return new P2() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - - public A _1() { - return a._1(); - } - - public B _2() { - return b._1(); - } - }; - } + /** + * Provides a memoising P2 that remembers its values. + * + * @return A P2 that calls this P2 once for any given element and remembers the value for subsequent calls. + */ + public final P2 memo() { + P2 self = this; + return new P2() { + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + + public A _1() { + return a._1(); + } + + public B _2() { + return b._1(); + } + }; + } /** * A first-class version of the split function. diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 4e7587dc..b5004e7d 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -126,10 +126,11 @@ public final P1 _3_() { * @return A P3 that calls this P3 once for any given element and remembers the value for subsequent calls. */ public final P3 memo() { + P3 self = this; return new P3() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - private final P1 c = P1Functions.memo(_3_()); + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 c = P1Functions.memo(() -> self._3()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 1711e9e6..6de72c63 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -180,11 +180,12 @@ public final P1 _4_() { * @return A P4 that calls this P4 once for any given element and remembers the value for subsequent calls. */ public final P4 memo() { + P4 self = this; return new P4() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - private final P1 c = P1Functions.memo(_3_()); - private final P1 d = P1Functions.memo(_4_()); + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 c = P1Functions.memo(() -> self._3()); + private final P1 d = P1Functions.memo(() -> self._4()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index c5d19ea2..da53902b 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -242,12 +242,13 @@ public final P1 _5_() { * @return A P5 that calls this P5 once for any given element and remembers the value for subsequent calls. */ public final P5 memo() { + P5 self = this; return new P5() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - private final P1 c = P1Functions.memo(_3_()); - private final P1 d = P1Functions.memo(_4_()); - private final P1 e = P1Functions.memo(_5_()); + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 c = P1Functions.memo(() -> self._3()); + private final P1 d = P1Functions.memo(() -> self._4()); + private final P1 e = P1Functions.memo(() -> self._5()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 6f557c8e..e12036ac 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -313,13 +313,14 @@ public final P1 _6_() { * @return A P6 that calls this P6 once for any given element and remembers the value for subsequent calls. */ public final P6 memo() { + P6 self = this; return new P6() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - private final P1 c = P1Functions.memo(_3_()); - private final P1 d = P1Functions.memo(_4_()); - private final P1 e = P1Functions.memo(_5_()); - private final P1 f = P1Functions.memo(_6_()); + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 c = P1Functions.memo(() -> self._3()); + private final P1 d = P1Functions.memo(() -> self._4()); + private final P1 e = P1Functions.memo(() -> self._5()); + private final P1 f = P1Functions.memo(() -> self._6()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index d1dc7b99..6bb7cbf2 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -391,14 +391,15 @@ public final P1 _7_() { * @return A P7 that calls this P7 once for any given element and remembers the value for subsequent calls. */ public final P7 memo() { + P7 self = this; return new P7() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - private final P1 c = P1Functions.memo(_3_()); - private final P1 d = P1Functions.memo(_4_()); - private final P1 e = P1Functions.memo(_5_()); - private final P1 f = P1Functions.memo(_6_()); - private final P1 g = P1Functions.memo(_7_()); + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 c = P1Functions.memo(() -> self._3()); + private final P1 d = P1Functions.memo(() -> self._4()); + private final P1 e = P1Functions.memo(() -> self._5()); + private final P1 f = P1Functions.memo(() -> self._6()); + private final P1 g = P1Functions.memo(() -> self._7()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index ffa60f51..503801db 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -478,15 +478,16 @@ public final P1 _8_() { * @return A P8 that calls this P8 once for any given element and remembers the value for subsequent calls. */ public final P8 memo() { + P8 self = this; return new P8() { - private final P1 a = P1Functions.memo(_1_()); - private final P1 b = P1Functions.memo(_2_()); - private final P1 c = P1Functions.memo(_3_()); - private final P1 d = P1Functions.memo(_4_()); - private final P1 e = P1Functions.memo(_5_()); - private final P1 f = P1Functions.memo(_6_()); - private final P1 g = P1Functions.memo(_7_()); - private final P1 h = P1Functions.memo(_8_()); + private final P1 a = P1Functions.memo(() -> self._1()); + private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 c = P1Functions.memo(() -> self._3()); + private final P1 d = P1Functions.memo(() -> self._4()); + private final P1 e = P1Functions.memo(() -> self._5()); + private final P1 f = P1Functions.memo(() -> self._6()); + private final P1 g = P1Functions.memo(() -> self._7()); + private final P1 h = P1Functions.memo(() -> self._8()); public A _1() { return a._1(); diff --git a/core/src/test/java/fj/MemoisationTest.java b/core/src/test/java/fj/MemoisationTest.java new file mode 100644 index 00000000..eb8ed18a --- /dev/null +++ b/core/src/test/java/fj/MemoisationTest.java @@ -0,0 +1,91 @@ +package fj; + +import fj.test.Arbitrary; +import fj.test.Property; +import org.junit.Test; + +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbString; +import static fj.test.CheckResult.summary; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by mperry on 14/07/2014. + */ +public class MemoisationTest { + + @Test + public void test1() { + final Property p = property(arbInteger, a -> { + P1 t = P1Functions.memo(P.p(a)); + return prop(t._1() == t._1()); + }); + summary.println(p.check()); + } + + @Test + public void test2() { + final Property p = property(arbInteger, arbInteger, (a, b) -> { + P2 t = P.p(a, b).memo(); + return prop(t._1() == t._1() && t._2() == t._2()); + }); + summary.println(p.check()); + } + + @Test + public void test3() { + final Property p = property(arbInteger, arbInteger, arbInteger, (a, b, c) -> { + P3 t = P.p(a, b, c).memo(); + return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3()); + }); + summary.println(p.check()); + } + + @Test + public void test4() { + final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d) -> { + P4 t = P.p(a, b, c, d).memo(); + return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4()); + }); + summary.println(p.check()); + } + + @Test + public void test5() { + final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e) -> { + P5 t = P.p(a, b, c, d, e).memo(); + return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5()); + }); + summary.println(p.check()); + } + + @Test + public void test6() { + final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f) -> { + P6 t = P.p(a, b, c, d, e, f).memo(); + return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5() && t._6() == t._6()); + }); + summary.println(p.check()); + } + + @Test + public void test7() { + final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f, g) -> { + P7 t = P.p(a, b, c, d, e, f, g).memo(); + return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5() && t._6() == t._6() && t._7() == t._7()); + }); + summary.println(p.check()); + } + + @Test + public void test8() { + final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f, g, h) -> { + P8 t = P.p(a, b, c, d, e, f, g, h).memo(); + return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5() && t._6() == t._6() && t._7() == t._7() && t._8() == t._8()); + }); + summary.println(p.check()); + } + + +} From 01bd0d9ff7aaeb75ffb11848a8b756ae6555c961 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 16:39:39 +1000 Subject: [PATCH 109/811] #35: Test memoisation returns the same value --- core/src/test/java/fj/MemoisationTest.java | 25 +++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/core/src/test/java/fj/MemoisationTest.java b/core/src/test/java/fj/MemoisationTest.java index eb8ed18a..967ef5c3 100644 --- a/core/src/test/java/fj/MemoisationTest.java +++ b/core/src/test/java/fj/MemoisationTest.java @@ -1,14 +1,13 @@ package fj; -import fj.test.Arbitrary; import fj.test.Property; import org.junit.Test; import static fj.test.Arbitrary.arbInteger; -import static fj.test.Arbitrary.arbString; import static fj.test.CheckResult.summary; import static fj.test.Property.prop; import static fj.test.Property.property; +import static org.junit.Assert.assertTrue; /** * Created by mperry on 14/07/2014. @@ -33,6 +32,27 @@ public void test2() { summary.println(p.check()); } + static P2 pair = P.p(0, 0); + + static Integer count(int i) { + if (i == 1) { + pair = P.p(pair._1() + 1, pair._2()); + return pair._1(); + } else if (i == 2) { + pair = P.p(pair._1(), pair._2() + 1); + return pair._2(); + } else { + return -1; + } + } + + @Test + public void testRecomputeP2() { + P2 t = P.lazy(() -> count(1), () -> count(2)).memo(); + System.out.println("tuple: " + t + " 1:" + t._1() + " 2: " + t._2()); + assertTrue(t._1() == t._1() && t._2() == t._2()); + } + @Test public void test3() { final Property p = property(arbInteger, arbInteger, arbInteger, (a, b, c) -> { @@ -87,5 +107,4 @@ public void test8() { summary.println(p.check()); } - } From 913fcf6eca461727a0bd824b25de57a3ca09d3ab Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 22:15:56 +1000 Subject: [PATCH 110/811] #36: Updated javadoc for List.group --- core/src/main/java/fj/data/List.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 17593919..cec4c433 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -403,7 +403,8 @@ public Boolean f(final A a) { } /** - * Groups elements according to the given equality implementation. + * Groups elements according to the given equality implementation by longest + * sequence of equal elements. * * @param e The equality implementation for the elements. * @return A list of grouped elements. From 779f58da12f03db32aa6d6a0ee1f6fc782637365 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Jul 2014 23:34:46 +1000 Subject: [PATCH 111/811] #33: Fixed ClassCastException, converted other similar usages --- core/src/main/java/fj/data/Java.java | 61 +++++++++++++++--------- core/src/test/java/fj/data/JavaTest.java | 26 ++++++++++ 2 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 core/src/test/java/fj/data/JavaTest.java diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index cbc96843..d0a59b72 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -11,6 +11,8 @@ import static fj.data.List.list; import static fj.data.Option.some; +import java.util.Arrays; +import java.util.Collection; import java.util.ArrayList; import java.util.BitSet; import java.util.EnumSet; @@ -1723,7 +1725,7 @@ public static F, List> ArrayList_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final ArrayList as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1741,7 +1743,7 @@ public static F, List> JUList_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final java.util.List as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1775,14 +1777,27 @@ public Option> f(final Integer i) { * @return A function that converts enum sets to lists. */ public static > F, List> EnumSet_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final EnumSet as) { - return list(as.toArray((A[]) new Object[as.size()])); - } - }; + return new F, List>() { + @SuppressWarnings({"unchecked"}) + public List f(final EnumSet as) { + return Collection_List(as); + } + }; } + public static List Collection_List(Collection c) { + return Java.Collection_List().f(c); + } + + public static F, List> Collection_List() { + return c -> list(c.toArray(array(c.size()))); + } + + @SafeVarargs + private static E[] array(int length, E... array) { + return Arrays.copyOf(array, length); + } + // todo // END EnumSet -> @@ -1798,7 +1813,7 @@ public static F, List> HashSet_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final HashSet as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1818,7 +1833,7 @@ public static F, List> LinkedHashSet_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final LinkedHashSet as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1838,7 +1853,7 @@ public static F, List> LinkedList_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final LinkedList as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1858,7 +1873,7 @@ public static F, List> PriorityQueue_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final PriorityQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1878,7 +1893,7 @@ public static F, List> Stack_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final Stack as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1898,7 +1913,7 @@ public static F, List> TreeSet_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final TreeSet as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1918,7 +1933,7 @@ public static F, List> Vector_List() { return new F, List>() { @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"}) public List f(final Vector as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1938,7 +1953,7 @@ public static F, List> ArrayBlockingQueue_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final ArrayBlockingQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1958,7 +1973,7 @@ public static F, List> ConcurrentLinkedQueue_Lis return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final ConcurrentLinkedQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1978,7 +1993,7 @@ public static F, List> CopyOnWriteArrayList_List( return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final CopyOnWriteArrayList as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -1998,7 +2013,7 @@ public static F, List> CopyOnWriteArraySet_List() return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final CopyOnWriteArraySet as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -2018,7 +2033,7 @@ public static F, List> DelayQueue_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final DelayQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -2038,7 +2053,7 @@ public static F, List> LinkedBlockingQueue_List() return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final LinkedBlockingQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -2058,7 +2073,7 @@ public static F, List> PriorityBlockingQueue_Lis return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final PriorityBlockingQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } @@ -2078,7 +2093,7 @@ public static F, List> SynchronousQueue_List() { return new F, List>() { @SuppressWarnings({"unchecked"}) public List f(final SynchronousQueue as) { - return list(as.toArray((A[]) new Object[as.size()])); + return Collection_List(as); } }; } diff --git a/core/src/test/java/fj/data/JavaTest.java b/core/src/test/java/fj/data/JavaTest.java new file mode 100644 index 00000000..3b5a5785 --- /dev/null +++ b/core/src/test/java/fj/data/JavaTest.java @@ -0,0 +1,26 @@ +package fj.data; + +import fj.Show; +import org.junit.Test; + +import java.util.EnumSet; + +import static fj.Show.listShow; + +/** + * Created by MarkPerry on 14/07/2014. + */ +public class JavaTest { + + @Test + public void test1() { + // #33: Fixes ClassCastException + final List colors = Java.EnumSet_List().f(EnumSet.allOf(Colors.class)); + listShow(Show.anyShow()).print(colors); + } + + enum Colors { + red, green, blue + } + +} From bb48f890fbeb71c3e80ad2113efcbaa5f32f3465 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 20 Jul 2014 03:15:49 +1000 Subject: [PATCH 112/811] Tidy up reader/writer/state --- core/src/main/java/fj/data/Reader.java | 4 +++ core/src/main/java/fj/data/State.java | 37 +++++++++++++------------- core/src/main/java/fj/data/Writer.java | 36 +++++++++++++++---------- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index badaae5a..f8210314 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -18,6 +18,10 @@ public static Reader unit(F f) { return new Reader(f); } + public static Reader constant(B b) { + return unit(a -> b); + } + public B f(A a) { return function.f(a); } diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 24835bc0..fec62b9e 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -19,23 +19,23 @@ public P2 run(S s) { return run.f(s); } - public static State unitF(F> f) { - return new State(f); + public static State unit(F> f) { + return new State(f); } - public static State unitS(F f) { - return unitF((S1 s) -> { - S1 s2 = f.f(s); + public static State units(F f) { + return unit((S s) -> { + S s2 = f.f(s); return p(s2, s2); }); } - public static State unit(A1 a) { - return unitF(s -> p(s, a)); + public static State constant(A a) { + return unit(s -> p(s, a)); } public State map(F f) { - return unitF((S s) -> { + return unit((S s) -> { P2 p2 = run(s); B b = f.f(p2._2()); return p(p2._1(), b); @@ -43,11 +43,11 @@ public State map(F f) { } public static State modify(F f) { - return State.get().flatMap(s -> unitF(s2 -> p(f.f(s), Unit.unit()))); + return State.init().flatMap(s -> unit(s2 -> p(f.f(s), Unit.unit()))); } public State mapState(F, P2> f) { - return unitF(s -> f.f(run(s))); + return unit(s -> f.f(run(s))); } public static State flatMap(State mb, F> f) { @@ -55,7 +55,7 @@ public static State flatMap(State mb, F> f) } public State flatMap(F> f) { - return unitF((S s) -> { + return unit((S s) -> { P2 p = run(s); A a = p._2(); S s2 = p._1(); @@ -64,21 +64,20 @@ public State flatMap(F> f) { }); } - - public static State get() { - return unitF(s -> p(s, s)); + public static State init() { + return unit(s -> p(s, s)); } public State gets() { - return unitF(s -> { + return unit(s -> { P2 p = run(s); S s2 = p._1(); return p(s2, s2); }); } - public static State put(S1 s) { - return State.unitF((S1 z) -> p(s, Unit.unit())); + public static State put(S s) { + return State.unit((S z) -> p(s, Unit.unit())); } public A eval(S s) { @@ -90,11 +89,11 @@ public S exec(S s) { } public State withs(F f) { - return unitF(F1Functions.andThen(f, run)); + return unit(F1Functions.andThen(f, run)); } public static State gets(F f) { - return State.get().map(s -> f.f(s)); + return State.init().map(s -> f.f(s)); } } diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index b16b77fb..4b09735b 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -10,39 +10,47 @@ */ public class Writer { - private A value; - private W log; - private F2 plus; + private A val; + private W logValue; + private F2 append; public static final F LOG_FUNCTION = o -> "Added " + o + " to the log\n"; public static final F2 STRING_CONCAT = (String a, String b) -> a + b; public static final String STRING_EMPTY = ""; private Writer(A a, W w, F2 f) { - value = a; - log = w; - plus = f; + val = a; + logValue = w; + append = f; } public P2 run() { - return P.p(log, value); + return P.p(logValue, val); } - public static Writer unit(B a, W w, F2 f) { - return new Writer(a, w, f); + public A value() { + return val; + } + + public W log() { + return logValue; + } + + public static Writer unit(A a, W w, F2 f) { + return new Writer(a, w, f); } public Writer tell(W w) { - return unit(value, plus.f(log, w), plus); + return unit(val, append.f(logValue, w), append); } public Writer map(F f) { - return unit(f.f(value), log, plus); + return unit(f.f(val), logValue, append); } public Writer flatMap(F> f) { - Writer writer = f.f(value); - return unit(writer.value, plus.f(log, writer.log), plus); + Writer writer = f.f(val); + return unit(writer.val, writer.append.f(logValue, writer.logValue), writer.append); } public static Writer unit(B b) { @@ -53,7 +61,7 @@ public static Writer log(B b) { return unit(b, LOG_FUNCTION.f(b), STRING_CONCAT); } - public static F> log() { + public static F> stringLogger() { return a -> Writer.unit(a, LOG_FUNCTION.f(a), STRING_CONCAT); } From 2ca88ffcf8e2d52b4cf06fcc823bbf807df2256b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 20 Jul 2014 03:16:07 +1000 Subject: [PATCH 113/811] Added vending state machine demo --- .../fj/demo/StateDemo_VendingMachine.java | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 demo/src/main/java/fj/demo/StateDemo_VendingMachine.java diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java new file mode 100644 index 00000000..c49395ff --- /dev/null +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -0,0 +1,93 @@ +package fj.demo; + +import fj.F2; +import fj.data.List; +import fj.data.State; + +import static fj.demo.StateDemo_VendingMachine.Input.COIN; +import static fj.demo.StateDemo_VendingMachine.Input.TURN; + +/** + * Created by MarkPerry on 20/07/2014. + */ +public class StateDemo_VendingMachine { + + public enum Input { COIN, TURN }; + + public static class VendingMachine { + + private boolean locked; + private int items; + private int coins; + + public VendingMachine(boolean lock, int things, int numCoins) { + locked = lock; + items = things; + coins = numCoins; + } + + /** + * Equals generated by Intellij + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + VendingMachine that = (VendingMachine) o; + + if (coins != that.coins) return false; + if (items != that.items) return false; + if (locked != that.locked) return false; + + return true; + } + + /** + * HashCode generated by Intellij + */ + @Override + public int hashCode() { + int result = (locked ? 1 : 0); + result = 31 * result + items; + result = 31 * result + coins; + return result; + } + + public String toString() { + return String.format("VendingMachine(locked=%b,items=%d,coins=%d)", locked, items, coins); + } + + VendingMachine next(Input i) { + if (items == 0) { + return this; + } else if (i == COIN && !locked) { + return this; + } else if (i == TURN && locked) { + return this; + } else if (i == COIN && locked) { + return new VendingMachine(false, items, coins + 1); + } else if (i == TURN && !locked) { + return new VendingMachine(true, items - 1, coins); + } else { + return this; + } + } + } + + static State simulate(List list) { + return list.foldLeft((s, i) -> s.map(m -> m.next(i)), State.init()); + } + + static void test() { + State s = simulate(List.list(COIN, TURN, TURN, COIN, COIN, TURN)); + VendingMachine m = s.eval(new VendingMachine(true, 5, 0)); + VendingMachine oracle = new VendingMachine(true, 3, 2); + System.out.printf("m1: %s, oracle: %s, equals: %b", m, oracle, m.equals(oracle)); + } + + public static void main(String args[]) { + test(); + } + +} From 191e38755e5cd5b7cf8766930468a49dd0f1b059 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 22 Jul 2014 00:33:14 +1000 Subject: [PATCH 114/811] #54: Added toString for product types P1-P8 --- core/src/main/java/fj/P1Functions.java | 3 +++ core/src/main/java/fj/P2.java | 4 ++++ core/src/main/java/fj/P3.java | 6 ++++++ core/src/main/java/fj/P4.java | 5 +++++ core/src/main/java/fj/P5.java | 6 ++++++ core/src/main/java/fj/P6.java | 5 +++++ core/src/main/java/fj/P7.java | 6 ++++++ core/src/main/java/fj/P8.java | 5 +++++ core/src/test/java/fj/P2Test.java | 17 +++++++++++++++++ 9 files changed, 57 insertions(+) create mode 100644 core/src/test/java/fj/P2Test.java diff --git a/core/src/main/java/fj/P1Functions.java b/core/src/main/java/fj/P1Functions.java index 0119c468..9b2c420d 100644 --- a/core/src/main/java/fj/P1Functions.java +++ b/core/src/main/java/fj/P1Functions.java @@ -234,4 +234,7 @@ static public P1> toP1(final TryCatch0 }; } + static public String toString(P1 p) { + return Show.p1Show(Show.anyShow()).showS(p); + } } diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 2860eab9..1a43558b 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -344,4 +344,8 @@ public C f(final A a, final B b) { }; } + public String toString() { + return Show.p2Show(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index b5004e7d..965f40d4 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -184,4 +184,10 @@ public C f(final P3 p) { } }; } + + public String toString() { + return Show.p3Show(Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); + } + + } diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 6de72c63..4b8c6de8 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -257,4 +257,9 @@ public D f(final P4 p) { } }; } + + public String toString() { + return Show.p4Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index da53902b..606578f3 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -336,4 +336,10 @@ public E f(final P5 p) { } }; } + + public String toString() { + return Show.p5Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); + } + + } diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index e12036ac..8fabd78b 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -426,4 +426,9 @@ public E f(final P6 p) { } }; } + + public String toString() { + return Show.p6Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 6bb7cbf2..d3c39d57 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -521,4 +521,10 @@ public G f(final P7 p) { } }; } + + public String toString() { + return Show.p7Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); + } + + } diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index 503801db..fa622e4e 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -627,4 +627,9 @@ public H f(final P8 p) { } }; } + + public String toString() { + return Show.p8Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/test/java/fj/P2Test.java b/core/src/test/java/fj/P2Test.java new file mode 100644 index 00000000..dc25a3e0 --- /dev/null +++ b/core/src/test/java/fj/P2Test.java @@ -0,0 +1,17 @@ +package fj; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by MarkPerry on 22/07/2014. + */ +public class P2Test { + + @Test + public void testToString() { + String s = P.p(1, 2).toString(); + Assert.assertTrue(s.equals("(1,2)")); + } + +} From 3d95053a52f4d2fa9d737ae8502f688f9230516d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 22 Jul 2014 11:54:21 +1000 Subject: [PATCH 115/811] Added Validation.toString --- core/src/main/java/fj/data/Validation.java | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 2b8af875..903a44e4 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -1,23 +1,10 @@ package fj.data; -import fj.Effect; -import fj.F; -import fj.F2; -import fj.F3; -import fj.F4; -import fj.F5; -import fj.F6; -import fj.F7; -import fj.F8; +import fj.*; import static fj.Function.curry; import static fj.P.p; -import fj.Function; -import fj.P1; -import fj.Semigroup; -import fj.Unit; - import static fj.Unit.unit; import static fj.Bottom.error; @@ -1186,4 +1173,9 @@ public Validation f(final String s) { return parseShort(s); } }; + + public String toString() { + return Show.validationShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } From 8c958050f71006243c81dc278eec844eea98ce0a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 22 Jul 2014 12:14:59 +1000 Subject: [PATCH 116/811] Added Option.toValidation --- core/src/main/java/fj/data/Option.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 80fd5a67..182d303c 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -479,6 +479,10 @@ public final Either toEither(final X x) { return isSome() ? Either.right(some()) : Either.left(x); } + public final Validation toValidation(final X x) { + return Validation.validation(toEither(x)); + } + /** * A first-class version of the toEither method. * From 985a1cf0e0dafdbc8d4157514d2a3659dfbe2caf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 13:23:20 +1000 Subject: [PATCH 117/811] #55 Added map and contramap for F and F2 --- core/src/main/java/fj/F1Functions.java | 8 ++++++++ core/src/main/java/fj/F2Functions.java | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index ca7bc02b..0df08d99 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -840,4 +840,12 @@ static public F> toF1(final TryC }; } + static public F map(F target, F f) { + return andThen(target, f); + } + + static public F contramap(F target, F f) { + return andThen(f, target); + } + } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index 3b11d7cd..a9946240 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -363,4 +363,20 @@ static public F2> toF2(fin }; } + static public F2 contramapFirst(F2 target, F f) { + return (z, b) -> target.f(f.f(z), b); + } + + static public F2 contramapSecond(F2 target, F f) { + return (a, z) -> target.f(a, f.f(z)); + } + + static public F2 contramap(F2 target, F f, F g) { + return contramapSecond(contramapFirst(target, f), g); + } + + static public F2 map(F2 target, F f) { + return (a, b) -> f.f(target.f(a, b)); + } + } From a384192c3ae7e8a82e360965f44cf012ba438812 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 14:32:49 +1000 Subject: [PATCH 118/811] #56: Make P1 an abstract class to maintain consistency. Instantiate using P.lazy --- core/src/main/java/fj/F1Functions.java | 2 +- core/src/main/java/fj/Hash.java | 2 +- core/src/main/java/fj/Ord.java | 2 +- core/src/main/java/fj/P.java | 188 +++++++++++++ core/src/main/java/fj/P1.java | 263 +++++++++++++++++- core/src/main/java/fj/P1Functions.java | 240 ---------------- core/src/main/java/fj/P2.java | 4 +- core/src/main/java/fj/P3.java | 6 +- core/src/main/java/fj/P4.java | 8 +- core/src/main/java/fj/P5.java | 10 +- core/src/main/java/fj/P6.java | 12 +- core/src/main/java/fj/P7.java | 14 +- core/src/main/java/fj/P8.java | 16 +- core/src/main/java/fj/TryCatch0.java | 2 +- core/src/main/java/fj/control/Trampoline.java | 9 +- .../main/java/fj/control/parallel/Actor.java | 3 +- .../java/fj/control/parallel/ParModule.java | 2 +- .../java/fj/control/parallel/Promise.java | 5 +- .../java/fj/control/parallel/Strategy.java | 27 +- core/src/main/java/fj/data/$.java | 2 +- core/src/main/java/fj/data/IOFunctions.java | 2 +- core/src/main/java/fj/data/IterableW.java | 3 +- core/src/main/java/fj/data/Iteratee.java | 5 +- core/src/main/java/fj/data/Stream.java | 11 +- core/src/main/java/fj/data/Tree.java | 9 +- core/src/main/java/fj/data/Zipper.java | 3 +- core/src/main/java/fj/data/vector/V3.java | 5 +- core/src/main/java/fj/data/vector/V4.java | 5 +- core/src/main/java/fj/data/vector/V5.java | 5 +- core/src/main/java/fj/data/vector/V6.java | 5 +- core/src/main/java/fj/data/vector/V7.java | 5 +- core/src/main/java/fj/data/vector/V8.java | 5 +- core/src/main/java/fj/test/Property.java | 5 +- core/src/test/java/fj/MemoisationTest.java | 4 +- .../main/java/fj/demo/concurrent/Fibs.java | 3 +- java8/src/main/java/fj/data/Java8.java | 4 +- .../scala/fj/FunctionalJavaJUnitTest.java | 2 +- .../fj/control/parallel/CheckStrategy.scala | 8 +- 38 files changed, 537 insertions(+), 369 deletions(-) delete mode 100644 core/src/main/java/fj/P1Functions.java diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 0df08d99..9ab88e9f 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -188,7 +188,7 @@ public B _1() { static public F, P1> mapP1(final F f) { return new F, P1>() { public P1 f(final P1 p) { - return P1Functions.map(p, f); + return p.map(f); } }; } diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 74a7de79..d5e80951 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -282,7 +282,7 @@ public static Hash> treeHash(final Hash ha) { * @return A hash instance for a product-1. */ public static Hash> p1Hash(final Hash ha) { - return ha.comap(P1Functions.__1()); + return ha.comap(P1.__1()); } /** diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index ed234ff9..8ecccfd0 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -577,7 +577,7 @@ public Ordering f(final Unit u1, final Unit u2) { * @return An order instance for a product-1. */ public static Ord> p1Ord(final Ord oa) { - return oa.comap(P1Functions.__1()); + return oa.comap(P1.__1()); } diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index e20bb45e..9347c060 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -1,5 +1,7 @@ package fj; +import static fj.Unit.unit; + /** * Functions across products. * @@ -672,4 +674,190 @@ public H _8() { } }; } + + public static P1 lazy(F f) { + return new P1() { + @Override + public A _1() { + return f.f(unit()); + } + }; + } + + public static P2 lazy(F fa, F fb) { + return new P2() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + }; + } + + public static P3 lazy(F fa, F fb, F fc) { + return new P3() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + @Override + public C _3() { + return fc.f(unit()); + } + }; + } + + + public static P4 lazy(F fa, F fb, F fc, F fd) { + return new P4() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + @Override + public C _3() { + return fc.f(unit()); + } + @Override + public D _4() { + return fd.f(unit()); + } + }; + } + + public static P5 lazy(F fa, F fb, F fc, F fd, F fe) { + return new P5() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + @Override + public C _3() { + return fc.f(unit()); + } + @Override + public D _4() { + return fd.f(unit()); + } + @Override + public E _5() { + return fe.f(unit()); + } + }; + } + + public static P6 lazy(F fa, F fb, F fc, F fd, F fe, F ff) { + return new P6() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + @Override + public C _3() { + return fc.f(unit()); + } + @Override + public D _4() { + return fd.f(unit()); + } + @Override + public E _5() { + return fe.f(unit()); + } + @Override + public F$ _6() { + return ff.f(unit()); + } + }; + } + + public static P7 lazy(F fa, F fb, F fc, F fd, F fe, F ff, F fg) { + return new P7() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + @Override + public C _3() { + return fc.f(unit()); + } + @Override + public D _4() { + return fd.f(unit()); + } + @Override + public E _5() { + return fe.f(unit()); + } + @Override + public F$ _6() { + return ff.f(unit()); + } + @Override + public G _7() { + return fg.f(unit()); + } + }; + } + + public static P8 lazy(F fa, F fb, F fc, F fd, F fe, F ff, F fg, F fh) { + return new P8() { + @Override + public A _1() { + return fa.f(unit()); + } + @Override + public B _2() { + return fb.f(unit()); + } + @Override + public C _3() { + return fc.f(unit()); + } + @Override + public D _4() { + return fd.f(unit()); + } + @Override + public E _5() { + return fe.f(unit()); + } + @Override + public F$ _6() { + return ff.f(unit()); + } + @Override + public G _7() { + return fg.f(unit()); + } + @Override + public H _8() { + return fh.f(unit()); + } + }; + } + } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 7f54f334..4f26efec 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -1,17 +1,256 @@ package fj; +import java.lang.ref.SoftReference; -/** - * A product-1. Also, the identity monad. - * - * @version %build.number% - */ -public interface P1 { - /** - * Access the first element of the product. - * - * @return The first element of the product. - */ - public abstract A _1(); +import fj.data.Array; +import fj.data.List; +import fj.data.Stream; +import fj.data.Validation; +public abstract class P1 { + + /** + * Access the first element of the product. + * + * @return The first element of the product. + */ + public abstract A _1(); + + /** + * Returns a function that returns the first element of a product. + * + * @return A function that returns the first element of a product. + */ + public static F, A> __1() { + return new F, A>() { + public A f(final P1 p) { + return p._1(); + } + }; + } + + /** + * Promote any function to a transformation between P1s. + * + * @param f A function to promote to a transformation between P1s. + * @return A function promoted to operate on P1s. + */ + public static F, P1> fmap(final F f) { + return new F, P1>() { + public P1 f(final P1 a) { + return a.map(f); + } + }; + } + + /** + * Binds the given function to the value in a product-1 with a final join. + * + * @param f A function to apply to the value in a product-1. + * @return The result of applying the given function to the value of given product-1. + */ + public P1 bind(final F> f) { + P1 self = this; + return new P1() { + public B _1() { + return f.f(self._1())._1(); + } + }; + } + + /** + * Promotes the given function so that it returns its value in a P1. + * + * @param f A function to have its result wrapped in a P1. + * @return A function whose result is wrapped in a P1. + */ + public static F> curry(final F f) { + return new F>() { + public P1 f(final A a) { + return new P1() { + public B _1() { + return f.f(a); + } + }; + } + }; + } + + /** + * Performs function application within a P1 (applicative functor pattern). + * + * @param cf The P1 function to apply. + * @return A new P1 after applying the given P1 function to the first argument. + */ + public P1 apply(final P1> cf) { + P1 self = this; + return cf.bind(new F, P1>() { + public P1 f(final F f) { + return fmap(f).f(self); + } + }); + } + + /** + * Binds the given function to the values in the given P1s with a final join. + * + * @param cb A given P1 to bind the given function with. + * @param f The function to apply to the values in the given P1s. + * @return A new P1 after performing the map, then final join. + */ + public P1 bind(final P1 cb, final F> f) { + return cb.apply(fmap(f).f(this)); + } + + /** + * Joins a P1 of a P1 with a bind operation. + * + * @param a The P1 of a P1 to join. + * @return A new P1 that is the join of the given P1. + */ + public static P1 join(final P1> a) { + return a.bind(Function.>identity()); + } + + /** + * Promotes a function of arity-2 to a function on P1s. + * + * @param f The function to promote. + * @return A function of arity-2 promoted to map over P1s. + */ + public static F, F, P1>> liftM2(final F> f) { + return Function.curry(new F2, P1, P1>() { + public P1 f(final P1 pa, final P1 pb) { + return pa.bind(pb, f); + } + }); + } + + /** + * Turns a List of P1s into a single P1 of a List. + * + * @param as The list of P1s to transform. + * @return A single P1 for the given List. + */ + public static P1> sequence(final List> as) { + return as.foldRight(liftM2(List.cons()), P.p(List.nil())); + } + + /** + * A first-class version of the sequence method for lists of P1s. + * + * @return A function from a List of P1s to a single P1 of a List. + */ + public static F>, P1>> sequenceList() { + return new F>, P1>>() { + public P1> f(final List> as) { + return sequence(as); + } + }; + } + + /** + * Turns a stream of P1s into a single P1 of a stream. + * + * @param as The stream of P1s to transform. + * @return A single P1 for the given stream. + */ + public static P1> sequence(final Stream> as) { + return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); + } + + /** + * Turns an array of P1s into a single P1 of an array. + * + * @param as The array of P1s to transform. + * @return A single P1 for the given array. + */ + public static P1> sequence(final Array> as) { + return new P1>() { + public Array _1() { + return as.map(P1.__1()); + } + }; + } + + /** + * Map the element of the product. + * + * @param f The function to map with. + * @return A product with the given function applied. + */ + public P1 map(final F f) { + final P1 self = this; + return new P1() { + public X _1() { + return f.f(self._1()); + } + }; + } + + /** + * Provides a memoising P1 that remembers its value. + * + * @return A P1 that calls this P1 once and remembers the value for subsequent calls. + */ + public P1 memo() { + final P1 self = this; + return new P1() { + private final Object latch = new Object(); + @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) + private volatile SoftReference v; + + public A _1() { + A a = v != null ? v.get() : null; + if (a == null) + synchronized (latch) { + if (v == null || v.get() == null) + a = self._1(); + v = new SoftReference(a); + } + return a; + } + }; + } + + static P1 memo(F f) { + return P.lazy(f).memo(); + } + + /** + * Returns a constant function that always uses this value. + * + * @return A constant function that always uses this value. + */ + public F constant() { + + return new F() { + public A f(final B b) { + return P1.this._1(); + } + }; + } + + /** + * Promotes the TryCatch0 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch0 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public P1> toP1(final TryCatch0 t) { + return new P1>() { + @Override + public Validation _1() { + try { + return Validation.success(t.f()); + } catch (Exception e) { + return Validation.fail((E) e); + } + } + }; + } + + public String toString() { + return Show.p1Show(Show.anyShow()).showS(this); + } } diff --git a/core/src/main/java/fj/P1Functions.java b/core/src/main/java/fj/P1Functions.java deleted file mode 100644 index 9b2c420d..00000000 --- a/core/src/main/java/fj/P1Functions.java +++ /dev/null @@ -1,240 +0,0 @@ -package fj; - -import java.lang.ref.SoftReference; - -import fj.data.Array; -import fj.data.List; -import fj.data.Stream; -import fj.data.Validation; - -public final class P1Functions { - - /** - * Returns a function that returns the first element of a product. - * - * @return A function that returns the first element of a product. - */ - public static F, A> __1() { - return new F, A>() { - public A f(final P1 p) { - return p._1(); - } - }; - } - - /** - * Promote any function to a transformation between P1s. - * - * @param f A function to promote to a transformation between P1s. - * @return A function promoted to operate on P1s. - */ - public static F, P1> fmap(final F f) { - return new F, P1>() { - public P1 f(final P1 a) { - return map(a, f); - } - }; - } - - /** - * Binds the given function to the value in a product-1 with a final join. - * - * @param a A value in a product-1 to which to apply a function. - * @param f A function to apply to the value in a product-1. - * @return The result of applying the given function to the value of given product-1. - */ - public static P1 bind(final P1 a, final F> f) { - return new P1() { - public B _1() { - return f.f(a._1())._1(); - } - }; - } - - /** - * Promotes the given function so that it returns its value in a P1. - * - * @param f A function to have its result wrapped in a P1. - * @return A function whose result is wrapped in a P1. - */ - public static F> curry(final F f) { - return new F>() { - public P1 f(final A a) { - return new P1() { - public B _1() { - return f.f(a); - } - }; - } - }; - } - - /** - * Performs function application within a P1 (applicative functor pattern). - * - * @param ca The P1 to which to apply a function. - * @param cf The P1 function to apply. - * @return A new P1 after applying the given P1 function to the first argument. - */ - public static P1 apply(final P1 ca, final P1> cf) { - return bind(cf, new F, P1>() { - public P1 f(final F f) { - return fmap(f).f(ca); - } - }); - } - - /** - * Binds the given function to the values in the given P1s with a final join. - * - * @param ca A given P1 to bind the given function with. - * @param cb A given P1 to bind the given function with. - * @param f The function to apply to the values in the given P1s. - * @return A new P1 after performing the map, then final join. - */ - public static P1 bind(final P1 ca, final P1 cb, final F> f) { - return apply(cb, fmap(f).f(ca)); - } - - /** - * Joins a P1 of a P1 with a bind operation. - * - * @param a The P1 of a P1 to join. - * @return A new P1 that is the join of the given P1. - */ - public static P1 join(final P1> a) { - return bind(a, Function.>identity()); - } - - /** - * Promotes a function of arity-2 to a function on P1s. - * - * @param f The function to promote. - * @return A function of arity-2 promoted to map over P1s. - */ - public static F, F, P1>> liftM2(final F> f) { - return Function.curry(new F2, P1, P1>() { - public P1 f(final P1 pa, final P1 pb) { - return bind(pa, pb, f); - } - }); - } - - /** - * Turns a List of P1s into a single P1 of a List. - * - * @param as The list of P1s to transform. - * @return A single P1 for the given List. - */ - public static P1> sequence(final List> as) { - return as.foldRight(liftM2(List.cons()), P.p(List.nil())); - } - - /** - * A first-class version of the sequence method for lists of P1s. - * - * @return A function from a List of P1s to a single P1 of a List. - */ - public static F>, P1>> sequenceList() { - return new F>, P1>>() { - public P1> f(final List> as) { - return sequence(as); - } - }; - } - - /** - * Turns a stream of P1s into a single P1 of a stream. - * - * @param as The stream of P1s to transform. - * @return A single P1 for the given stream. - */ - public static P1> sequence(final Stream> as) { - return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); - } - - /** - * Turns an array of P1s into a single P1 of an array. - * - * @param as The array of P1s to transform. - * @return A single P1 for the given array. - */ - public static P1> sequence(final Array> as) { - return new P1>() { - public Array _1() { - return as.map(P1Functions.__1()); - } - }; - } - - /** - * Map the element of the product. - * - * @param f The function to map with. - * @return A product with the given function applied. - */ - public static P1 map(final P1 a, final F f) { - return new P1() { - public X _1() { - return f.f(a._1()); - } - }; - } - - /** - * Provides a memoising P1 that remembers its value. - * - * @return A P1 that calls this P1 once and remembers the value for subsequent calls. - */ - public static P1 memo(final P1 self) { - return new P1() { - private final Object latch = new Object(); - @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) - private volatile SoftReference v; - - public A _1() { - A a = v != null ? v.get() : null; - if (a == null) - synchronized (latch) { - if (v == null || v.get() == null) - a = self._1(); - v = new SoftReference(a); - } - return a; - } - }; - } - - /** - * Returns a constant function that always uses this value. - * - * @return A constant function that always uses this value. - */ - public static F constant(final P1 a) { - return new F() { - public A f(final B b) { - return a._1(); - } - }; - } - - /** - * Promotes the TryCatch0 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch0 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public P1> toP1(final TryCatch0 t) { - return () -> { - try { - return Validation.success(t.f()); - } catch (Exception e) { - return Validation.fail((E) e); - } - }; - } - - static public String toString(P1 p) { - return Show.p1Show(Show.anyShow()).showS(p); - } -} diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 1a43558b..25eeed7d 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -188,8 +188,8 @@ public final P1 _2_() { public final P2 memo() { P2 self = this; return new P2() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 965f40d4..06babb9c 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -128,9 +128,9 @@ public final P1 _3_() { public final P3 memo() { P3 self = this; return new P3() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); - private final P1 c = P1Functions.memo(() -> self._3()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); + private final P1 c = P1.memo(u -> self._3()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 4b8c6de8..5cfac53e 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -182,10 +182,10 @@ public final P1 _4_() { public final P4 memo() { P4 self = this; return new P4() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); - private final P1 c = P1Functions.memo(() -> self._3()); - private final P1 d = P1Functions.memo(() -> self._4()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); + private final P1 c = P1.memo(u -> self._3()); + private final P1 d = P1.memo(u -> self._4()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 606578f3..ed300f41 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -244,11 +244,11 @@ public final P1 _5_() { public final P5 memo() { P5 self = this; return new P5() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); - private final P1 c = P1Functions.memo(() -> self._3()); - private final P1 d = P1Functions.memo(() -> self._4()); - private final P1 e = P1Functions.memo(() -> self._5()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); + private final P1 c = P1.memo(u -> self._3()); + private final P1 d = P1.memo(u -> self._4()); + private final P1 e = P1.memo(u -> self._5()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 8fabd78b..772003c7 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -315,12 +315,12 @@ public final P1 _6_() { public final P6 memo() { P6 self = this; return new P6() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); - private final P1 c = P1Functions.memo(() -> self._3()); - private final P1 d = P1Functions.memo(() -> self._4()); - private final P1 e = P1Functions.memo(() -> self._5()); - private final P1 f = P1Functions.memo(() -> self._6()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); + private final P1 c = P1.memo(u -> self._3()); + private final P1 d = P1.memo(u -> self._4()); + private final P1 e = P1.memo(u -> self._5()); + private final P1 f = P1.memo(u -> self._6()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index d3c39d57..7fa413e4 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -393,13 +393,13 @@ public final P1 _7_() { public final P7 memo() { P7 self = this; return new P7() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); - private final P1 c = P1Functions.memo(() -> self._3()); - private final P1 d = P1Functions.memo(() -> self._4()); - private final P1 e = P1Functions.memo(() -> self._5()); - private final P1 f = P1Functions.memo(() -> self._6()); - private final P1 g = P1Functions.memo(() -> self._7()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); + private final P1 c = P1.memo(u -> self._3()); + private final P1 d = P1.memo(u -> self._4()); + private final P1 e = P1.memo(u -> self._5()); + private final P1 f = P1.memo(u -> self._6()); + private final P1 g = P1.memo(u -> self._7()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index fa622e4e..9e471c7f 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -480,14 +480,14 @@ public final P1 _8_() { public final P8 memo() { P8 self = this; return new P8() { - private final P1 a = P1Functions.memo(() -> self._1()); - private final P1 b = P1Functions.memo(() -> self._2()); - private final P1 c = P1Functions.memo(() -> self._3()); - private final P1 d = P1Functions.memo(() -> self._4()); - private final P1 e = P1Functions.memo(() -> self._5()); - private final P1 f = P1Functions.memo(() -> self._6()); - private final P1 g = P1Functions.memo(() -> self._7()); - private final P1 h = P1Functions.memo(() -> self._8()); + private final P1 a = P1.memo(u -> self._1()); + private final P1 b = P1.memo(u -> self._2()); + private final P1 c = P1.memo(u -> self._3()); + private final P1 d = P1.memo(u -> self._4()); + private final P1 e = P1.memo(u -> self._5()); + private final P1 f = P1.memo(u -> self._6()); + private final P1 g = P1.memo(u -> self._7()); + private final P1 h = P1.memo(u -> self._8()); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/TryCatch0.java b/core/src/main/java/fj/TryCatch0.java index cdaf8b5d..7a39e7f8 100644 --- a/core/src/main/java/fj/TryCatch0.java +++ b/core/src/main/java/fj/TryCatch0.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to a P1. * - * @see P1Functions#toP1 + * @see P1#toP1 * @version %build.number% */ diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 47a35b1a..70f29f9b 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -5,7 +5,6 @@ import fj.F1Functions; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.data.Either; import fj.F2Functions; import static fj.Function.curry; @@ -67,7 +66,7 @@ public Trampoline _1() { public Either>, A> resume() { return left(sub.resume().either(new F>, P1>>() { public P1> f(final P1> p) { - return P1Functions.map(p, new F, Trampoline>() { + return p.map(new F, Trampoline>() { public Trampoline f(final Trampoline ot) { return ot.fold(new F, Trampoline>() { public Trampoline f(final Normal o) { @@ -338,7 +337,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(P1Functions.bind(x, y, F2Functions.curry(new F2, Trampoline, Trampoline>() { + return suspend(x.bind(y, F2Functions.curry(new F2, Trampoline, Trampoline>() { public Trampoline f(final Trampoline ta, final Trampoline tb) { return suspend(new P1>() { public Trampoline _1() { @@ -349,7 +348,7 @@ public Trampoline _1() { }))); } for (final B y : eb.right()) { - return suspend(P1Functions.map(x, new F, Trampoline>() { + return suspend(x.map(new F, Trampoline>() { public Trampoline f(final Trampoline ta) { return ta.map(F2Functions.f(F2Functions.flip(f), y)); } @@ -365,7 +364,7 @@ public Trampoline _1() { }); } for (final P1> y : eb.left()) { - return suspend(P1Functions.map(y, liftM2(F2Functions.curry(f)).f(pure(x)))); + return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); } } throw Bottom.error("Match error: Trampoline is neither done nor suspended."); diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 76ba6657..5cf7f47f 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -5,7 +5,6 @@ import fj.Effect; import fj.F; -import fj.P1Functions; import fj.Unit; import fj.P1; @@ -94,7 +93,7 @@ public P1 f(final A a) { * @return A new actor that uses the given parallelization strategy and has the given side-effect. */ public static Actor actor(final Strategy s, final Effect e) { - return new Actor(s, P1Functions.curry(e.e())); + return new Actor(s, P1.curry(e.e())); } /** diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 4e984af5..4bc6580e 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -260,7 +260,7 @@ public Promise> f(final F> f, final Stream stream) { * @return A promised product of the result of mapping the given function over the given product. */ public Promise> mapM(final P1 a, final F> f) { - return sequence(P1Functions.map(a, f)); + return sequence(a.map(f)); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 522bf8a3..ce78d6b9 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -5,7 +5,6 @@ import fj.F2; import fj.P; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.Unit; import static fj.P.p; @@ -124,7 +123,7 @@ public Callable _1() { public static F> promise(final Strategy s, final F f) { return new F>() { public Promise f(final A a) { - return promise(s, P1Functions.curry(f).f(a)); + return promise(s, P1.curry(f).f(a)); } }; } @@ -335,7 +334,7 @@ public static F, Promise> foldRight(final Strategy s, fi return new F, Promise>() { public Promise f(final List as) { return as.isEmpty() ? promise(s, p(b)) : liftM2(f).f(promise(s, P.p(as.head()))).f( - join(s, P1Functions.curry(this).f(as.tail()))); + join(s, P1.curry(this).f(as.tail()))); } }; } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index af850908..09680186 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -6,11 +6,8 @@ import fj.Function; import fj.P; import fj.P1; -import fj.P1Functions; import static fj.Function.compose; import static fj.Function.curry; -import static fj.P1Functions.fmap; -import static fj.P1Functions.sequence; import fj.data.Java; import fj.data.List; import fj.data.Array; @@ -74,7 +71,7 @@ public P1 par(final P1 a) { * @return A function that executes concurrently when called, yielding a Future value. */ public F> concurry(final F f) { - return compose(f(), P1Functions.curry(f)); + return compose(f(), P1.curry(f)); } /** @@ -108,7 +105,7 @@ public static List> mergeAll(final List> xs) { * @return A list of the values of the product-1s in the argument. */ public P1> parList(final List> ps) { - return sequence(ps.map(f())); + return P1.sequence(ps.map(f())); } /** @@ -119,7 +116,7 @@ public P1> parList(final List> ps) { * @return A product-1 that returns the list with all of its elements transformed by the given function. */ public P1> parMap(final F f, final List bs) { - return sequence(bs.map(concurry(f))); + return P1.sequence(bs.map(concurry(f))); } /** @@ -130,7 +127,7 @@ public P1> parMap(final F f, final List bs) { * @return A product-1 that returns the array with all of its elements transformed by the given function. */ public P1> parMap(final F f, final Array bs) { - return sequence(bs.map(concurry(f))); + return P1.sequence(bs.map(concurry(f))); } /** @@ -143,7 +140,7 @@ public P1> parMap(final F f, final Array bs) { * @return A list with all of its elements transformed by the given function. */ public List parMap1(final F f, final List bs) { - return compose(P1Functions.>__1(), parMapList(f)).f(bs); + return compose(P1.>__1(), parMapList(f)).f(bs); } /** @@ -156,7 +153,7 @@ public List parMap1(final F f, final List bs) { * @return An array with all of its elements transformed by the given function. */ public Array parMap1(final F f, final Array bs) { - return compose(P1Functions.>__1(), parMapArray(f)).f(bs); + return compose(P1.>__1(), parMapArray(f)).f(bs); } /** @@ -258,7 +255,7 @@ public Array f(final Array bs) { public static P1> parFlatMap(final Strategy> s, final F> f, final List as) { - return fmap(List.join()).f(s.parMap(f, as)); + return P1.fmap(List.join()).f(s.parMap(f, as)); } /** @@ -272,7 +269,7 @@ public static P1> parFlatMap(final Strategy> s, public static P1> parFlatMap(final Strategy> s, final F> f, final Array as) { - return fmap(Array.join()).f(s.parMap(f, as)); + return P1.fmap(Array.join()).f(s.parMap(f, as)); } /** @@ -287,7 +284,7 @@ public static P1> parFlatMap(final Strategy> s, public static P1> parListChunk(final Strategy> s, final int chunkLength, final List> as) { - return fmap(List.join()).f(s.parList(as.partition(chunkLength).map(P1Functions.sequenceList()))); + return P1.fmap(List.join()).f(s.parList(as.partition(chunkLength).map(P1.sequenceList()))); } /** @@ -303,7 +300,7 @@ public static P1> parListChunk(final Strategy> s, * @return The list of the results of calling the given function on corresponding elements of the given lists. */ public P1> parZipWith(final F2 f, final List bs, final List cs) { - return sequence(bs.zipWith(cs, concurry(f))); + return P1.sequence(bs.zipWith(cs, concurry(f))); } /** @@ -319,7 +316,7 @@ public P1> parZipWith(final F2 f, final List bs, fina * @return The array of the results of calling the given function on corresponding elements of the given arrays. */ public P1> parZipWith(final F2 f, final Array bs, final Array cs) { - return sequence(bs.zipWith(cs, concurry(f))); + return P1.sequence(bs.zipWith(cs, concurry(f))); } /** @@ -547,7 +544,7 @@ public A _1() { public static Strategy> callableStrategy(final Strategy> s) { return s.comap(new F>, P1>>() { public P1> f(final P1> a) { - return P1Functions.curry(Callables.normalise()).f(a._1()); + return P1.curry(Callables.normalise()).f(a._1()); } }); } diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index abdcb507..9418afd0 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -7,7 +7,7 @@ * is the identity morphism from B to B. */ @SuppressWarnings({"UnusedDeclaration"}) -public final class $ implements P1 { +public final class $ extends P1 { private final B b; diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 86aac967..1fc32fc0 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -328,7 +328,7 @@ public static IO join(IO> io1) { } public static SafeIO toSafeIO(IO io) { - return () -> P1Functions.toP1(() -> io.run())._1(); + return () -> P1.toP1(() -> io.run())._1(); } public static IO append(final IO io1, final IO io2) { diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index f12f1a58..5a3aa66e 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -7,7 +7,6 @@ import fj.F2; import fj.F3; import fj.P1; -import fj.P1Functions; import fj.P2; import static fj.Function.curry; import static fj.Function.identity; @@ -156,7 +155,7 @@ public static > IterableW> sequence(final final Stream ts = iterableStream(as); return ts.isEmpty() ? iterable(wrap(Option.none())) : wrap(ts.head()).bind(new F>>() { public Iterable> f(final A a) { - return sequence(P1Functions.map(ts.tail(), IterableW.>wrap())._1()) + return sequence(ts.tail().map(IterableW.>wrap())._1()) .bind(new F, Iterable>>() { public Iterable> f(final IterableW as) { return iterable(wrap(Stream.cons(a, new P1>() { diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index affcfbed..7d3cc503 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -5,7 +5,6 @@ import fj.Function; import fj.P; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.Unit; @@ -162,7 +161,7 @@ public IterV _1() { new P1>>() { @Override public F> _1() { - return P1Functions.constant(P.p(cont(step.f(acc + 1)))); + return P.p(cont(step.f(acc + 1))).constant(); } }; final P1> eof = @@ -200,7 +199,7 @@ public IterV _1() { new P1>>() { @Override public F> _1() { - return P1Functions.constant(P.p(IterV.drop(n - 1))); + return P.p(IterV.drop(n - 1)).constant(); } }; final P1> eof = diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index c11bc5f9..c903c514 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -10,7 +10,6 @@ import fj.Ord; import fj.P; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.Unit; import fj.control.parallel.Promise; @@ -136,7 +135,7 @@ public final B foldRight(final F2, B> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight1(final F> f, final B b) { - return foldRight(compose(Function., B, B>andThen().f(P1Functions.__1()), f), b); + return foldRight(compose(Function., B, B>andThen().f(P1.__1()), f), b); } /** @@ -655,8 +654,8 @@ private Promise> qs(final Ord o, final Strategy s) { final F id = identity(); final A x = head(); final P1> xs = tail(); - final Promise> left = Promise.join(s, P1Functions.map(xs, flt(o, s, x, id))); - final Promise> right = P1Functions.map(xs, flt(o, s, x, not))._1(); + final Promise> left = Promise.join(s, xs.map(flt(o, s, x, id))); + final Promise> right = xs.map(flt(o, s, x, not))._1(); final Monoid> m = Monoid.streamMonoid(); return right.fmap(m.sum(single(x))).apply(left.fmap(m.sum())); } @@ -1170,7 +1169,7 @@ else if (p.f(head())) { }; return new P2, Stream>() { @Override public Stream _1() { - return cons(head(), P1Functions.map(yszs, P2., Stream>__1())); + return cons(head(), yszs.map(P2., Stream>__1())); } @Override public Stream _2() { @@ -1499,7 +1498,7 @@ private static final class Cons extends Stream { Cons(final A head, final P1> tail) { this.head = head; - this.tail = P1Functions.memo(tail); + this.tail = tail.memo(); } public A head() { diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 28bd3012..8c3cd8b1 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -5,7 +5,6 @@ import fj.F2Functions; import fj.P; import fj.P1; -import fj.P1Functions; import fj.P2; import static fj.Function.*; import static fj.data.Stream.*; @@ -146,7 +145,7 @@ public P1>> f(final Tree a) { public Stream flatten() { final F2, P1>, Stream> squish = new F2, P1>, Stream>() { public Stream f(final Tree t, final P1> xs) { - return cons(t.root(), P1Functions.map(t.subForest(), Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); + return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); } }; return squish.f(this, P.p(Stream.nil())); @@ -175,7 +174,7 @@ public Stream f(final Tree t) { */ public Stream> levels() { final F>, Stream>> flatSubForests = - Stream., Tree>bind_().f(compose(P1Functions.>>__1(), Tree.subForest_())); + Stream., Tree>bind_().f(compose(P1.>>__1(), Tree.subForest_())); final F>, Stream> roots = Stream., A>map_().f(Tree.root_()); return iterateWhile(flatSubForests, Stream.>isNotEmpty_(), single(this)).map(roots); } @@ -187,7 +186,7 @@ public Stream> levels() { * @return The new Tree after the function has been applied to each element in this Tree. */ public Tree fmap(final F f) { - return node(f.f(root()), P1Functions.map(subForest(), Stream., Tree>map_().f(Tree.fmap_().f(f)))); + return node(f.f(root()), subForest().map(Stream., Tree>map_().f(Tree.fmap_().f(f)))); } /** @@ -252,7 +251,7 @@ public static F> unfoldTree(final F>>> f return new F>() { public Tree f(final B b) { final P2>> p = f.f(b); - return node(p._1(), P1Functions.map(p._2(), Stream.>map_().f(unfoldTree(f)))); + return node(p._1(), p._2().map(Stream.>map_().f(unfoldTree(f)))); } }; } diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index 293d94f4..c94a8129 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -9,7 +9,6 @@ import fj.Ord; import fj.P; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P3; import fj.Show; @@ -158,7 +157,7 @@ public Zipper map(final F f) { public B foldRight(final F> f, final B z) { return left.foldLeft(flip(f), right.cons(focus).foldRight(compose( - Function., B, B>andThen().f(P1Functions.__1()), f), z)); + Function., B, B>andThen().f(P1.__1()), f), z)); } /** diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index b7d7a962..5d7dcfed 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -3,7 +3,6 @@ import fj.F; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P3; import static fj.Function.curry; @@ -144,7 +143,7 @@ public Array toArray() { * @return A new vector after zipping the given vector of functions over this vector. */ public V3 apply(final V3> vf) { - return new V3(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); + return new V3(head.apply(vf.head()), tail.apply(vf.tail())); } /** @@ -219,7 +218,7 @@ public Stream _1() { * @return A new vector after the given function has been applied to each element. */ public V3 map(final F f) { - return new V3(P1Functions.map(head(), f), tail().map(f)); + return new V3(head().map(f), tail().map(f)); } /** diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index d139fd9f..960c52e9 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -3,7 +3,6 @@ import fj.F; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P3; import fj.P4; @@ -192,7 +191,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V4 map(final F f) { - return new V4(P1Functions.map(head, f), tail.map(f)); + return new V4(head.map(f), tail.map(f)); } /** @@ -202,7 +201,7 @@ public V4 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V4 apply(final V4> vf) { - return new V4(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); + return new V4(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 3e6be00d..22564862 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -3,7 +3,6 @@ import fj.F; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P4; import fj.P5; @@ -209,7 +208,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V5 map(final F f) { - return new V5(P1Functions.map(head, f), tail.map(f)); + return new V5(head.map(f), tail.map(f)); } /** @@ -219,7 +218,7 @@ public V5 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V5 apply(final V5> vf) { - return new V5(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); + return new V5(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 66fb8102..031b5761 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -3,7 +3,6 @@ import fj.F; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P5; import fj.P6; @@ -226,7 +225,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V6 map(final F f) { - return new V6(P1Functions.map(head, f), tail.map(f)); + return new V6(head.map(f), tail.map(f)); } /** @@ -236,7 +235,7 @@ public V6 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V6 apply(final V6> vf) { - return new V6(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); + return new V6(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index 552f8ee9..8db9db6d 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -3,7 +3,6 @@ import fj.F; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P6; import fj.P7; @@ -243,7 +242,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V7 map(final F f) { - return new V7(P1Functions.map(head, f), tail.map(f)); + return new V7(head.map(f), tail.map(f)); } /** @@ -253,7 +252,7 @@ public V7 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V7 apply(final V7> vf) { - return new V7(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); + return new V7(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index b5db597e..b29635d0 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -3,7 +3,6 @@ import fj.F; import fj.F2; import fj.P1; -import fj.P1Functions; import fj.P2; import fj.P7; import fj.P8; @@ -260,7 +259,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V8 map(final F f) { - return new V8(P1Functions.map(head, f), tail.map(f)); + return new V8(head.map(f), tail.map(f)); } /** @@ -270,7 +269,7 @@ public V8 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V8 apply(final V8> vf) { - return new V8(P1Functions.apply(head, vf.head()), tail.apply(vf.tail())); + return new V8(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/test/Property.java b/core/src/main/java/fj/test/Property.java index e7fc857a..d914d092 100644 --- a/core/src/main/java/fj/test/Property.java +++ b/core/src/main/java/fj/test/Property.java @@ -13,7 +13,6 @@ import fj.F8; import fj.P; import fj.P1; -import fj.P1Functions; import fj.P2; import static fj.P2.__2; import fj.data.List; @@ -527,7 +526,7 @@ public static Property propertyP(final Arbitrary aa, final Shrink sa, * application of its arguments. */ public static Property property(final Arbitrary aa, final Shrink sa, final F f) { - return propertyP(aa, sa, P1Functions.curry(f)); + return propertyP(aa, sa, P1.curry(f)); } /** @@ -553,7 +552,7 @@ public static Property propertyP(final Arbitrary aa, final F Property property(final Arbitrary aa, final F f) { - return propertyP(aa, P1Functions.curry(f)); + return propertyP(aa, P1.curry(f)); } diff --git a/core/src/test/java/fj/MemoisationTest.java b/core/src/test/java/fj/MemoisationTest.java index 967ef5c3..b3c2853b 100644 --- a/core/src/test/java/fj/MemoisationTest.java +++ b/core/src/test/java/fj/MemoisationTest.java @@ -17,7 +17,7 @@ public class MemoisationTest { @Test public void test1() { final Property p = property(arbInteger, a -> { - P1 t = P1Functions.memo(P.p(a)); + P1 t = P.p(a).memo(); return prop(t._1() == t._1()); }); summary.println(p.check()); @@ -48,7 +48,7 @@ static Integer count(int i) { @Test public void testRecomputeP2() { - P2 t = P.lazy(() -> count(1), () -> count(2)).memo(); + P2 t = P.lazy(u -> count(1), u -> count(2)).memo(); System.out.println("tuple: " + t + " 1:" + t._1() + " 2: " + t._2()); assertTrue(t._1() == t._1() && t._2() == t._2()); } diff --git a/demo/src/main/java/fj/demo/concurrent/Fibs.java b/demo/src/main/java/fj/demo/concurrent/Fibs.java index 6bb324ba..018f92a5 100644 --- a/demo/src/main/java/fj/demo/concurrent/Fibs.java +++ b/demo/src/main/java/fj/demo/concurrent/Fibs.java @@ -4,7 +4,6 @@ import fj.Effect; import fj.F; import fj.P; -import fj.P1Functions; import fj.P2; import fj.Unit; import fj.data.List; @@ -51,7 +50,7 @@ public static void main(final String[] args) {return n < CUTOFF ? promise(su, P.p(seqFib(n))) : f(n - 1).bind(f(n - 2), add);}}; System.out.println("Calculating Fibonacci sequence in parallel..."); - join(su, P1Functions.map(spi.parMap(fib, range(0, 46)), Promise.sequence(su))).to(out);} + join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} // The sequential version of the recursive Fibonacci function public static int seqFib(final int n) diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index b66bf157..84a15b28 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -21,7 +21,7 @@ public static P1 Supplier_P1(final Supplier s) { } public static F, P1> Supplier_P1() { - return s -> () -> s.get(); + return s -> P.lazy(u -> s.get()); } public static Supplier P1_Supplier(final P1 p) { @@ -69,7 +69,7 @@ static public Supplier> TryCatch0_Supp } static public F, Supplier>> TryCatch0_Supplier() { - return t -> () -> P1Functions.toP1(t)._1(); + return t -> () -> P1.toP1(t)._1(); } static public Function> TryCatch1_Function(final TryCatch1 t) { diff --git a/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java b/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java index d66b2816..b8b7ebfe 100644 --- a/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java +++ b/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java @@ -17,7 +17,7 @@ public void runScalacheckTests() { // System.out.println("Hello world"); Assert.assertTrue(true); // new Tests$().main(null); - Tests.main(null); +// Tests.main(null); } } diff --git a/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala b/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala index 6a3409f3..3014e2f7 100644 --- a/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala +++ b/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala @@ -24,19 +24,19 @@ object CheckStrategy extends Properties("Strategy") { property("par") = forAll((a: P1[Int], s: Strategy[Int]) => a._1 == s.par(a)._1) property("parMapList") = forAll((a: List[String], s: Strategy[String]) => - listEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1Functions.__1[String], s.concurry[String](rev))))) + listEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1.__1[String], s.concurry[String](rev))))) property("parMapArray") = forAll((a: Array[String], s: Strategy[String]) => - arrayEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1Functions.__1[String], s.concurry[String](rev))))) + arrayEqual(stringEqual).eq(s.parMap(rev, a)._1, a.map(compose(P1.__1[String], s.concurry[String](rev))))) property("parFlatMapList") = forAll((a: List[String], st: Strategy[List[String]]) => { def f = (x: String) => single[String](x) - listEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1Functions.__1[List[String]], st.concurry[String](f)))) + listEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1.__1[List[String]], st.concurry[String](f)))) }) property("parFlatMapArray") = forAll((a: Array[String], st: Strategy[Array[String]]) => { def f = (x: String) => array[String](scala.Array(x): _*) - arrayEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1Functions.__1[Array[String]], st.concurry[String](f)))) + arrayEqual(stringEqual).eq(parFlatMap(st, f, a)._1, a.bind(compose(P1.__1[Array[String]], st.concurry[String](f)))) }) property("xmapID") = forAll((s: Strategy[Int], n: P1[Int]) => From 41145e3210b15345eb24adfe0ea7aeed4974e99a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 14:50:31 +1000 Subject: [PATCH 119/811] #57: Support partial application on one argument functions --- core/src/main/java/fj/F1Functions.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 9ab88e9f..f269337a 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -180,6 +180,16 @@ public B _1() { }; } + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument to return a lazy value. + */ + static public P1 f(final F f, final A a) { + return P.lazy(u -> f.f(a)); + } + /** * Promotes this function to map over a product-1. * From 17979b0048fd57196a2555fd9a9067010d9de283 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 14:52:59 +1000 Subject: [PATCH 120/811] #56 Added scala tests back in after accidental removal --- tests/src/test/scala/fj/FunctionalJavaJUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java b/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java index b8b7ebfe..d66b2816 100644 --- a/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java +++ b/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java @@ -17,7 +17,7 @@ public void runScalacheckTests() { // System.out.println("Hello world"); Assert.assertTrue(true); // new Tests$().main(null); -// Tests.main(null); + Tests.main(null); } } From 71761232585d78a6bff1bf131f851456ab12efdb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 14:58:58 +1000 Subject: [PATCH 121/811] Set Scala source compatibility for IDE' --- tests/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/build.gradle b/tests/build.gradle index d39a3bf6..d9a4e0bd 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -21,3 +21,6 @@ dependencies { testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" testCompile dependencyJunit } + +sourceCompatibility = "1.7" + From 28f22a63ba8b915bda4ee69d2dc4a169a44f9278 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 15:06:24 +1000 Subject: [PATCH 122/811] #58: Added toString to Either using Show --- core/src/main/java/fj/data/Either.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 95c2a4ee..375a796b 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -6,6 +6,7 @@ import static fj.Function.identity; import static fj.P.p; +import fj.Show; import fj.Function; import fj.P1; import fj.Unit; @@ -792,5 +793,10 @@ public List f(final List bs) { } }, List.nil()); } + + public String toString() { + return Show.eitherShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } From 7b6447bb270ae5946d187d619457f67a6003ee0e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 24 Jul 2014 15:27:14 +1000 Subject: [PATCH 123/811] Added overloaded methods to new Try class to instantiate functions from lambdas that throw exceptions --- core/src/main/java/fj/P1.java | 15 +++++------ core/src/main/java/fj/Try.java | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 core/src/main/java/fj/Try.java diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 4f26efec..efa61659 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -238,16 +238,13 @@ public A f(final B b) { * @return A Validation with an Exception on the failure side and its result on the success side. */ static public P1> toP1(final TryCatch0 t) { - return new P1>() { - @Override - public Validation _1() { - try { - return Validation.success(t.f()); - } catch (Exception e) { - return Validation.fail((E) e); - } + return P.lazy(u -> { + try { + return Validation.success(t.f()); + } catch (Exception e) { + return Validation.fail((E) e); } - }; + }); } public String toString() { diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java new file mode 100644 index 00000000..b24e269c --- /dev/null +++ b/core/src/main/java/fj/Try.java @@ -0,0 +1,46 @@ +package fj; + +import fj.data.Validation; + +/** + * Created by mperry on 24/07/2014. + */ +public class Try { + + public static P1> f(TryCatch0 t) { + return P1.toP1(t); + } + + public static F> f(TryCatch1 t) { + return F1Functions.toF1(t); + } + + public static F2> f(TryCatch2 t) { + return F2Functions.toF2(t); + } + + public static F3> f(TryCatch3 t) { + return F3Functions.toF3(t); + } + + public static F4> f(TryCatch4 t) { + return F4Functions.toF4(t); + } + + public static F5> f(TryCatch5 t) { + return F5Functions.toF5(t); + } + + public static F6> f(TryCatch6 t) { + return F6Functions.toF6(t); + } + + public static F7> f(TryCatch7 t) { + return F7Functions.toF7(t); + } + + public static F8> f(TryCatch8 t) { + return F8Functions.toF8(t); + } + +} From 990274899cbbac3bf9482175c079ae11f38f6f3c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 4 Aug 2014 00:31:44 +1000 Subject: [PATCH 124/811] Added monad methods to IO --- core/src/main/java/fj/data/IOFunctions.java | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 1fc32fc0..383674a2 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -313,6 +313,14 @@ public static IO> sequence(List> list) { return list.foldRight(f2, IOFunctions.unit(List.nil())); } + + public static IO> sequence(Stream> stream) { + F2>, IO, IO>> f2 = (ioList, io) -> + IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, P.lazy(u -> xs)))); + return stream.foldLeft(f2, IOFunctions.unit(Stream.nil())); + } + + /** * Map each element of a structure to an action, evaluate these actions from left to right * and collect the results. @@ -374,4 +382,34 @@ public Stream run() throws IOException { } }; } + + public static IO apply(IO io, IO> iof) { + return bind(iof, f -> map(io, a -> f.f(a))); + } + + public static IO liftM2(IO ioa, IO iob, F2 f) { + return bind(ioa, a -> map(iob, b -> f.f(a, b))); + } + + public static IO> replicateM(IO ioa, int n) { + return sequence(List.replicate(n, ioa)); + } + + public static IO>> readerState() { + return () -> State.unit((BufferedReader r) -> P.p(r, Try.f((BufferedReader r2) -> r2.readLine()).f(r))); + } + + public static final BufferedReader stdinBufferedReader = new BufferedReader(new InputStreamReader(System.in)); + + public static IO stdinReadLine() { + return () -> stdinBufferedReader.readLine(); + } + + public static IO stdoutPrintln(final String s) { + return () -> { + System.out.println(s); + return Unit.unit(); + }; + } + } From d8e6b419ba7a079a1b24e6d6d747b01639eceef5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 4 Aug 2014 00:31:59 +1000 Subject: [PATCH 125/811] Document 4.2 changes --- etc/release-notes.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 etc/release-notes.md diff --git a/etc/release-notes.md b/etc/release-notes.md new file mode 100644 index 00000000..ca93449b --- /dev/null +++ b/etc/release-notes.md @@ -0,0 +1,42 @@ + +3.2 + +4.0 + +4.1 + +4.2 + +Enhancements + +* Added Java 8 examples +* Added new website +* Added Option.none_() +* Gradle 2.0 support with wrapper +* Added to Strings: isNullOrEmpty, isNullOrBlank and isNotNullOrBlank +* Added Try with arity 0-8 for lambdas that throw exceptions +* Conversion from Java 8 types to Functional Java types and vice-versa +* Added monadic IO methods +* Support instantiation of IO with lambdas +* Added first class cons_ for List +* Added partial application of first parameter for F 1-8 +* Added SafeIO that encodes IOExceptions into Validations +* Added simple RNG +* Added Reader, Writer and State +* Deprecated $._ +* Added Array.scan family of methods +* Support instantiating P1 values using lambdas to P.lazy +* Added toString for Validation, P arities 1 to 8, Either +* Added vending machine demo +* Added Option.toValidation +* Added map and contramap for F and F2. +* Added partial application for F1. + +Fixes +* Javadoc fixes +* Fixed large inserts into TreeMap +* Fixed Javadoc support for Java 8 +* Fixed null parameter NullPointerException for Show.anyShow +* Fixed exception propagation in test data generators +* Fixed product memoisation for arities 1 to 8 +* Fixed ClassCastException in class Java \ No newline at end of file From f90d4fe7c3022559b8d43f9ebb74b519bf40c408 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 4 Aug 2014 16:56:08 +1000 Subject: [PATCH 126/811] Some examples for writer and state --- core/src/main/java/fj/RNG.java | 6 +- core/src/main/java/fj/SimpleRNG.java | 32 ++++++++-- core/src/main/java/fj/data/Writer.java | 39 +++++------- .../main/java/fj/demo/StateDemo_Greeter.java | 20 ++++++ demo/src/main/java/fj/demo/StateDemo_Rng.java | 61 +++++++++++++++++++ .../fj/demo/StateDemo_VendingMachine.java | 1 + .../main/java/fj/demo/WriterDemo_Halver.java | 30 +++++++++ 7 files changed, 159 insertions(+), 30 deletions(-) create mode 100644 demo/src/main/java/fj/demo/StateDemo_Greeter.java create mode 100644 demo/src/main/java/fj/demo/StateDemo_Rng.java create mode 100644 demo/src/main/java/fj/demo/WriterDemo_Halver.java diff --git a/core/src/main/java/fj/RNG.java b/core/src/main/java/fj/RNG.java index 64399696..67be8257 100644 --- a/core/src/main/java/fj/RNG.java +++ b/core/src/main/java/fj/RNG.java @@ -5,8 +5,12 @@ */ public abstract class RNG { - public abstract P2 nextInt(); + public abstract P2 nextInt(); + public abstract P2 nextLong(); + public P2 range(int low, int high) { + return nextInt().map2(x -> (Math.abs(x) % (high - low + 1)) + low); + } } diff --git a/core/src/main/java/fj/SimpleRNG.java b/core/src/main/java/fj/SimpleRNG.java index e97568d8..b1ac478d 100644 --- a/core/src/main/java/fj/SimpleRNG.java +++ b/core/src/main/java/fj/SimpleRNG.java @@ -2,21 +2,41 @@ /** * Created by MarkPerry on 7/07/2014. + * + * https://en.wikipedia.org/wiki/Linear_congruential_generator */ public class SimpleRNG extends RNG { private Long seed; + public SimpleRNG() { + this(System.currentTimeMillis()); + } + public SimpleRNG(long s) { seed = s; } - public P2 nextInt() { - long newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL; - SimpleRNG nextRng = new SimpleRNG(newSeed); - long n = (Long) (newSeed >>> 16); - Integer i = (int) n; - return P.p(i, nextRng); + public P2 nextInt() { + P2 p = nextLong(); + int i = (int) p._2().longValue(); + return P.p(p._1(), i); } + public P2 nextLong() { + P2 p = nextLong(seed); + return P.p(new SimpleRNG(p._1()), p._2()); + } + + /** + * + * @param seed + * @return Product of Seed and value + */ + static P2 nextLong(long seed) { + long newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL; + long n = (Long) (newSeed >>> 16); + return P.p(newSeed, n); + } + } diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index 4b09735b..3aea8826 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -1,9 +1,6 @@ package fj.data; -import fj.F; -import fj.F2; -import fj.P; -import fj.P2; +import fj.*; /** * Created by MarkPerry on 7/07/2014. @@ -12,16 +9,12 @@ public class Writer { private A val; private W logValue; - private F2 append; + private Monoid monoid; - public static final F LOG_FUNCTION = o -> "Added " + o + " to the log\n"; - public static final F2 STRING_CONCAT = (String a, String b) -> a + b; - public static final String STRING_EMPTY = ""; - - private Writer(A a, W w, F2 f) { + private Writer(A a, W w, Monoid m) { val = a; logValue = w; - append = f; + monoid = m; } public P2 run() { @@ -36,33 +29,33 @@ public W log() { return logValue; } - public static Writer unit(A a, W w, F2 f) { - return new Writer(a, w, f); + public static Writer unit(A a, W w, Monoid m) { + return new Writer(a, w, m); } - public Writer tell(W w) { - return unit(val, append.f(logValue, w), append); + public static Writer unit(A a, Monoid m) { + return new Writer(a, m.zero(), m); + } + + public Writer tell(W w) { + return unit(val, monoid.sum(logValue, w), monoid); } public Writer map(F f) { - return unit(f.f(val), logValue, append); + return unit(f.f(val), logValue, monoid); } public Writer flatMap(F> f) { Writer writer = f.f(val); - return unit(writer.val, writer.append.f(logValue, writer.logValue), writer.append); + return unit(writer.val, writer.monoid.sum(logValue, writer.logValue), writer.monoid); } public static Writer unit(B b) { - return unit(b, STRING_EMPTY, STRING_CONCAT); - } - - public static Writer log(B b) { - return unit(b, LOG_FUNCTION.f(b), STRING_CONCAT); + return unit(b, Monoid.stringMonoid); } public static F> stringLogger() { - return a -> Writer.unit(a, LOG_FUNCTION.f(a), STRING_CONCAT); + return a -> Writer.unit(a, Monoid.stringMonoid); } } diff --git a/demo/src/main/java/fj/demo/StateDemo_Greeter.java b/demo/src/main/java/fj/demo/StateDemo_Greeter.java new file mode 100644 index 00000000..578f414e --- /dev/null +++ b/demo/src/main/java/fj/demo/StateDemo_Greeter.java @@ -0,0 +1,20 @@ +package fj.demo; + +import fj.P; +import fj.data.State; + +/** + * Created by mperry on 4/08/2014. + */ +public class StateDemo_Greeter { + + public static void main(String args[]) { + stateDemo(); + } + + static void stateDemo() { + State st1 = State.init().flatMap(s -> State.unit(s2 -> P.p("Batman", "Hello " + s))); + System.out.println(st1.run("Robin")); + } + +} diff --git a/demo/src/main/java/fj/demo/StateDemo_Rng.java b/demo/src/main/java/fj/demo/StateDemo_Rng.java new file mode 100644 index 00000000..27374f7f --- /dev/null +++ b/demo/src/main/java/fj/demo/StateDemo_Rng.java @@ -0,0 +1,61 @@ +package fj.demo; + +import fj.F; +import fj.P2; +import fj.RNG; +import fj.SimpleRNG; +import fj.data.State; +import fj.data.Stream; + +import static fj.data.Option.some; +import static fj.data.Stream.unfold; + +/** + * Created by mperry on 4/08/2014. + */ +public class StateDemo_Rng { + + static public void main(String args[]) { + listRandoms(); + stateExamples(); + } + + static RNG initRNG() { + return new SimpleRNG(0); + } + + private static void listRandoms() { + RNG rng = initRNG(); + Stream s = unfold(r -> some(num(r).swap()), rng); + System.out.println(s.take(100).toList()); + } + + private static void stateExamples() { + RNG rng = initRNG(); + State s0 = State.unit(r -> num(r)); + + State s1 = nextState().f(s0); + State s2 = nextState().f(s1); + State s3 = nextState().f(s2); + State s4 = nextState().f(s3); + State s5 = nextState().f(s4); + State s6 = nextState().f(s5); + + System.out.println(s0.run(rng)); + System.out.println(s1.run(rng)); + System.out.println(s2.run(rng)); + System.out.println(s3.run(rng)); + System.out.println(s4.run(rng)); + System.out.println(s5.run(rng)); + System.out.println(s6.run(rng)); + } + + static P2 num(RNG r) { + return r.range(1, 5); + } + + static F, State> nextState() { + return s -> s.mapState(p2 -> num(p2._1())); + } + +} diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index c49395ff..0f09318a 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -82,6 +82,7 @@ static State simulate(List list) { static void test() { State s = simulate(List.list(COIN, TURN, TURN, COIN, COIN, TURN)); VendingMachine m = s.eval(new VendingMachine(true, 5, 0)); + System.out.println(s.run(new VendingMachine(true, 5, 0))); VendingMachine oracle = new VendingMachine(true, 3, 2); System.out.printf("m1: %s, oracle: %s, equals: %b", m, oracle, m.equals(oracle)); } diff --git a/demo/src/main/java/fj/demo/WriterDemo_Halver.java b/demo/src/main/java/fj/demo/WriterDemo_Halver.java new file mode 100644 index 00000000..a2a270f6 --- /dev/null +++ b/demo/src/main/java/fj/demo/WriterDemo_Halver.java @@ -0,0 +1,30 @@ +package fj.demo; + +import fj.F; +import fj.P2; +import fj.data.Writer; + +import static fj.F1Functions.map; +import static fj.Monoid.stringMonoid; + +/** + * Created by mperry on 4/08/2014. + */ +public class WriterDemo_Halver { + + public static void main(String args[]) { + testWriter(); + } + + static F> half() { + return x -> Writer.unit(x / 2, stringMonoid).tell("I just2 halved " + x + "!"); + } + + static void testWriter() { + Integer init = 32; + P2 p1 = half().f(init).flatMap(half()).flatMap(half()).run(); + System.out.println(p1); + System.out.println(map(half(), w -> w.flatMap(half()).flatMap(half()).run()).f(init)); + } + +} From 9c12c3def9ba0195c1b655ca5a15769e300af08c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 00:48:01 +1000 Subject: [PATCH 127/811] Added State traverse and sequence. Tested State for RNGs. --- core/src/main/java/fj/RNG.java | 8 ++- core/src/main/java/fj/SimpleRNG.java | 3 +- core/src/main/java/fj/data/State.java | 21 +++++++ core/src/test/java/fj/data/StateDemo_Rng.java | 62 +++++++++++++++++++ demo/src/main/java/fj/demo/StateDemo_Rng.java | 61 ------------------ 5 files changed, 92 insertions(+), 63 deletions(-) create mode 100644 core/src/test/java/fj/data/StateDemo_Rng.java delete mode 100644 demo/src/main/java/fj/demo/StateDemo_Rng.java diff --git a/core/src/main/java/fj/RNG.java b/core/src/main/java/fj/RNG.java index 67be8257..915b7089 100644 --- a/core/src/main/java/fj/RNG.java +++ b/core/src/main/java/fj/RNG.java @@ -10,7 +10,13 @@ public abstract class RNG { public abstract P2 nextLong(); public P2 range(int low, int high) { - return nextInt().map2(x -> (Math.abs(x) % (high - low + 1)) + low); + return nextNatural().map2(x -> (x % (high - low + 1)) + low); } + + public P2 nextNatural() { + return nextInt().map2(x -> x < 0 ? -(x + 1) : x); + } + + } diff --git a/core/src/main/java/fj/SimpleRNG.java b/core/src/main/java/fj/SimpleRNG.java index b1ac478d..92cf31b9 100644 --- a/core/src/main/java/fj/SimpleRNG.java +++ b/core/src/main/java/fj/SimpleRNG.java @@ -23,7 +23,8 @@ public P2 nextInt() { return P.p(p._1(), i); } - public P2 nextLong() { + + public P2 nextLong() { P2 p = nextLong(seed); return P.p(new SimpleRNG(p._1()), p._2()); } diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index fec62b9e..46af5392 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -2,6 +2,8 @@ import fj.*; +import java.util.*; + import static fj.P.p; /** @@ -96,4 +98,23 @@ public static State gets(F f) { return State.init().map(s -> f.f(s)); } + /** + * Evaluate each action in the sequence from left to right, and collect the results. + */ + public static State> sequence(List> list) { + return list.foldLeft((State> acc, State ma) -> + acc.flatMap((List xs) -> ma.map((A x) -> xs.snoc(x)) + ), constant(List.nil())); + } + + /** + * Map each element of a structure to an action, evaluate these actions from left to right + * and collect the results. + */ + public static State> traverse(List list, F> f) { + return list.foldLeft((State> acc, A a) -> + acc.flatMap(bs -> f.f(a).map(b -> bs.snoc(b)) + ), constant(List.nil())); + } + } diff --git a/core/src/test/java/fj/data/StateDemo_Rng.java b/core/src/test/java/fj/data/StateDemo_Rng.java new file mode 100644 index 00000000..bd1bce2b --- /dev/null +++ b/core/src/test/java/fj/data/StateDemo_Rng.java @@ -0,0 +1,62 @@ +package fj.data; + +import fj.*; +import fj.data.State; +import fj.data.Stream; +import org.junit.Assert; +import org.junit.Test; + +import static fj.data.Option.some; +import static fj.data.Stream.unfold; + +/** + * Created by mperry on 4/08/2014. + */ +public class StateDemo_Rng { + + static String expected1 = "<4,4,2,2,2,5,3,3,1,5>"; + static int size = 10; + + static RNG initRNG() { + return new SimpleRNG(1); + } + + @Test + public void testUnfold() { + Stream s = unfold(r -> some(num(r).swap()), initRNG()); + Assert.assertTrue(s.take(size).toList().toString().equals(expected1)); + } + + @Test + public void testTransitions() { + P2>, State> p = List.replicate(size, nextState()).foldLeft( + (P2>, State> p2, F, State> f) -> { + State s = f.f(p2._2()); + return P.p(p2._1().snoc(p2._2()), s); + } + , P.p(List.nil(), defaultState()) + ); + List ints = p._1().map(s -> s.eval(initRNG())); + Assert.assertTrue(ints.toString().equals(expected1)); + } + + + static P2 num(RNG r) { + return r.range(1, 5); + } + + static State defaultState() { + return State.unit(s -> num(s)); + } + + static F, State> nextState() { + return s -> s.mapState(p2 -> num(p2._1())); + } + + @Test + public void testSequence() { + List list = State.sequence(List.replicate(size, defaultState())).eval(initRNG()); + Assert.assertTrue(list.toString().equals(expected1)); + } + +} diff --git a/demo/src/main/java/fj/demo/StateDemo_Rng.java b/demo/src/main/java/fj/demo/StateDemo_Rng.java deleted file mode 100644 index 27374f7f..00000000 --- a/demo/src/main/java/fj/demo/StateDemo_Rng.java +++ /dev/null @@ -1,61 +0,0 @@ -package fj.demo; - -import fj.F; -import fj.P2; -import fj.RNG; -import fj.SimpleRNG; -import fj.data.State; -import fj.data.Stream; - -import static fj.data.Option.some; -import static fj.data.Stream.unfold; - -/** - * Created by mperry on 4/08/2014. - */ -public class StateDemo_Rng { - - static public void main(String args[]) { - listRandoms(); - stateExamples(); - } - - static RNG initRNG() { - return new SimpleRNG(0); - } - - private static void listRandoms() { - RNG rng = initRNG(); - Stream s = unfold(r -> some(num(r).swap()), rng); - System.out.println(s.take(100).toList()); - } - - private static void stateExamples() { - RNG rng = initRNG(); - State s0 = State.unit(r -> num(r)); - - State s1 = nextState().f(s0); - State s2 = nextState().f(s1); - State s3 = nextState().f(s2); - State s4 = nextState().f(s3); - State s5 = nextState().f(s4); - State s6 = nextState().f(s5); - - System.out.println(s0.run(rng)); - System.out.println(s1.run(rng)); - System.out.println(s2.run(rng)); - System.out.println(s3.run(rng)); - System.out.println(s4.run(rng)); - System.out.println(s5.run(rng)); - System.out.println(s6.run(rng)); - } - - static P2 num(RNG r) { - return r.range(1, 5); - } - - static F, State> nextState() { - return s -> s.mapState(p2 -> num(p2._1())); - } - -} From 07d84d251fa4eb585a4236919cc94c2c2d30b9fa Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 01:06:55 +1000 Subject: [PATCH 128/811] Renamed state rng test --- .../test/java/fj/data/{StateDemo_Rng.java => TestRngState.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename core/src/test/java/fj/data/{StateDemo_Rng.java => TestRngState.java} (98%) diff --git a/core/src/test/java/fj/data/StateDemo_Rng.java b/core/src/test/java/fj/data/TestRngState.java similarity index 98% rename from core/src/test/java/fj/data/StateDemo_Rng.java rename to core/src/test/java/fj/data/TestRngState.java index bd1bce2b..cd25d7c8 100644 --- a/core/src/test/java/fj/data/StateDemo_Rng.java +++ b/core/src/test/java/fj/data/TestRngState.java @@ -12,7 +12,7 @@ /** * Created by mperry on 4/08/2014. */ -public class StateDemo_Rng { +public class TestRngState { static String expected1 = "<4,4,2,2,2,5,3,3,1,5>"; static int size = 10; From 53700dc817001f02c62a593208aea648631e6858 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 11:09:43 +1000 Subject: [PATCH 129/811] Test IO traverse --- core/src/test/java/fj/data/TestRngState.java | 47 ++++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/core/src/test/java/fj/data/TestRngState.java b/core/src/test/java/fj/data/TestRngState.java index cd25d7c8..1274fbec 100644 --- a/core/src/test/java/fj/data/TestRngState.java +++ b/core/src/test/java/fj/data/TestRngState.java @@ -1,8 +1,6 @@ package fj.data; import fj.*; -import fj.data.State; -import fj.data.Stream; import org.junit.Assert; import org.junit.Test; @@ -17,13 +15,29 @@ public class TestRngState { static String expected1 = "<4,4,2,2,2,5,3,3,1,5>"; static int size = 10; - static RNG initRNG() { + static RNG defaultRng() { return new SimpleRNG(1); } + static P2 num(RNG r) { + return r.range(1, 5); + } + + static State defaultState() { + return State.unit(s -> num(s)); + } + + static F, State> nextState() { + return s -> s.mapState(p2 -> num(p2._1())); + } + + static P2 num(RNG r, int x) { + return r.range(x, x + 1); + } + @Test public void testUnfold() { - Stream s = unfold(r -> some(num(r).swap()), initRNG()); + Stream s = unfold(r -> some(num(r).swap()), defaultRng()); Assert.assertTrue(s.take(size).toList().toString().equals(expected1)); } @@ -36,27 +50,22 @@ public void testTransitions() { } , P.p(List.nil(), defaultState()) ); - List ints = p._1().map(s -> s.eval(initRNG())); + List ints = p._1().map(s -> s.eval(defaultRng())); Assert.assertTrue(ints.toString().equals(expected1)); } - - static P2 num(RNG r) { - return r.range(1, 5); - } - - static State defaultState() { - return State.unit(s -> num(s)); - } - - static F, State> nextState() { - return s -> s.mapState(p2 -> num(p2._1())); - } - @Test public void testSequence() { - List list = State.sequence(List.replicate(size, defaultState())).eval(initRNG()); + List list = State.sequence(List.replicate(size, defaultState())).eval(defaultRng()); Assert.assertTrue(list.toString().equals(expected1)); } + @Test + public void testTraverse() { + List list = State.traverse(List.range(1, 10), a -> (State.unit((RNG s) -> num(s, a)))).eval(defaultRng()); +// System.out.println(list.toString()); + String expected = "<1,2,3,5,6,7,7,9,10>"; + Assert.assertTrue(list.toString().equals(expected)); + } + } From e128256f6f0c28767b21ca0bbda5683134275ffd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 11:10:06 +1000 Subject: [PATCH 130/811] Added conversion from io to P1 and TryCatch0 --- core/src/main/java/fj/Try.java | 8 ++++++++ core/src/main/java/fj/data/IOFunctions.java | 18 +++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index b24e269c..92c05a8f 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -1,7 +1,11 @@ package fj; +import fj.data.IO; +import fj.data.IOFunctions; import fj.data.Validation; +import java.io.IOException; + /** * Created by mperry on 24/07/2014. */ @@ -43,4 +47,8 @@ public static F4 IO io(TryCatch0 t) { + return IOFunctions.io(t); + } + } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 383674a2..d04e1b3f 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -30,7 +30,23 @@ public class IOFunctions { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - public static final F> closeReader = + public static TryCatch0 toTry(IO io) { + return () -> io.run(); + } + + public static P1> p(IO io) { + return Try.f(toTry(io)); + } + + public static IO io(P1 p) { + return () -> p._1(); + } + + public static IO io(TryCatch0 t) { + return () -> t.f(); + } + + public static final F> closeReader = new F>() { @Override public IO f(final Reader r) { From 0e150d67322df2c7155352727d3676a13114b9b8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 13:15:34 +1000 Subject: [PATCH 131/811] Added release notes for 3.2, 4.0, 4.1 and 4.2 --- etc/release-notes.md | 92 +++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/etc/release-notes.md b/etc/release-notes.md index ca93449b..45eeea21 100644 --- a/etc/release-notes.md +++ b/etc/release-notes.md @@ -1,42 +1,62 @@ -3.2 +Release Notes +============= -4.0 + +4.2 +=== + +* Enhancements + * Added Java 8 examples + * Added new website + * Added Option.none_() + * Gradle 2.0 support with wrapper + * Added to Strings: isNullOrEmpty, isNullOrBlank and isNotNullOrBlank + * Added Try with arity 0-8 for lambdas that throw exceptions + * Conversion from Java 8 types to Functional Java types and vice-versa + * Added monadic IO methods + * Support instantiation of IO with lambdas + * Added first class cons_ for List + * Added partial application of first parameter for F 1-8 + * Added SafeIO that encodes IOExceptions into Validations + * Added simple RNG + * Added Reader, Writer and State + * Deprecated $._ + * Added Array.scan family of methods + * Support instantiating P1 values using lambdas to P.lazy + * Added toString for Validation, P arities 1 to 8, Either + * Added vending machine demo + * Added Option.toValidation + * Added map and contramap for F and F2. + * Added partial application for F1. +* Fixes + * Various Javadoc issues + * Large inserts into TreeMap + * Javadoc support for Java 8 + * Null parameter NullPointerException for Show.anyShow + * Exception propagation in test data generators + * Product memoisation for arities 1 to 8 + * ClassCastException in class fj.data.Java 4.1 +=== -4.2 +* Support Java 7 by removing default methods. Methods on class C with default methods moved to static methods on new class ${C}Functions. + +4.0 +=== + +* Merged changes from 3.2 +* Minimal changes to support Java 8. +* Changed abstract classes to interfaces with default methods (P1, F1 to F8). + +3.2 +=== + +* Added methods to HashMap: toList, toStream, toOption, toArray, map, mapKeys, foreach, convert to/from java.util.Map. +* Convert from java.util.List to List. +* Fixed findChild method in TreeZipper to handle empty stream. +* Fixed stack overflow when sorting and zipping. +* Fixed stack overflow in Stream's bind method. +* Small Javadoc fixes. -Enhancements - -* Added Java 8 examples -* Added new website -* Added Option.none_() -* Gradle 2.0 support with wrapper -* Added to Strings: isNullOrEmpty, isNullOrBlank and isNotNullOrBlank -* Added Try with arity 0-8 for lambdas that throw exceptions -* Conversion from Java 8 types to Functional Java types and vice-versa -* Added monadic IO methods -* Support instantiation of IO with lambdas -* Added first class cons_ for List -* Added partial application of first parameter for F 1-8 -* Added SafeIO that encodes IOExceptions into Validations -* Added simple RNG -* Added Reader, Writer and State -* Deprecated $._ -* Added Array.scan family of methods -* Support instantiating P1 values using lambdas to P.lazy -* Added toString for Validation, P arities 1 to 8, Either -* Added vending machine demo -* Added Option.toValidation -* Added map and contramap for F and F2. -* Added partial application for F1. - -Fixes -* Javadoc fixes -* Fixed large inserts into TreeMap -* Fixed Javadoc support for Java 8 -* Fixed null parameter NullPointerException for Show.anyShow -* Fixed exception propagation in test data generators -* Fixed product memoisation for arities 1 to 8 -* Fixed ClassCastException in class Java \ No newline at end of file From 607cb06d21c4b71d1d7c0a851e8b99f1aebc911f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 14:02:34 +1000 Subject: [PATCH 132/811] Move toward 4.2-beta-1 --- README | 5 +++++ build.gradle | 2 +- etc/release-notes.md | 13 ++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/README b/README index a56eda18..e41ca2ed 100644 --- a/README +++ b/README @@ -19,8 +19,12 @@ Functional Java includes the following features: * Array wrapper (fj.data.Array). * Optional value — type-safe null (fj.data.Option). * Disjoint union data type — compositional exception handling (fj.data.Either). + * Validation, a right biased either for chaining computations over potentially failed operations. + * Reader, Writer and State. * Monoid (fj.Monoid). + * Input/Output monad for abstracting IO. * Functions with arity 1 to 8. + * Functions with arity 0 to 8 that can produce exceptions (fj.TryCatch). * Products of 1 to 8. * Configurable equality and hash-code for HashMap and HashSet. * Natural number data type (fj.data.Natural). @@ -29,3 +33,4 @@ Functional Java includes the following features: * Immutable tree-map using a red/black tree implementation (fj.data.TreeMap). * Zipper implementations for streams and trees. * Automated specification-based testing framework (fj.test). + * Conversion between FunctionalJava and Java 8 function types. diff --git a/build.gradle b/build.gradle index f05c160f..b700e8ab 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ allprojects { ext { isSnapshot = true - fjBaseVersion = "4.2" + fjBaseVersion = "4.2-beta-1" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") diff --git a/etc/release-notes.md b/etc/release-notes.md index 45eeea21..e5e26a9c 100644 --- a/etc/release-notes.md +++ b/etc/release-notes.md @@ -2,9 +2,9 @@ Release Notes ============= - 4.2 === +Release target: Aug 2014 * Enhancements * Added Java 8 examples @@ -40,11 +40,13 @@ Release Notes 4.1 === +Released: 30 May, 2014 * Support Java 7 by removing default methods. Methods on class C with default methods moved to static methods on new class ${C}Functions. 4.0 === +Released: 30 May, 2014 * Merged changes from 3.2 * Minimal changes to support Java 8. @@ -52,6 +54,7 @@ Release Notes 3.2 === +Released: 30 May, 2014 * Added methods to HashMap: toList, toStream, toOption, toArray, map, mapKeys, foreach, convert to/from java.util.Map. * Convert from java.util.List to List. @@ -60,3 +63,11 @@ Release Notes * Fixed stack overflow in Stream's bind method. * Small Javadoc fixes. +3.1 +=== +Released: May 2012 + +3.0 +=== +Released: Jun 2010 + From 3efe5ae50a2dfb76d6a427764b9e81873d5e6714 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 23:34:12 +1000 Subject: [PATCH 133/811] Tweak signing process for release 4.2-beta-1 --- build.gradle | 59 +++---------------------------------------- core/build.gradle | 13 ++++++---- java8/build.gradle | 9 ++++--- lib.gradle | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 63 deletions(-) diff --git a/build.gradle b/build.gradle index b700e8ab..0964ef1b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,6 @@ defaultTasks 'build' -Boolean doSigning() { - signingEnabled.trim() == "true" -} - ext { } @@ -19,13 +15,15 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.2-beta-1" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") fjConsumeVersion = "4.1" + signModule = false + projectTitle = "Functional Java" projectName = "functionaljava" pomProjectName = projectTitle @@ -74,16 +72,10 @@ subprojects { apply from: "$rootDir/lib.gradle" apply plugin: "maven" apply plugin: "java" + apply plugin: "signing" sourceCompatibility = "1.8" - if (doSigning()) { - apply plugin: "signing" - signing { - sign configurations.archives - } - } - task javadocJar(type: Jar, dependsOn: "javadoc") { classifier = 'javadoc' from "build/docs/javadoc" @@ -107,49 +99,6 @@ subprojects { } } - uploadArchives { - enabled = false - repositories { - mavenDeployer { - if (doSigning()) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - } - - repository(url: sonatypeUploadUrl) { - authentication(userName: sonatypeUsername, password: sonatypePassword) - } - pom { - groupId = project.group - project { - name pomProjectName - packaging 'jar' - description projectDescription - url projectUrl - organization { - name pomOrganisation - url projectUrl - } - scm { - url scmUrl - } - licenses { - license { - name "The BSD3 License" - url "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" - distribution 'repo' - } - } - developers { - developer { - email primaryEmail - } - } - } - } - } - } - } - } task wrapper(type: Wrapper) { diff --git a/core/build.gradle b/core/build.gradle index 40a5ce59..ae71be3f 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,20 +1,23 @@ apply plugin: 'retrolambda' -jar { - baseName project.projectName +ext { + signModule = true } +archivesBaseName = project.projectName + dependencies { testCompile dependencyJunit } +performSigning(signingEnabled, signModule) +configureUpload(signingEnabled, signModule) + +uploadArchives.enabled = true retrolambda { jdk System.getenv("JAVA8_HOME") oldJdk System.getenv("JAVA7_HOME") javaVersion JavaVersion.VERSION_1_7 } - -uploadArchives.enabled = true - diff --git a/java8/build.gradle b/java8/build.gradle index 6dc23320..88e9a25f 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -1,13 +1,16 @@ -jar { - baseName "${project.projectName}-${project.name}" -} +archivesBaseName = "${project.projectName}-${project.name}" +ext { + signModule = true +} dependencies { compile project(":core") testCompile dependencyJunit } +performSigning(signingEnabled, signModule) +configureUpload(signingEnabled, signModule) uploadArchives.enabled = true diff --git a/lib.gradle b/lib.gradle index 33dff1cb..12e55bfa 100644 --- a/lib.gradle +++ b/lib.gradle @@ -18,6 +18,68 @@ String findJavaCommand(String command) { findCommand("$jh/bin", command) } +Boolean doSigning(String signingAllowed, Boolean doModule) { + def b = signingAllowed.trim() == "true" && doModule + println("signModule: ${project.name} signingEnabled: $signingAllowed module: $doModule") + b +} + +void performSigning(String signingAllowed, Boolean doModule) { + signing { + required { doSigning(signingEnabled, signModule) } + sign configurations.archives + } +} + +void configureUpload(String signingEnabled, Boolean signModule) { + + uploadArchives { + enabled = false + repositories { + mavenDeployer { + if (doSigning(signingEnabled, signModule)) { + beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + } + + repository(url: sonatypeUploadUrl) { + authentication(userName: sonatypeUsername, password: sonatypePassword) + } + pom { + groupId = project.group + project { + name pomProjectName + packaging 'jar' + description projectDescription + url projectUrl + organization { + name pomOrganisation + url projectUrl + } + scm { + url scmUrl + } + licenses { + license { + name "The BSD3 License" + url "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" + distribution 'repo' + } + } + developers { + developer { + email primaryEmail + } + } + } + } + } + } + } +} + ext { findJavaCommand = this.&findJavaCommand + doSigning = this.&doSigning + performSigning = this.&performSigning + configureUpload = this.&configureUpload } From ac331ec73e8e4dc3400378032c1c63948f829fb1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 7 Aug 2014 23:41:48 +1000 Subject: [PATCH 134/811] Removed println --- lib.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib.gradle b/lib.gradle index 12e55bfa..30d6878e 100644 --- a/lib.gradle +++ b/lib.gradle @@ -20,7 +20,7 @@ String findJavaCommand(String command) { Boolean doSigning(String signingAllowed, Boolean doModule) { def b = signingAllowed.trim() == "true" && doModule - println("signModule: ${project.name} signingEnabled: $signingAllowed module: $doModule") +// println("signModule: ${project.name} signingEnabled: $signingAllowed module: $doModule") b } From 9109cc558f5cafc5c384bc3ed7455fc892fba915 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 8 Aug 2014 00:01:48 +1000 Subject: [PATCH 135/811] Increase version to 4.2-beta-2-SNAPSHOT --- build.gradle | 4 ++-- lib.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 0964ef1b..c71560d2 100644 --- a/build.gradle +++ b/build.gradle @@ -15,8 +15,8 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = false - fjBaseVersion = "4.2-beta-1" + isSnapshot = true + fjBaseVersion = "4.2-beta-2" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") diff --git a/lib.gradle b/lib.gradle index 30d6878e..39ce7a7e 100644 --- a/lib.gradle +++ b/lib.gradle @@ -26,7 +26,7 @@ Boolean doSigning(String signingAllowed, Boolean doModule) { void performSigning(String signingAllowed, Boolean doModule) { signing { - required { doSigning(signingEnabled, signModule) } + required { doSigning(signingAllowed, doModule) } sign configurations.archives } } From 8e16c3678ab2083b1e2648e5b246ede41d5eab04 Mon Sep 17 00:00:00 2001 From: rxxg Date: Fri, 8 Aug 2014 14:48:24 +0200 Subject: [PATCH 136/811] Fix performance issue with Set.member() --- core/src/main/java/fj/data/Set.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 30ea53ef..56a27ba4 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -166,7 +166,7 @@ public static Set empty(final Ord ord) { * @return true if the given element is a member of this set. */ public final boolean member(final A x) { - return !isEmpty() && (ord.isLessThan(x, head()) && l().member(x) || ord.eq(head(), x) || r().member(x)); + return !isEmpty() && (ord.isLessThan(x, head()) ? l().member(x) : ord.eq(head(), x) || r().member(x)); } From e60244511f4bbf383e0878d202bb949de9edcdb1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 14 Aug 2014 06:25:55 +1000 Subject: [PATCH 137/811] Added filter and uncurried foldLeft and foldRight to FingerTree --- .../java/fj/data/fingertrees/FingerTree.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index e915e6f6..8fb2f158 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -1,9 +1,7 @@ package fj.data.fingertrees; -import fj.F; -import fj.P2; +import fj.*; import fj.data.Seq; -import fj.Monoid; /** * Provides 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in @@ -32,6 +30,10 @@ public abstract class FingerTree { */ public abstract B foldRight(final F> f, final B z); + public B foldRight(final F2 f, final B z) { + return foldRight(F2Functions.curry(f), z); + } + /** * Folds the tree to the right with the given function. * @@ -49,6 +51,10 @@ public abstract class FingerTree { */ public abstract B foldLeft(final F> f, final B z); + public B foldLeft(final F2 f, final B z) { + return foldLeft(F2Functions.curry(f), z); + } + /** * Folds the tree to the left with the given function. * @@ -67,6 +73,11 @@ public abstract class FingerTree { */ public abstract FingerTree map(final F f, final Measured m); + public FingerTree filter(final F f) { + FingerTree tree = new Empty(m); + return foldLeft((acc, a) -> f.f(a) ? acc.snoc(a) : acc, tree); + } + /** * Returns the sum of this tree's annotations. * From 5ca4fb63312a583d27ade67c40781b4a1b9f97a4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 14 Aug 2014 06:26:42 +1000 Subject: [PATCH 138/811] Added foldLeft, foldRight and map to Seq --- core/src/main/java/fj/data/Seq.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 98861521..ec48086b 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -1,5 +1,8 @@ package fj.data; +import fj.F; +import fj.F2; +import fj.F2Functions; import fj.Function; import static fj.Bottom.error; import static fj.Monoid.intAdditionMonoid; @@ -106,4 +109,17 @@ public A index(final int i) { throw error("Index " + i + "out of bounds."); return ftree.lookup(Function.identity(), i)._2(); } + + public B foldLeft(final F2 f, final B z) { + return ftree.foldLeft(f, z); + } + + public B foldRight(final F2 f, final B z) { + return ftree.foldRight(f, z); + } + + public Seq map(F f) { + return new Seq(ftree.map(f, Seq.elemMeasured())); + } + } From 72b70fab63047aff79261b1103c5b793c1152b06 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 14 Aug 2014 06:29:34 +1000 Subject: [PATCH 139/811] Added lazy unit to differentiate from unit for lambdas --- core/src/main/java/fj/data/IOFunctions.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index d04e1b3f..7420028d 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -149,10 +149,13 @@ public A run() throws IOException { }; } - public static final IO unit(final P1 p) { + public static final IO lazy(final P1 p) { return () -> p._1(); } + public static final IO lazy(final F f) { + return () -> f.f(Unit.unit()); + } /** * A function that feeds an iteratee with lines read from a {@link BufferedReader}. From 8a166a80c2d08a535c249860b308aea6039dbe18 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 16 Aug 2014 02:28:52 +1000 Subject: [PATCH 140/811] Added CNAME --- CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..f24adb94 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +www.functionaljava.org \ No newline at end of file From 703a15d02e0af8b654719a206542645bfcfa2111 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 21 Aug 2014 13:48:37 +1000 Subject: [PATCH 141/811] Added release notes for 2.19-2.21 --- etc/release-notes.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/etc/release-notes.md b/etc/release-notes.md index e5e26a9c..b0b9219a 100644 --- a/etc/release-notes.md +++ b/etc/release-notes.md @@ -71,3 +71,25 @@ Released: May 2012 === Released: Jun 2010 +2.21 +==== +Released Feb, 2010 + +* Bug fixes +* Immutable 2-3 finger tree + +2.20 +=== +Unknown + +2.19 +=== +Released March 2009 + +* Comonadic operations on Stream, Tree and others +* Database monad (java.sql.Connection as a functor) +* Natural Number data type +* The Constant Arrow ($) +* Immutable Tree Map +* A parallel quick-sort using Functional Java actors + From 575760e88880cd26f7dac96c75c3c2c0a927ba3b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 21 Aug 2014 16:27:00 +1000 Subject: [PATCH 142/811] Renamed RNG class --- .../java/fj/{SimpleRNG.java => LcgRng.java} | 14 ++++++------ core/src/main/java/fj/RNG.java | 22 ------------------- core/src/main/java/fj/Rng2.java | 22 +++++++++++++++++++ core/src/test/java/fj/data/TestRngState.java | 20 ++++++++--------- 4 files changed, 39 insertions(+), 39 deletions(-) rename core/src/main/java/fj/{SimpleRNG.java => LcgRng.java} (71%) delete mode 100644 core/src/main/java/fj/RNG.java create mode 100644 core/src/main/java/fj/Rng2.java diff --git a/core/src/main/java/fj/SimpleRNG.java b/core/src/main/java/fj/LcgRng.java similarity index 71% rename from core/src/main/java/fj/SimpleRNG.java rename to core/src/main/java/fj/LcgRng.java index 92cf31b9..1e9a7271 100644 --- a/core/src/main/java/fj/SimpleRNG.java +++ b/core/src/main/java/fj/LcgRng.java @@ -5,28 +5,28 @@ * * https://en.wikipedia.org/wiki/Linear_congruential_generator */ -public class SimpleRNG extends RNG { +public class LcgRng extends Rng2 { private Long seed; - public SimpleRNG() { + public LcgRng() { this(System.currentTimeMillis()); } - public SimpleRNG(long s) { + public LcgRng(long s) { seed = s; } - public P2 nextInt() { - P2 p = nextLong(); + public P2 nextInt() { + P2 p = nextLong(); int i = (int) p._2().longValue(); return P.p(p._1(), i); } - public P2 nextLong() { + public P2 nextLong() { P2 p = nextLong(seed); - return P.p(new SimpleRNG(p._1()), p._2()); + return P.p(new LcgRng(p._1()), p._2()); } /** diff --git a/core/src/main/java/fj/RNG.java b/core/src/main/java/fj/RNG.java deleted file mode 100644 index 915b7089..00000000 --- a/core/src/main/java/fj/RNG.java +++ /dev/null @@ -1,22 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 7/07/2014. - */ -public abstract class RNG { - - public abstract P2 nextInt(); - - public abstract P2 nextLong(); - - public P2 range(int low, int high) { - return nextNatural().map2(x -> (x % (high - low + 1)) + low); - } - - - public P2 nextNatural() { - return nextInt().map2(x -> x < 0 ? -(x + 1) : x); - } - - -} diff --git a/core/src/main/java/fj/Rng2.java b/core/src/main/java/fj/Rng2.java new file mode 100644 index 00000000..9c2fb60f --- /dev/null +++ b/core/src/main/java/fj/Rng2.java @@ -0,0 +1,22 @@ +package fj; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public abstract class Rng2 { + + public abstract P2 nextInt(); + + public abstract P2 nextLong(); + + public P2 range(int low, int high) { + return nextNatural().map2(x -> (x % (high - low + 1)) + low); + } + + + public P2 nextNatural() { + return nextInt().map2(x -> x < 0 ? -(x + 1) : x); + } + + +} diff --git a/core/src/test/java/fj/data/TestRngState.java b/core/src/test/java/fj/data/TestRngState.java index 1274fbec..4289d2da 100644 --- a/core/src/test/java/fj/data/TestRngState.java +++ b/core/src/test/java/fj/data/TestRngState.java @@ -15,23 +15,23 @@ public class TestRngState { static String expected1 = "<4,4,2,2,2,5,3,3,1,5>"; static int size = 10; - static RNG defaultRng() { - return new SimpleRNG(1); + static Rng2 defaultRng() { + return new LcgRng(1); } - static P2 num(RNG r) { + static P2 num(Rng2 r) { return r.range(1, 5); } - static State defaultState() { + static State defaultState() { return State.unit(s -> num(s)); } - static F, State> nextState() { + static F, State> nextState() { return s -> s.mapState(p2 -> num(p2._1())); } - static P2 num(RNG r, int x) { + static P2 num(Rng2 r, int x) { return r.range(x, x + 1); } @@ -43,9 +43,9 @@ public void testUnfold() { @Test public void testTransitions() { - P2>, State> p = List.replicate(size, nextState()).foldLeft( - (P2>, State> p2, F, State> f) -> { - State s = f.f(p2._2()); + P2>, State> p = List.replicate(size, nextState()).foldLeft( + (P2>, State> p2, F, State> f) -> { + State s = f.f(p2._2()); return P.p(p2._1().snoc(p2._2()), s); } , P.p(List.nil(), defaultState()) @@ -62,7 +62,7 @@ public void testSequence() { @Test public void testTraverse() { - List list = State.traverse(List.range(1, 10), a -> (State.unit((RNG s) -> num(s, a)))).eval(defaultRng()); + List list = State.traverse(List.range(1, 10), a -> (State.unit((Rng2 s) -> num(s, a)))).eval(defaultRng()); // System.out.println(list.toString()); String expected = "<1,2,3,5,6,7,7,9,10>"; Assert.assertTrue(list.toString().equals(expected)); From fd19c48fc75c8c4959a44309237fb474febb6179 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 21 Aug 2014 16:29:07 +1000 Subject: [PATCH 143/811] Renamed back to Rng --- core/src/main/java/fj/LcgRng.java | 8 +++---- core/src/main/java/fj/Rng.java | 22 ++++++++++++++++++++ core/src/main/java/fj/Rng2.java | 22 -------------------- core/src/test/java/fj/data/TestRngState.java | 18 ++++++++-------- 4 files changed, 35 insertions(+), 35 deletions(-) create mode 100644 core/src/main/java/fj/Rng.java delete mode 100644 core/src/main/java/fj/Rng2.java diff --git a/core/src/main/java/fj/LcgRng.java b/core/src/main/java/fj/LcgRng.java index 1e9a7271..16962c15 100644 --- a/core/src/main/java/fj/LcgRng.java +++ b/core/src/main/java/fj/LcgRng.java @@ -5,7 +5,7 @@ * * https://en.wikipedia.org/wiki/Linear_congruential_generator */ -public class LcgRng extends Rng2 { +public class LcgRng extends Rng { private Long seed; @@ -17,14 +17,14 @@ public LcgRng(long s) { seed = s; } - public P2 nextInt() { - P2 p = nextLong(); + public P2 nextInt() { + P2 p = nextLong(); int i = (int) p._2().longValue(); return P.p(p._1(), i); } - public P2 nextLong() { + public P2 nextLong() { P2 p = nextLong(seed); return P.p(new LcgRng(p._1()), p._2()); } diff --git a/core/src/main/java/fj/Rng.java b/core/src/main/java/fj/Rng.java new file mode 100644 index 00000000..679be544 --- /dev/null +++ b/core/src/main/java/fj/Rng.java @@ -0,0 +1,22 @@ +package fj; + +/** + * Created by MarkPerry on 7/07/2014. + */ +public abstract class Rng { + + public abstract P2 nextInt(); + + public abstract P2 nextLong(); + + public P2 range(int low, int high) { + return nextNatural().map2(x -> (x % (high - low + 1)) + low); + } + + + public P2 nextNatural() { + return nextInt().map2(x -> x < 0 ? -(x + 1) : x); + } + + +} diff --git a/core/src/main/java/fj/Rng2.java b/core/src/main/java/fj/Rng2.java deleted file mode 100644 index 9c2fb60f..00000000 --- a/core/src/main/java/fj/Rng2.java +++ /dev/null @@ -1,22 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 7/07/2014. - */ -public abstract class Rng2 { - - public abstract P2 nextInt(); - - public abstract P2 nextLong(); - - public P2 range(int low, int high) { - return nextNatural().map2(x -> (x % (high - low + 1)) + low); - } - - - public P2 nextNatural() { - return nextInt().map2(x -> x < 0 ? -(x + 1) : x); - } - - -} diff --git a/core/src/test/java/fj/data/TestRngState.java b/core/src/test/java/fj/data/TestRngState.java index 4289d2da..4a6e77fe 100644 --- a/core/src/test/java/fj/data/TestRngState.java +++ b/core/src/test/java/fj/data/TestRngState.java @@ -15,23 +15,23 @@ public class TestRngState { static String expected1 = "<4,4,2,2,2,5,3,3,1,5>"; static int size = 10; - static Rng2 defaultRng() { + static Rng defaultRng() { return new LcgRng(1); } - static P2 num(Rng2 r) { + static P2 num(Rng r) { return r.range(1, 5); } - static State defaultState() { + static State defaultState() { return State.unit(s -> num(s)); } - static F, State> nextState() { + static F, State> nextState() { return s -> s.mapState(p2 -> num(p2._1())); } - static P2 num(Rng2 r, int x) { + static P2 num(Rng r, int x) { return r.range(x, x + 1); } @@ -43,9 +43,9 @@ public void testUnfold() { @Test public void testTransitions() { - P2>, State> p = List.replicate(size, nextState()).foldLeft( - (P2>, State> p2, F, State> f) -> { - State s = f.f(p2._2()); + P2>, State> p = List.replicate(size, nextState()).foldLeft( + (P2>, State> p2, F, State> f) -> { + State s = f.f(p2._2()); return P.p(p2._1().snoc(p2._2()), s); } , P.p(List.nil(), defaultState()) @@ -62,7 +62,7 @@ public void testSequence() { @Test public void testTraverse() { - List list = State.traverse(List.range(1, 10), a -> (State.unit((Rng2 s) -> num(s, a)))).eval(defaultRng()); + List list = State.traverse(List.range(1, 10), a -> (State.unit((Rng s) -> num(s, a)))).eval(defaultRng()); // System.out.println(list.toString()); String expected = "<1,2,3,5,6,7,7,9,10>"; Assert.assertTrue(list.toString().equals(expected)); From 9e41f704f8976f966b6acf93097f553ee6f7fedf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:25:04 +1000 Subject: [PATCH 144/811] Changed README to asciidoc. Update from website --- README | 36 ------------------------------------ README.adoc | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 36 deletions(-) delete mode 100644 README create mode 100644 README.adoc diff --git a/README b/README deleted file mode 100644 index e41ca2ed..00000000 --- a/README +++ /dev/null @@ -1,36 +0,0 @@ -Functional Java is an open source library that seeks to improve the experience of using the Java programming language in a production environment. The library implements several advanced programming concepts that assist in achieving composition-oriented development. Functional Java is written using vanilla Java 1.5 syntax and requires no external supporting libraries. The JAR file will work with your Java 1.5 project without any additional effort. - -Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. - -Note that the website is in the midst of being updated. The URLs are: -* Old site, http://functionaljava.org -* New site, http://functionaljava.github.io -* New website on Github, https://github.com/functionaljava/functionaljava.github.io - -Functional Java includes the following features: - - * Fully operational Actors for parallel computations (fj.control.parallel) and layered abstractions such as parallel-map, map-reduce, parallel-zip. - * A package (fj.data.fingertrees) providing 2-3 finger trees for a functional representation of persistent sequences supporting access to the ends in amortized O(1) time. - * Type-safe heterogeneous list (fj.data.hlist) for lists of elements of differing types without sacrificing type-safety. - * Monadic parser combinators for writing parsers by combining smaller parsers using composition. - * Conversion of data types to/from standard Java types. - * Immutable, in-memory singly linked list (fj.data.List). - * Immutable lazy singly linked list (fj.data.Stream). - * Array wrapper (fj.data.Array). - * Optional value — type-safe null (fj.data.Option). - * Disjoint union data type — compositional exception handling (fj.data.Either). - * Validation, a right biased either for chaining computations over potentially failed operations. - * Reader, Writer and State. - * Monoid (fj.Monoid). - * Input/Output monad for abstracting IO. - * Functions with arity 1 to 8. - * Functions with arity 0 to 8 that can produce exceptions (fj.TryCatch). - * Products of 1 to 8. - * Configurable equality and hash-code for HashMap and HashSet. - * Natural number data type (fj.data.Natural). - * Immutable set implementation using a red/black tree. - * Immutable multi-way tree — aka rose tree (fj.data.Tree). - * Immutable tree-map using a red/black tree implementation (fj.data.TreeMap). - * Zipper implementations for streams and trees. - * Automated specification-based testing framework (fj.test). - * Conversion between FunctionalJava and Java 8 function types. diff --git a/README.adoc b/README.adoc new file mode 100644 index 00000000..5b270d53 --- /dev/null +++ b/README.adoc @@ -0,0 +1,51 @@ += Functional Java + +Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. + +The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8 and beyond. + +Important URLs for the project are: + +* Website, http://www.functionaljava.org +* Website repository, http://github.com/functionaljava/functionaljava.github.io + +Functional Java provides abstractions for the following types: + +* Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). +* Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list. +* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing, actors, concurrency and type conversion. + +A more complete description of the types above are: + +* Basic Data Structures +** Functions with arity 1 to 8 (`fj.F`). +** Functions with arity 0 to 8 that can produce exceptions (`fj.TryCatch`). +** Products with arity 1 to 8 (`fj.P`). +** Unit type (`fj.Unit`). +** Optional value - _type-safe null_ (`fj.data.Option`). +** Disjoint union data type - _compositional exception handling_ (`fj.data.Either`). +** Validation - _right biased_ compositional exception handling (`fj.data.Validation`). +* Immutable Collections +** Array wrapper (`fj.data.Array`). +** Immutable, in-memory singly linked list (`fj.data.List`). +** Immutable lazy singly linked list (`fj.data.Stream`). +** A package (`fj.data.fingertrees`) providing 2-3 finger trees for a functional representation of persistent sequences, supporting access to the ends in amortized O(1) time. +** Type-safe heterogeneous list (`fj.data.hlist`) for lists of elements of differing types without sacrificing type-safety. +** Immutable set implementation using a red/black tree (`fj.data.Set`). +** Immutable multi-way tree - aka rose tree (`fj.data.Tree`). +** Immutable tree-map using a red/black tree implementation (`fj.data.TreeMap`). +* Other +** Monoid (`fj.Monoid`). +** Semigroup (`fj.Semigroup`). +** Natural number data type (`fj.data.Natural`). +** Random number generator using a _linear congruential generator_ (`fj.LcgRng`). +** Reader, Writer and State monads (`fj.data.Reader`,`fj.data.Writer`, `fj.data.State`). +** Input/Output monad for abstracting IO (`fj.IO`). +** Monadic parser combinators for writing parsers by combining smaller parsers using composition. +** Conversion of data types to/from standard Java types. +** Conversion between FunctionalJava and Java 8 specific types. +** Configurable equality and hash-code for HashMap and HashSet. +** Zipper implementations for streams and trees. +** Automated specification-based testing framework (`fj.test`). +** Fully operational Actors for parallel computations (`fj.control.parallel`) and layered abstractions such as parallel-map, map-reduce, parallel-zip. + From 59feda673c34d46aa5ea8a3b9aeb5fdea51cb0bb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:34:09 +1000 Subject: [PATCH 145/811] Added license and image to README --- README.adoc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.adoc b/README.adoc index 5b270d53..eeb4dd79 100644 --- a/README.adoc +++ b/README.adoc @@ -1,14 +1,21 @@ = Functional Java +image::http://www.functionaljava.org/img/logo-600x144.png[] + + Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8 and beyond. +== URLs + Important URLs for the project are: * Website, http://www.functionaljava.org * Website repository, http://github.com/functionaljava/functionaljava.github.io +== Features + Functional Java provides abstractions for the following types: * Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). @@ -49,3 +56,6 @@ A more complete description of the types above are: ** Automated specification-based testing framework (`fj.test`). ** Fully operational Actors for parallel computations (`fj.control.parallel`) and layered abstractions such as parallel-map, map-reduce, parallel-zip. +== License + +Functional Java uses the BSD 3 license (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses). \ No newline at end of file From 36df00ffcf2058e39159f340ecd789b449632792 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:36:16 +1000 Subject: [PATCH 146/811] Attempt to fix license URL --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index eeb4dd79..f375eb1f 100644 --- a/README.adoc +++ b/README.adoc @@ -58,4 +58,4 @@ A more complete description of the types above are: == License -Functional Java uses the BSD 3 license (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses). \ No newline at end of file +Functional Java uses the BSD 3 license (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses ). \ No newline at end of file From a3d98daac2b9537e97ab573839802569910e5a7a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:37:09 +1000 Subject: [PATCH 147/811] Attempt to fix license URL --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index f375eb1f..19734e59 100644 --- a/README.adoc +++ b/README.adoc @@ -58,4 +58,4 @@ A more complete description of the types above are: == License -Functional Java uses the BSD 3 license (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses ). \ No newline at end of file +Functional Java uses the BSD 3 license (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses[]). \ No newline at end of file From 4e0fc061d4dd9944feff03f834eb25f6a056f2cb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:45:02 +1000 Subject: [PATCH 148/811] Added license link --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 19734e59..5dda9b48 100644 --- a/README.adoc +++ b/README.adoc @@ -58,4 +58,4 @@ A more complete description of the types above are: == License -Functional Java uses the BSD 3 license (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses[]). \ No newline at end of file +link:etc/LICENSE[The Functional Java license] uses the BSD 3 license, available at (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses[]). \ No newline at end of file From 5f2e8751086e352ae5467d6d75a8be8df15ecd7b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:46:42 +1000 Subject: [PATCH 149/811] Fxied license spelling link --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 5dda9b48..0eed4d4f 100644 --- a/README.adoc +++ b/README.adoc @@ -58,4 +58,4 @@ A more complete description of the types above are: == License -link:etc/LICENSE[The Functional Java license] uses the BSD 3 license, available at (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses[]). \ No newline at end of file +link:etc/LICENCE[The Functional Java license] uses the BSD 3 license, available at (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses[]). \ No newline at end of file From f3eebc35419356c9ee90bbfb36115575fc562a4e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 09:54:15 +1000 Subject: [PATCH 150/811] Added downloading description --- README.adoc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.adoc b/README.adoc index 0eed4d4f..337b3e7c 100644 --- a/README.adoc +++ b/README.adoc @@ -14,6 +14,19 @@ Important URLs for the project are: * Website, http://www.functionaljava.org * Website repository, http://github.com/functionaljava/functionaljava.github.io +== Downloading + +The recommended way to download and use the project is through your build tool. + +The Functional Java artifact is published to Maven Central using the group `org.functionaljava` with two published artifacts: + +* the core library (`functionaljava`) +* Java 8 specific support (`functionaljava-java8`) + +== Building + +TODO + == Features Functional Java provides abstractions for the following types: From 7699e0f8b7bc5326b633e8ab549c5d888a995a28 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 10:09:19 +1000 Subject: [PATCH 151/811] Added download and building instructions --- README.adoc | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index 337b3e7c..9f06d88c 100644 --- a/README.adoc +++ b/README.adoc @@ -2,7 +2,6 @@ image::http://www.functionaljava.org/img/logo-600x144.png[] - Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8 and beyond. @@ -23,9 +22,35 @@ The Functional Java artifact is published to Maven Central using the group `org. * the core library (`functionaljava`) * Java 8 specific support (`functionaljava-java8`) +The latest version is `4.2-beta-1`. This can be added to your Gradle project by adding the dependencies: +---- +compile "org.functionaljava:functionaljava:4.2-beta-1" +compile "org.functionaljava:functionaljava-java8:4.2-beta-1" +---- + +and in Maven: +---- + + org.functionaljava + functionaljava + 4.2-beta-1 + + + org.functionaljava + functionaljava-java8 + 4.2-beta-1 + +---- + == Building -TODO +FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 7 bytecode. This requires access to both JDK 7 and 8. The build system requires the environment variables `JAVA7_HOME` and `JAVA8_HOME` to refer to the appropriate directories. + +Building is done using Gradle 2.0. In the root directory run: +---- +./gradlew +---- +This will download the Gradle build tool and necessary dependencies and build FunctionalJava. == Features From 9eb0412fc924b20bff343c5890ad70dd7494c42a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 10:14:41 +1000 Subject: [PATCH 152/811] Moved feature summary to near top of README --- README.adoc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.adoc b/README.adoc index 9f06d88c..a505a39f 100644 --- a/README.adoc +++ b/README.adoc @@ -6,6 +6,12 @@ Functional Java is an open source library facilitating functional programming in The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8 and beyond. +Functional Java provides abstractions for the following types: + +* Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). +* Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list. +* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing, actors, concurrency and type conversion. + == URLs Important URLs for the project are: @@ -54,13 +60,7 @@ This will download the Gradle build tool and necessary dependencies and build Fu == Features -Functional Java provides abstractions for the following types: - -* Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). -* Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list. -* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing, actors, concurrency and type conversion. - -A more complete description of the types above are: +A more complete description of the features mentioned above are: * Basic Data Structures ** Functions with arity 1 to 8 (`fj.F`). From 9a4af9a829d3964245759b2f83d124ce87e8afc6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 22 Aug 2014 10:17:02 +1000 Subject: [PATCH 153/811] Tweak README --- README.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index a505a39f..8e15dbf8 100644 --- a/README.adoc +++ b/README.adoc @@ -79,7 +79,7 @@ A more complete description of the features mentioned above are: ** Immutable set implementation using a red/black tree (`fj.data.Set`). ** Immutable multi-way tree - aka rose tree (`fj.data.Tree`). ** Immutable tree-map using a red/black tree implementation (`fj.data.TreeMap`). -* Other +* Other Abstractions ** Monoid (`fj.Monoid`). ** Semigroup (`fj.Semigroup`). ** Natural number data type (`fj.data.Natural`). From 3324a70e9b2bee53cd2791ba4709c75a1ab22a31 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 26 Aug 2014 10:27:56 +1000 Subject: [PATCH 154/811] Updated SafeIO to not need a validation --- core/src/main/java/fj/data/IOFunctions.java | 2 +- core/src/main/java/fj/data/SafeIO.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 7420028d..1052c1d3 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -354,7 +354,7 @@ public static IO join(IO> io1) { return bind(io1, io2 -> io2); } - public static SafeIO toSafeIO(IO io) { + public static SafeIO> toSafeIO(IO io) { return () -> P1.toP1(() -> io.run())._1(); } diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index 6dfa64a5..2935ca83 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -5,10 +5,10 @@ /** * Created by MarkPerry on 3/07/2014. */ -public interface SafeIO extends IO> { +public interface SafeIO extends IO { @Override - public Validation run(); + public A run(); } From 2e8db441c9b187cb3165a6af43f34c03044038a4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 14:35:51 +1000 Subject: [PATCH 155/811] Renamed TryCatchN to TryN --- core/src/main/java/fj/{TryCatch0.java => Try0.java} | 2 +- core/src/main/java/fj/{TryCatch1.java => Try1.java} | 2 +- core/src/main/java/fj/{TryCatch2.java => Try2.java} | 2 +- core/src/main/java/fj/{TryCatch3.java => Try3.java} | 2 +- core/src/main/java/fj/{TryCatch4.java => Try4.java} | 2 +- core/src/main/java/fj/{TryCatch5.java => Try5.java} | 2 +- core/src/main/java/fj/{TryCatch6.java => Try6.java} | 2 +- core/src/main/java/fj/{TryCatch7.java => Try7.java} | 2 +- core/src/main/java/fj/{TryCatch8.java => Try8.java} | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) rename core/src/main/java/fj/{TryCatch0.java => Try0.java} (84%) rename core/src/main/java/fj/{TryCatch1.java => Try1.java} (85%) rename core/src/main/java/fj/{TryCatch2.java => Try2.java} (86%) rename core/src/main/java/fj/{TryCatch3.java => Try3.java} (86%) rename core/src/main/java/fj/{TryCatch4.java => Try4.java} (86%) rename core/src/main/java/fj/{TryCatch5.java => Try5.java} (86%) rename core/src/main/java/fj/{TryCatch6.java => Try6.java} (86%) rename core/src/main/java/fj/{TryCatch7.java => Try7.java} (86%) rename core/src/main/java/fj/{TryCatch8.java => Try8.java} (86%) diff --git a/core/src/main/java/fj/TryCatch0.java b/core/src/main/java/fj/Try0.java similarity index 84% rename from core/src/main/java/fj/TryCatch0.java rename to core/src/main/java/fj/Try0.java index 7a39e7f8..9dbe6fad 100644 --- a/core/src/main/java/fj/TryCatch0.java +++ b/core/src/main/java/fj/Try0.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch0 { +public interface Try0 { A f() throws E; diff --git a/core/src/main/java/fj/TryCatch1.java b/core/src/main/java/fj/Try1.java similarity index 85% rename from core/src/main/java/fj/TryCatch1.java rename to core/src/main/java/fj/Try1.java index 02a17afa..f244708b 100644 --- a/core/src/main/java/fj/TryCatch1.java +++ b/core/src/main/java/fj/Try1.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch1 { +public interface Try1 { B f(A a) throws E; diff --git a/core/src/main/java/fj/TryCatch2.java b/core/src/main/java/fj/Try2.java similarity index 86% rename from core/src/main/java/fj/TryCatch2.java rename to core/src/main/java/fj/Try2.java index a92ab00c..3f1f444b 100644 --- a/core/src/main/java/fj/TryCatch2.java +++ b/core/src/main/java/fj/Try2.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch2 { +public interface Try2 { C f(A a, B b) throws E; diff --git a/core/src/main/java/fj/TryCatch3.java b/core/src/main/java/fj/Try3.java similarity index 86% rename from core/src/main/java/fj/TryCatch3.java rename to core/src/main/java/fj/Try3.java index 970f7044..be7bce5d 100644 --- a/core/src/main/java/fj/TryCatch3.java +++ b/core/src/main/java/fj/Try3.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch3 { +public interface Try3 { D f(A a, B b, C c) throws E; diff --git a/core/src/main/java/fj/TryCatch4.java b/core/src/main/java/fj/Try4.java similarity index 86% rename from core/src/main/java/fj/TryCatch4.java rename to core/src/main/java/fj/Try4.java index f15cafdc..da0d1d75 100644 --- a/core/src/main/java/fj/TryCatch4.java +++ b/core/src/main/java/fj/Try4.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch4 { +public interface Try4 { E f(A a, B b, C c, D d) throws Z; diff --git a/core/src/main/java/fj/TryCatch5.java b/core/src/main/java/fj/Try5.java similarity index 86% rename from core/src/main/java/fj/TryCatch5.java rename to core/src/main/java/fj/Try5.java index ace1b537..7ae288c1 100644 --- a/core/src/main/java/fj/TryCatch5.java +++ b/core/src/main/java/fj/Try5.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch5 { +public interface Try5 { F f(A a, B b, C c, D d, E e) throws Z; diff --git a/core/src/main/java/fj/TryCatch6.java b/core/src/main/java/fj/Try6.java similarity index 86% rename from core/src/main/java/fj/TryCatch6.java rename to core/src/main/java/fj/Try6.java index 82dc5fad..fb124382 100644 --- a/core/src/main/java/fj/TryCatch6.java +++ b/core/src/main/java/fj/Try6.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch6 { +public interface Try6 { G f(A a, B b, C c, D d, E e, F f) throws Z; diff --git a/core/src/main/java/fj/TryCatch7.java b/core/src/main/java/fj/Try7.java similarity index 86% rename from core/src/main/java/fj/TryCatch7.java rename to core/src/main/java/fj/Try7.java index 97f90cfc..a3eadfff 100644 --- a/core/src/main/java/fj/TryCatch7.java +++ b/core/src/main/java/fj/Try7.java @@ -10,7 +10,7 @@ * @version %build.number% */ -public interface TryCatch7 { +public interface Try7 { H f(A a, B b, C c, D d, E e, F f, G g) throws Z; diff --git a/core/src/main/java/fj/TryCatch8.java b/core/src/main/java/fj/Try8.java similarity index 86% rename from core/src/main/java/fj/TryCatch8.java rename to core/src/main/java/fj/Try8.java index f90f2c6e..bd503737 100644 --- a/core/src/main/java/fj/TryCatch8.java +++ b/core/src/main/java/fj/Try8.java @@ -9,7 +9,7 @@ * @version %build.number% */ -public interface TryCatch8 { +public interface Try8 { I f(A a, B b, C c, D d, E e, F f, G g, H h) throws Z; From f86ba89bc0d370ae77b8709a09717339b461b7e7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 14:37:53 +1000 Subject: [PATCH 156/811] Support name change for TryCatch --- core/src/main/java/fj/F1Functions.java | 2 +- core/src/main/java/fj/F2Functions.java | 2 +- core/src/main/java/fj/F3Functions.java | 2 +- core/src/main/java/fj/F4Functions.java | 2 +- core/src/main/java/fj/F5Functions.java | 2 +- core/src/main/java/fj/F6Functions.java | 2 +- core/src/main/java/fj/F7Functions.java | 2 +- core/src/main/java/fj/F8Functions.java | 2 +- core/src/main/java/fj/P1.java | 2 +- core/src/main/java/fj/Try.java | 20 ++++++++++---------- core/src/main/java/fj/data/IOFunctions.java | 4 ++-- java8/src/main/java/fj/data/Java8.java | 12 ++++++------ 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index f269337a..2fc476df 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -840,7 +840,7 @@ static public ArrayList mapJ(final F f, final ArrayList as) { * @param t A TryCatch1 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F> toF1(final TryCatch1 t) { + static public F> toF1(final Try1 t) { return a -> { try { return Validation.success(t.f(a)); diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index a9946240..7c0c8476 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -353,7 +353,7 @@ public P3>, C, Stream>> f(final P3>, A, St * @param t A TryCatch2 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F2> toF2(final TryCatch2 t) { + static public F2> toF2(final Try2 t) { return (a, b) -> { try { return Validation.success(t.f(a, b)); diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index bdc4b35c..d7983794 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -16,7 +16,7 @@ public class F3Functions { * @param t A TryCatch3 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F3> toF3(final TryCatch3 t) { + static public F3> toF3(final Try3 t) { return (a, b, c) -> { try { return success(t.f(a, b, c)); diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index 3f605598..182c08b8 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -14,7 +14,7 @@ public class F4Functions { * @param t A TryCatch4 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F4> toF4(final TryCatch4 t) { + static public F4> toF4(final Try4 t) { return (a, b, c, d) -> { try { return Validation.success(t.f(a, b, c, d)); diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index bf951868..23f218ac 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -13,7 +13,7 @@ public class F5Functions { * @param t A TryCatch5 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F5> toF5(final TryCatch5 t) { + static public F5> toF5(final Try5 t) { return (a, b, c, d, e) -> { try { return Validation.success(t.f(a, b, c, d, e)); diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 9f1f881f..1e3a426d 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -13,7 +13,7 @@ public class F6Functions { * @param t A TryCatch6 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F6> toF6(final TryCatch6 t) { + static public F6> toF6(final Try6 t) { return (a, b, c, d, e, f) -> { try { return Validation.success(t.f(a, b, c, d, e, f)); diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index c453297e..6c986383 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -13,7 +13,7 @@ public class F7Functions { * @param t A TryCatch7 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F7> toF7(final TryCatch7 t) { + static public F7> toF7(final Try7 t) { return (a, b, c, d, e, f, g) -> { try { return Validation.success(t.f(a, b, c, d, e, f, g)); diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index aa4b6391..fc8fc5f8 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -13,7 +13,7 @@ public class F8Functions { * @param t A TryCatch8 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public F8> toF8(final TryCatch8 t) { + static public F8> toF8(final Try8 t) { return (a, b, c, d, e, f, g, h) -> { try { return Validation.success(t.f(a, b, c, d, e, f, g, h)); diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index efa61659..98f98d5a 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -237,7 +237,7 @@ public A f(final B b) { * @param t A TryCatch0 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ - static public P1> toP1(final TryCatch0 t) { + static public P1> toP1(final Try0 t) { return P.lazy(u -> { try { return Validation.success(t.f()); diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index 92c05a8f..6d2ceab0 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -11,43 +11,43 @@ */ public class Try { - public static P1> f(TryCatch0 t) { + public static P1> f(Try0 t) { return P1.toP1(t); } - public static F> f(TryCatch1 t) { + public static F> f(Try1 t) { return F1Functions.toF1(t); } - public static F2> f(TryCatch2 t) { + public static F2> f(Try2 t) { return F2Functions.toF2(t); } - public static F3> f(TryCatch3 t) { + public static F3> f(Try3 t) { return F3Functions.toF3(t); } - public static F4> f(TryCatch4 t) { + public static F4> f(Try4 t) { return F4Functions.toF4(t); } - public static F5> f(TryCatch5 t) { + public static F5> f(Try5 t) { return F5Functions.toF5(t); } - public static F6> f(TryCatch6 t) { + public static F6> f(Try6 t) { return F6Functions.toF6(t); } - public static F7> f(TryCatch7 t) { + public static F7> f(Try7 t) { return F7Functions.toF7(t); } - public static F8> f(TryCatch8 t) { + public static F8> f(Try8 t) { return F8Functions.toF8(t); } - public static IO io(TryCatch0 t) { + public static IO io(Try0 t) { return IOFunctions.io(t); } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 1052c1d3..e29feb5f 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -30,7 +30,7 @@ public class IOFunctions { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - public static TryCatch0 toTry(IO io) { + public static Try0 toTry(IO io) { return () -> io.run(); } @@ -42,7 +42,7 @@ public static IO io(P1 p) { return () -> p._1(); } - public static IO io(TryCatch0 t) { + public static IO io(Try0 t) { return () -> t.f(); } diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 84a15b28..36fa8170 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -64,27 +64,27 @@ public static F, BiFunction> F2_BiFunction() { return f -> (a, b) -> f.f(a, b); } - static public Supplier> TryCatch0_Supplier(final TryCatch0 t) { + static public Supplier> TryCatch0_Supplier(final Try0 t) { return Java8.TryCatch0_Supplier().f(t); } - static public F, Supplier>> TryCatch0_Supplier() { + static public F, Supplier>> TryCatch0_Supplier() { return t -> () -> P1.toP1(t)._1(); } - static public Function> TryCatch1_Function(final TryCatch1 t) { + static public Function> TryCatch1_Function(final Try1 t) { return Java8.TryCatch1_Function().f(t); } - static public F, Function>> TryCatch1_Function() { + static public F, Function>> TryCatch1_Function() { return t -> a -> F1Functions.toF1(t).f(a); } - static public BiFunction> TryCatch2_BiFunction(final TryCatch2 t) { + static public BiFunction> TryCatch2_BiFunction(final Try2 t) { return Java8.TryCatch2_BiFunction().f(t); } - static public F, BiFunction>> TryCatch2_BiFunction() { + static public F, BiFunction>> TryCatch2_BiFunction() { return t -> (a, b) -> F2Functions.toF2(t).f(a, b); } From 9630c8ae4e4519572aca3270f868f4d5900dcf6a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 14:38:30 +1000 Subject: [PATCH 157/811] Added Effect and TryEffect with arity 0 to 8 --- core/src/main/java/fj/function/Effect0.java | 10 ++++++++++ core/src/main/java/fj/function/Effect1.java | 10 ++++++++++ core/src/main/java/fj/function/Effect2.java | 10 ++++++++++ core/src/main/java/fj/function/Effect3.java | 11 +++++++++++ core/src/main/java/fj/function/Effect4.java | 10 ++++++++++ core/src/main/java/fj/function/Effect5.java | 10 ++++++++++ core/src/main/java/fj/function/Effect6.java | 10 ++++++++++ core/src/main/java/fj/function/Effect7.java | 10 ++++++++++ core/src/main/java/fj/function/Effect8.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect0.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect1.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect2.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect3.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect4.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect5.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect6.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect7.java | 10 ++++++++++ core/src/main/java/fj/function/TryEffect8.java | 10 ++++++++++ 18 files changed, 181 insertions(+) create mode 100644 core/src/main/java/fj/function/Effect0.java create mode 100644 core/src/main/java/fj/function/Effect1.java create mode 100644 core/src/main/java/fj/function/Effect2.java create mode 100644 core/src/main/java/fj/function/Effect3.java create mode 100644 core/src/main/java/fj/function/Effect4.java create mode 100644 core/src/main/java/fj/function/Effect5.java create mode 100644 core/src/main/java/fj/function/Effect6.java create mode 100644 core/src/main/java/fj/function/Effect7.java create mode 100644 core/src/main/java/fj/function/Effect8.java create mode 100644 core/src/main/java/fj/function/TryEffect0.java create mode 100644 core/src/main/java/fj/function/TryEffect1.java create mode 100644 core/src/main/java/fj/function/TryEffect2.java create mode 100644 core/src/main/java/fj/function/TryEffect3.java create mode 100644 core/src/main/java/fj/function/TryEffect4.java create mode 100644 core/src/main/java/fj/function/TryEffect5.java create mode 100644 core/src/main/java/fj/function/TryEffect6.java create mode 100644 core/src/main/java/fj/function/TryEffect7.java create mode 100644 core/src/main/java/fj/function/TryEffect8.java diff --git a/core/src/main/java/fj/function/Effect0.java b/core/src/main/java/fj/function/Effect0.java new file mode 100644 index 00000000..c5d4fe50 --- /dev/null +++ b/core/src/main/java/fj/function/Effect0.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect0 { + + void f(); + +} diff --git a/core/src/main/java/fj/function/Effect1.java b/core/src/main/java/fj/function/Effect1.java new file mode 100644 index 00000000..8c89b715 --- /dev/null +++ b/core/src/main/java/fj/function/Effect1.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect1 { + + void f(A a); + +} diff --git a/core/src/main/java/fj/function/Effect2.java b/core/src/main/java/fj/function/Effect2.java new file mode 100644 index 00000000..c0735043 --- /dev/null +++ b/core/src/main/java/fj/function/Effect2.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect2 { + + void f(A a, B b); + +} diff --git a/core/src/main/java/fj/function/Effect3.java b/core/src/main/java/fj/function/Effect3.java new file mode 100644 index 00000000..0609584b --- /dev/null +++ b/core/src/main/java/fj/function/Effect3.java @@ -0,0 +1,11 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect3 { + + void f(A a, B b, C c); + +} + diff --git a/core/src/main/java/fj/function/Effect4.java b/core/src/main/java/fj/function/Effect4.java new file mode 100644 index 00000000..b24a7624 --- /dev/null +++ b/core/src/main/java/fj/function/Effect4.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect4 { + + void f(A a, B b, C c, D d); + +} diff --git a/core/src/main/java/fj/function/Effect5.java b/core/src/main/java/fj/function/Effect5.java new file mode 100644 index 00000000..142be280 --- /dev/null +++ b/core/src/main/java/fj/function/Effect5.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect5 { + + void f(A a, B b, C c, D d, E e); + +} diff --git a/core/src/main/java/fj/function/Effect6.java b/core/src/main/java/fj/function/Effect6.java new file mode 100644 index 00000000..fe72314b --- /dev/null +++ b/core/src/main/java/fj/function/Effect6.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect6 { + + void f(A a, B b, C c, D d, E e, F f); + +} diff --git a/core/src/main/java/fj/function/Effect7.java b/core/src/main/java/fj/function/Effect7.java new file mode 100644 index 00000000..944273af --- /dev/null +++ b/core/src/main/java/fj/function/Effect7.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect7 { + + void f(A a, B b, C c, D d, E e, F f, G g); + +} diff --git a/core/src/main/java/fj/function/Effect8.java b/core/src/main/java/fj/function/Effect8.java new file mode 100644 index 00000000..a8cfd3bb --- /dev/null +++ b/core/src/main/java/fj/function/Effect8.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface Effect8 { + + void f(A a, B b, C c, D d, E e, F f, G g, H h); + +} diff --git a/core/src/main/java/fj/function/TryEffect0.java b/core/src/main/java/fj/function/TryEffect0.java new file mode 100644 index 00000000..a6c9cbee --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect0.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect0 { + + void f() throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect1.java b/core/src/main/java/fj/function/TryEffect1.java new file mode 100644 index 00000000..40db423d --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect1.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect1 { + + void f(A a) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect2.java b/core/src/main/java/fj/function/TryEffect2.java new file mode 100644 index 00000000..c9c13da9 --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect2.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect2 { + + void f(A a, B b) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect3.java b/core/src/main/java/fj/function/TryEffect3.java new file mode 100644 index 00000000..c581221e --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect3.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect3 { + + void f(A a, B b, C c) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect4.java b/core/src/main/java/fj/function/TryEffect4.java new file mode 100644 index 00000000..f99900ca --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect4.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect4 { + + void f(A a, B b, C c, D d) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect5.java b/core/src/main/java/fj/function/TryEffect5.java new file mode 100644 index 00000000..d0445e3e --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect5.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect5 { + + void f(A a, B b, C c, D d, E e) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect6.java b/core/src/main/java/fj/function/TryEffect6.java new file mode 100644 index 00000000..b4d81a41 --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect6.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect6 { + + void f(A a, B b, C c, D d, E e, F f) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect7.java b/core/src/main/java/fj/function/TryEffect7.java new file mode 100644 index 00000000..2e6004e9 --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect7.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect7 { + + void f(A a, B b, C c, D d, E e, F f, G g) throws Z; + +} diff --git a/core/src/main/java/fj/function/TryEffect8.java b/core/src/main/java/fj/function/TryEffect8.java new file mode 100644 index 00000000..4424bf00 --- /dev/null +++ b/core/src/main/java/fj/function/TryEffect8.java @@ -0,0 +1,10 @@ +package fj.function; + +/** + * Created by mperry on 28/08/2014. + */ +public interface TryEffect8 { + + void f(A a, B b, C c, D d, E e, F f, G g, H h) throws Z; + +} From aaf0b8b62ce2c29f66fdd6906205c03db179ffae Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 14:39:46 +1000 Subject: [PATCH 158/811] Test passing a method to instantiate an interface --- .../src/test/java/fj/function/TestEffect.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 core/src/test/java/fj/function/TestEffect.java diff --git a/core/src/test/java/fj/function/TestEffect.java b/core/src/test/java/fj/function/TestEffect.java new file mode 100644 index 00000000..00da26f0 --- /dev/null +++ b/core/src/test/java/fj/function/TestEffect.java @@ -0,0 +1,25 @@ +package fj.function; + +import fj.F; +import org.junit.Test; + +/** + * Created by mperry on 28/08/2014. + */ +public class TestEffect { + + @Test + public void test1() { + higher(TestEffect::m1); + } + + + static void higher(Effect1 f) { + + } + + static void m1(String s) { + + } + +} From f17b1138e8c8cb1a82fb6fe057fa5ad81824ea4a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 14:44:23 +1000 Subject: [PATCH 159/811] Moved TryN to function package --- core/src/main/java/fj/F1Functions.java | 1 + core/src/main/java/fj/F2Functions.java | 1 + core/src/main/java/fj/F3Functions.java | 1 + core/src/main/java/fj/F4Functions.java | 1 + core/src/main/java/fj/F5Functions.java | 1 + core/src/main/java/fj/F6Functions.java | 1 + core/src/main/java/fj/F7Functions.java | 1 + core/src/main/java/fj/F8Functions.java | 1 + core/src/main/java/fj/P1.java | 1 + core/src/main/java/fj/Try.java | 1 + core/src/main/java/fj/data/IOFunctions.java | 1 + core/src/main/java/fj/{ => function}/Try0.java | 4 ++-- core/src/main/java/fj/{ => function}/Try1.java | 4 ++-- core/src/main/java/fj/{ => function}/Try2.java | 4 ++-- core/src/main/java/fj/{ => function}/Try3.java | 4 ++-- core/src/main/java/fj/{ => function}/Try4.java | 4 ++-- core/src/main/java/fj/{ => function}/Try5.java | 4 ++-- core/src/main/java/fj/{ => function}/Try6.java | 4 ++-- core/src/main/java/fj/{ => function}/Try7.java | 4 ++-- core/src/main/java/fj/{ => function}/Try8.java | 4 ++-- java8/src/main/java/fj/data/Java8.java | 3 +++ 21 files changed, 32 insertions(+), 18 deletions(-) rename core/src/main/java/fj/{ => function}/Try0.java (88%) rename core/src/main/java/fj/{ => function}/Try1.java (87%) rename core/src/main/java/fj/{ => function}/Try2.java (88%) rename core/src/main/java/fj/{ => function}/Try3.java (89%) rename core/src/main/java/fj/{ => function}/Try4.java (89%) rename core/src/main/java/fj/{ => function}/Try5.java (90%) rename core/src/main/java/fj/{ => function}/Try6.java (90%) rename core/src/main/java/fj/{ => function}/Try7.java (91%) rename core/src/main/java/fj/{ => function}/Try8.java (91%) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 2fc476df..d4a1cfb8 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -4,6 +4,7 @@ import fj.control.parallel.Promise; import fj.control.parallel.Strategy; import fj.data.*; +import fj.function.Try1; import java.util.ArrayList; import java.util.LinkedList; diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index 7c0c8476..e164404f 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -2,6 +2,7 @@ import fj.control.parallel.Promise; import fj.data.*; +import fj.function.Try2; import static fj.P.p; import static fj.data.IterableW.wrap; diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index d7983794..938ccf2f 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -1,6 +1,7 @@ package fj; import fj.data.Validation; +import fj.function.Try3; import static fj.data.Validation.fail; import static fj.data.Validation.success; diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index 182c08b8..e82f1fd9 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -1,6 +1,7 @@ package fj; import fj.data.Validation; +import fj.function.Try4; /** * Created by MarkPerry on 6/04/2014. diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index 23f218ac..b5e3155c 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -1,6 +1,7 @@ package fj; import fj.data.Validation; +import fj.function.Try5; /** * Created by MarkPerry on 6/04/2014. diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 1e3a426d..238bcfc5 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -1,6 +1,7 @@ package fj; import fj.data.Validation; +import fj.function.Try6; /** * Created by MarkPerry on 6/04/2014. diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 6c986383..743fa608 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -1,6 +1,7 @@ package fj; import fj.data.Validation; +import fj.function.Try7; /** * Created by MarkPerry on 6/04/2014. diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index fc8fc5f8..a1bf2217 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -1,6 +1,7 @@ package fj; import fj.data.Validation; +import fj.function.Try8; /** * Created by MarkPerry on 6/04/2014. diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 98f98d5a..88469138 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -6,6 +6,7 @@ import fj.data.List; import fj.data.Stream; import fj.data.Validation; +import fj.function.Try0; public abstract class P1 { diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index 6d2ceab0..f585f657 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -3,6 +3,7 @@ import fj.data.IO; import fj.data.IOFunctions; import fj.data.Validation; +import fj.function.*; import java.io.IOException; diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index e29feb5f..d14fbbdb 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -16,6 +16,7 @@ import fj.*; import fj.data.Iteratee.Input; import fj.data.Iteratee.IterV; +import fj.function.Try0; /** * IO monad for processing files, with main methods {@link #enumFileLines }, diff --git a/core/src/main/java/fj/Try0.java b/core/src/main/java/fj/function/Try0.java similarity index 88% rename from core/src/main/java/fj/Try0.java rename to core/src/main/java/fj/function/Try0.java index 9dbe6fad..32655296 100644 --- a/core/src/main/java/fj/Try0.java +++ b/core/src/main/java/fj/function/Try0.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A product of A which may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to a P1. * - * @see P1#toP1 + * @see fj.P1#toP1 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try1.java b/core/src/main/java/fj/function/Try1.java similarity index 87% rename from core/src/main/java/fj/Try1.java rename to core/src/main/java/fj/function/Try1.java index f244708b..715e4400 100644 --- a/core/src/main/java/fj/Try1.java +++ b/core/src/main/java/fj/function/Try1.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function from A to B that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F. * - * @see F1Functions#toF1 + * @see fj.F1Functions#toF1 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try2.java b/core/src/main/java/fj/function/Try2.java similarity index 88% rename from core/src/main/java/fj/Try2.java rename to core/src/main/java/fj/function/Try2.java index 3f1f444b..3d0cd5d4 100644 --- a/core/src/main/java/fj/Try2.java +++ b/core/src/main/java/fj/function/Try2.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function of arity-2 from A and B to C that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F2. * - * @see F2Functions#toF2 + * @see fj.F2Functions#toF2 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try3.java b/core/src/main/java/fj/function/Try3.java similarity index 89% rename from core/src/main/java/fj/Try3.java rename to core/src/main/java/fj/function/Try3.java index be7bce5d..fdb9b176 100644 --- a/core/src/main/java/fj/Try3.java +++ b/core/src/main/java/fj/function/Try3.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function of arity-3 from A, B and C to D that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F3. * - * @see F3Functions#toF3 + * @see fj.F3Functions#toF3 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try4.java b/core/src/main/java/fj/function/Try4.java similarity index 89% rename from core/src/main/java/fj/Try4.java rename to core/src/main/java/fj/function/Try4.java index da0d1d75..6c360596 100644 --- a/core/src/main/java/fj/Try4.java +++ b/core/src/main/java/fj/function/Try4.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function of arity-4 from A, B, C and D to E that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F4. * - * @see F4Functions#toF4 + * @see fj.F4Functions#toF4 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try5.java b/core/src/main/java/fj/function/Try5.java similarity index 90% rename from core/src/main/java/fj/Try5.java rename to core/src/main/java/fj/function/Try5.java index 7ae288c1..1ad45894 100644 --- a/core/src/main/java/fj/Try5.java +++ b/core/src/main/java/fj/function/Try5.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function of arity-5 from A, B, C, D and E to F that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F5. * - * @see F5Functions#toF5 + * @see fj.F5Functions#toF5 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try6.java b/core/src/main/java/fj/function/Try6.java similarity index 90% rename from core/src/main/java/fj/Try6.java rename to core/src/main/java/fj/function/Try6.java index fb124382..ed97da2f 100644 --- a/core/src/main/java/fj/Try6.java +++ b/core/src/main/java/fj/function/Try6.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function of arity-6 from A, B, C, D, E and F to G that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F6. * - * @see F6Functions#toF6 + * @see fj.F6Functions#toF6 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try7.java b/core/src/main/java/fj/function/Try7.java similarity index 91% rename from core/src/main/java/fj/Try7.java rename to core/src/main/java/fj/function/Try7.java index a3eadfff..4fb1aa27 100644 --- a/core/src/main/java/fj/Try7.java +++ b/core/src/main/java/fj/function/Try7.java @@ -1,4 +1,4 @@ -package fj; +package fj.function; /** @@ -6,7 +6,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F7. * - * @see F7Functions#toF7 + * @see fj.F7Functions#toF7 * @version %build.number% */ diff --git a/core/src/main/java/fj/Try8.java b/core/src/main/java/fj/function/Try8.java similarity index 91% rename from core/src/main/java/fj/Try8.java rename to core/src/main/java/fj/function/Try8.java index bd503737..42f6fcd0 100644 --- a/core/src/main/java/fj/Try8.java +++ b/core/src/main/java/fj/function/Try8.java @@ -1,11 +1,11 @@ -package fj; +package fj.function; /** * A transformation function of arity-8 from A, B, C, D, E, F, G and H to I that may throw an Exception. * * Used to instantiate a lambda that may throw an Exception before converting to an F8. * - * @see F8Functions#toF8 + * @see fj.F8Functions#toF8 * @version %build.number% */ diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 36fa8170..44e2c7ab 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -1,6 +1,9 @@ package fj.data; import fj.*; +import fj.function.Try0; +import fj.function.Try1; +import fj.function.Try2; import java.util.Optional; import java.util.function.BiFunction; From c65c1833cf70356aabdbf22ad46f8af52b8e9536 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 14:46:04 +1000 Subject: [PATCH 160/811] Changed name of type parameter for Try0-3 --- core/src/main/java/fj/function/Try0.java | 4 ++-- core/src/main/java/fj/function/Try1.java | 4 ++-- core/src/main/java/fj/function/Try2.java | 4 ++-- core/src/main/java/fj/function/Try3.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/function/Try0.java b/core/src/main/java/fj/function/Try0.java index 32655296..b42cf1b0 100644 --- a/core/src/main/java/fj/function/Try0.java +++ b/core/src/main/java/fj/function/Try0.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface Try0 { +public interface Try0 { - A f() throws E; + A f() throws Z; } diff --git a/core/src/main/java/fj/function/Try1.java b/core/src/main/java/fj/function/Try1.java index 715e4400..36a048cc 100644 --- a/core/src/main/java/fj/function/Try1.java +++ b/core/src/main/java/fj/function/Try1.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface Try1 { +public interface Try1 { - B f(A a) throws E; + B f(A a) throws Z; } diff --git a/core/src/main/java/fj/function/Try2.java b/core/src/main/java/fj/function/Try2.java index 3d0cd5d4..20e9cbfb 100644 --- a/core/src/main/java/fj/function/Try2.java +++ b/core/src/main/java/fj/function/Try2.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface Try2 { +public interface Try2 { - C f(A a, B b) throws E; + C f(A a, B b) throws Z; } diff --git a/core/src/main/java/fj/function/Try3.java b/core/src/main/java/fj/function/Try3.java index fdb9b176..4471906e 100644 --- a/core/src/main/java/fj/function/Try3.java +++ b/core/src/main/java/fj/function/Try3.java @@ -9,8 +9,8 @@ * @version %build.number% */ -public interface Try3 { +public interface Try3 { - D f(A a, B b, C c) throws E; + D f(A a, B b, C c) throws Z; } From 5bd8677c94757a72ef17ada196cce545db733c49 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 15:11:50 +1000 Subject: [PATCH 161/811] Changed Effect to Effect1 and renamed e to f --- core/src/main/java/fj/Effect.java | 27 +++++++++------ .../main/java/fj/control/parallel/Actor.java | 17 +++++----- .../java/fj/control/parallel/ParModule.java | 18 +++++----- .../java/fj/control/parallel/Promise.java | 9 ++--- .../java/fj/control/parallel/Strategy.java | 13 +++---- core/src/main/java/fj/data/Array.java | 5 +-- core/src/main/java/fj/data/Conversions.java | 34 ++++++------------- core/src/main/java/fj/data/Either.java | 10 +++--- core/src/main/java/fj/data/HashMap.java | 3 +- core/src/main/java/fj/data/Java.java | 17 +++++----- core/src/main/java/fj/data/List.java | 5 +-- core/src/main/java/fj/data/NonEmptyList.java | 6 ++-- core/src/main/java/fj/data/Option.java | 5 +-- core/src/main/java/fj/data/Stream.java | 5 +-- core/src/main/java/fj/data/Validation.java | 5 +-- core/src/main/java/fj/test/Arbitrary.java | 10 +++--- core/src/main/java/fj/test/Gen.java | 6 ++-- core/src/main/java/fj/test/Shrink.java | 6 ++-- core/src/main/java/fj/test/reflect/Main.java | 6 ++-- demo/src/main/java/fj/demo/ChequeWrite.java | 5 +-- .../main/java/fj/demo/concurrent/Fibs.java | 6 ++-- .../main/java/fj/demo/concurrent/Ping.java | 5 +-- .../java/fj/demo/concurrent/PingPong.java | 5 +-- .../main/java/fj/demo/concurrent/Pong.java | 5 +-- .../java/fj/demo/concurrent/WordCount.java | 5 +-- .../java/fj/demo/test/ListFunctorLaws.java | 6 ++-- demo/src/main/java/fj/demo/test/Reflect.java | 6 ++-- .../fj/demo/test/StringBuilderReverse.java | 6 ++-- .../src/test/scala/fj/data/CheckHashMap.scala | 5 +-- 29 files changed, 145 insertions(+), 116 deletions(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 46bda819..c72b3134 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -1,5 +1,7 @@ package fj; +import fj.function.Effect1; + import static fj.Unit.unit; /** @@ -7,19 +9,19 @@ * * @version %build.number% */ -public abstract class Effect { - public abstract void e(A a); +public class Effect { + private Effect() {} /** * Returns a function for the given effect. * * @return The function using the given effect. */ - public final F e() { + public static final F f(Effect1 e1) { return new F() { public Unit f(final A a) { - e(a); + e1.f(a); return unit(); } }; @@ -31,19 +33,22 @@ public Unit f(final A a) { * @param f The function to map over the effect. * @return An effect after a contra-variant map. */ - public final Effect comap(final F f) { - return new Effect() { - public void e(final B b) { - Effect.this.e(f.f(b)); + public final Effect1 comap(Effect1 e1, final F f) { + return new Effect1() { + public void f(final B b) { + e1.f(f.f(b)); } }; } - public static Effect f(final F f) { - return new Effect() { - public void e(final A a) { + public static Effect1 f(final F f) { + return new Effect1() { + public void f(final A a) { f.f(a); } }; } + +// public static void f(Effect1 ) + } diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 5cf7f47f..86201147 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -7,6 +7,7 @@ import fj.F; import fj.Unit; import fj.P1; +import fj.function.Effect1; /** * Light weight actors for Java. Concurrency is controlled by a parallel Strategy. @@ -31,8 +32,8 @@ public final class Actor { * With respect to an enqueueing actor or thread, this actor will process messages in the same order * as they are sent. */ - public static Actor queueActor(final Strategy s, final Effect ea) { - return actor(Strategy.seqStrategy(), new Effect() { + public static Actor queueActor(final Strategy s, final Effect1 ea) { + return actor(Strategy.seqStrategy(), new Effect1() { // Lock to ensure the actor only acts on one message at a time AtomicBoolean suspended = new AtomicBoolean(true); @@ -48,7 +49,7 @@ public static Actor queueActor(final Strategy s, final Effect ea T a = mbox.poll(); // if there is one, process it if (a != null) { - ea.e(a); + ea.f(a); // try again, in case there are more messages s.par(this); } else { @@ -62,7 +63,7 @@ public static Actor queueActor(final Strategy s, final Effect ea }; // Effect's body -- queues up a message and tries to unsuspend the actor - @Override public void e(T a) { + @Override public void f(T a) { mbox.offer(a); work(); } @@ -92,8 +93,8 @@ public P1 f(final A a) { * @param e The side-effect to apply to messages passed to the Actor. * @return A new actor that uses the given parallelization strategy and has the given side-effect. */ - public static Actor actor(final Strategy s, final Effect e) { - return new Actor(s, P1.curry(e.e())); + public static Actor actor(final Strategy s, final Effect1 e) { + return new Actor(s, P1.curry(Effect.f(e))); } /** @@ -139,8 +140,8 @@ public P1 f(final B b) { * @return A new actor, equivalent to this actor, that acts on promises. */ public Actor> promise() { - return actor(s, new Effect>() { - public void e(final Promise b) { + return actor(s, new Effect1>() { + public void f(final Promise b) { b.to(Actor.this); } }); diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 4bc6580e..9d04fc7a 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -15,6 +15,8 @@ import fj.data.Tree; import fj.data.TreeZipper; import fj.data.Zipper; +import fj.function.Effect1; + import static fj.data.Option.some; import static fj.data.Stream.iterableStream; @@ -105,7 +107,7 @@ public F2> promise(final F2 f) { * @param e The effect that the actor should have on its messages. * @return A concurrent actor that does not guarantee ordering of its messages. */ - public Actor effect(final Effect e) { + public Actor effect(final Effect1 e) { return Actor.actor(strategy, e); } @@ -115,9 +117,9 @@ public Actor effect(final Effect e) { * * @return A function that takes an effect and returns a concurrent effect. */ - public F, Actor> effect() { - return new F, Actor>() { - public Actor f(final Effect effect) { + public F, Actor> effect() { + return new F, Actor>() { + public Actor f(final Effect1 effect) { return effect(effect); } }; @@ -129,7 +131,7 @@ public Actor f(final Effect effect) { * @param e The effect that the actor should have on its messages. * @return A concurrent actor that is guaranteed to process its messages in order. */ - public Actor actor(final Effect e) { + public Actor actor(final Effect1 e) { return Actor.queueActor(strategy, e); } @@ -138,9 +140,9 @@ public Actor actor(final Effect e) { * * @return A function that takes an effect and returns an actor that processes messages in some order. */ - public F, Actor> actor() { - return new F, Actor>() { - public Actor f(final Effect effect) { + public F, Actor> actor() { + return new F, Actor>() { + public Actor f(final Effect1 effect) { return actor(effect); } }; diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index ce78d6b9..81389e26 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -19,6 +19,7 @@ import static fj.data.Option.none; import static fj.data.Option.some; import fj.data.Stream; +import fj.function.Effect1; import java.util.LinkedList; import java.util.Queue; @@ -50,8 +51,8 @@ private Promise(final Strategy s, final Actor, Actor>, private static Promise mkPromise(final Strategy s) { final Actor, Actor>, Promise>> q = - queueActor(s, new Effect, Actor>, Promise>>() { - public void e(final P2, Actor>, Promise> p) { + queueActor(s, new Effect1, Actor>, Promise>>() { + public void f(final P2, Actor>, Promise> p) { final Promise snd = p._2(); final Queue> as = snd.waiting; if (p._1().isLeft()) { @@ -194,8 +195,8 @@ public static Promise join(final Strategy s, final P1> p */ public Promise bind(final F> f) { final Promise r = mkPromise(s); - final Actor ab = actor(s, new Effect() { - public void e(final B b) { + final Actor ab = actor(s, new Effect1() { + public void f(final B b) { r.actor.act(P.p(Either., Actor>left(P.p(b)), r)); } }); diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index 09680186..daf8098e 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -11,6 +11,7 @@ import fj.data.Java; import fj.data.List; import fj.data.Array; +import fj.function.Effect1; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; @@ -388,9 +389,9 @@ public A _1() { * * @return An effect, which, given a Future, waits for it to obtain a value, discarding the value. */ - public static Effect> discard() { - return new Effect>() { - public void e(final Future a) { + public static Effect1> discard() { + return new Effect1>() { + public void f(final Future a) { Strategy.obtain().f(a)._1(); } }; @@ -505,7 +506,7 @@ public Strategy comap(final F, P1> f) { * @param e The effect that should handle errors. * @return A strategy that captures any runtime errors with a side-effect. */ - public Strategy errorStrategy(final Effect e) { + public Strategy errorStrategy(final Effect1 e) { return errorStrategy(this, e); } @@ -517,7 +518,7 @@ public Strategy errorStrategy(final Effect e) { * @param e The effect that should handle errors. * @return A strategy that captures any runtime errors with a side-effect. */ - public static Strategy errorStrategy(final Strategy s, final Effect e) { + public static Strategy errorStrategy(final Strategy s, final Effect1 e) { return s.comap(new F, P1>() { public P1 f(final P1 a) { return new P1() { @@ -526,7 +527,7 @@ public A _1() { return a._1(); } catch (Throwable t) { final Error error = new Error(t); - e.e(error); + e.f(error); throw error; } } diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index bc29151f..43baa462 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -7,6 +7,7 @@ import fj.P1; import fj.P2; import fj.Unit; +import fj.function.Effect1; import static fj.Function.*; import static fj.P.p; @@ -229,9 +230,9 @@ public Unit foreach(final F f) { * @param f The side-effect to perform for the given element. */ @SuppressWarnings("unchecked") - public void foreach(final Effect f) { + public void foreach(final Effect1 f) { for (final Object x : a) { - f.e((A) x); + f.f((A) x); } } diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 85f28b00..3ae7fed3 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -3,6 +3,8 @@ import fj.Effect; import fj.F; import fj.P1; +import fj.function.Effect1; + import static fj.data.List.asString; import static fj.data.List.fromString; @@ -167,8 +169,8 @@ public Either f(final Array bs) { public static final F, String> Array_String = new F, String>() { public String f(final Array cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach(new Effect() { - public void e(final Character c) { + cs.foreach(new Effect1() { + public void f(final Character c) { sb.append(c); } }); @@ -182,8 +184,8 @@ public void e(final Character c) { public static final F, StringBuffer> Array_StringBuffer = new F, StringBuffer>() { public StringBuffer f(final Array cs) { final StringBuffer sb = new StringBuffer(); - cs.foreach(new Effect() { - public void e(final Character c) { + cs.foreach(new Effect1() { + public void f(final Character c) { sb.append(c); } }); @@ -198,11 +200,7 @@ public void e(final Character c) { new F, StringBuilder>() { public StringBuilder f(final Array cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach(new Effect() { - public void e(final Character c) { - sb.append(c); - } - }); + cs.foreach((Character c) -> sb.append(c)); return sb; } }; @@ -273,11 +271,7 @@ public Either f(final Stream bs) { public static final F, String> Stream_String = new F, String>() { public String f(final Stream cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach(new Effect() { - public void e(final Character c) { - sb.append(c); - } - }); + cs.foreach((Character c) -> sb.append(c)); return sb.toString(); } }; @@ -289,11 +283,7 @@ public void e(final Character c) { new F, StringBuffer>() { public StringBuffer f(final Stream cs) { final StringBuffer sb = new StringBuffer(); - cs.foreach(new Effect() { - public void e(final Character c) { - sb.append(c); - } - }); + cs.foreach((Character c) -> sb.append(c)); return sb; } }; @@ -305,11 +295,7 @@ public void e(final Character c) { new F, StringBuilder>() { public StringBuilder f(final Stream cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach(new Effect() { - public void e(final Character c) { - sb.append(c); - } - }); + cs.foreach((Character c) -> sb.append(c)); return sb; } }; diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 375a796b..f656471d 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -10,6 +10,8 @@ import fj.Function; import fj.P1; import fj.Unit; +import fj.function.Effect1; + import static fj.Unit.unit; import static fj.data.Array.mkArray; import static fj.data.List.single; @@ -230,9 +232,9 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect f) { + public void foreach(final Effect1 f) { if (isLeft()) - f.e(value()); + f.f(value()); } /** @@ -463,9 +465,9 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect f) { + public void foreach(final Effect1 f) { if (isRight()) - f.e(value()); + f.f(value()); } /** diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 4ddaa233..83ab9c79 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -1,6 +1,7 @@ package fj.data; import fj.*; +import fj.function.Effect1; import java.util.Collection; import java.util.Iterator; @@ -290,7 +291,7 @@ public HashMap mapValues(F function) { return map(Function.identity(), function, e, h); } - public void foreach(Effect> effect) { + public void foreach(Effect1> effect) { toStream().foreach(effect); } diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index d0a59b72..dcc83127 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -7,6 +7,7 @@ import fj.Function; import fj.P1; import fj.P2; +import fj.function.Effect1; import static fj.data.List.list; import static fj.data.Option.some; @@ -69,8 +70,8 @@ public ArrayList f(final List as) { public static final F, BitSet> List_BitSet = new F, BitSet>() { public BitSet f(final List bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect>() { - public void e(final P2 bi) { + bs.zipIndex().foreach(new Effect1>() { + public void f(final P2 bi) { s.set(bi._2(), bi._1()); } }); @@ -317,8 +318,8 @@ public ArrayList f(final Array as) { public BitSet f(final Array bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect>() { - public void e(final P2 bi) { + bs.zipIndex().foreach(new Effect1>() { + public void f(final P2 bi) { s.set(bi._2(), bi._1()); } }); @@ -601,8 +602,8 @@ public ArrayList f(final Stream as) { public static final F, BitSet> Stream_BitSet = new F, BitSet>() { public BitSet f(final Stream bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect>() { - public void e(final P2 bi) { + bs.zipIndex().foreach(new Effect1>() { + public void f(final P2 bi) { s.set(bi._2(), bi._1()); } }); @@ -849,8 +850,8 @@ public ArrayList f(final Option as) { public BitSet f(final Option bs) { final BitSet s = new BitSet(bs.length()); - bs.foreach(new Effect() { - public void e(final Boolean b) { + bs.foreach(new Effect1() { + public void f(final Boolean b) { if (b) s.set(0); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index cec4c433..1490d15a 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -33,6 +33,7 @@ import fj.Ordering; import fj.control.Trampoline; +import fj.function.Effect1; import java.util.AbstractCollection; import java.util.Collection; @@ -278,9 +279,9 @@ public final Unit foreach(final F f) { * * @param f The side-effect to perform for the given element. */ - public final void foreach(final Effect f) { + public final void foreach(final Effect1 f) { for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) { - f.e(xs.head()); + f.f(xs.head()); } } diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 9450b918..46241b81 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -3,6 +3,8 @@ import fj.Effect; import fj.F; import fj.F1Functions; +import fj.function.Effect1; + import static fj.data.Option.some; import static fj.data.Option.somes; @@ -88,8 +90,8 @@ public NonEmptyList bind(final F> f) { final NonEmptyList p = f.f(head); b.snoc(p.head); b.append(p.tail); - tail.foreach(new Effect() { - public void e(final A a) { + tail.foreach(new Effect1() { + public void f(final A a) { final NonEmptyList p = f.f(a); b.snoc(p.head); b.append(p.tail); diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 182d303c..4fdbddaa 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -16,6 +16,7 @@ import fj.P8; import fj.Unit; import fj.Show; +import fj.function.Effect1; import static fj.Function.*; import static fj.P.p; @@ -225,9 +226,9 @@ public final Unit foreach(final F f) { * * @param f The side-effect to perform for the given element. */ - public final void foreach(final Effect f) { + public final void foreach(final Effect1 f) { if (isSome()) - f.e(some()); + f.f(some()); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index c903c514..44bac66a 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -15,6 +15,7 @@ import fj.control.parallel.Promise; import fj.control.parallel.Strategy; import fj.Ordering; +import fj.function.Effect1; import java.util.AbstractCollection; import java.util.Collection; @@ -291,9 +292,9 @@ public final Unit foreach(final F f) { * * @param f The side-effect to perform for the given element. */ - public final void foreach(final Effect f) { + public final void foreach(final Effect1 f) { for (Stream xs = this; xs.isNotEmpty(); xs = xs.tail()._1()) - f.e(xs.head()); + f.f(xs.head()); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 903a44e4..274e3665 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -1,6 +1,7 @@ package fj.data; import fj.*; +import fj.function.Effect1; import static fj.Function.curry; import static fj.P.p; @@ -160,7 +161,7 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect f) { + public void foreach(final Effect1 f) { e.right().foreach(f); } @@ -811,7 +812,7 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect f) { + public void foreach(final Effect1 f) { v.toEither().left().foreach(f); } diff --git a/core/src/main/java/fj/test/Arbitrary.java b/core/src/main/java/fj/test/Arbitrary.java index bced5045..4cb7f484 100644 --- a/core/src/main/java/fj/test/Arbitrary.java +++ b/core/src/main/java/fj/test/Arbitrary.java @@ -31,6 +31,8 @@ import fj.data.Option; import static fj.data.Option.some; import fj.data.Stream; +import fj.function.Effect1; + import static fj.data.Stream.range; import static fj.test.Gen.choose; import static fj.test.Gen.elements; @@ -785,8 +787,8 @@ public ArrayList f(final Array a) { arbitrary(arbList(arbBoolean).gen.map(new F, BitSet>() { public BitSet f(final List bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect>() { - public void e(final P2 bi) { + bs.zipIndex().foreach(new Effect1>() { + public void f(final P2 bi) { s.set(bi._2(), bi._1()); } }); @@ -916,8 +918,8 @@ public F, Hashtable> f(final List ks) { public Hashtable f(final List vs) { final Hashtable t = new Hashtable(); - ks.zip(vs).foreach(new Effect>() { - public void e(final P2 kv) { + ks.zip(vs).foreach(new Effect1>() { + public void f(final P2 kv) { t.put(kv._1(), kv._2()); } }); diff --git a/core/src/main/java/fj/test/Gen.java b/core/src/main/java/fj/test/Gen.java index 7a4c8800..2a7b0807 100644 --- a/core/src/main/java/fj/test/Gen.java +++ b/core/src/main/java/fj/test/Gen.java @@ -15,6 +15,8 @@ import static fj.data.List.nil; import static fj.data.List.replicate; import fj.data.Option; +import fj.function.Effect1; + import static fj.Monoid.intAdditionMonoid; import static fj.Ord.intOrd; @@ -155,8 +157,8 @@ public Unit foreach(final Integer i, final Rand r, final F f) { * @param r The random generator to generate the result to apply the side-effect to. * @param f The side-effect to execute on the generated value. */ - public void foreach(final Integer i, final Rand r, final Effect f) { - f.e(this.f.f(i).f(r)); + public void foreach(final Integer i, final Rand r, final Effect1 f) { + f.f(this.f.f(i).f(r)); } /** diff --git a/core/src/main/java/fj/test/Shrink.java b/core/src/main/java/fj/test/Shrink.java index aebdb9cd..4e11e38d 100644 --- a/core/src/main/java/fj/test/Shrink.java +++ b/core/src/main/java/fj/test/Shrink.java @@ -41,6 +41,8 @@ import fj.data.List; import fj.data.Option; import fj.data.Stream; +import fj.function.Effect1; + import static fj.data.Stream.cons; import static fj.data.Stream.iterate; import static fj.data.Stream.nil; @@ -521,8 +523,8 @@ public static Shrink> shrinkHashtable(final Shrink sk, @SuppressWarnings({"UseOfObsoleteCollectionType"}) public Hashtable f(final List> kvs) { final Hashtable h = new Hashtable(); - kvs.foreach(new Effect>() { - public void e(final P2 kv) { + kvs.foreach(new Effect1>() { + public void f(final P2 kv) { h.put(kv._1(), kv._2()); } }); diff --git a/core/src/main/java/fj/test/reflect/Main.java b/core/src/main/java/fj/test/reflect/Main.java index f77f788c..154d1430 100644 --- a/core/src/main/java/fj/test/reflect/Main.java +++ b/core/src/main/java/fj/test/reflect/Main.java @@ -3,6 +3,8 @@ import fj.Effect; import fj.P2; import static fj.data.Array.array; + +import fj.function.Effect1; import fj.test.CheckResult; import static fj.test.CheckResult.summary; import static fj.test.reflect.Check.check; @@ -35,8 +37,8 @@ public static void main(final String... args) { exit(441); } else { try { - check(forName(args[0]), array(args).toList().tail()).foreach(new Effect>() { - public void e(final P2 r) { + check(forName(args[0]), array(args).toList().tail()).foreach(new Effect1>() { + public void f(final P2 r) { summary.print(r._2()); out.println(" (" + r._1() + ')'); } diff --git a/demo/src/main/java/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java index 78c6737a..9d4af8e4 100644 --- a/demo/src/main/java/fj/demo/ChequeWrite.java +++ b/demo/src/main/java/fj/demo/ChequeWrite.java @@ -8,6 +8,7 @@ import fj.data.Option; import fj.data.Stream; import fj.function.Characters; +import fj.function.Effect1; import static fj.Equal.charEqual; import static fj.Equal.listEqual; @@ -124,8 +125,8 @@ public List f(final List cs) { final List, Integer>> k = split(cs); final int c = k.head()._2(); - k.foreach(new Effect, Integer>>() { - public void e(final P2, Integer> z) { + k.foreach(new Effect1, Integer>>() { + public void f(final P2, Integer> z) { final List w = z._1(); final int i = z._2(); diff --git a/demo/src/main/java/fj/demo/concurrent/Fibs.java b/demo/src/main/java/fj/demo/concurrent/Fibs.java index 018f92a5..b3aae799 100644 --- a/demo/src/main/java/fj/demo/concurrent/Fibs.java +++ b/demo/src/main/java/fj/demo/concurrent/Fibs.java @@ -10,6 +10,8 @@ import fj.control.parallel.Actor; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; +import fj.function.Effect1; + import static fj.data.List.range; import static fj.function.Integers.add; import static fj.control.parallel.Promise.join; @@ -38,8 +40,8 @@ public static void main(final String[] args) final Strategy> spi = Strategy.executorStrategy(pool); // This actor performs output and detects the termination condition. - final Actor> out = actor(su, new Effect>() - {public void e(final List fs) + final Actor> out = actor(su, new Effect1>() + {public void f(final List fs) {for (final P2 p : fs.zipIndex()) {System.out.println(MessageFormat.format("n={0} => {1}", p._2(), p._1()));} pool.shutdown();}}); diff --git a/demo/src/main/java/fj/demo/concurrent/Ping.java b/demo/src/main/java/fj/demo/concurrent/Ping.java index 3d94a8cf..82aad6b3 100644 --- a/demo/src/main/java/fj/demo/concurrent/Ping.java +++ b/demo/src/main/java/fj/demo/concurrent/Ping.java @@ -6,6 +6,7 @@ import fj.control.parallel.Actor; import static fj.control.parallel.Actor.actor; import fj.control.parallel.Strategy; +import fj.function.Effect1; /** * Pings a Pong actor a given number of times, one at a time, and calls back with its ID when done. @@ -21,8 +22,8 @@ public Ping(final Strategy s, final int i, final Pong pong, final int id, n = i; this.pong = pong; cb = callback; - ping = actor(s, new Effect() { - public void e(final Pong pong) { + ping = actor(s, new Effect1() { + public void f(final Pong pong) { n--; if (n > 0) pong.act(Ping.this); diff --git a/demo/src/main/java/fj/demo/concurrent/PingPong.java b/demo/src/main/java/fj/demo/concurrent/PingPong.java index ace3e036..59038679 100644 --- a/demo/src/main/java/fj/demo/concurrent/PingPong.java +++ b/demo/src/main/java/fj/demo/concurrent/PingPong.java @@ -5,6 +5,7 @@ import fj.Effect; import fj.control.parallel.Strategy; import fj.control.parallel.Actor; +import fj.function.Effect1; import java.text.MessageFormat; import java.util.concurrent.ExecutorService; @@ -30,8 +31,8 @@ public PingPong(final ExecutorService pool, final int actors, final int pings) { // This actor gives feedback to the user that work is being done // and also terminates the program when all work has been completed. - callback = Actor.queueActor(s, new Effect() { - public void e(final Integer i) { + callback = Actor.queueActor(s, new Effect1() { + public void f(final Integer i) { done++; if (done >= actors) { System.out.println("All done."); diff --git a/demo/src/main/java/fj/demo/concurrent/Pong.java b/demo/src/main/java/fj/demo/concurrent/Pong.java index 7cd792aa..d85eda7e 100644 --- a/demo/src/main/java/fj/demo/concurrent/Pong.java +++ b/demo/src/main/java/fj/demo/concurrent/Pong.java @@ -6,6 +6,7 @@ import fj.control.parallel.Actor; import static fj.control.parallel.Actor.actor; import fj.control.parallel.Strategy; +import fj.function.Effect1; /** * Receives Ping messages concurrently and responds with a Pong message. @@ -15,8 +16,8 @@ public class Pong { private final Actor p; public Pong(final Strategy s) { - p = actor(s, new Effect() { - public void e(final Ping m) { + p = actor(s, new Effect1() { + public void f(final Ping m) { m.act(Pong.this); } }); diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 124c05c7..145291b5 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -32,6 +32,7 @@ import fj.data.*; import fj.data.Iteratee.Input; import fj.data.Iteratee.IterV; +import fj.function.Effect1; /** * Reads words and their counts from files ({@link #getWordsAndCountsFromFiles} in a single thread @@ -312,9 +313,9 @@ public Long f(Long a, String file) { assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); // we have tmpfiles, but still want to be sure not to leave rubbish - fileNames.foreach(new Effect() { + fileNames.foreach(new Effect1() { @Override - public void e(final String a) { + public void f(final String a) { new File(a).delete(); }}); } diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index 418a5c2c..f1cd7fd5 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -14,6 +14,8 @@ import static fj.test.Arbitrary.arbList; import static fj.test.Arbitrary.arbLong; import static fj.test.Arbitrary.arbString; + +import fj.function.Effect1; import fj.test.CheckResult; import static fj.test.CheckResult.summary; import static fj.test.Coarbitrary.coarbInteger; @@ -59,8 +61,8 @@ public Property f(final F f, final F g, final Li // composition: OK, passed 1000 tests. @SuppressWarnings("unchecked") public static void main(final String[] args) { - check(ListFunctorLaws.class).foreach(new Effect>() { - public void e(final P2 r) { + check(ListFunctorLaws.class).foreach(new Effect1>() { + public void f(final P2 r) { System.out.print(r._1() + ": "); summary.println(r._2()); } diff --git a/demo/src/main/java/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java index 92f0de33..ed4db48c 100644 --- a/demo/src/main/java/fj/demo/test/Reflect.java +++ b/demo/src/main/java/fj/demo/test/Reflect.java @@ -13,6 +13,8 @@ import static fj.test.Arbitrary.arbIntegerBoundaries; import static fj.test.Arbitrary.arbStringBuilder; import static fj.test.Bool.bool; + +import fj.function.Effect1; import fj.test.CheckResult; import static fj.test.CheckResult.summary; import fj.test.Property; @@ -142,8 +144,8 @@ public static void main(final String[] args) { } private static void printResults(final List> results) { - results.foreach(new Effect>() { - public void e(final P2 result) { + results.foreach(new Effect1>() { + public void f(final P2 result) { summary.print(result._2()); out.println(" (" + result._1() + ')'); } diff --git a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java index 88932864..14e0553b 100644 --- a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java +++ b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java @@ -8,6 +8,8 @@ import static fj.test.Arbitrary.arbCharacter; import static fj.test.Arbitrary.arbStringBuilder; import static fj.test.CheckResult.summary; + +import fj.function.Effect1; import fj.test.Property; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -45,8 +47,8 @@ public Property f(final StringBuilder x, final StringBuilder y) { //OK, passed 100 tests. //OK, passed 100 tests. //OK, passed 100 tests. - list(p1, p2, p3).foreach(new Effect() { - public void e(final Property p) { + list(p1, p2, p3).foreach(new Effect1() { + public void f(final Property p) { summary.println(p.check()); } }); diff --git a/tests/src/test/scala/fj/data/CheckHashMap.scala b/tests/src/test/scala/fj/data/CheckHashMap.scala index 40a8a498..4a7646d1 100755 --- a/tests/src/test/scala/fj/data/CheckHashMap.scala +++ b/tests/src/test/scala/fj/data/CheckHashMap.scala @@ -1,6 +1,7 @@ package fj package data +import fj.function.Effect1 import org.scalacheck.Prop._ import ArbitraryHashMap._ import Equal._ @@ -106,8 +107,8 @@ object CheckHashMap extends Properties("HashMap") { property("No null values") = forAll((m: List[Int]) => { val map = HashMap.hashMap[Int, Int]() - m.foreach(new Effect[Int] { - def e(a: Int) { + m.foreach(new Effect1[Int] { + def f(a: Int) { map.set(a, null.asInstanceOf[Int]) } }) From 8ed2662ad0f9b11aab6ba6d2a21daf63926c4c00 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 15:49:05 +1000 Subject: [PATCH 162/811] Accumulate validation errors in a list --- core/src/main/java/fj/data/Validation.java | 125 ++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 274e3665..f71afb13 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -728,6 +728,121 @@ public Iterator iterator() { return toEither().right().iterator(); } + + public Validation, T> accumulate() { + if (isFail()) { + return Validation.fail(List.single(fail())); + } else { + return Validation.success(success()); + } + } + + public Validation, B> accumulate(F f) { + if (isFail()) { + return Validation.fail(List.single(fail())); + } else { + return Validation.success(f.f(success())); + } + } + + + public Validation, C> accumulate(Validation v2, F2 f) { + List list = List.nil(); + if (isFail()) { + list = list.cons(fail()); + } + if (v2.isFail()) { + list = list.cons(v2.fail()); + } + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success())); + } + } + + + + public Validation, D> accumulate(Validation v2, Validation v3, F3 f) { + List list = fails(List.list(this, v2, v3)); + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success(), v3.success())); + } + } + + public Validation, E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { + List list = fails(List.list(this, v2, v3, v4)); + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success())); + } + } + + public Validation, $F> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, F5 f) { + List list = fails(List.list(this, v2, v3, v4, v5)); + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success())); + } + } + + + public Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { + List list = fails(List.list(this, v2, v3, v4, v5)); + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success())); + } + } + + public Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { + List list = fails(List.list(this, v2, v3, v4, v5)); + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success(), v7.success())); + } + } + + public Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { + List list = fails(List.list(this, v2, v3, v4, v5)); + if (!list.isEmpty()) { + return Validation.fail(list); + } else { + return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success(), v7.success(), v8.success())); + } + } + + + + public static Validation, List> sequence(List> list) { + F2, Validation, List>, Validation, List>> f2 = (v, acc) -> { + if (acc.isFail() && v.isFail()) { + return Validation.validation(acc.toEither().left().map(l -> l.cons(v.fail()))); + } else if (acc.isSuccess() && v.isSuccess()) { + return acc.map(l -> l.cons(v.success())); + } else { + return acc; + } + }; + return list.foldRight(f2, Validation.success(List.nil())); + } + + + + public static List fails(List> list) { + return list.filter(v -> v.isFail()).map(v -> v.fail()); + } + + public static List successes(List> list) { + return list.filter(v -> v.isSuccess()).map(v -> v.success()); + } + /** * A failing projection of a validation. */ @@ -850,7 +965,12 @@ public Validation f(final E e) { }); } - /** + + + + + + /** * Returns None if this is a success or if the given predicate p does not hold for the * failing value, otherwise, returns a fail in Some. * @@ -1179,4 +1299,7 @@ public String toString() { return Show.validationShow(Show.anyShow(), Show.anyShow()).showS(this); } + + + } From 64ad2e907eee334c078ee95a163db9254a014cfb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 Aug 2014 16:19:56 +1000 Subject: [PATCH 163/811] Added conversion functions between types --- core/src/main/java/fj/data/Conversions.java | 54 ++++++++++++++++++++- java8/src/main/java/fj/data/Java8.java | 13 +++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 3ae7fed3..ce611493 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -1,10 +1,13 @@ package fj.data; -import fj.Effect; import fj.F; +import fj.P; import fj.P1; +import fj.Unit; +import fj.function.Effect0; import fj.function.Effect1; +import static fj.Unit.unit; import static fj.data.List.asString; import static fj.data.List.fromString; @@ -391,6 +394,43 @@ public StringBuilder f(final Option o) { // END Option -> + // BEGIN Effect + + public static F> Effect0_P1() { + return e -> Effect0_P1(e); + } + + public static P1 Effect0_P1(Effect0 e) { + return P.lazy(u -> { + e.f(); + return unit(); + }); + } + + public static IO Effect_IO(Effect0 e) { + return () ->{ + e.f(); + return Unit.unit(); + }; + } + + public static F> Effect_IO() { + return e -> Effect_IO(e); + } + + public static SafeIO Effect_SafeIO(Effect0 e) { + return () -> { + e.f(); + return unit(); + }; + } + + public static F> Effect_SafeIO() { + return e -> Effect_SafeIO(e); + } + + // END Effect + // BEGIN Either -> /** @@ -577,6 +617,18 @@ public StringBuilder f(final Either e) { // END Either -> + // BEGIN F + + public static SafeIO F_SafeIO(F f) { + return () -> f.f(unit()); + } + + public static F, SafeIO> F_SafeIO() { + return f -> F_SafeIO(f); + } + + // END F + // BEGIN String -> /** diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 44e2c7ab..f1e7db4e 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -7,6 +7,7 @@ import java.util.Optional; import java.util.function.BiFunction; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -107,4 +108,16 @@ static public F, Optional> Option_Optional() { return o -> o.isSome() ? Optional.ofNullable(o.some()) : Optional.empty(); } + static public F, F> Consumer_F() { + return c -> Consumer_F(c); + } + + public static F Consumer_F(Consumer c) { + return a -> { + c.accept(a); + return Unit.unit(); + }; + } + + } From 9d196970277296550e3f96c64f7a0d7ba64ad490 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 29 Aug 2014 08:46:09 +1000 Subject: [PATCH 164/811] Renamed List.foreach to foreachDoEffect to support lambdas --- core/src/main/java/fj/data/Java.java | 9 ++++---- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/NonEmptyList.java | 13 +++++------ core/src/main/java/fj/test/Arbitrary.java | 17 +++++++------- core/src/main/java/fj/test/Shrink.java | 8 +------ core/src/main/java/fj/test/reflect/Main.java | 11 ++++----- demo/src/main/java/fj/demo/ChequeWrite.java | 23 +++++++++---------- .../java/fj/demo/concurrent/WordCount.java | 12 +++++----- .../java/fj/demo/test/ListFunctorLaws.java | 11 ++++----- demo/src/main/java/fj/demo/test/Reflect.java | 12 +++++----- .../fj/demo/test/StringBuilderReverse.java | 9 ++++---- .../src/test/scala/fj/data/CheckHashMap.scala | 2 +- 12 files changed, 58 insertions(+), 71 deletions(-) diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index dcc83127..b75c7c94 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1,6 +1,5 @@ package fj.data; -import fj.Effect; import fj.F; import static fj.P.p; @@ -70,10 +69,10 @@ public ArrayList f(final List as) { public static final F, BitSet> List_BitSet = new F, BitSet>() { public BitSet f(final List bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect1>() { - public void f(final P2 bi) { - s.set(bi._2(), bi._1()); - } + bs.zipIndex().foreachDoEffect(new Effect1>() { + public void f(final P2 bi) { + s.set(bi._2(), bi._1()); + } }); return s; } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 1490d15a..a957bc5d 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -279,7 +279,7 @@ public final Unit foreach(final F f) { * * @param f The side-effect to perform for the given element. */ - public final void foreach(final Effect1 f) { + public final void foreachDoEffect(final Effect1 f) { for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) { f.f(xs.head()); } diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 46241b81..1c14c535 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -1,6 +1,5 @@ package fj.data; -import fj.Effect; import fj.F; import fj.F1Functions; import fj.function.Effect1; @@ -90,12 +89,12 @@ public NonEmptyList bind(final F> f) { final NonEmptyList p = f.f(head); b.snoc(p.head); b.append(p.tail); - tail.foreach(new Effect1() { - public void f(final A a) { - final NonEmptyList p = f.f(a); - b.snoc(p.head); - b.append(p.tail); - } + tail.foreachDoEffect(new Effect1() { + public void f(final A a) { + final NonEmptyList p = f.f(a); + b.snoc(p.head); + b.append(p.tail); + } }); final List bb = b.toList(); return nel(bb.head(), bb.tail()); diff --git a/core/src/main/java/fj/test/Arbitrary.java b/core/src/main/java/fj/test/Arbitrary.java index 4cb7f484..e50a3d78 100644 --- a/core/src/main/java/fj/test/Arbitrary.java +++ b/core/src/main/java/fj/test/Arbitrary.java @@ -1,6 +1,5 @@ package fj.test; -import fj.Effect; import fj.F; import fj.F2; import fj.F3; @@ -787,10 +786,10 @@ public ArrayList f(final Array a) { arbitrary(arbList(arbBoolean).gen.map(new F, BitSet>() { public BitSet f(final List bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect1>() { - public void f(final P2 bi) { - s.set(bi._2(), bi._1()); - } + bs.zipIndex().foreachDoEffect(new Effect1>() { + public void f(final P2 bi) { + s.set(bi._2(), bi._1()); + } }); return s; } @@ -918,10 +917,10 @@ public F, Hashtable> f(final List ks) { public Hashtable f(final List vs) { final Hashtable t = new Hashtable(); - ks.zip(vs).foreach(new Effect1>() { - public void f(final P2 kv) { - t.put(kv._1(), kv._2()); - } + ks.zip(vs).foreachDoEffect(new Effect1>() { + public void f(final P2 kv) { + t.put(kv._1(), kv._2()); + } }); return t; diff --git a/core/src/main/java/fj/test/Shrink.java b/core/src/main/java/fj/test/Shrink.java index 4e11e38d..8f43d181 100644 --- a/core/src/main/java/fj/test/Shrink.java +++ b/core/src/main/java/fj/test/Shrink.java @@ -1,6 +1,5 @@ package fj.test; -import fj.Effect; import fj.F; import static fj.P.p; import static fj.P.p2; @@ -41,7 +40,6 @@ import fj.data.List; import fj.data.Option; import fj.data.Stream; -import fj.function.Effect1; import static fj.data.Stream.cons; import static fj.data.Stream.iterate; @@ -523,11 +521,7 @@ public static Shrink> shrinkHashtable(final Shrink sk, @SuppressWarnings({"UseOfObsoleteCollectionType"}) public Hashtable f(final List> kvs) { final Hashtable h = new Hashtable(); - kvs.foreach(new Effect1>() { - public void f(final P2 kv) { - h.put(kv._1(), kv._2()); - } - }); + kvs.foreachDoEffect(kv -> h.put(kv._1(), kv._2())); return h; } }, new F, List>>() { diff --git a/core/src/main/java/fj/test/reflect/Main.java b/core/src/main/java/fj/test/reflect/Main.java index 154d1430..a7e8be3c 100644 --- a/core/src/main/java/fj/test/reflect/Main.java +++ b/core/src/main/java/fj/test/reflect/Main.java @@ -1,6 +1,5 @@ package fj.test.reflect; -import fj.Effect; import fj.P2; import static fj.data.Array.array; @@ -37,11 +36,11 @@ public static void main(final String... args) { exit(441); } else { try { - check(forName(args[0]), array(args).toList().tail()).foreach(new Effect1>() { - public void f(final P2 r) { - summary.print(r._2()); - out.println(" (" + r._1() + ')'); - } + check(forName(args[0]), array(args).toList().tail()).foreachDoEffect(new Effect1>() { + public void f(final P2 r) { + summary.print(r._2()); + out.println(" (" + r._1() + ')'); + } }); } catch(ClassNotFoundException e) { System.err.println(e); diff --git a/demo/src/main/java/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java index 9d4af8e4..e95950f8 100644 --- a/demo/src/main/java/fj/demo/ChequeWrite.java +++ b/demo/src/main/java/fj/demo/ChequeWrite.java @@ -1,6 +1,5 @@ package fj.demo; -import fj.Effect; import fj.F; import fj.F2; import fj.P2; @@ -125,20 +124,20 @@ public List f(final List cs) { final List, Integer>> k = split(cs); final int c = k.head()._2(); - k.foreach(new Effect1, Integer>>() { - public void f(final P2, Integer> z) { - final List w = z._1(); - final int i = z._2(); + k.foreachDoEffect(new Effect1, Integer>>() { + public void f(final P2, Integer> z) { + final List w = z._1(); + final int i = z._2(); - if (i == 0 && c > 0 && and(w)) - x.snoc(fromString("and")); + if (i == 0 && c > 0 && and(w)) + x.snoc(fromString("and")); - if (existsNotZero(w)) { - x.snoc(show(w)); - if (i != 0) - x.snoc(illion(i - 1)); + if (existsNotZero(w)) { + x.snoc(show(w)); + if (i != 0) + x.snoc(illion(i - 1)); + } } - } }); x.snoc(fromString(eq(cs, list('1')) ? "dollar" : "dollars")); diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 145291b5..277ca9dc 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -18,7 +18,6 @@ import java.util.Map; import java.util.concurrent.ExecutorService; -import fj.Effect; import fj.F; import fj.F2; import fj.Monoid; @@ -313,11 +312,12 @@ public Long f(Long a, String file) { assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); // we have tmpfiles, but still want to be sure not to leave rubbish - fileNames.foreach(new Effect1() { - @Override - public void f(final String a) { - new File(a).delete(); - }}); + fileNames.foreachDoEffect(new Effect1() { + @Override + public void f(final String a) { + new File(a).delete(); + } + }); } @SuppressWarnings("unused") diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index f1cd7fd5..edf94ed8 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -1,6 +1,5 @@ package fj.demo.test; -import fj.Effect; import fj.F; import fj.F3; import fj.Function; @@ -61,11 +60,11 @@ public Property f(final F f, final F g, final Li // composition: OK, passed 1000 tests. @SuppressWarnings("unchecked") public static void main(final String[] args) { - check(ListFunctorLaws.class).foreach(new Effect1>() { - public void f(final P2 r) { - System.out.print(r._1() + ": "); - summary.println(r._2()); - } + check(ListFunctorLaws.class).foreachDoEffect(new Effect1>() { + public void f(final P2 r) { + System.out.print(r._1() + ": "); + summary.println(r._2()); + } }); } } diff --git a/demo/src/main/java/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java index ed4db48c..f83b8ce8 100644 --- a/demo/src/main/java/fj/demo/test/Reflect.java +++ b/demo/src/main/java/fj/demo/test/Reflect.java @@ -1,7 +1,7 @@ package fj.demo.test; import static fj.Bottom.error; -import fj.Effect; + import fj.F; import fj.F2; import fj.P2; @@ -144,11 +144,11 @@ public static void main(final String[] args) { } private static void printResults(final List> results) { - results.foreach(new Effect1>() { - public void f(final P2 result) { - summary.print(result._2()); - out.println(" (" + result._1() + ')'); - } + results.foreachDoEffect(new Effect1>() { + public void f(final P2 result) { + summary.print(result._2()); + out.println(" (" + result._1() + ')'); + } }); out.println("--------------------------------------------------------------------------------"); } diff --git a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java index 14e0553b..b5155739 100644 --- a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java +++ b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java @@ -1,6 +1,5 @@ package fj.demo.test; -import fj.Effect; import fj.F; import fj.F2; import static fj.data.List.list; @@ -47,10 +46,10 @@ public Property f(final StringBuilder x, final StringBuilder y) { //OK, passed 100 tests. //OK, passed 100 tests. //OK, passed 100 tests. - list(p1, p2, p3).foreach(new Effect1() { - public void f(final Property p) { - summary.println(p.check()); - } + list(p1, p2, p3).foreachDoEffect(new Effect1() { + public void f(final Property p) { + summary.println(p.check()); + } }); } } diff --git a/tests/src/test/scala/fj/data/CheckHashMap.scala b/tests/src/test/scala/fj/data/CheckHashMap.scala index 4a7646d1..ecf09174 100755 --- a/tests/src/test/scala/fj/data/CheckHashMap.scala +++ b/tests/src/test/scala/fj/data/CheckHashMap.scala @@ -107,7 +107,7 @@ object CheckHashMap extends Properties("HashMap") { property("No null values") = forAll((m: List[Int]) => { val map = HashMap.hashMap[Int, Int]() - m.foreach(new Effect1[Int] { + m.foreachDoEffect(new Effect1[Int] { def f(a: Int) { map.set(a, null.asInstanceOf[Int]) } From 5d93466a911a6fc3dc0d07c5a9597150211616d9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 29 Aug 2014 10:35:36 +1000 Subject: [PATCH 165/811] Added conversion from Effects, Trys and TryEffects back to ordinary functions --- core/src/main/java/fj/Effect.java | 65 ++++++++++- core/src/main/java/fj/P1.java | 2 +- core/src/main/java/fj/TryEffect.java | 118 ++++++++++++++++++++ core/src/main/java/fj/data/Conversions.java | 61 +++++++++- 4 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 core/src/main/java/fj/TryEffect.java diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index c72b3134..31d9b901 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -1,6 +1,14 @@ package fj; +import fj.function.Effect0; import fj.function.Effect1; +import fj.function.Effect2; +import fj.function.Effect3; +import fj.function.Effect4; +import fj.function.Effect5; +import fj.function.Effect6; +import fj.function.Effect7; +import fj.function.Effect8; import static fj.Unit.unit; @@ -13,7 +21,11 @@ public class Effect { private Effect() {} - /** + public static P1 f(Effect0 e) { + return P.lazy(u -> unit()); + } + + /** * Returns a function for the given effect. * * @return The function using the given effect. @@ -27,7 +39,56 @@ public Unit f(final A a) { }; } - /** + public static F2 f(Effect2 e) { + return (a, b) -> { + e.f(a, b); + return unit(); + }; + } + + public static F3 f(Effect3 e) { + return (a, b, c) -> { + e.f(a, b, c); + return unit(); + }; + } + + public static F4 f(Effect4 e) { + return (a, b, c, d) -> { + e.f(a, b, c, d); + return unit(); + }; + } + + public static F5 f(Effect5 z) { + return (a, b, c, d, e) -> { + z.f(a, b, c, d, e); + return unit(); + }; + } + + public static F6 f(Effect6 z) { + return (a, b, c, d, e, f) -> { + z.f(a, b, c, d, e, f); + return unit(); + }; + } + + public static F7 f(Effect7 z) { + return (a, b, c, d, e, f, g) -> { + z.f(a, b, c, d, e, f, g); + return unit(); + }; + } + + public static F8 f(Effect8 z) { + return (a, b, c, d, e, f, g, h) -> { + z.f(a, b, c, d, e, f, g, h); + return unit(); + }; + } + + /** * A contra-variant functor on effect. * * @param f The function to map over the effect. diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 88469138..ecd6e393 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -248,7 +248,7 @@ static public P1> toP1(final Try0anyShow()).showS(this); } } diff --git a/core/src/main/java/fj/TryEffect.java b/core/src/main/java/fj/TryEffect.java new file mode 100644 index 00000000..7db7ee11 --- /dev/null +++ b/core/src/main/java/fj/TryEffect.java @@ -0,0 +1,118 @@ +package fj; + +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.Validation; +import fj.function.*; + +import java.io.IOException; + +/** + * Created by mperry on 29/08/2014. + */ +public class TryEffect { + + private TryEffect(){} + + public static P1> f(TryEffect0 t) { + return P.lazy(u -> { + try { + t.f(); + return Validation.success(Unit.unit()); + } catch (Exception e) { + return Validation.fail((Z) e); + } + }); + } + + public static F> f(TryEffect1 t) { + return a -> { + try { + t.f(a); + return Validation.success(Unit.unit()); + } catch (Exception e) { + return Validation.fail((Z) e); + } + }; + + } + + public static F2> f(TryEffect2 t) { + return (a, b) -> { + try { + t.f(a, b); + return Validation.success(Unit.unit()); + } catch (Exception e) { + return Validation.fail((Z) e); + } + }; + + } + + public static F3> f(TryEffect3 t) { + return (a, b, c) -> { + try { + t.f(a, b, c); + return Validation.success(Unit.unit()); + } catch (Exception e) { + return Validation.fail((Z) e); + } + }; + } + + public static F4> f(TryEffect4 t) { + return (a, b, c, d) -> { + try { + t.f(a, b, c, d); + return Validation.success(Unit.unit()); + } catch (Exception e) { + return Validation.fail((Z) e); + } + }; + } + + public static F5> f(TryEffect5 t) { + return (a, b, c, d, e) -> { + try { + t.f(a, b, c, d, e); + return Validation.success(Unit.unit()); + } catch (Exception z) { + return Validation.fail((Z) z); + } + }; + } + + public static F6> f(TryEffect6 t) { + return (a, b, c, d, e, f) -> { + try { + t.f(a, b, c, d, e, f); + return Validation.success(Unit.unit()); + } catch (Exception z) { + return Validation.fail((Z) z); + } + }; + } + + public static F7> f(TryEffect7 t) { + return (a, b, c, d, e, f, g) -> { + try { + t.f(a, b, c, d, e, f, g); + return Validation.success(Unit.unit()); + } catch (Exception z) { + return Validation.fail((Z) z); + } + }; + } + + public static F8> f(TryEffect8 t) { + return (a, b, c, d, e, f, g, h) -> { + try { + t.f(a, b, c, d, e, f, g, h); + return Validation.success(Unit.unit()); + } catch (Exception z) { + return Validation.fail((Z) z); + } + }; + } + +} diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index ce611493..2b4a51ca 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -1,12 +1,19 @@ package fj.data; import fj.F; -import fj.P; import fj.P1; import fj.Unit; +import fj.function.TryEffect0; import fj.function.Effect0; import fj.function.Effect1; +import fj.Try; +import fj.TryEffect; +import fj.Effect; +import fj.function.Try0; +import fj.function.Try1; + +import java.io.IOException; import static fj.Unit.unit; import static fj.data.List.asString; import static fj.data.List.fromString; @@ -401,10 +408,15 @@ public static F> Effect0_P1() { } public static P1 Effect0_P1(Effect0 e) { - return P.lazy(u -> { - e.f(); - return unit(); - }); + return Effect.f(e); + } + + public static F Effect1_F(Effect1 e) { + return Effect.f(e); + } + + public static F, F> Effect1_F() { + return e -> Effect1_F(e); } public static IO Effect_IO(Effect0 e) { @@ -858,4 +870,43 @@ public StringBuffer f(final StringBuilder s) { }; // END StringBuilder -> + + + // BEGIN Try + + public static SafeIO> Try_SafeIO(Try0 t) { + return F_SafeIO(u -> Try.f(t)._1()); + } + + public static F, SafeIO>> Try_SafeIO() { + return t -> Try_SafeIO(t); + } + + public static IO Try_IO(Try0 t) { + return () -> t.f(); + } + + public static F, IO> Try_IO() { + return t -> Try_IO(t); + } + + public static F> Try_F(Try1 t) { + return Try.f(t); + } + + public static F, F>> Try_F() { + return t -> Try_F(t); + } + + // END Try + + // BEGIN TryEffect + + static public P1> TryEffect_P(final TryEffect0 t) { + return TryEffect.f(t); + } + + + // END TryEffect + } From 62977fcc4d88bc014fa4afaf6bc4197b3d7247e0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 29 Aug 2014 17:57:30 +1000 Subject: [PATCH 166/811] Moved Try type conversions to Try --- core/src/main/java/fj/Effect.java | 4 +- core/src/main/java/fj/F1Functions.java | 16 --- core/src/main/java/fj/F2Functions.java | 17 --- core/src/main/java/fj/F3Functions.java | 15 -- core/src/main/java/fj/F4Functions.java | 17 --- core/src/main/java/fj/F5Functions.java | 16 --- core/src/main/java/fj/F6Functions.java | 17 --- core/src/main/java/fj/F7Functions.java | 16 --- core/src/main/java/fj/F8Functions.java | 16 --- core/src/main/java/fj/P1.java | 16 --- core/src/main/java/fj/Try.java | 147 +++++++++++++++++--- core/src/main/java/fj/data/IOFunctions.java | 2 +- java8/src/main/java/fj/data/Java8.java | 6 +- 13 files changed, 134 insertions(+), 171 deletions(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 31d9b901..b3203b6c 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -31,11 +31,9 @@ public static P1 f(Effect0 e) { * @return The function using the given effect. */ public static final F f(Effect1 e1) { - return new F() { - public Unit f(final A a) { + return a -> { e1.f(a); return unit(); - } }; } diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index d4a1cfb8..b0e84f00 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -835,22 +835,6 @@ static public ArrayList mapJ(final F f, final ArrayList as) { return new ArrayList(iterableStream(as).map(f).toCollection()); } - /** - * Promotes the TryCatch1 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch1 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F> toF1(final Try1 t) { - return a -> { - try { - return Validation.success(t.f(a)); - } catch (Exception e) { - return Validation.fail((E) e); - } - }; - } - static public F map(F target, F f) { return andThen(target, f); } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index e164404f..fda0421b 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -347,23 +347,6 @@ public P3>, C, Stream>> f(final P3>, A, St }; } - - /** - * Promotes the TryCatch2 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch2 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F2> toF2(final Try2 t) { - return (a, b) -> { - try { - return Validation.success(t.f(a, b)); - } catch (Exception e) { - return Validation.fail((E) e); - } - }; - } - static public F2 contramapFirst(F2 target, F f) { return (z, b) -> target.f(f.f(z), b); } diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 938ccf2f..62d91aee 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -11,21 +11,6 @@ */ public class F3Functions { - /** - * Promotes the TryCatch3 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch3 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F3> toF3(final Try3 t) { - return (a, b, c) -> { - try { - return success(t.f(a, b, c)); - } catch (Exception e) { - return fail((E) e); - } - }; - } /** * Partial application. diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index e82f1fd9..71ee56a3 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -8,23 +8,6 @@ */ public class F4Functions { - - /** - * Promotes the TryCatch4 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch4 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F4> toF4(final Try4 t) { - return (a, b, c, d) -> { - try { - return Validation.success(t.f(a, b, c, d)); - } catch (Exception ex) { - return Validation.fail((Z) ex); - } - }; - } - /** * Partial application. * diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index b5e3155c..8cb26c6d 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -8,22 +8,6 @@ */ public class F5Functions { - /** - * Promotes the TryCatch5 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch5 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F5> toF5(final Try5 t) { - return (a, b, c, d, e) -> { - try { - return Validation.success(t.f(a, b, c, d, e)); - } catch (Exception ex) { - return Validation.fail((Z) ex); - } - }; - } - /** * Partial application. * diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 238bcfc5..70458593 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -8,23 +8,6 @@ */ public class F6Functions { - /** - * Promotes the TryCatch6 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch6 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F6> toF6(final Try6 t) { - return (a, b, c, d, e, f) -> { - try { - return Validation.success(t.f(a, b, c, d, e, f)); - } catch (Exception ex) { - return Validation.fail((Z) ex); - } - }; - } - - /** * Partial application. * diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 743fa608..a6ceff9f 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -8,22 +8,6 @@ */ public class F7Functions { - /** - * Promotes the TryCatch7 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch7 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F7> toF7(final Try7 t) { - return (a, b, c, d, e, f, g) -> { - try { - return Validation.success(t.f(a, b, c, d, e, f, g)); - } catch (Exception ex) { - return Validation.fail((Z) ex); - } - }; - } - /** * Partial application. * diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index a1bf2217..788f106d 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -8,22 +8,6 @@ */ public class F8Functions { - /** - * Promotes the TryCatch8 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch8 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public F8> toF8(final Try8 t) { - return (a, b, c, d, e, f, g, h) -> { - try { - return Validation.success(t.f(a, b, c, d, e, f, g, h)); - } catch (Exception ex) { - return Validation.fail((Z) ex); - } - }; - } - /** * Partial application. * diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index ecd6e393..dcdeb77a 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -232,22 +232,6 @@ public A f(final B b) { }; } - /** - * Promotes the TryCatch0 to a Validation that returns an Exception on the failure side and its result on the success side. - * - * @param t A TryCatch0 to promote - * @return A Validation with an Exception on the failure side and its result on the success side. - */ - static public P1> toP1(final Try0 t) { - return P.lazy(u -> { - try { - return Validation.success(t.f()); - } catch (Exception e) { - return Validation.fail((E) e); - } - }); - } - public String toString() { return Show.p1Show(Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index f585f657..934201e8 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -7,45 +7,156 @@ import java.io.IOException; +import static fj.data.Validation.fail; +import static fj.data.Validation.success; + /** * Created by mperry on 24/07/2014. */ public class Try { - public static P1> f(Try0 t) { - return P1.toP1(t); + /** + * Promotes the TryCatch0 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch0 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public P1> f(final Try0 t) { + return P.lazy(u -> { + try { + return Validation.success(t.f()); + } catch (Exception e) { + return Validation.fail((E) e); + } + }); } - public static F> f(Try1 t) { - return F1Functions.toF1(t); + /** + * Promotes the TryCatch1 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch1 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F> f(final Try1 t) { + return a -> { + try { + return Validation.success(t.f(a)); + } catch (Exception e) { + return Validation.fail((E) e); + } + }; } - public static F2> f(Try2 t) { - return F2Functions.toF2(t); + /** + * Promotes the TryCatch2 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch2 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F2> f(final Try2 t) { + return (a, b) -> { + try { + return Validation.success(t.f(a, b)); + } catch (Exception e) { + return Validation.fail((E) e); + } + }; } - public static F3> f(Try3 t) { - return F3Functions.toF3(t); + /** + * Promotes the TryCatch3 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch3 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F3> f(final Try3 t) { + return (a, b, c) -> { + try { + return success(t.f(a, b, c)); + } catch (Exception e) { + return fail((E) e); + } + }; } - public static F4> f(Try4 t) { - return F4Functions.toF4(t); + /** + * Promotes the TryCatch4 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch4 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F4> f(final Try4 t) { + return (a, b, c, d) -> { + try { + return Validation.success(t.f(a, b, c, d)); + } catch (Exception ex) { + return Validation.fail((Z) ex); + } + }; } - public static F5> f(Try5 t) { - return F5Functions.toF5(t); + /** + * Promotes the TryCatch5 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch5 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F5> f(final Try5 t) { + return (a, b, c, d, e) -> { + try { + return Validation.success(t.f(a, b, c, d, e)); + } catch (Exception ex) { + return Validation.fail((Z) ex); + } + }; } - public static F6> f(Try6 t) { - return F6Functions.toF6(t); + /** + * Promotes the TryCatch6 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch6 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F6> f(final Try6 t) { + return (a, b, c, d, e, f) -> { + try { + return Validation.success(t.f(a, b, c, d, e, f)); + } catch (Exception ex) { + return Validation.fail((Z) ex); + } + }; } - public static F7> f(Try7 t) { - return F7Functions.toF7(t); + /** + * Promotes the TryCatch7 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch7 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F7> f(final Try7 t) { + return (a, b, c, d, e, f, g) -> { + try { + return Validation.success(t.f(a, b, c, d, e, f, g)); + } catch (Exception ex) { + return Validation.fail((Z) ex); + } + }; } - public static F8> f(Try8 t) { - return F8Functions.toF8(t); + /** + * Promotes the TryCatch8 to a Validation that returns an Exception on the failure side and its result on the success side. + * + * @param t A TryCatch8 to promote + * @return A Validation with an Exception on the failure side and its result on the success side. + */ + static public F8> f(final Try8 t) { + return (a, b, c, d, e, f, g, h) -> { + try { + return Validation.success(t.f(a, b, c, d, e, f, g, h)); + } catch (Exception ex) { + return Validation.fail((Z) ex); + } + }; } public static IO io(Try0 t) { diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index d14fbbdb..86362a20 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -356,7 +356,7 @@ public static IO join(IO> io1) { } public static SafeIO> toSafeIO(IO io) { - return () -> P1.toP1(() -> io.run())._1(); + return () -> Try.f(() -> io.run())._1(); } public static IO append(final IO io1, final IO io2) { diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index f1e7db4e..bd5acd78 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -73,7 +73,7 @@ static public Supplier> TryCatch0_Supp } static public F, Supplier>> TryCatch0_Supplier() { - return t -> () -> P1.toP1(t)._1(); + return t -> () -> Try.f(t)._1(); } static public Function> TryCatch1_Function(final Try1 t) { @@ -81,7 +81,7 @@ static public Function> TryCatch } static public F, Function>> TryCatch1_Function() { - return t -> a -> F1Functions.toF1(t).f(a); + return t -> a -> Try.f(t).f(a); } static public BiFunction> TryCatch2_BiFunction(final Try2 t) { @@ -89,7 +89,7 @@ static public BiFunction> } static public F, BiFunction>> TryCatch2_BiFunction() { - return t -> (a, b) -> F2Functions.toF2(t).f(a, b); + return t -> (a, b) -> Try.f(t).f(a, b); } static public Option Optional_Option(final Optional o) { From 7188a147d2895506affa106186bd48ef8661fbcf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 3 Sep 2014 09:53:01 +1000 Subject: [PATCH 167/811] Added lazy IO creation --- core/src/main/java/fj/data/IOFunctions.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 86362a20..7755b8fe 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -158,7 +158,15 @@ public static final IO lazy(final F f) { return () -> f.f(Unit.unit()); } - /** + public static final SafeIO lazySafe(final F f) { + return () -> f.f(Unit.unit()); + } + + public static final SafeIO lazySafe(final P1 f) { + return () -> f._1(); + } + + /** * A function that feeds an iteratee with lines read from a {@link BufferedReader}. */ public static F, IO>>> lineReader() { From 360600235f322b14b06a84bdb717ac69b48a5a78 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 3 Sep 2014 09:53:16 +1000 Subject: [PATCH 168/811] Added try javadoc --- core/src/main/java/fj/function/Try0.java | 2 +- core/src/main/java/fj/function/Try1.java | 2 +- core/src/main/java/fj/function/Try2.java | 2 +- core/src/main/java/fj/function/Try3.java | 2 +- core/src/main/java/fj/function/Try4.java | 2 +- core/src/main/java/fj/function/Try5.java | 2 +- core/src/main/java/fj/function/Try6.java | 2 +- core/src/main/java/fj/function/Try7.java | 2 +- core/src/main/java/fj/function/Try8.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/fj/function/Try0.java b/core/src/main/java/fj/function/Try0.java index b42cf1b0..9898e2af 100644 --- a/core/src/main/java/fj/function/Try0.java +++ b/core/src/main/java/fj/function/Try0.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to a P1. * - * @see fj.P1#toP1 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try1.java b/core/src/main/java/fj/function/Try1.java index 36a048cc..9bf3d068 100644 --- a/core/src/main/java/fj/function/Try1.java +++ b/core/src/main/java/fj/function/Try1.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F. * - * @see fj.F1Functions#toF1 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try2.java b/core/src/main/java/fj/function/Try2.java index 20e9cbfb..15dc25fe 100644 --- a/core/src/main/java/fj/function/Try2.java +++ b/core/src/main/java/fj/function/Try2.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F2. * - * @see fj.F2Functions#toF2 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try3.java b/core/src/main/java/fj/function/Try3.java index 4471906e..4d3ed383 100644 --- a/core/src/main/java/fj/function/Try3.java +++ b/core/src/main/java/fj/function/Try3.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F3. * - * @see fj.F3Functions#toF3 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try4.java b/core/src/main/java/fj/function/Try4.java index 6c360596..f919ccbb 100644 --- a/core/src/main/java/fj/function/Try4.java +++ b/core/src/main/java/fj/function/Try4.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F4. * - * @see fj.F4Functions#toF4 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try5.java b/core/src/main/java/fj/function/Try5.java index 1ad45894..cd9fb31f 100644 --- a/core/src/main/java/fj/function/Try5.java +++ b/core/src/main/java/fj/function/Try5.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F5. * - * @see fj.F5Functions#toF5 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try6.java b/core/src/main/java/fj/function/Try6.java index ed97da2f..c12d1672 100644 --- a/core/src/main/java/fj/function/Try6.java +++ b/core/src/main/java/fj/function/Try6.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F6. * - * @see fj.F6Functions#toF6 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try7.java b/core/src/main/java/fj/function/Try7.java index 4fb1aa27..69c4dddd 100644 --- a/core/src/main/java/fj/function/Try7.java +++ b/core/src/main/java/fj/function/Try7.java @@ -6,7 +6,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F7. * - * @see fj.F7Functions#toF7 + * @see fj.Try#f * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try8.java b/core/src/main/java/fj/function/Try8.java index 42f6fcd0..51e61990 100644 --- a/core/src/main/java/fj/function/Try8.java +++ b/core/src/main/java/fj/function/Try8.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F8. * - * @see fj.F8Functions#toF8 + * @see fj.Try#f * @version %build.number% */ From 0c4405b57cf4bb0086c92c94bd42766d6d6e1205 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 9 Sep 2014 10:01:28 +1000 Subject: [PATCH 169/811] Resolved lambda conflict on Effect --- core/src/main/java/fj/Effect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index b3203b6c..c9bb252d 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -100,7 +100,7 @@ public void f(final B b) { }; } - public static Effect1 f(final F f) { + public static Effect1 lazy(final F f) { return new Effect1() { public void f(final A a) { f.f(a); From 675e465db7d96cf93d88950398628948d1a30ac1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 11 Sep 2014 08:58:55 +1000 Subject: [PATCH 170/811] Upgrade to Gradle 2.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e7244adc..deccec26 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -4,4 +4,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip -distributionUrl=https\://services.gradle.org/distributions/gradle-2.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-bin.zip From c20b00fcedf4de9d6f1077f66c00e162409a573d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 11 Sep 2014 09:20:54 +1000 Subject: [PATCH 171/811] Convert from fj.data.Stream to java.util.stream.Stream --- java8/src/main/java/fj/data/Java8.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index bd5acd78..c22cd149 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -6,10 +6,13 @@ import fj.function.Try2; import java.util.Optional; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.StreamSupport; /** * Created by mperry on 3/06/2014. @@ -119,5 +122,13 @@ public static F Consumer_F(Consumer c) { }; } + static public java.util.stream.Stream Stream_JStream(fj.data.Stream s) { + Spliterator sit = Spliterators.spliteratorUnknownSize(s.iterator(), 0); + return StreamSupport.stream(sit, false); + } + + static public F, java.util.stream.Stream> Stream_JStream() { + return s -> Stream_JStream(s); + } } From 7108e119a57f4ad6b43f08f564b2d28c9a61ff2f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Dec 2014 22:39:36 +1000 Subject: [PATCH 172/811] issue 62: Implement workaround for compiler bug in jdk 1.8.0 updates 20 and 25 (current update is 25). --- demo/src/main/java/fj/demo/Array_foldLeft.java | 8 +++++++- demo/src/main/java/fj/demo/euler/Problem1.java | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/demo/src/main/java/fj/demo/Array_foldLeft.java b/demo/src/main/java/fj/demo/Array_foldLeft.java index 1082a07b..63d90bb0 100644 --- a/demo/src/main/java/fj/demo/Array_foldLeft.java +++ b/demo/src/main/java/fj/demo/Array_foldLeft.java @@ -1,5 +1,6 @@ package fj.demo; +import fj.F; import fj.data.Array; import static fj.data.Array.array; import static fj.function.Integers.add; @@ -8,7 +9,12 @@ public final class Array_foldLeft { public static void main(final String[] args) { final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); final int b = a.foldLeft(add, 0); - final int c = a.foldLeft(i -> (j -> i + j), 0); + + // WARNING: In JDK 8, update 20 and 25 (current version) the following code triggers an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. + // final int c = a.foldLeft(i -> (j -> i + j), 0); + F> add2 = i -> (j -> i + j); + final int c = a.foldLeft(add2, 0); + System.out.println(b); // 1774 } } diff --git a/demo/src/main/java/fj/demo/euler/Problem1.java b/demo/src/main/java/fj/demo/euler/Problem1.java index 8f7cf5a6..cebdf9fa 100644 --- a/demo/src/main/java/fj/demo/euler/Problem1.java +++ b/demo/src/main/java/fj/demo/euler/Problem1.java @@ -24,7 +24,10 @@ public static void java7() { } public static void java8() { - out.println(Stream.range(0, 1000).filter(i -> i % 3 == 0 || i % 5 == 0).foldLeft((acc, i) -> acc + i, 0)); + // WARNING: In JDK 8, update 20 and 25 (current version) the following code causes an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. +// out.println(Stream.range(0, 1000).filter(i -> i % 3 == 0 || i % 5 == 0).foldLeft((acc, i) -> acc + i, 0)); + Integer sum = Stream.range(0, 1000).filter(i -> i % 3 == 0 || i % 5 == 0).foldLeft((acc, i) -> acc + i, 0); + out.println(sum); } } From e71078ea1c563b1e42bd7be4bc657c2c709ed9f3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Dec 2014 23:19:03 +1000 Subject: [PATCH 173/811] issue 63: Updated gradlew to 2.2.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index deccec26..212683d8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -4,4 +4,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip -distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip From 9e0a6a1858c0716311dbe641e115b5c6f78ee4a6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Dec 2014 01:20:11 +1000 Subject: [PATCH 174/811] Added simple Reader tests --- core/src/test/java/fj/data/ReaderTest.java | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 core/src/test/java/fj/data/ReaderTest.java diff --git a/core/src/test/java/fj/data/ReaderTest.java b/core/src/test/java/fj/data/ReaderTest.java new file mode 100644 index 00000000..5ab494a2 --- /dev/null +++ b/core/src/test/java/fj/data/ReaderTest.java @@ -0,0 +1,30 @@ +package fj.data; + +import fj.data.Reader; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 4/12/2014. + * + * Examples taken from http://learnyouahaskell.com/for-a-few-monads-more + */ +public class ReaderTest { + + @Test + public void testMap() { + int x = Reader.unit((Integer i) -> i + 3).map(i -> i * 5).f(8); + assertTrue(x == 55); +// System.out.println(x); // 55 + } + + @Test + public void testFlatMap() { + int y = Reader.unit((Integer i) -> i * 2).flatMap(a -> Reader.unit((Integer i) -> i + 10).map(b -> a + b)).f(3); +// System.out.println(y); // 19 + assertTrue(y == 19); + } + +} From 2f38b98e57e6fed1b21136ffd7ea67fbc9cd01a9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Dec 2014 23:01:51 +1000 Subject: [PATCH 175/811] #66: Renamed foreach methods that had effects as parameters to foreachDoEffect --- build.gradle | 2 +- core/src/main/java/fj/data/Array.java | 2 +- core/src/main/java/fj/data/Conversions.java | 12 ++++++------ core/src/main/java/fj/data/Either.java | 4 ++-- core/src/main/java/fj/data/HashMap.java | 4 ++-- core/src/main/java/fj/data/Java.java | 6 +++--- core/src/main/java/fj/data/Option.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/Validation.java | 8 ++++---- core/src/main/java/fj/test/Gen.java | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index c71560d2..b13c16e0 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.1" + fjConsumeVersion = "4.2-beta-1" signModule = false diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 43baa462..ce9be167 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -230,7 +230,7 @@ public Unit foreach(final F f) { * @param f The side-effect to perform for the given element. */ @SuppressWarnings("unchecked") - public void foreach(final Effect1 f) { + public void foreachDoEffect(final Effect1 f) { for (final Object x : a) { f.f((A) x); } diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 2b4a51ca..47db668f 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -179,7 +179,7 @@ public Either f(final Array bs) { public static final F, String> Array_String = new F, String>() { public String f(final Array cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach(new Effect1() { + cs.foreachDoEffect(new Effect1() { public void f(final Character c) { sb.append(c); } @@ -194,7 +194,7 @@ public void f(final Character c) { public static final F, StringBuffer> Array_StringBuffer = new F, StringBuffer>() { public StringBuffer f(final Array cs) { final StringBuffer sb = new StringBuffer(); - cs.foreach(new Effect1() { + cs.foreachDoEffect(new Effect1() { public void f(final Character c) { sb.append(c); } @@ -210,7 +210,7 @@ public void f(final Character c) { new F, StringBuilder>() { public StringBuilder f(final Array cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach((Character c) -> sb.append(c)); + cs.foreachDoEffect((Character c) -> sb.append(c)); return sb; } }; @@ -281,7 +281,7 @@ public Either f(final Stream bs) { public static final F, String> Stream_String = new F, String>() { public String f(final Stream cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach((Character c) -> sb.append(c)); + cs.foreachDoEffect((Character c) -> sb.append(c)); return sb.toString(); } }; @@ -293,7 +293,7 @@ public String f(final Stream cs) { new F, StringBuffer>() { public StringBuffer f(final Stream cs) { final StringBuffer sb = new StringBuffer(); - cs.foreach((Character c) -> sb.append(c)); + cs.foreachDoEffect((Character c) -> sb.append(c)); return sb; } }; @@ -305,7 +305,7 @@ public StringBuffer f(final Stream cs) { new F, StringBuilder>() { public StringBuilder f(final Stream cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach((Character c) -> sb.append(c)); + cs.foreachDoEffect((Character c) -> sb.append(c)); return sb; } }; diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index f656471d..281f4411 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -232,7 +232,7 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect1 f) { + public void foreachDoEffect(final Effect1 f) { if (isLeft()) f.f(value()); } @@ -465,7 +465,7 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect1 f) { + public void foreachDoEffect(final Effect1 f) { if (isRight()) f.f(value()); } diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 83ab9c79..f2a3189b 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -291,8 +291,8 @@ public HashMap mapValues(F function) { return map(Function.identity(), function, e, h); } - public void foreach(Effect1> effect) { - toStream().foreach(effect); + public void foreachDoEffect(Effect1> effect) { + toStream().foreachDoEffect(effect); } public void foreach(F, Unit> function) { diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index b75c7c94..4c62b0ad 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -317,7 +317,7 @@ public ArrayList f(final Array as) { public BitSet f(final Array bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect1>() { + bs.zipIndex().foreachDoEffect(new Effect1>() { public void f(final P2 bi) { s.set(bi._2(), bi._1()); } @@ -601,7 +601,7 @@ public ArrayList f(final Stream as) { public static final F, BitSet> Stream_BitSet = new F, BitSet>() { public BitSet f(final Stream bs) { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreach(new Effect1>() { + bs.zipIndex().foreachDoEffect(new Effect1>() { public void f(final P2 bi) { s.set(bi._2(), bi._1()); } @@ -849,7 +849,7 @@ public ArrayList f(final Option as) { public BitSet f(final Option bs) { final BitSet s = new BitSet(bs.length()); - bs.foreach(new Effect1() { + bs.foreachDoEffect(new Effect1() { public void f(final Boolean b) { if (b) s.set(0); diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 4fdbddaa..c952133c 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -226,7 +226,7 @@ public final Unit foreach(final F f) { * * @param f The side-effect to perform for the given element. */ - public final void foreach(final Effect1 f) { + public final void foreachDoEffect(final Effect1 f) { if (isSome()) f.f(some()); } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 44bac66a..f04249e6 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -292,7 +292,7 @@ public final Unit foreach(final F f) { * * @param f The side-effect to perform for the given element. */ - public final void foreach(final Effect1 f) { + public final void foreachDoEffect(final Effect1 f) { for (Stream xs = this; xs.isNotEmpty(); xs = xs.tail()._1()) f.f(xs.head()); } diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index f71afb13..7716b269 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -161,8 +161,8 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect1 f) { - e.right().foreach(f); + public void foreachDoEffect(final Effect1 f) { + e.right().foreachDoEffect(f); } /** @@ -927,8 +927,8 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreach(final Effect1 f) { - v.toEither().left().foreach(f); + public void foreachDoEffect(final Effect1 f) { + v.toEither().left().foreachDoEffect(f); } /** diff --git a/core/src/main/java/fj/test/Gen.java b/core/src/main/java/fj/test/Gen.java index 2a7b0807..67ea4beb 100644 --- a/core/src/main/java/fj/test/Gen.java +++ b/core/src/main/java/fj/test/Gen.java @@ -157,7 +157,7 @@ public Unit foreach(final Integer i, final Rand r, final F f) { * @param r The random generator to generate the result to apply the side-effect to. * @param f The side-effect to execute on the generated value. */ - public void foreach(final Integer i, final Rand r, final Effect1 f) { + public void foreachDoEffect(final Integer i, final Rand r, final Effect1 f) { f.f(this.f.f(i).f(r)); } From 5637ce31d589a0c9298ae8cdc86fd2c08dd1d370 Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Wed, 3 Dec 2014 23:33:07 +0100 Subject: [PATCH 176/811] Implement groupBy on List --- core/src/main/java/fj/data/List.java | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index a957bc5d..6fcf947d 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1237,6 +1237,50 @@ public final A mode(final Ord o) { return sort(o).group(o.equal()).maximum(intOrd.comap(List.length_())).head(); } + public final HashMap> groupBy(final F keyFunction) { + return groupBy(keyFunction, Function.identity()); + } + + public final HashMap> groupBy( + final F keyFunction, + final F valueFunction) { + return this.groupBy(keyFunction, valueFunction, List.nil(), + new F2, List>() { + @Override + public List f(final V head, final List tail) { + return List.cons(head, tail); + } + }); + } + + public final HashMap groupBy( + final F keyFunction, + final F valueFunction, final R groupingIdentity, final F2 groupingAcc) { + return this.foldLeft( + new F, F>>() { + @Override + public F> f(final HashMap map) { + return new F>() { + @Override + public HashMap f(final A element) { + final K key = keyFunction.f(element); + final V value = valueFunction.f(element); + map.set(key, map.get(key) + .map(new F() { + @Override + public R f(final R existing) { + return groupingAcc.f(value, existing); + } + }) + .orSome(groupingAcc.f(value, groupingIdentity))); + return map; + } + }; + } + }, HashMap.hashMap() + ); + } + /** * Returns whether or not all elements in the list are equal according to the given equality test. * From 33786f8afe3597d3672931c298a387861823ab65 Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Thu, 4 Dec 2014 22:50:58 +0100 Subject: [PATCH 177/811] Change generic names --- core/src/main/java/fj/data/List.java | 38 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 6fcf947d..b67f9061 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1237,38 +1237,38 @@ public final A mode(final Ord o) { return sort(o).group(o.equal()).maximum(intOrd.comap(List.length_())).head(); } - public final HashMap> groupBy(final F keyFunction) { + public final HashMap> groupBy(final F keyFunction) { return groupBy(keyFunction, Function.identity()); } - public final HashMap> groupBy( - final F keyFunction, - final F valueFunction) { - return this.groupBy(keyFunction, valueFunction, List.nil(), - new F2, List>() { + public final HashMap> groupBy( + final F keyFunction, + final F valueFunction) { + return this.groupBy(keyFunction, valueFunction, List.nil(), + new F2, List>() { @Override - public List f(final V head, final List tail) { + public List f(final C head, final List tail) { return List.cons(head, tail); } }); } - public final HashMap groupBy( - final F keyFunction, - final F valueFunction, final R groupingIdentity, final F2 groupingAcc) { + public final HashMap groupBy( + final F keyFunction, + final F valueFunction, final D groupingIdentity, final F2 groupingAcc) { return this.foldLeft( - new F, F>>() { + new F, F>>() { @Override - public F> f(final HashMap map) { - return new F>() { + public F> f(final HashMap map) { + return new F>() { @Override - public HashMap f(final A element) { - final K key = keyFunction.f(element); - final V value = valueFunction.f(element); + public HashMap f(final A element) { + final B key = keyFunction.f(element); + final C value = valueFunction.f(element); map.set(key, map.get(key) - .map(new F() { + .map(new F() { @Override - public R f(final R existing) { + public D f(final D existing) { return groupingAcc.f(value, existing); } }) @@ -1277,7 +1277,7 @@ public R f(final R existing) { } }; } - }, HashMap.hashMap() + }, HashMap.hashMap() ); } From fc9fe00e55b3b9607f87372da1caf67080a28b73 Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Thu, 4 Dec 2014 22:51:56 +0100 Subject: [PATCH 178/811] Add demo for groupBy --- demo/src/main/java/fj/demo/List_groupBy.java | 47 ++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 demo/src/main/java/fj/demo/List_groupBy.java diff --git a/demo/src/main/java/fj/demo/List_groupBy.java b/demo/src/main/java/fj/demo/List_groupBy.java new file mode 100644 index 00000000..a68333dc --- /dev/null +++ b/demo/src/main/java/fj/demo/List_groupBy.java @@ -0,0 +1,47 @@ +package fj.demo; + +import fj.Function; +import fj.data.HashMap; +import fj.data.List; + +import static fj.data.List.list; + +public final class List_groupBy { + + public static void main(final String... args) { + keyDemo(); + keyValueDemo(); + keyValueAccDemo(); + } + + private static void keyDemo() { + System.out.println("KeyDemo"); + final List words = list("Hello", "World", "how", "are", "your", "doing"); + final HashMap> lengthMap = words.groupBy(String::length); + + lengthMap.foreach(entry -> { + System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2())); + }); + } + + private static void keyValueDemo() { + System.out.println("KeyValueDemo"); + final List xs = list(1, 2, 3, 4, 5, 6, 7, 8, 9); + final HashMap> result = xs.groupBy(x -> x % 3, Integer::toBinaryString); + + result.foreach(entry -> { + System.out.println(String.format("Numbers with reminder %d are %s", entry._1(), entry._2())); + }); + } + + private static void keyValueAccDemo() { + System.out.println("KeyValueAccDemo"); + final List words = list("Hello", "World", "how", "are", "your", "doing"); + final HashMap lengthCounts = + words.groupBy(String::length, Function.identity(), 0, (word, sum) -> sum + 1); + + lengthCounts.foreach(entry -> { + System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2())); + }); + } +} From b63769f8797e04df92076563121876d80b1a7b77 Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Thu, 4 Dec 2014 23:02:01 +0100 Subject: [PATCH 179/811] Add javadoc to groupBy --- core/src/main/java/fj/data/List.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index b67f9061..987a795e 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1237,10 +1237,24 @@ public final A mode(final Ord o) { return sort(o).group(o.equal()).maximum(intOrd.comap(List.length_())).head(); } + /** + * Groups the elements of this list by a given keyFunction into a {@link HashMap}. + * + * @param keyFunction The function to select the keys for the map. + * @return A HashMap containing the keys with the accumulated list of matched elements. + */ public final HashMap> groupBy(final F keyFunction) { return groupBy(keyFunction, Function.identity()); } + /** + * Groups the elements of this list by a given keyFunction into a {@link HashMap} and transforms + * the matching elements with the given valueFunction. + * + * @param keyFunction The function to select the keys for the map. + * @param valueFunction The function to apply on each matching value. + * @return A HashMap containing the keys with the accumulated list of matched and mapped elements. + */ public final HashMap> groupBy( final F keyFunction, final F valueFunction) { @@ -1253,6 +1267,18 @@ public List f(final C head, final List tail) { }); } + /** + * Groups the elements of this list by a given keyFunction, applies the valueFunction and + * accumulates the mapped values with the given grouping accumulator function on the grouping + * identity. + * + * @param keyFunction The function to select the keys. + * @param valueFunction The function to apply on each element. + * @param groupingIdentity The identity, or start value, for the grouping. + * @param groupingAcc The accumulator to apply on each matching value. + * @return A HashMap containing the keys with the accumulated result of matched and mapped + * elements. + */ public final HashMap groupBy( final F keyFunction, final F valueFunction, final D groupingIdentity, final F2 groupingAcc) { From a733f977da9320f9a6c94b8f0e8dcb798c6cd62f Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Mon, 15 Dec 2014 19:33:45 +0100 Subject: [PATCH 180/811] Switch from anonymous inner classes to lambdas --- core/src/main/java/fj/data/List.java | 36 +++++++--------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 987a795e..3285bcd2 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1258,13 +1258,7 @@ public final HashMap> groupBy(final F keyFunction) { public final HashMap> groupBy( final F keyFunction, final F valueFunction) { - return this.groupBy(keyFunction, valueFunction, List.nil(), - new F2, List>() { - @Override - public List f(final C head, final List tail) { - return List.cons(head, tail); - } - }); + return this.groupBy(keyFunction, valueFunction, List.nil(), List::cons); } /** @@ -1282,27 +1276,13 @@ public List f(final C head, final List tail) { public final HashMap groupBy( final F keyFunction, final F valueFunction, final D groupingIdentity, final F2 groupingAcc) { - return this.foldLeft( - new F, F>>() { - @Override - public F> f(final HashMap map) { - return new F>() { - @Override - public HashMap f(final A element) { - final B key = keyFunction.f(element); - final C value = valueFunction.f(element); - map.set(key, map.get(key) - .map(new F() { - @Override - public D f(final D existing) { - return groupingAcc.f(value, existing); - } - }) - .orSome(groupingAcc.f(value, groupingIdentity))); - return map; - } - }; - } + return this.foldLeft(map -> element -> { + final B key = keyFunction.f(element); + final C value = valueFunction.f(element); + map.set(key, map.get(key) + .map(existing -> groupingAcc.f(value, existing)) + .orSome(groupingAcc.f(value, groupingIdentity))); + return map; }, HashMap.hashMap() ); } From 93c1d3ad2f13682b26d6c8be77d29fd5217c1aaa Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Mon, 15 Dec 2014 21:53:49 +0100 Subject: [PATCH 181/811] Switch HashMap to TreeMap --- core/src/main/java/fj/data/List.java | 62 ++++++++++++++++---- demo/src/main/java/fj/demo/List_groupBy.java | 17 +++--- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 3285bcd2..f6ac86df 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1238,27 +1238,57 @@ public final A mode(final Ord o) { } /** - * Groups the elements of this list by a given keyFunction into a {@link HashMap}. + * Groups the elements of this list by a given keyFunction into a {@link TreeMap}. + * The ordering of the keys is determined by {@link fj.Ord#hashOrd()}. * * @param keyFunction The function to select the keys for the map. - * @return A HashMap containing the keys with the accumulated list of matched elements. + * @return A TreeMap containing the keys with the accumulated list of matched elements. */ - public final HashMap> groupBy(final F keyFunction) { - return groupBy(keyFunction, Function.identity()); + public final TreeMap> groupBy(final F keyFunction) { + return groupBy(keyFunction, Ord.hashOrd()); } /** - * Groups the elements of this list by a given keyFunction into a {@link HashMap} and transforms - * the matching elements with the given valueFunction. + * Groups the elements of this list by a given keyFunction into a {@link TreeMap}. + * + * @param keyFunction The function to select the keys for the map. + * @param keyOrd An order for the keys of the tree map. + * @return A TreeMap containing the keys with the accumulated list of matched elements. + */ + public final TreeMap> groupBy(final F keyFunction, final Ord keyOrd) { + return groupBy(keyFunction, Function.identity(), keyOrd); + } + + /** + * Groups the elements of this list by a given keyFunction into a {@link TreeMap} and transforms + * the matching elements with the given valueFunction. The ordering of the keys is determined by + * {@link fj.Ord#hashOrd()}. * * @param keyFunction The function to select the keys for the map. * @param valueFunction The function to apply on each matching value. - * @return A HashMap containing the keys with the accumulated list of matched and mapped elements. + * @return A TreeMap containing the keys with the accumulated list of matched and mapped elements. */ - public final HashMap> groupBy( + public final TreeMap> groupBy( final F keyFunction, final F valueFunction) { - return this.groupBy(keyFunction, valueFunction, List.nil(), List::cons); + return this.groupBy(keyFunction, valueFunction, Ord.hashOrd()); + } + + /** + * Groups the elements of this list by a given keyFunction into a {@link TreeMap} and transforms + * the matching elements with the given valueFunction. The ordering of the keys is determined by + * the keyOrd parameter. + * + * @param keyFunction The function to select the keys for the map. + * @param valueFunction The function to apply on each matching value. + * @param keyOrd An order for the keys of the tree map. + * @return A TreeMap containing the keys with the accumulated list of matched and mapped elements. + */ + public final TreeMap> groupBy( + final F keyFunction, + final F valueFunction, + final Ord keyOrd) { + return this.groupBy(keyFunction, valueFunction, List.nil(), List::cons, keyOrd); } /** @@ -1270,12 +1300,16 @@ public final HashMap> groupBy( * @param valueFunction The function to apply on each element. * @param groupingIdentity The identity, or start value, for the grouping. * @param groupingAcc The accumulator to apply on each matching value. - * @return A HashMap containing the keys with the accumulated result of matched and mapped + * @param keyOrd An order for the keys of the tree map. + * @return A TreeMap containing the keys with the accumulated result of matched and mapped * elements. */ - public final HashMap groupBy( + public final TreeMap groupBy( final F keyFunction, - final F valueFunction, final D groupingIdentity, final F2 groupingAcc) { + final F valueFunction, + final D groupingIdentity, + final F2 groupingAcc, + final Ord keyOrd) { return this.foldLeft(map -> element -> { final B key = keyFunction.f(element); final C value = valueFunction.f(element); @@ -1283,10 +1317,12 @@ public final HashMap groupBy( .map(existing -> groupingAcc.f(value, existing)) .orSome(groupingAcc.f(value, groupingIdentity))); return map; - }, HashMap.hashMap() + }, TreeMap.empty(keyOrd) ); } + + /** * Returns whether or not all elements in the list are equal according to the given equality test. * diff --git a/demo/src/main/java/fj/demo/List_groupBy.java b/demo/src/main/java/fj/demo/List_groupBy.java index a68333dc..1dc8866d 100644 --- a/demo/src/main/java/fj/demo/List_groupBy.java +++ b/demo/src/main/java/fj/demo/List_groupBy.java @@ -1,8 +1,9 @@ package fj.demo; import fj.Function; -import fj.data.HashMap; +import fj.Ord; import fj.data.List; +import fj.data.TreeMap; import static fj.data.List.list; @@ -17,9 +18,9 @@ public static void main(final String... args) { private static void keyDemo() { System.out.println("KeyDemo"); final List words = list("Hello", "World", "how", "are", "your", "doing"); - final HashMap> lengthMap = words.groupBy(String::length); + final TreeMap> lengthMap = words.groupBy(String::length); - lengthMap.foreach(entry -> { + lengthMap.forEach(entry -> { System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2())); }); } @@ -27,9 +28,9 @@ private static void keyDemo() { private static void keyValueDemo() { System.out.println("KeyValueDemo"); final List xs = list(1, 2, 3, 4, 5, 6, 7, 8, 9); - final HashMap> result = xs.groupBy(x -> x % 3, Integer::toBinaryString); + final TreeMap> result = xs.groupBy(x -> x % 3, Integer::toBinaryString); - result.foreach(entry -> { + result.forEach(entry -> { System.out.println(String.format("Numbers with reminder %d are %s", entry._1(), entry._2())); }); } @@ -37,10 +38,10 @@ private static void keyValueDemo() { private static void keyValueAccDemo() { System.out.println("KeyValueAccDemo"); final List words = list("Hello", "World", "how", "are", "your", "doing"); - final HashMap lengthCounts = - words.groupBy(String::length, Function.identity(), 0, (word, sum) -> sum + 1); + final TreeMap lengthCounts = + words.groupBy(String::length, Function.identity(), 0, (word, sum) -> sum + 1, Ord.hashOrd()); - lengthCounts.foreach(entry -> { + lengthCounts.forEach(entry -> { System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2())); }); } From 39d221a5c958b7dc84ae2c992057e887c9f2dd3c Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Mon, 15 Dec 2014 21:55:47 +0100 Subject: [PATCH 182/811] Add groupBy with Monoid --- core/src/main/java/fj/data/List.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index f6ac86df..c60363c3 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1291,6 +1291,26 @@ public final TreeMap> groupBy( return this.groupBy(keyFunction, valueFunction, List.nil(), List::cons, keyOrd); } + /** + * Groups the elements of this list by a given keyFunction into a {@link TreeMap} and transforms + * the matching elements with the given valueFunction. The ordering of the keys is determined by + * the keyOrd parameter. + * + * @param keyFunction The function to select the keys for the map. + * @param valueFunction The function to apply on each matching value. + * @param monoid A monoid, which defines the accumulator for the values and the zero value. + * @param keyOrd An order for the keys of the tree map. + * @return A TreeMap containing the keys with the accumulated list of matched and mapped elements. + */ + public final TreeMap groupBy( + final F keyFunction, + final F valueFunction, + final Monoid monoid, + final Ord keyOrd) { + return groupBy(keyFunction, valueFunction, monoid.zero(), + Function.uncurryF2(monoid.sum()), keyOrd); + } + /** * Groups the elements of this list by a given keyFunction, applies the valueFunction and * accumulates the mapped values with the given grouping accumulator function on the grouping From 94195af2b466f1adb469b9c43412c6966944b9e8 Mon Sep 17 00:00:00 2001 From: Martin Seeler Date: Mon, 15 Dec 2014 21:56:41 +0100 Subject: [PATCH 183/811] Add property based tests for groupBy --- tests/src/test/scala/fj/data/CheckList.scala | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/src/test/scala/fj/data/CheckList.scala b/tests/src/test/scala/fj/data/CheckList.scala index 807e1293..90e7b1d7 100644 --- a/tests/src/test/scala/fj/data/CheckList.scala +++ b/tests/src/test/scala/fj/data/CheckList.scala @@ -1,6 +1,9 @@ package fj package data +import java.lang + +import fj.Monoid import org.scalacheck.Prop._ import ArbitraryList.arbitraryList import ArbitraryP.arbitraryP1 @@ -174,6 +177,25 @@ object CheckList extends Properties("List") { a.foldRight((a: List[String], b: List[String]) => a.append(b), nil[String]), join(a))) + property("groupBy") = forAll((a: List[Int]) => { + val result = a.groupBy((x: Int) => (x % 2 == 0): lang.Boolean) + result.get(true).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 == 0): lang.Boolean): lang.Boolean) && + result.get(false).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 != 0): lang.Boolean): lang.Boolean) + }) + + property("groupByMonoid") = forAll((a: List[Int]) => { + val result = a.groupBy((x: Int) => (x % 2 == 0): lang.Boolean, (x: Int) => x: lang.Integer, Monoid.intAdditionMonoid, Ord.booleanOrd) + result.get(true).forall((x: lang.Integer) => + x == a.filter((x: Int) => (x % 2 == 0): lang.Boolean). + map((x: Int) => x:lang.Integer). + foldLeft(Function.uncurryF2[lang.Integer, lang.Integer, lang.Integer](Monoid.intAdditionMonoid.sum), Monoid.intAdditionMonoid.zero()): lang.Boolean) && + result.get(false).forall((x: lang.Integer) => + x == a.filter((x: Int) => (x % 2 != 0): lang.Boolean). + map((x: Int) => x:lang.Integer). + foldLeft(Function.uncurryF2[lang.Integer, lang.Integer, lang.Integer](Monoid.intAdditionMonoid.sum), Monoid.intAdditionMonoid.zero()): lang.Boolean) + }) + + /*property("iterateWhile") = forAll((n: Int) => n > 0 ==> (iterateWhile(((x:Int) => x - 1), ((x:Int) => ((x > 0): java.lang.Boolean)), n).length == n))*/ } From f762bf3fdd0e2cae13e05b0e4f0273806f387daa Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 16 Dec 2014 23:46:37 +1000 Subject: [PATCH 184/811] #64: Fixed adding items to the immutable tree map --- core/src/main/java/fj/data/List.java | 3 +-- tests/src/test/scala/fj/data/CheckList.scala | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index c60363c3..58f3b071 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1333,10 +1333,9 @@ public final TreeMap groupBy( return this.foldLeft(map -> element -> { final B key = keyFunction.f(element); final C value = valueFunction.f(element); - map.set(key, map.get(key) + return map.set(key, map.get(key) .map(existing -> groupingAcc.f(value, existing)) .orSome(groupingAcc.f(value, groupingIdentity))); - return map; }, TreeMap.empty(keyOrd) ); } diff --git a/tests/src/test/scala/fj/data/CheckList.scala b/tests/src/test/scala/fj/data/CheckList.scala index 90e7b1d7..1f41e5ec 100644 --- a/tests/src/test/scala/fj/data/CheckList.scala +++ b/tests/src/test/scala/fj/data/CheckList.scala @@ -180,7 +180,8 @@ object CheckList extends Properties("List") { property("groupBy") = forAll((a: List[Int]) => { val result = a.groupBy((x: Int) => (x % 2 == 0): lang.Boolean) result.get(true).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 == 0): lang.Boolean): lang.Boolean) && - result.get(false).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 != 0): lang.Boolean): lang.Boolean) + result.get(false).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 != 0): lang.Boolean): lang.Boolean) && + a.map((x: Int) => (x % 2) == 0: lang.Boolean).nub().length() == result.size() }) property("groupByMonoid") = forAll((a: List[Int]) => { From 1a4b4bc8867ca5ef623aaeda6ffbab9e86236736 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 17 Dec 2014 22:24:22 +1000 Subject: [PATCH 185/811] Added tests to the reader monad --- core/src/main/java/fj/data/Reader.java | 1 + core/src/test/java/fj/data/ReaderTest.java | 110 ++++++++++++++++++++- 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index f8210314..c25b228d 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -4,6 +4,7 @@ import fj.F1Functions; /** + * The Reader monad (also called the function monad, so equivalent to the idea of F). * Created by MarkPerry on 7/07/2014. */ public class Reader { diff --git a/core/src/test/java/fj/data/ReaderTest.java b/core/src/test/java/fj/data/ReaderTest.java index 5ab494a2..b3ac9668 100644 --- a/core/src/test/java/fj/data/ReaderTest.java +++ b/core/src/test/java/fj/data/ReaderTest.java @@ -1,20 +1,30 @@ package fj.data; -import fj.data.Reader; -import org.junit.Assert; +import fj.F; +import fj.F2; +import fj.test.*; import org.junit.Test; +import static fj.F1Functions.bind; +import static fj.F1Functions.map; +import static fj.F2Functions.curry; +import static fj.test.Arbitrary.arbF; +import static fj.test.Arbitrary.arbF2; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Property.prop; +import static fj.test.Property.property; import static org.junit.Assert.assertTrue; /** * Created by MarkPerry on 4/12/2014. - * - * Examples taken from http://learnyouahaskell.com/for-a-few-monads-more */ public class ReaderTest { @Test public void testMap() { + // (3 + 8) * 11 + // example taken from http://learnyouahaskell.com/for-a-few-monads-more int x = Reader.unit((Integer i) -> i + 3).map(i -> i * 5).f(8); assertTrue(x == 55); // System.out.println(x); // 55 @@ -22,9 +32,101 @@ public void testMap() { @Test public void testFlatMap() { + // (3 * 2) + (3 + 10) + // example taken from http://learnyouahaskell.com/for-a-few-monads-more int y = Reader.unit((Integer i) -> i * 2).flatMap(a -> Reader.unit((Integer i) -> i + 10).map(b -> a + b)).f(3); // System.out.println(y); // 19 assertTrue(y == 19); } + @Test + public void testMapProp() { + CheckResult cr = property( + arbF(coarbInteger, arbInteger), + arbF(coarbInteger, arbInteger), + arbInteger, + (f, g, i) -> { + int expected = map(f, g).f(i); +// System.out.println(String.format("input: %d, result: %d", i, expected)); + return prop(expected == Reader.unit(f).map(g).f(i)); + }).check(); + CheckResult.summary.println(cr); + assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + } + + @Test + public void testFlatMapProp() { + CheckResult cr = property( + arbF(coarbInteger, arbInteger), + arbF2(coarbInteger, coarbInteger, arbInteger), + arbInteger, + (f, g, i) -> { + int expected = bind(f, curry(g)).f(i); +// System.out.println(String.format("input: %d, result: %d", i, expected)); + return prop(expected == Reader.unit(f).flatMap(toBindable(g)).f(i)); + } + ).check(); + CheckResult.summary.println(cr); + assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + } + + @Test + public void testLeftIdentity() { + CheckResult cr = Property.property( + arbInteger, + arbF(coarbInteger, arbInteger), + arbF2(coarbInteger, coarbInteger, arbInteger), + (i, f, g) -> { +// F> h = convert(g); + int a = Reader.unit(f).flatMap(toBindable(g)).f(i); + int b = g.f(f.f(i), i); +// System.out.println(String.format("i=%d, a=%d, b=%d, truth=%b", i, a, b, a == b)); + return prop(a == b); + }).check(); + CheckResult.summary.println(cr); + assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + } + + F> toBindable(F2 f) { +// F> h = map(curry(f), z -> Reader.unit(z)); + return map(curry(f), z -> Reader.unit(z)); + } + + @Test + public void testRightIdentity() { + CheckResult cr = Property.property( + arbInteger, + arbF(coarbInteger, arbInteger), + (i, f) -> { + Reader r = Reader.unit(f); + boolean b = r.flatMap(a -> r).f(i) == r.f(i); +// System.out.println(String.format("i=%d, a=%d, b=%d, truth=%b", i, a, b, a == b)); + return prop(b); + }).check(); + CheckResult.summary.println(cr); + assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + } + + + + @Test + public void testAssociativity() { + CheckResult cr = Property.property( + arbInteger, + arbF(coarbInteger, arbInteger), + arbF2(coarbInteger, coarbInteger, arbInteger), + arbF2(coarbInteger, coarbInteger, arbInteger), + (i, f, g, h) -> { + Reader r = Reader.unit(f); + int a = r.flatMap(toBindable(g)).flatMap(toBindable(h)).f(i); + int b = r.flatMap(x -> toBindable(g).f(x).flatMap(toBindable(h))).f(i); +// System.out.println(String.format("i=%d, a=%d, b=%d, truth=%b", i, a, b, a == b)); + return prop(a == b); + }).check(); + CheckResult.summary.println(cr); + assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + } + + + } From aa9a68344263d13906014bee5cb7879868f795eb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 18 Dec 2014 01:04:01 +1000 Subject: [PATCH 186/811] Added Writer monad tests --- core/src/main/java/fj/Equal.java | 17 ++- core/src/main/java/fj/data/Writer.java | 4 + core/src/test/java/fj/data/WriterTest.java | 120 +++++++++++++++++++++ 3 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 core/src/test/java/fj/data/WriterTest.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index e510671f..d47e51dd 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -1,17 +1,9 @@ package fj; import static fj.Function.curry; + +import fj.data.*; import fj.data.hlist.HList; -import fj.data.Array; -import fj.data.Either; -import fj.data.LazyString; -import fj.data.List; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Set; -import fj.data.Stream; -import fj.data.Tree; -import fj.data.Validation; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; @@ -667,4 +659,9 @@ public Boolean f(final Set a, final Set b) { } })); } + + public static Equal> writerEqual(Equal eq1, Equal eq2) { + return new Equal>(w1 -> w2 -> Equal.p2Equal(eq1, eq2).eq(w1.run(), w2.run())); + } + } diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index 3aea8826..96e449e3 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -29,6 +29,10 @@ public W log() { return logValue; } + public Monoid monoid() { + return monoid; + } + public static Writer unit(A a, W w, Monoid m) { return new Writer(a, w, m); } diff --git a/core/src/test/java/fj/data/WriterTest.java b/core/src/test/java/fj/data/WriterTest.java new file mode 100644 index 00000000..fa14e0a9 --- /dev/null +++ b/core/src/test/java/fj/data/WriterTest.java @@ -0,0 +1,120 @@ +package fj.data; + +import fj.Equal; +import fj.F; +import fj.F2; +import fj.test.Arbitrary; +import fj.test.CheckResult; +import fj.test.Property; +import org.junit.Assert; +import org.junit.Test; + +import static fj.F1Functions.map; +import static fj.F2Functions.curry; +import static fj.test.Arbitrary.*; +import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 17/12/2014. + */ +public class WriterTest { + + @Test + public void base() { + Assert.assertTrue(tellTruth("a", "b", 0)); + } + + boolean tellTruth(String s1, String s2, int i) { + Writer w = defaultWriter.f(i); + Writer w1 = w.tell(s1).tell(s2); + Writer w2 = w.tell(w.monoid().sum(s1, s2)); + boolean b = eq.eq(w1, w2); +// System.out.println(String.format("p1: %s, p2: %s, b: %s", w1, w2, b)); + return b; + } + + final Equal> eq = Equal.writerEqual(Equal.stringEqual, Equal.intEqual); + final F> defaultWriter = Writer.stringLogger(); + + void assertProperty(Property p) { + CheckResult cr = p.check(); + CheckResult.summary.println(cr); + assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + } + + @Test + public void testTellProp() { + Property p = property(arbString, arbString, arbInteger, (s1, s2, i) -> prop(tellTruth(s1, s2, i))); + assertProperty(p); + } + + @Test + public void testMap() { + Property p = property(arbInteger, arbF(coarbInteger, arbInteger), (i, f) -> { + boolean b = eq.eq(defaultWriter.f(i).map(f), defaultWriter.f(f.f(i))); + return prop(b); + }); + assertProperty(p); + } + + @Test + public void testFlatMap() { + Property p = property(arbInteger,arbF(coarbInteger, arbWriterStringInt()), (i, f) -> { + boolean b = eq.eq(Writer.stringLogger().f(i).flatMap(f), f.f(i)); + return prop(b); + }); + assertProperty(p); + + } + + public Arbitrary> arbWriterStringInt() { + return arbWriterString(arbInteger); + } + + public Arbitrary> arbWriterString(Arbitrary arb) { + return Arbitrary.arbitrary(arb.gen.map(a -> Writer.stringLogger().f(a))); + } + + // Left identity: return a >>= f == f a + @Test + public void testLeftIdentity() { + Property p = Property.property( + arbInteger, + arbF(coarbInteger, arbWriterStringInt()), + (i, f) -> { + return prop(eq.eq(defaultWriter.f(i).flatMap(f), f.f(i))); + }); + assertProperty(p); + } + + // Right identity: m >>= return == m + @Test + public void testRightIdentity() { + Property p = Property.property( + arbWriterStringInt(), + (w) -> prop(eq.eq(w.flatMap(a -> defaultWriter.f(a)), w)) + ); + assertProperty(p); + } + + // Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g) + @Test + public void testAssociativity() { + Property p = Property.property( + arbWriterStringInt(), + arbF(coarbInteger, arbWriterStringInt()), + arbF(coarbInteger, arbWriterStringInt()), + (w, f, g) -> { + boolean t = eq.eq(w.flatMap(f).flatMap(g), w.flatMap(x -> f.f(x).flatMap(g))); + return prop(t); + }); + assertProperty(p); + } + + + + +} From 5bec2580036e484fc4149a8c3037df6f74e5d80f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 18 Dec 2014 01:53:46 +1000 Subject: [PATCH 187/811] Clean up reader tests --- core/src/main/java/fj/data/Reader.java | 4 + core/src/main/java/fj/test/Arbitrary.java | 12 ++- core/src/main/java/fj/test/Property.java | 17 ++- core/src/test/java/fj/data/ReaderTest.java | 100 ++++++++---------- core/src/test/java/fj/data/WriterTest.java | 26 ++--- .../java/fj/data/test/PropertyAssert.java | 20 ++++ 6 files changed, 88 insertions(+), 91 deletions(-) create mode 100644 core/src/test/java/fj/data/test/PropertyAssert.java diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index c25b228d..34a98c72 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -15,6 +15,10 @@ public Reader(F f) { function = f; } + public F getFunction() { + return function; + } + public static Reader unit(F f) { return new Reader(f); } diff --git a/core/src/main/java/fj/test/Arbitrary.java b/core/src/main/java/fj/test/Arbitrary.java index e50a3d78..cd4fd38c 100644 --- a/core/src/main/java/fj/test/Arbitrary.java +++ b/core/src/main/java/fj/test/Arbitrary.java @@ -19,17 +19,15 @@ import fj.P6; import fj.P7; import fj.P8; -import fj.data.Array; -import fj.data.Either; +import fj.data.*; + import static fj.data.Either.left; import static fj.data.Either.right; import static fj.data.Enumerator.charEnumerator; -import fj.data.List; import static fj.data.List.asString; import static fj.data.List.list; -import fj.data.Option; import static fj.data.Option.some; -import fj.data.Stream; + import fj.function.Effect1; import static fj.data.Stream.range; @@ -125,6 +123,10 @@ public Gen f(final A x) { })); } + public static Arbitrary> arbReader(Coarbitrary aa, Arbitrary ab) { + return arbitrary(Arbitrary.arbF(aa, ab).gen.map(f -> Reader.unit(f))); + } + /** * An arbitrary for functions. * diff --git a/core/src/main/java/fj/test/Property.java b/core/src/main/java/fj/test/Property.java index d914d092..6e54ebab 100644 --- a/core/src/main/java/fj/test/Property.java +++ b/core/src/main/java/fj/test/Property.java @@ -3,17 +3,9 @@ import static fj.Function.curry; import static fj.Function.compose2; import static fj.P.p; -import fj.F; -import fj.F2; -import fj.F3; -import fj.F4; -import fj.F5; -import fj.F6; -import fj.F7; -import fj.F8; -import fj.P; -import fj.P1; -import fj.P2; + +import fj.*; + import static fj.P2.__2; import fj.data.List; import fj.data.Option; @@ -1663,4 +1655,7 @@ public Result f(final Rand r) { }); } } + + + } diff --git a/core/src/test/java/fj/data/ReaderTest.java b/core/src/test/java/fj/data/ReaderTest.java index b3ac9668..083716e9 100644 --- a/core/src/test/java/fj/data/ReaderTest.java +++ b/core/src/test/java/fj/data/ReaderTest.java @@ -1,16 +1,13 @@ package fj.data; import fj.F; -import fj.F2; +import fj.data.test.PropertyAssert; import fj.test.*; import org.junit.Test; import static fj.F1Functions.bind; import static fj.F1Functions.map; -import static fj.F2Functions.curry; -import static fj.test.Arbitrary.arbF; -import static fj.test.Arbitrary.arbF2; -import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.*; import static fj.test.Coarbitrary.coarbInteger; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -41,7 +38,7 @@ public void testFlatMap() { @Test public void testMapProp() { - CheckResult cr = property( + Property p = property( arbF(coarbInteger, arbInteger), arbF(coarbInteger, arbInteger), arbInteger, @@ -49,84 +46,71 @@ public void testMapProp() { int expected = map(f, g).f(i); // System.out.println(String.format("input: %d, result: %d", i, expected)); return prop(expected == Reader.unit(f).map(g).f(i)); - }).check(); - CheckResult.summary.println(cr); - assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + }); + PropertyAssert.assertResult(p); } @Test public void testFlatMapProp() { - CheckResult cr = property( + Arbitrary>> a = arbF(coarbInteger, arbReader()); + Property p = property( arbF(coarbInteger, arbInteger), - arbF2(coarbInteger, coarbInteger, arbInteger), + a, arbInteger, (f, g, i) -> { - int expected = bind(f, curry(g)).f(i); + int expected = bind(f, j -> g.f(j).getFunction()).f(i); // System.out.println(String.format("input: %d, result: %d", i, expected)); - return prop(expected == Reader.unit(f).flatMap(toBindable(g)).f(i)); + return prop(expected == Reader.unit(f).flatMap(g).f(i)); } - ).check(); - CheckResult.summary.println(cr); - assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + ); + PropertyAssert.assertResult(p); } + // Left identity: return a >>= f == f a @Test public void testLeftIdentity() { - CheckResult cr = Property.property( + Property p = Property.property( arbInteger, - arbF(coarbInteger, arbInteger), - arbF2(coarbInteger, coarbInteger, arbInteger), - (i, f, g) -> { -// F> h = convert(g); - int a = Reader.unit(f).flatMap(toBindable(g)).f(i); - int b = g.f(f.f(i), i); -// System.out.println(String.format("i=%d, a=%d, b=%d, truth=%b", i, a, b, a == b)); - return prop(a == b); - }).check(); - CheckResult.summary.println(cr); - assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); - } - - F> toBindable(F2 f) { -// F> h = map(curry(f), z -> Reader.unit(z)); - return map(curry(f), z -> Reader.unit(z)); + arbInteger, + arbF(coarbInteger, arbReader()), + (i, j, f) -> { + int a = Reader.constant(i).flatMap(f).f(j); + int b = f.f(i).f(j); + return prop(a == b); + }); + PropertyAssert.assertResult(p); } + // Right identity: m >>= return == m @Test public void testRightIdentity() { - CheckResult cr = Property.property( + Property p = Property.property( arbInteger, - arbF(coarbInteger, arbInteger), - (i, f) -> { - Reader r = Reader.unit(f); - boolean b = r.flatMap(a -> r).f(i) == r.f(i); -// System.out.println(String.format("i=%d, a=%d, b=%d, truth=%b", i, a, b, a == b)); - return prop(b); - }).check(); - CheckResult.summary.println(cr); - assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + arbReader(), + (i, r2) -> { + return prop(r2.flatMap(a -> Reader.constant(a)).f(i) == r2.f(i)); + }); + PropertyAssert.assertResult(p); } - - + // Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g) @Test public void testAssociativity() { - CheckResult cr = Property.property( + Property p = Property.property( arbInteger, - arbF(coarbInteger, arbInteger), - arbF2(coarbInteger, coarbInteger, arbInteger), - arbF2(coarbInteger, coarbInteger, arbInteger), - (i, f, g, h) -> { - Reader r = Reader.unit(f); - int a = r.flatMap(toBindable(g)).flatMap(toBindable(h)).f(i); - int b = r.flatMap(x -> toBindable(g).f(x).flatMap(toBindable(h))).f(i); -// System.out.println(String.format("i=%d, a=%d, b=%d, truth=%b", i, a, b, a == b)); - return prop(a == b); - }).check(); - CheckResult.summary.println(cr); - assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + arbReader(), + arbF(coarbInteger, arbReader()), + arbF(coarbInteger, arbReader()), + (i, r, f, g) -> { + boolean b2 = r.flatMap(f).flatMap(g).f(i) == r.flatMap(x -> f.f(x).flatMap(g)).f(i); + return prop(b2); + }); + PropertyAssert.assertResult(p); } + public Arbitrary> arbReader() { + return Arbitrary.arbReader(coarbInteger, arbInteger); + } } diff --git a/core/src/test/java/fj/data/WriterTest.java b/core/src/test/java/fj/data/WriterTest.java index fa14e0a9..d8f2d2a0 100644 --- a/core/src/test/java/fj/data/WriterTest.java +++ b/core/src/test/java/fj/data/WriterTest.java @@ -2,15 +2,13 @@ import fj.Equal; import fj.F; -import fj.F2; +import fj.data.test.PropertyAssert; import fj.test.Arbitrary; -import fj.test.CheckResult; import fj.test.Property; import org.junit.Assert; import org.junit.Test; -import static fj.F1Functions.map; -import static fj.F2Functions.curry; +import static fj.data.test.PropertyAssert.assertResult; import static fj.test.Arbitrary.*; import static fj.test.Coarbitrary.coarbInteger; import static fj.test.Property.prop; @@ -37,18 +35,12 @@ boolean tellTruth(String s1, String s2, int i) { } final Equal> eq = Equal.writerEqual(Equal.stringEqual, Equal.intEqual); - final F> defaultWriter = Writer.stringLogger(); - - void assertProperty(Property p) { - CheckResult cr = p.check(); - CheckResult.summary.println(cr); - assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); - } + final F> defaultWriter = Writer.stringLogger();git @Test public void testTellProp() { Property p = property(arbString, arbString, arbInteger, (s1, s2, i) -> prop(tellTruth(s1, s2, i))); - assertProperty(p); + assertResult(p); } @Test @@ -57,7 +49,7 @@ public void testMap() { boolean b = eq.eq(defaultWriter.f(i).map(f), defaultWriter.f(f.f(i))); return prop(b); }); - assertProperty(p); + assertResult(p); } @Test @@ -66,7 +58,7 @@ public void testFlatMap() { boolean b = eq.eq(Writer.stringLogger().f(i).flatMap(f), f.f(i)); return prop(b); }); - assertProperty(p); + assertResult(p); } @@ -87,7 +79,7 @@ public void testLeftIdentity() { (i, f) -> { return prop(eq.eq(defaultWriter.f(i).flatMap(f), f.f(i))); }); - assertProperty(p); + assertResult(p); } // Right identity: m >>= return == m @@ -97,7 +89,7 @@ public void testRightIdentity() { arbWriterStringInt(), (w) -> prop(eq.eq(w.flatMap(a -> defaultWriter.f(a)), w)) ); - assertProperty(p); + assertResult(p); } // Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g) @@ -111,7 +103,7 @@ public void testAssociativity() { boolean t = eq.eq(w.flatMap(f).flatMap(g), w.flatMap(x -> f.f(x).flatMap(g))); return prop(t); }); - assertProperty(p); + assertResult(p); } diff --git a/core/src/test/java/fj/data/test/PropertyAssert.java b/core/src/test/java/fj/data/test/PropertyAssert.java new file mode 100644 index 00000000..bec07f7f --- /dev/null +++ b/core/src/test/java/fj/data/test/PropertyAssert.java @@ -0,0 +1,20 @@ +package fj.data.test; + +import fj.Unit; +import fj.test.CheckResult; +import fj.test.Property; +import org.junit.Assert; + +/** + * Created by MarkPerry on 18/12/2014. + */ +public class PropertyAssert { + + public static Unit assertResult(Property p) { + CheckResult cr = p.check(); + CheckResult.summary.println(cr); + Assert.assertTrue(cr.isExhausted() || cr.isPassed() || cr.isProven()); + return Unit.unit(); + } + +} From 158276fcc435fc5c9d07a2a085ac9608355d49ea Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 18 Dec 2014 02:02:29 +1000 Subject: [PATCH 188/811] Fixed inadvertent edit --- core/src/test/java/fj/data/WriterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/fj/data/WriterTest.java b/core/src/test/java/fj/data/WriterTest.java index d8f2d2a0..158a2314 100644 --- a/core/src/test/java/fj/data/WriterTest.java +++ b/core/src/test/java/fj/data/WriterTest.java @@ -35,7 +35,7 @@ boolean tellTruth(String s1, String s2, int i) { } final Equal> eq = Equal.writerEqual(Equal.stringEqual, Equal.intEqual); - final F> defaultWriter = Writer.stringLogger();git + final F> defaultWriter = Writer.stringLogger(); @Test public void testTellProp() { From 26c674c4ea4dfa2785b2cb3350861c321afa1fb4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 19 Dec 2014 01:24:03 +1000 Subject: [PATCH 189/811] Added property based tests for State --- core/src/main/java/fj/LcgRng.java | 6 +- core/src/main/java/fj/Rng.java | 1 + core/src/main/java/fj/test/Arbitrary.java | 15 ++++ core/src/main/java/fj/test/Coarbitrary.java | 56 ++++++++------ core/src/test/java/fj/data/StateTest.java | 15 ++++ core/src/test/java/fj/data/TestRngState.java | 78 ++++++++++++++++++++ 6 files changed, 149 insertions(+), 22 deletions(-) create mode 100644 core/src/test/java/fj/data/StateTest.java diff --git a/core/src/main/java/fj/LcgRng.java b/core/src/main/java/fj/LcgRng.java index 16962c15..d2c244b6 100644 --- a/core/src/main/java/fj/LcgRng.java +++ b/core/src/main/java/fj/LcgRng.java @@ -7,7 +7,7 @@ */ public class LcgRng extends Rng { - private Long seed; + private final Long seed; public LcgRng() { this(System.currentTimeMillis()); @@ -17,6 +17,10 @@ public LcgRng(long s) { seed = s; } + public long getSeed() { + return seed; + } + public P2 nextInt() { P2 p = nextLong(); int i = (int) p._2().longValue(); diff --git a/core/src/main/java/fj/Rng.java b/core/src/main/java/fj/Rng.java index 679be544..45f03c06 100644 --- a/core/src/main/java/fj/Rng.java +++ b/core/src/main/java/fj/Rng.java @@ -9,6 +9,7 @@ public abstract class Rng { public abstract P2 nextLong(); + // [low, high] inclusive public P2 range(int low, int high) { return nextNatural().map2(x -> (x % (high - low + 1)) + low); } diff --git a/core/src/main/java/fj/test/Arbitrary.java b/core/src/main/java/fj/test/Arbitrary.java index cd4fd38c..e7545fe6 100644 --- a/core/src/main/java/fj/test/Arbitrary.java +++ b/core/src/main/java/fj/test/Arbitrary.java @@ -20,6 +20,7 @@ import fj.P7; import fj.P8; import fj.data.*; +import fj.LcgRng; import static fj.data.Either.left; import static fj.data.Either.right; @@ -127,6 +128,20 @@ public static Arbitrary> arbReader(Coarbitrary aa, Arbitr return arbitrary(Arbitrary.arbF(aa, ab).gen.map(f -> Reader.unit(f))); } + /** + * An arbitrary for state. + */ + public static Arbitrary> arbState(Arbitrary as, Coarbitrary cs, Arbitrary aa) { + return arbitrary(arbF(cs, arbP2(as, aa)).gen.map(f -> State.unit(f))); + } + + /** + * An arbitrary for the LcgRng. + */ + public static Arbitrary arbLcgRng() { + return arbitrary(Arbitrary.arbLong.gen.map(l -> new LcgRng(l))); + } + /** * An arbitrary for functions. * diff --git a/core/src/main/java/fj/test/Coarbitrary.java b/core/src/main/java/fj/test/Coarbitrary.java index d506e428..34b3f07a 100644 --- a/core/src/main/java/fj/test/Coarbitrary.java +++ b/core/src/main/java/fj/test/Coarbitrary.java @@ -1,31 +1,15 @@ package fj.test; -import fj.F; -import fj.F2; -import fj.F3; -import fj.F4; -import fj.F5; -import fj.F6; -import fj.F7; -import fj.F8; +import fj.*; + import static fj.Function.curry; import static fj.P.p; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.P4; -import fj.P5; -import fj.P6; -import fj.P7; -import fj.P8; -import fj.data.Array; + +import fj.data.*; + import static fj.data.Array.array; -import fj.data.Either; -import fj.data.List; import static fj.data.List.fromString; import static fj.data.List.nil; -import fj.data.Option; -import fj.data.Stream; import static fj.test.Variant.variant; @@ -84,6 +68,7 @@ public abstract class Coarbitrary { */ public abstract Gen coarbitrary(A a, Gen g); + /** * A curried version of {@link #coarbitrary(Object, Gen)}. * @@ -472,6 +457,35 @@ public Gen coarbitrary(final Stream as, final Gen g) { }; } + /** + * A coarbitrary for the provided LcgRng + * @return A coarbitrary for the provided LcgRng. + */ + public static Coarbitrary coarbLcgRng() { + return new Coarbitrary() { + @Override + public Gen coarbitrary(LcgRng rng, Gen g) { + long i = rng.getSeed(); + return variant(i >= 0 ? 2 * i : -2 * i + 1, g); + } + }; + } + + /** + * A coarbitrary for state. + */ + public static Coarbitrary> coarbState(Arbitrary as, F2 f) { + return new Coarbitrary>() { + @Override + public Gen coarbitrary(State s1, Gen g) { + return as.gen.bind(r -> { + P2 p = s1.run(r); + return variant(f.f(p._1(), p._2()), g); + }); + } + }; + } + /** * A coarbitrary for arrays. * diff --git a/core/src/test/java/fj/data/StateTest.java b/core/src/test/java/fj/data/StateTest.java new file mode 100644 index 00000000..9fc8a9fb --- /dev/null +++ b/core/src/test/java/fj/data/StateTest.java @@ -0,0 +1,15 @@ +package fj.data; + +import org.junit.Test; + +/** + * Created by MarkPerry on 18/12/2014. + */ +public class StateTest { + + @Test + public void map() { + + } + +} diff --git a/core/src/test/java/fj/data/TestRngState.java b/core/src/test/java/fj/data/TestRngState.java index 4a6e77fe..0deac432 100644 --- a/core/src/test/java/fj/data/TestRngState.java +++ b/core/src/test/java/fj/data/TestRngState.java @@ -1,11 +1,21 @@ package fj.data; import fj.*; +import fj.test.Arbitrary; +import fj.test.Coarbitrary; +import fj.test.Gen; +import fj.test.Property; import org.junit.Assert; import org.junit.Test; import static fj.data.Option.some; import static fj.data.Stream.unfold; +import static fj.data.test.PropertyAssert.assertResult; +import static fj.test.Arbitrary.*; +import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static fj.test.Variant.variant; /** * Created by mperry on 4/08/2014. @@ -68,4 +78,72 @@ public void testTraverse() { Assert.assertTrue(list.toString().equals(expected)); } + public static Arbitrary> arbState() { + return Arbitrary.arbState(Arbitrary.arbLcgRng(), Coarbitrary.coarbLcgRng(), arbInteger); + } + + public static Arbitrary>> arbStateF() { + return arbF(Coarbitrary.coarbLcgRng(), arbP2(arbLcgRng(), arbInteger)); + } + + public static Coarbitrary> coarbState() { + return Coarbitrary.coarbState(Arbitrary.arbLcgRng(), (LcgRng s, Integer j) -> (long) (j >= 0 ? 2 * j : -2 * j + 1)); + } + + public static Arbitrary>> arbBindable() { + return arbF(coarbInteger, arbState()); + } + + // Left identity: return i >>= f == f i + @Test + public void testLeftIdentity() { + Property p = property( + arbBindable(), + arbInteger, + arbLcgRng(), + (f, i, r) -> { + int a = State.constant(i).flatMap(f).eval(r); + int b = f.f(i).eval(r); +// System.out.println(String.format("a=%d, b=%d", a, b)); + return prop(a == b); + } + ); + assertResult(p); + } + + + // Right identity: m >>= return == m + @Test + public void testRightIdentity() { + Property p = Property.property( + arbState(), + arbLcgRng(), + (s, r) -> { + int x = s.flatMap(a -> State.constant(a)).eval(r); + int y = s.eval(r); +// System.out.println(String.format("x=%d, y=%d", x, y)); + return prop(x == y); + } + ); + assertResult(p); + } + + // Associativity: (m >>= f) >>= g == m >>= (\x -> f x >>= g) + @Test + public void testAssociativity() { + Property p = Property.property( + arbState(), + arbBindable(), + arbBindable(), + arbLcgRng(), + (s, f, g, r) -> { + int t = s.flatMap(f).flatMap(g).eval(r); + int u = s.flatMap(x -> f.f(x).flatMap(g)).eval(r); +// System.out.println(String.format("x=%d, y=%d", t, u)); + return prop(t == u); + }); + assertResult(p); + } + + } From be6f83250ad090afece1b31d5d45afc6feb4088b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 20 Dec 2014 23:19:31 +1000 Subject: [PATCH 190/811] Updated readme for potential 4.2 release --- README.adoc | 10 ++++++---- etc/release-notes.md | 10 +++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/README.adoc b/README.adoc index 8e15dbf8..44dadda3 100644 --- a/README.adoc +++ b/README.adoc @@ -4,7 +4,7 @@ image::http://www.functionaljava.org/img/logo-600x144.png[] Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. -The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8 and beyond. +The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8. Functional Java provides abstractions for the following types: @@ -52,7 +52,7 @@ and in Maven: FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 7 bytecode. This requires access to both JDK 7 and 8. The build system requires the environment variables `JAVA7_HOME` and `JAVA8_HOME` to refer to the appropriate directories. -Building is done using Gradle 2.0. In the root directory run: +Building is done using Gradle 2.2.1. In the root directory run: ---- ./gradlew ---- @@ -64,7 +64,9 @@ A more complete description of the features mentioned above are: * Basic Data Structures ** Functions with arity 1 to 8 (`fj.F`). -** Functions with arity 0 to 8 that can produce exceptions (`fj.TryCatch`). +** Functions with arity 0 to 8 that can produce exceptions (`fj.Try`). +** Functions with arity 0 to 8 that have a void return (`fj.Effect`). +** Functions with arity 0 to 8 that have a void return and can throw an exception (`fj.TryEffect`). ** Products with arity 1 to 8 (`fj.P`). ** Unit type (`fj.Unit`). ** Optional value - _type-safe null_ (`fj.data.Option`). @@ -96,4 +98,4 @@ A more complete description of the features mentioned above are: == License -link:etc/LICENCE[The Functional Java license] uses the BSD 3 license, available at (3-clause license, https://en.wikipedia.org/wiki/BSD_licenses[]). \ No newline at end of file +link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause license) available at https://en.wikipedia.org/wiki/BSD_licenses[]. \ No newline at end of file diff --git a/etc/release-notes.md b/etc/release-notes.md index b0b9219a..9e13b55f 100644 --- a/etc/release-notes.md +++ b/etc/release-notes.md @@ -10,9 +10,11 @@ Release target: Aug 2014 * Added Java 8 examples * Added new website * Added Option.none_() - * Gradle 2.0 support with wrapper + * Gradle 2.2.1 support with wrapper * Added to Strings: isNullOrEmpty, isNullOrBlank and isNotNullOrBlank * Added Try with arity 0-8 for lambdas that throw exceptions + * Added Effect with arity 0-8 for lambdas with a void return + * Added TryEffect with arity 0-8 for lambdas with a void return that throw an Exception. * Conversion from Java 8 types to Functional Java types and vice-versa * Added monadic IO methods * Support instantiation of IO with lambdas @@ -29,6 +31,11 @@ Release target: Aug 2014 * Added Option.toValidation * Added map and contramap for F and F2. * Added partial application for F1. + * Added filter and uncurried foldLeft and foldRight to FingerTree. + * Added foldLeft, foldRight and map to Seq. + * Accumulate Validation errors in a List. + * Convert from fj.data.Stream to java.util.Stream and vice versa. + * Added groupBy on List. * Fixes * Various Javadoc issues * Large inserts into TreeMap @@ -37,6 +44,7 @@ Release target: Aug 2014 * Exception propagation in test data generators * Product memoisation for arities 1 to 8 * ClassCastException in class fj.data.Java + * Fixed performance of Set.member. 4.1 === From b5b852db02b435a3eae61f5c1836bf1ad1163ef1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 20 Dec 2014 23:43:22 +1000 Subject: [PATCH 191/811] Updated version to 4.2, updated gradle retrolambda version --- build.gradle | 6 +++--- core/build.gradle | 2 +- demo/build.gradle | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index b13c16e0..321a87ba 100644 --- a/build.gradle +++ b/build.gradle @@ -15,8 +15,8 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = true - fjBaseVersion = "4.2-beta-2" + isSnapshot = false + fjBaseVersion = "4.2" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") @@ -57,7 +57,7 @@ subprojects { } dependencies { - classpath 'me.tatarka:gradle-retrolambda:1.3.1' + classpath 'me.tatarka:gradle-retrolambda:2.5.0' } } diff --git a/core/build.gradle b/core/build.gradle index ae71be3f..1d6e6b76 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,5 +1,5 @@ -apply plugin: 'retrolambda' +apply plugin: 'me.tatarka.retrolambda' ext { signModule = true diff --git a/demo/build.gradle b/demo/build.gradle index df833911..6d95183f 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'application' -apply plugin: 'retrolambda' +apply plugin: 'me.tatarka.retrolambda' mainClassName = "fj.demo.euler.Problem2" From ec6283069ecfcaa6cde648e4e4f38e6a716420dd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 21 Dec 2014 01:38:39 +1000 Subject: [PATCH 192/811] Consume FJ 4.2 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 321a87ba..1777e147 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.2-beta-1" + fjConsumeVersion = "4.2" signModule = false From 9954c3753c41307e2e8a862a70604f8b87f1e06b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 21 Dec 2014 01:54:25 +1000 Subject: [PATCH 193/811] Update version to 4.3-SNAPSHOT --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1777e147..ef8501dc 100644 --- a/build.gradle +++ b/build.gradle @@ -15,8 +15,8 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { ext { - isSnapshot = false - fjBaseVersion = "4.2" + isSnapshot = true + fjBaseVersion = "4.3" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") From 8f2a793b4ca298ef3a6899c25df6dba8f1e9b7f3 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sun, 21 Dec 2014 14:05:36 +0530 Subject: [PATCH 194/811] Refactoring Try type --- core/src/main/java/fj/Try.java | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index 934201e8..0d881b8f 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -24,9 +24,9 @@ public class Try { static public P1> f(final Try0 t) { return P.lazy(u -> { try { - return Validation.success(t.f()); + return success(t.f()); } catch (Exception e) { - return Validation.fail((E) e); + return fail((E) e); } }); } @@ -42,7 +42,7 @@ static public F> f(final Try1 F> f(final Try1 F2> f(final Try2 t) { return (a, b) -> { try { - return Validation.success(t.f(a, b)); + return success(t.f(a, b)); } catch (Exception e) { - return Validation.fail((E) e); + return fail((E) e); } }; } @@ -88,9 +88,9 @@ static public F3> f( static public F4> f(final Try4 t) { return (a, b, c, d) -> { try { - return Validation.success(t.f(a, b, c, d)); + return success(t.f(a, b, c, d)); } catch (Exception ex) { - return Validation.fail((Z) ex); + return fail((Z) ex); } }; } @@ -104,9 +104,9 @@ static public F4 F5> f(final Try5 t) { return (a, b, c, d, e) -> { try { - return Validation.success(t.f(a, b, c, d, e)); + return success(t.f(a, b, c, d, e)); } catch (Exception ex) { - return Validation.fail((Z) ex); + return fail((Z) ex); } }; } @@ -120,9 +120,9 @@ static public F5 F6> f(final Try6 t) { return (a, b, c, d, e, f) -> { try { - return Validation.success(t.f(a, b, c, d, e, f)); + return success(t.f(a, b, c, d, e, f)); } catch (Exception ex) { - return Validation.fail((Z) ex); + return fail((Z) ex); } }; } @@ -136,9 +136,9 @@ static public F6 F7> f(final Try7 t) { return (a, b, c, d, e, f, g) -> { try { - return Validation.success(t.f(a, b, c, d, e, f, g)); + return success(t.f(a, b, c, d, e, f, g)); } catch (Exception ex) { - return Validation.fail((Z) ex); + return fail((Z) ex); } }; } @@ -149,12 +149,12 @@ static public F7 F8> f(final Try8 t) { + public static F8> f(final Try8 t) { return (a, b, c, d, e, f, g, h) -> { try { - return Validation.success(t.f(a, b, c, d, e, f, g, h)); + return success(t.f(a, b, c, d, e, f, g, h)); } catch (Exception ex) { - return Validation.fail((Z) ex); + return fail((Z) ex); } }; } From dbce6aaad8479e864eb5c0f1fbb163bf3c305591 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sun, 21 Dec 2014 16:27:21 +0530 Subject: [PATCH 195/811] Refactoring F1Functions : replacing anonymous classes using lamda --- core/src/main/java/fj/F1Functions.java | 260 +++++-------------------- 1 file changed, 49 insertions(+), 211 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index b0e84f00..14730860 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -29,11 +29,7 @@ public class F1Functions { * @return The composed function such that this function is applied last. */ static public F o(final F f, final F g) { - return new F() { - public B f(final C c) { - return f.f(g.f(c)); - } - }; + return (c) -> f.f(g.f(c)); } /** @@ -42,11 +38,7 @@ public B f(final C c) { * @return A function that composes this function with another. */ static public F, F> o(final F f) { - return new F, F>() { - public F f(final F g) { - return o(f, g); - } - }; + return (g) -> o(f, g); } /** @@ -66,11 +58,7 @@ static public F andThen(final F f, final F g) { * @return A function that invokes this function and then a given function on the result. */ static public F, F> andThen(final F f) { - return new F, F>() { - public F f(final F g) { - return andThen(f, g); - } - }; + return (g) -> andThen(f, g); } /** @@ -80,12 +68,7 @@ public F f(final F g) { * @return A function that invokes this function on its argument and then the given function on the result. */ static public F bind(final F f, final F> g) { - return new F() { - @SuppressWarnings({"unchecked"}) - public C f(final A a) { - return g.f(f.f(a)).f(a); - } - }; + return (a) -> g.f(f.f(a)).f(a); } /** @@ -94,11 +77,7 @@ public C f(final A a) { * @return A function that binds another function across this function. */ static public F>, F> bind(final F f) { - return new F>, F>() { - public F f(final F> g) { - return bind(f, g); - } - }; + return (g) -> bind(f, g); } /** @@ -110,12 +89,7 @@ public F f(final F> g) { * applied to the result of applying this function to the argument. */ static public F apply(final F f, final F> g) { - return new F() { - @SuppressWarnings({"unchecked"}) - public C f(final A a) { - return g.f(a).f(f.f(a)); - } - }; + return (a) -> g.f(a).f(f.f(a)); } /** @@ -124,11 +98,7 @@ public C f(final A a) { * @return A function that applies a given function within the environment of this function. */ static public F>, F> apply(final F f) { - return new F>, F>() { - public F f(final F> g) { - return apply(f, g); - } - }; + return (g) -> apply(f, g); } /** @@ -138,30 +108,20 @@ public F f(final F> g) { * @return A new function that invokes this function on its arguments before invoking the given function. */ static public F> on(final F f, final F> g) { - return new F>() { - public F f(final A a1) { - return new F() { - @SuppressWarnings({"unchecked"}) - public C f(final A a2) { - return g.f(f.f(a1)).f(f.f(a2)); - } - }; - } - }; + return (a1) -> + (a2) -> + g.f(f.f(a1)).f(f.f(a2)); } + /** * Applies this function over the arguments of another function. * * @return A function that applies this function over the arguments of another function. */ static public F>, F>> on(final F f) { - return new F>, F>>() { - public F> f(final F> g) { - return on(f, g); - } - }; + return (g) -> on(f, g); } /** @@ -170,15 +130,11 @@ public F> f(final F> g) { * @return This function promoted to return its result in a product-1. */ static public F> lazy(final F f) { - return new F>() { - public P1 f(final A a) { - return new P1() { - public B _1() { - return f.f(a); - } - }; - } - }; + return (a) -> new P1(){ + public B _1() { + return f.f(a); + } + }; } /** @@ -197,11 +153,7 @@ static public P1 f(final F f, final A a) { * @return This function promoted to map over a product-1. */ static public F, P1> mapP1(final F f) { - return new F, P1>() { - public P1 f(final P1 p) { - return p.map(f); - } - }; + return (p) -> p.map(f); } /** @@ -210,11 +162,7 @@ public P1 f(final P1 p) { * @return This function promoted to return its result in an Option. */ static public F> optionK(final F f) { - return new F>() { - public Option f(final A a) { - return some(f.f(a)); - } - }; + return (a) -> some(f.f(a)); } /** @@ -223,11 +171,7 @@ public Option f(final A a) { * @return This function promoted to map over an optional value. */ static public F, Option> mapOption(final F f) { - return new F, Option>() { - public Option f(final Option o) { - return o.map(f); - } - }; + return (o) -> o.map(f); } /** @@ -236,11 +180,7 @@ public Option f(final Option o) { * @return This function promoted to return its result in a List. */ static public F> listK(final F f) { - return new F>() { - public List f(final A a) { - return List.single(f.f(a)); - } - }; + return (a) -> List.single(f.f(a)); } /** @@ -249,11 +189,7 @@ public List f(final A a) { * @return This function promoted to map over a List. */ static public F, List> mapList(final F f) { - return new F, List>() { - public List f(final List x) { - return x.map(f); - } - }; + return (x) -> x.map(f); } /** @@ -262,11 +198,7 @@ public List f(final List x) { * @return This function promoted to return its result in a Stream. */ static public F> streamK(final F f) { - return new F>() { - public Stream f(final A a) { - return Stream.single(f.f(a)); - } - }; + return (a) -> Stream.single(f.f(a)); } /** @@ -275,11 +207,7 @@ public Stream f(final A a) { * @return This function promoted to map over a Stream. */ static public F, Stream> mapStream(final F f) { - return new F, Stream>() { - public Stream f(final Stream x) { - return x.map(f); - } - }; + return (x) -> x.map(f); } /** @@ -288,11 +216,8 @@ public Stream f(final Stream x) { * @return This function promoted to return its result in a Array. */ static public F> arrayK(final F f) { - return new F>() { - public Array f(final A a) { - return Array.single(f.f(a)); - } - }; + return (a) -> Array.single(f.f(a)); + } /** @@ -301,11 +226,7 @@ public Array f(final A a) { * @return This function promoted to map over a Array. */ static public F, Array> mapArray(final F f) { - return new F, Array>() { - public Array f(final Array x) { - return x.map(f); - } - }; + return (x) -> x.map(f); } /** @@ -314,11 +235,7 @@ public Array f(final Array x) { * @return A function that comaps over a given actor. */ static public F, Actor> comapActor(final F f) { - return new F, Actor>() { - public Actor f(final Actor a) { - return a.comap(f); - } - }; + return (a) -> a.comap(f); } /** @@ -337,11 +254,7 @@ static public F> promiseK(final F f, final Strategy F, Promise> mapPromise(final F f) { - return new F, Promise>() { - public Promise f(final Promise p) { - return p.fmap(f); - } - }; + return (p) -> p.fmap(f); } /** @@ -392,11 +305,7 @@ static public F, Either> mapRight(final F f) * @return a function that returns the left side of a given Either, or this function applied to the right side. */ static public F, B> onLeft(final F f) { - return new F, B>() { - public B f(final Either either) { - return either.left().on(f); - } - }; + return (e) -> e.left().on(f); } /** @@ -405,11 +314,7 @@ public B f(final Either either) { * @return a function that returns the right side of a given Either, or this function applied to the left side. */ static public F, B> onRight(final F f) { - return new F, B>() { - public B f(final Either either) { - return either.right().on(f); - } - }; + return (e) -> e.right().on(f); } /** @@ -448,11 +353,7 @@ static public F> nelK(final F f) { * @return This function promoted to map over a NonEmptyList. */ static public F, NonEmptyList> mapNel(final F f) { - return new F, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList list) { - return list.map(f); - } - }; + return (list) -> list.map(f); } /** @@ -463,11 +364,7 @@ public NonEmptyList f(final NonEmptyList list) { */ static public F> setK(final F f, final Ord o ) { - return new F>() { - public Set f(final A a) { - return Set.single(o, f.f(a)); - } - }; + return (a) -> Set.single(o, f.f(a)); } /** @@ -477,11 +374,7 @@ public Set f(final A a) { * @return This function promoted to map over a Set. */ static public F, Set> mapSet(final F f, final Ord o) { - return new F, Set>() { - public Set f(final Set set) { - return set.map(o, f); - } - }; + return (s) -> s.map(o, f); } /** @@ -490,11 +383,7 @@ public Set f(final Set set) { * @return This function promoted to return its value in a Tree. */ static public F> treeK(final F f) { - return new F>() { - public Tree f(final A a) { - return Tree.leaf(f.f(a)); - } - }; + return (a) -> Tree.leaf(f.f(a)); } /** @@ -532,11 +421,7 @@ static public F> treeZipperK(final F f) { * @return This function promoted to map over a TreeZipper. */ static public F, TreeZipper> mapTreeZipper(final F f) { - return new F, TreeZipper>() { - public TreeZipper f(final TreeZipper zipper) { - return zipper.map(f); - } - }; + return (z) -> z.map(f); } /** @@ -546,11 +431,8 @@ public TreeZipper f(final TreeZipper zipper) { * @return This function promoted to return its result on the failure side of a Validation. */ static public F> failK(final F f) { - return new F>() { - public Validation f(final A a) { - return Validation.fail(f.f(a)); - } - }; + return (a) -> Validation.fail(f.f(a)); + } /** @@ -560,11 +442,7 @@ public Validation f(final A a) { * @return This function promoted to return its result on the success side of an Validation. */ static public F> successK(final F f) { - return new F>() { - public Validation f(final A a) { - return Validation.success(f.f(a)); - } - }; + return (a) -> Validation.success(f.f(a)); } /** @@ -573,11 +451,7 @@ public Validation f(final A a) { * @return This function promoted to map over the failure side of a Validation. */ static public F, Validation> mapFail(final F f) { - return new F, Validation>() { - public Validation f(final Validation validation) { - return validation.f().map(f); - } - }; + return (v) -> v.f().map(f); } /** @@ -586,11 +460,7 @@ public Validation f(final Validation validation) { * @return This function promoted to map over the success side of a Validation. */ static public F, Validation> mapSuccess(final F f) { - return new F, Validation>() { - public Validation f(final Validation validation) { - return validation.map(f); - } - }; + return (v) -> v.map(f); } /** @@ -601,11 +471,7 @@ public Validation f(final Validation validation) { * or this function applied to the success side. */ static public F, B> onFail(final F f) { - return new F, B>() { - public B f(final Validation v) { - return v.f().on(f); - } - }; + return (v) -> v.f().on(f); } /** @@ -616,11 +482,7 @@ public B f(final Validation v) { * or this function applied to the failure side. */ static public F, B> onSuccess(final F f) { - return new F, B>() { - public B f(final Validation v) { - return v.on(f); - } - }; + return (v) -> v.on(f); } /** @@ -629,11 +491,7 @@ public B f(final Validation v) { * @return This function promoted to return its value in a Zipper. */ static public F> zipperK(final F f) { - return andThen(streamK(f), new F, Zipper>() { - public Zipper f(final Stream stream) { - return fromStream(stream).some(); - } - }); + return andThen(streamK(f), (s) -> fromStream(s).some()); } /** @@ -642,11 +500,7 @@ public Zipper f(final Stream stream) { * @return This function promoted to map over a Zipper. */ static public F, Zipper> mapZipper(final F f) { - return new F, Zipper>() { - public Zipper f(final Zipper zipper) { - return zipper.map(f); - } - }; + return (z) -> z.map(f); } /** @@ -655,11 +509,7 @@ public Zipper f(final Zipper zipper) { * @return This function promoted to map over an Equal as a contravariant functor. */ static public F, Equal> comapEqual(final F f) { - return new F, Equal>() { - public Equal f(final Equal equal) { - return equal.comap(f); - } - }; + return (e) -> e.comap(f); } /** @@ -668,11 +518,7 @@ public Equal f(final Equal equal) { * @return This function promoted to map over a Hash as a contravariant functor. */ static public F, Hash> comapHash(final F f) { - return new F, Hash>() { - public Hash f(final Hash hash) { - return hash.comap(f); - } - }; + return (h) -> h.comap(f); } /** @@ -681,11 +527,7 @@ public Hash f(final Hash hash) { * @return This function promoted to map over a Show as a contravariant functor. */ static public F, Show> comapShow(final F f) { - return new F, Show>() { - public Show f(final Show s) { - return s.comap(f); - } - }; + return (s) -> s.comap(f); } /** @@ -712,11 +554,7 @@ static public F, P2> mapSnd(final F f) { * @return This function promoted to map over both elements of a pair. */ static public F, P2> mapBoth(final F f) { - return new F, P2>() { - public P2 f(final P2 aap2) { - return P2.map(f, aap2); - } - }; + return (p2) -> P2.map(f, p2); } /** From d41301da263815ffabf47dbd907f1adf06d19e6f Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sun, 21 Dec 2014 20:55:24 +0530 Subject: [PATCH 196/811] Refactorings: using lamdas instead of anonymous classes --- core/src/main/java/fj/Digit.java | 24 +--- core/src/main/java/fj/Effect.java | 12 +- core/src/main/java/fj/F2Functions.java | 161 ++++++------------------- 3 files changed, 45 insertions(+), 152 deletions(-) diff --git a/core/src/main/java/fj/Digit.java b/core/src/main/java/fj/Digit.java index ed6e86ab..ba3c2245 100644 --- a/core/src/main/java/fj/Digit.java +++ b/core/src/main/java/fj/Digit.java @@ -176,36 +176,20 @@ public static Option fromChar(final char c) { /** * First-class conversion from digit to a long. */ - public static final F toLong = new F() { - public Long f(final Digit d) { - return d.toLong(); - } - }; + public static final F toLong = d -> d.toLong(); /** * First-class conversion from a long to a digit. */ - public static final F fromLong = new F() { - public Digit f(final Long i) { - return fromLong(i); - } - }; + public static final F fromLong = i -> fromLong(i); /** * First-class conversion from a digit to a character. */ - public static final F toChar = new F() { - public Character f(final Digit d) { - return d.toChar(); - } - }; + public static final F toChar = d -> d.toChar(); /** * First-class conversion from a character to a digit. */ - public static final F> fromChar = new F>() { - public Option f(final Character c) { - return fromChar(c); - } - }; + public static final F> fromChar = c -> fromChar(c); } diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index c9bb252d..3e9cbc93 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -93,18 +93,14 @@ public static F5 f(Effect5 z * @return An effect after a contra-variant map. */ public final Effect1 comap(Effect1 e1, final F f) { - return new Effect1() { - public void f(final B b) { - e1.f(f.f(b)); - } + return b -> { + e1.f(f.f(b)); }; } public static Effect1 lazy(final F f) { - return new Effect1() { - public void f(final A a) { - f.f(a); - } + return a -> { + f.f(a); }; } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index fda0421b..e9de58b9 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -24,11 +24,7 @@ public class F2Functions { * @return The function partially applied to the given argument. */ static public F f(final F2 f, final A a) { - return new F() { - public C f(final B b) { - return f.f(a, b); - } - }; + return b -> f.f(a, b); } /** @@ -37,15 +33,7 @@ public C f(final B b) { * @return a wrapped function of arity-1 that returns another wrapped function. */ static public F> curry(final F2 f) { - return new F>() { - public F f(final A a) { - return new F() { - public C f(final B b) { - return f.f(a, b); - } - }; - } - }; + return a -> b -> f.f(a, b); } /** @@ -54,11 +42,7 @@ public C f(final B b) { * @return A new function with the arguments of this function flipped. */ static public F2 flip(final F2 f) { - return new F2() { - public C f(final B b, final A a) { - return f.f(a, b); - } - }; + return (b, a) -> f.f(a, b); } /** @@ -67,11 +51,7 @@ public C f(final B b, final A a) { * @return A new function that calls this function with the elements of a given tuple. */ static public F, C> tuple(final F2 f) { - return new F, C>() { - public C f(final P2 p) { - return f.f(p._1(), p._2()); - } - }; + return p -> f.f(p._1(), p._2()); } /** @@ -80,11 +60,7 @@ public C f(final P2 p) { * @return This function promoted to transform Arrays. */ static public F2, Array, Array> arrayM(final F2 f) { - return new F2, Array, Array>() { - public Array f(final Array a, final Array b) { - return a.bind(b, curry(f)); - } - }; + return (a, b) -> a.bind(b, curry(f)); } /** @@ -93,11 +69,7 @@ public Array f(final Array a, final Array b) { * @return This function promoted to transform Promises. */ static public F2, Promise, Promise> promiseM(final F2 f) { - return new F2, Promise, Promise>() { - public Promise f(final Promise a, final Promise b) { - return a.bind(b, curry(f)); - } - }; + return (a, b) -> a.bind(b, curry(f)); } /** @@ -106,11 +78,7 @@ public Promise f(final Promise a, final Promise b) { * @return This function promoted to transform Iterables. */ static public F2, Iterable, IterableW> iterableM(final F2 f) { - return new F2, Iterable, IterableW>() { - public IterableW f(final Iterable a, final Iterable b) { - return IterableW.liftM2(curry(f)).f(a).f(b); - } - }; + return (a, b) -> IterableW.liftM2(curry(f)).f(a).f(b); } /** @@ -119,11 +87,7 @@ public IterableW f(final Iterable a, final Iterable b) { * @return This function promoted to transform Lists. */ static public F2, List, List> listM(final F2 f) { - return new F2, List, List>() { - public List f(final List a, final List b) { - return List.liftM2(curry(f)).f(a).f(b); - } - }; + return (a, b) -> List.liftM2(curry(f)).f(a).f(b); } /** @@ -132,11 +96,7 @@ public List f(final List a, final List b) { * @return This function promoted to transform non-empty lists. */ static public F2, NonEmptyList, NonEmptyList> nelM(final F2 f) { - return new F2, NonEmptyList, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { - return NonEmptyList.fromList(as.toList().bind(bs.toList(), f)).some(); - } - }; + return (as, bs) -> NonEmptyList.fromList(as.toList().bind(bs.toList(), f)).some(); } /** @@ -145,11 +105,7 @@ public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { * @return This function promoted to transform Options. */ static public F2, Option, Option> optionM(final F2 f) { - return new F2, Option, Option>() { - public Option f(final Option a, final Option b) { - return Option.liftM2(curry(f)).f(a).f(b); - } - }; + return (a, b) -> Option.liftM2(curry(f)).f(a).f(b); } /** @@ -159,14 +115,12 @@ public Option f(final Option a, final Option b) { * @return This function promoted to transform Sets. */ static public F2, Set, Set> setM(final F2 f, final Ord o) { - return new F2, Set, Set>() { - public Set f(final Set as, final Set bs) { - Set cs = Set.empty(o); - for (final A a : as) - for (final B b : bs) - cs = cs.insert(f.f(a, b)); - return cs; - } + return (as, bs) -> { + Set cs = Set.empty(o); + for (final A a : as) + for (final B b : bs) + cs = cs.insert(f.f(a, b)); + return cs; }; } @@ -176,11 +130,7 @@ public Set f(final Set as, final Set bs) { * @return This function promoted to transform Streams. */ static public F2, Stream, Stream> streamM(final F2 f) { - return new F2, Stream, Stream>() { - public Stream f(final Stream as, final Stream bs) { - return as.bind(bs, f); - } - }; + return (as, bs) -> as.bind(bs, f); } /** @@ -207,11 +157,7 @@ public Stream> _1() { * @return A function that zips two arrays with this function. */ static public F2, Array, Array> zipArrayM(final F2 f) { - return new F2, Array, Array>() { - public Array f(final Array as, final Array bs) { - return as.zipWith(bs, f); - } - }; + return (as, bs) -> as.zipWith(bs, f); } /** @@ -220,11 +166,7 @@ public Array f(final Array as, final Array bs) { * @return A function that zips two iterables with this function. */ static public F2, Iterable, Iterable> zipIterableM(final F2 f) { - return new F2, Iterable, Iterable>() { - public Iterable f(final Iterable as, final Iterable bs) { - return wrap(as).zipWith(bs, f); - } - }; + return (as, bs) -> wrap(as).zipWith(bs, f); } /** @@ -233,11 +175,7 @@ public Iterable f(final Iterable as, final Iterable bs) { * @return A function that zips two lists with this function. */ static public F2, List, List> zipListM(final F2 f) { - return new F2, List, List>() { - public List f(final List as, final List bs) { - return as.zipWith(bs, f); - } - }; + return (as, bs) -> as.zipWith(bs, f); } @@ -247,11 +185,7 @@ public List f(final List as, final List bs) { * @return A function that zips two streams with this function. */ static public F2, Stream, Stream> zipStreamM(final F2 f) { - return new F2, Stream, Stream>() { - public Stream f(final Stream as, final Stream bs) { - return as.zipWith(bs, f); - } - }; + return (as, bs) -> as.zipWith(bs, f); } /** @@ -260,11 +194,7 @@ public Stream f(final Stream as, final Stream bs) { * @return A function that zips two non-empty lists with this function. */ static public F2, NonEmptyList, NonEmptyList> zipNelM(final F2 f) { - return new F2, NonEmptyList, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { - return NonEmptyList.fromList(as.toList().zipWith(bs.toList(), f)).some(); - } - }; + return (as, bs) -> NonEmptyList.fromList(as.toList().zipWith(bs.toList(), f)).some(); } /** @@ -274,11 +204,7 @@ public NonEmptyList f(final NonEmptyList as, final NonEmptyList bs) { * @return A function that zips two sets with this function. */ static public F2, Set, Set> zipSetM(final F2 f, final Ord o) { - return new F2, Set, Set>() { - public Set f(final Set as, final Set bs) { - return iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); - } - }; + return (as, bs) -> iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); } /** @@ -307,12 +233,9 @@ public Stream> _1() { * @return A function that zips two zippers with this function. */ static public F2, Zipper, Zipper> zipZipperM(final F2 f) { - return new F2, Zipper, Zipper>() { - @SuppressWarnings({"unchecked"}) - public Zipper f(final Zipper ta, final Zipper tb) { - final F2, Stream, Stream> sf = zipStreamM(f); - return zipper(sf.f(ta.lefts(), tb.lefts()), f.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); - } + return (ta, tb) -> { + final F2, Stream, Stream> sf = zipStreamM(f); + return zipper(sf.f(ta.lefts(), tb.lefts()), f.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); }; } @@ -323,27 +246,17 @@ public Zipper f(final Zipper ta, final Zipper tb) { * @return A function that zips two TreeZippers with this function. */ static public F2, TreeZipper, TreeZipper> zipTreeZipperM(final F2 f) { - return new F2, TreeZipper, TreeZipper>() { - @SuppressWarnings({"unchecked"}) - public TreeZipper f(final TreeZipper ta, final TreeZipper tb) { - final F2>, Stream>, Stream>> sf = zipStreamM(treeM(f)); - final - F2>, A, Stream>>>, - Stream>, B, Stream>>>, - Stream>, C, Stream>>>> - pf = - zipStreamM(new F2>, A, Stream>>, - P3>, B, Stream>>, - P3>, C, Stream>>>() { - public P3>, C, Stream>> f(final P3>, A, Stream>> pa, - final P3>, B, Stream>> pb) { - return p(zipStreamM(treeM(f)).f(pa._1(), pb._1()), f.f(pa._2(), pb._2()), - zipStreamM(treeM(f)).f(pa._3(), pb._3())); - } - }); - return treeZipper(treeM(f).f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()), - sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4())); - } + return (ta, tb) -> { + final F2>, Stream>, Stream>> sf = zipStreamM(treeM(f)); + final + F2>, A, Stream>>>, + Stream>, B, Stream>>>, + Stream>, C, Stream>>>> + pf = + zipStreamM((pa, pb) -> p(zipStreamM(treeM(f)).f(pa._1(), pb._1()), f.f(pa._2(), pb._2()), + zipStreamM(treeM(f)).f(pa._3(), pb._3()))); + return treeZipper(treeM(f).f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()), + sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4())); }; } From 3a5f36ed729378d0a5697e8cc5769cead8f34ddb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 22 Dec 2014 23:23:03 +1000 Subject: [PATCH 197/811] Updated latest version to 4.2 --- README.adoc | 10 +++++----- etc/release-notes.md | 11 ++++++++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/README.adoc b/README.adoc index 44dadda3..d256f5e8 100644 --- a/README.adoc +++ b/README.adoc @@ -28,10 +28,10 @@ The Functional Java artifact is published to Maven Central using the group `org. * the core library (`functionaljava`) * Java 8 specific support (`functionaljava-java8`) -The latest version is `4.2-beta-1`. This can be added to your Gradle project by adding the dependencies: +The latest version is `4.2`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.2-beta-1" -compile "org.functionaljava:functionaljava-java8:4.2-beta-1" +compile "org.functionaljava:functionaljava:4.2" +compile "org.functionaljava:functionaljava-java8:4.2" ---- and in Maven: @@ -39,12 +39,12 @@ and in Maven: org.functionaljava functionaljava - 4.2-beta-1 + 4.2 org.functionaljava functionaljava-java8 - 4.2-beta-1 + 4.2 ---- diff --git a/etc/release-notes.md b/etc/release-notes.md index 9e13b55f..c1649f01 100644 --- a/etc/release-notes.md +++ b/etc/release-notes.md @@ -2,9 +2,18 @@ Release Notes ============= +4.3 +=== +Target date: To be decided + +* Enhancements + * To be decided +* Fixes + * To be decided + 4.2 === -Release target: Aug 2014 +Released: 20 December, 2014 * Enhancements * Added Java 8 examples From 7e03906166fea725ec10b6fa630e50866e88c993 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 15:38:57 +0530 Subject: [PATCH 198/811] Refactoring Option type: replacing anonymous classes with lambda --- core/src/main/java/fj/data/Option.java | 122 +++++-------------------- 1 file changed, 22 insertions(+), 100 deletions(-) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index c952133c..64ddebf9 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -204,11 +204,7 @@ public final Option map(final F f) { * @return A function that maps a given function across a given optional value. */ public static F, F, Option>> map() { - return curry(new F2, Option, Option>() { - public Option f(final F abf, final Option option) { - return option.map(abf); - } - }); + return curry((abf, option) -> option.map(abf)); } /** @@ -656,11 +652,7 @@ public boolean equals(Object obj) { } public static F> some_() { - return new F>() { - public Option f(final T t) { - return some(t); - } - }; + return t -> some(t); } /** @@ -674,11 +666,7 @@ public static Option some(final T t) { } public static F> none_() { - return new F>() { - public Option f(final T t) { - return none(); - } - }; + return t -> none(); } /** @@ -708,11 +696,7 @@ public static Option fromNull(final T t) { * @return If t == null then return it in some, otherwise, return none. */ public static F> fromNull() { - return new F>() { - public Option f(final T t) { - return fromNull(t); - } - }; + return t -> fromNull(t); } /** @@ -735,11 +719,7 @@ public static Option join(final Option> o) { public static Option> sequence(final List> a) { return a.isEmpty() ? some(List.nil()) : - a.head().bind(new F>>() { - public Option> f(final A aa) { - return sequence(a.tail()).map(cons_(aa)); - } - }); + a.head().bind(aa -> sequence(a.tail()).map(cons_(aa))); } /** @@ -789,11 +769,7 @@ public static Option iif(final boolean p, final A a) { * holds on that argument, or no value otherwise. */ public static F2, A, Option> iif() { - return new F2, A, Option>() { - public Option f(final F p, final A a) { - return iif(p, a); - } - }; + return (p, a) -> iif(p, a); } /** @@ -803,11 +779,7 @@ public Option f(final F p, final A a) { * @return All the values in the given list. */ public static List somes(final List> as) { - return as.filter(Option.isSome_()).map(new F, A>() { - public A f(final Option o) { - return o.some(); - } - }); + return as.filter(Option.isSome_()).map(o -> o.some()); } @@ -818,11 +790,7 @@ public A f(final Option o) { * @return All the values in the given stream. */ public static Stream somes(final Stream> as) { - return as.filter(Option.isSome_()).map(new F, A>() { - public A f(final Option o) { - return o.some(); - } - }); + return as.filter(Option.isSome_()).map(o -> o.some()); } /** @@ -832,11 +800,9 @@ public A f(final Option o) { * @return an optional non-empty string, or no value if the given string is empty. */ public static Option fromString(final String s) { - return fromNull(s).bind(new F>() { - public Option f(final String s) { - final Option none = none(); - return s.length() == 0 ? none : some(s); - } + return fromNull(s).bind(s1 -> { + final Option none = none(); + return s.length() == 0 ? none : some(s); }); } @@ -848,11 +814,7 @@ public Option f(final String s) { * or no value if the string is empty. */ public static F> fromString() { - return new F>() { - public Option f(final String s) { - return fromString(s); - } - }; + return s -> fromString(s); } /** @@ -861,11 +823,7 @@ public Option f(final String s) { * @return A function that takes an optional value to a value or errors if there is no value. */ public static F, A> fromSome() { - return new F, A>() { - public A f(final Option option) { - return option.some(); - } - }; + return option -> option.some(); } /** @@ -875,11 +833,7 @@ public A f(final Option option) { * @return The given function promoted to operate on options. */ public static F, F, Option>> liftM2(final F> f) { - return curry(new F2, Option, Option>() { - public Option f(final Option a, final Option b) { - return a.bind(b, f); - } - }); + return curry((a, b) -> a.bind(b, f)); } /** @@ -888,11 +842,7 @@ public Option f(final Option a, final Option b) { * @return A function that binds a given function across an option with a final join. */ public static F>, F, Option>> bind() { - return curry(new F2>, Option, Option>() { - public Option f(final F> f, final Option a) { - return a.bind(f); - } - }); + return curry((f, a) -> a.bind(f)); } /** @@ -901,64 +851,36 @@ public Option f(final F> f, final Option a) { * @return A function that joins an Option of an Option to make a single Option. */ public static F>, Option> join() { - return new F>, Option>() { - public Option f(final Option> option) { - return join(option); - } - }; + return option -> join(option); } /** * A function that parses a string to a byte. */ - public static final F> parseByte = new F>() { - public Option f(final String s) { - return parseByte(s).toOption(); - } - }; + public static final F> parseByte = s -> parseByte(s).toOption(); /** * A function that parses a string to a double. */ - public static final F> parseDouble = new F>() { - public Option f(final String s) { - return parseDouble(s).toOption(); - } - }; + public static final F> parseDouble = s -> parseDouble(s).toOption(); /** * A function that parses a string to a float. */ - public static final F> parseFloat = new F>() { - public Option f(final String s) { - return parseFloat(s).toOption(); - } - }; + public static final F> parseFloat = s -> parseFloat(s).toOption(); /** * A function that parses a string to an integer. */ - public static final F> parseInt = new F>() { - public Option f(final String s) { - return parseInt(s).toOption(); - } - }; + public static final F> parseInt = s -> parseInt(s).toOption(); /** * A function that parses a string to a long. */ - public static final F> parseLong = new F>() { - public Option f(final String s) { - return parseLong(s).toOption(); - } - }; + public static final F> parseLong = s -> parseLong(s).toOption(); /** * A function that parses a string to a short. */ - public static final F> parseShort = new F>() { - public Option f(final String s) { - return parseShort(s).toOption(); - } - }; + public static final F> parseShort = s -> parseShort(s).toOption(); } From 0097ecacf423843cff45f01e1901de8b3c980bcd Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 15:53:12 +0530 Subject: [PATCH 199/811] Refactoring Semigroup --- core/src/main/java/fj/Semigroup.java | 200 +++++---------------------- 1 file changed, 38 insertions(+), 162 deletions(-) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 2b377cb5..4637ac2f 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -81,38 +81,22 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that adds integers. */ - public static final Semigroup intAdditionSemigroup = semigroup(new F2() { - public Integer f(final Integer i1, final Integer i2) { - return i1 + i2; - } - }); + public static final Semigroup intAdditionSemigroup = semigroup((i1, i2) -> i1 + i2); /** * A semigroup that adds doubles. */ - public static final Semigroup doubleAdditionSemigroup = semigroup(new F2() { - public Double f(final Double d1, final Double d2) { - return d1 + d2; - } - }); + public static final Semigroup doubleAdditionSemigroup = semigroup((d1, d2) -> d1 + d2); /** * A semigroup that multiplies integers. */ - public static final Semigroup intMultiplicationSemigroup = semigroup(new F2() { - public Integer f(final Integer i1, final Integer i2) { - return i1 * i2; - } - }); + public static final Semigroup intMultiplicationSemigroup = semigroup((i1, i2) -> i1 * i2); /** * A semigroup that multiplies doubles. */ - public static final Semigroup doubleMultiplicationSemigroup = semigroup(new F2() { - public Double f(final Double d1, final Double d2) { - return d1 * d2; - } - }); + public static final Semigroup doubleMultiplicationSemigroup = semigroup((d1, d2) -> d1 * d2); /** * A semigroup that yields the maximum of integers. @@ -128,21 +112,13 @@ public Double f(final Double d1, final Double d2) { * A semigroup that adds big integers. */ public static final Semigroup bigintAdditionSemigroup = - semigroup(new F2() { - public BigInteger f(final BigInteger i1, final BigInteger i2) { - return i1.add(i2); - } - }); + semigroup((i1, i2) -> i1.add(i2)); /** * A semigroup that multiplies big integers. */ public static final Semigroup bigintMultiplicationSemigroup = - semigroup(new F2() { - public BigInteger f(final BigInteger i1, final BigInteger i2) { - return i1.multiply(i2); - } - }); + semigroup((i1, i2) -> i1.multiply(i2)); /** * A semigroup that yields the maximum of big integers. @@ -158,21 +134,13 @@ public BigInteger f(final BigInteger i1, final BigInteger i2) { * A semigroup that adds big decimals. */ public static final Semigroup bigdecimalAdditionSemigroup = - semigroup(new F2() { - public BigDecimal f(final BigDecimal i1, final BigDecimal i2) { - return i1.add(i2); - } - }); + semigroup((i1, i2) -> i1.add(i2)); /** * A semigroup that multiplies big decimals. */ public static final Semigroup bigdecimalMultiplicationSemigroup = - semigroup(new F2() { - public BigDecimal f(final BigDecimal i1, final BigDecimal i2) { - return i1.multiply(i2); - } - }); + semigroup((i1, i2) -> i1.multiply(i2)); /** * A semigroup that yields the maximum of big decimals. @@ -188,21 +156,13 @@ public BigDecimal f(final BigDecimal i1, final BigDecimal i2) { * A semigroup that multiplies natural numbers. */ public static final Semigroup naturalMultiplicationSemigroup = - semigroup(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n1.multiply(n2); - } - }); + semigroup((n1, n2) -> n1.multiply(n2)); /** * A semigroup that multiplies natural numbers. */ public static final Semigroup naturalAdditionSemigroup = - semigroup(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n1.add(n2); - } - }); + semigroup((n1, n2) -> n1.add(n2)); /** * A semigroup that yields the maximum of natural numbers. @@ -217,20 +177,12 @@ public Natural f(final Natural n1, final Natural n2) { /** * A semigroup that adds longs. */ - public static final Semigroup longAdditionSemigroup = semigroup(new F2() { - public Long f(final Long x, final Long y) { - return x + y; - } - }); + public static final Semigroup longAdditionSemigroup = semigroup((x, y) -> x + y); /** * A semigroup that multiplies longs. */ - public static final Semigroup longMultiplicationSemigroup = semigroup(new F2() { - public Long f(final Long x, final Long y) { - return x * y; - } - }); + public static final Semigroup longMultiplicationSemigroup = semigroup((x, y) -> x * y); /** * A semigroup that yields the maximum of longs. @@ -245,58 +197,34 @@ public Long f(final Long x, final Long y) { /** * A semigroup that ORs booleans. */ - public static final Semigroup disjunctionSemigroup = semigroup(new F2() { - public Boolean f(final Boolean b1, final Boolean b2) { - return b1 || b2; - } - }); + public static final Semigroup disjunctionSemigroup = semigroup((b1, b2) -> b1 || b2); /** * A semigroup that XORs booleans. */ - public static final Semigroup exclusiveDisjunctionSemiGroup = semigroup(new F2() { - public Boolean f(final Boolean p, final Boolean q) { - return p && !q || !p && q; - } - }); + public static final Semigroup exclusiveDisjunctionSemiGroup = semigroup((p, q) -> p && !q || !p && q); /** * A semigroup that ANDs booleans. */ - public static final Semigroup conjunctionSemigroup = semigroup(new F2() { - public Boolean f(final Boolean b1, final Boolean b2) { - return b1 && b2; - } - }); + public static final Semigroup conjunctionSemigroup = semigroup((b1, b2) -> b1 && b2); /** * A semigroup that appends strings. */ - public static final Semigroup stringSemigroup = semigroup(new F2() { - public String f(final String s1, final String s2) { - return s1 + s2; - } - }); + public static final Semigroup stringSemigroup = semigroup((s1, s2) -> s1 + s2); /** * A semigroup that appends string buffers. */ public static final Semigroup stringBufferSemigroup = - semigroup(new F2() { - public StringBuffer f(final StringBuffer s1, final StringBuffer s2) { - return new StringBuffer(s1).append(s2); - } - }); + semigroup((s1, s2) -> new StringBuffer(s1).append(s2)); /** * A semigroup that appends string builders. */ public static final Semigroup stringBuilderSemigroup = - semigroup(new F2() { - public StringBuilder f(final StringBuilder s1, final StringBuilder s2) { - return new StringBuilder(s1).append(s2); - } - }); + semigroup((s1, s2) -> new StringBuilder(s1).append(s2)); /** * A semigroup for functions. @@ -305,15 +233,7 @@ public StringBuilder f(final StringBuilder s1, final StringBuilder s2) { * @return A semigroup for functions. */ public static Semigroup> functionSemigroup(final Semigroup sb) { - return semigroup(new F2, F, F>() { - public F f(final F a1, final F a2) { - return new F() { - public B f(final A a) { - return sb.sum(a1.f(a), a2.f(a)); - } - }; - } - }); + return semigroup((a1, a2) -> a -> sb.sum(a1.f(a), a2.f(a))); } /** @@ -322,11 +242,7 @@ public B f(final A a) { * @return A semigroup for lists. */ public static Semigroup> listSemigroup() { - return semigroup(new F2, List, List>() { - public List f(final List a1, final List a2) { - return a1.append(a2); - } - }); + return semigroup((a1, a2) -> a1.append(a2)); } /** @@ -335,11 +251,7 @@ public List f(final List a1, final List a2) { * @return A semigroup for non-empty lists. */ public static Semigroup> nonEmptyListSemigroup() { - return semigroup(new F2, NonEmptyList, NonEmptyList>() { - public NonEmptyList f(final NonEmptyList a1, final NonEmptyList a2) { - return a1.append(a2); - } - }); + return semigroup((a1, a2) -> a1.append(a2)); } /** @@ -347,11 +259,7 @@ public NonEmptyList f(final NonEmptyList a1, final NonEmptyList a2) { ** @return A semigroup for optional values. */ public static Semigroup> optionSemigroup() { - return semigroup(new F2, Option, Option>() { - public Option f(final Option a1, final Option a2) { - return a1.isSome() ? a1 : a2; - } - }); + return semigroup((a1, a2) -> a1.isSome() ? a1 : a2); } /** @@ -360,11 +268,7 @@ public Option f(final Option a1, final Option a2) { * @return A semigroup for optional values that take the first available value. */ public static Semigroup> firstOptionSemigroup() { - return semigroup(new F2, Option, Option>() { - public Option f(final Option a1, final Option a2) { - return a1.orElse(a2); - } - }); + return semigroup((a1, a2) -> a1.orElse(a2)); } /** @@ -373,11 +277,7 @@ public Option f(final Option a1, final Option a2) { * @return A semigroup for optional values that take the last available value. */ public static Semigroup> lastOptionSemigroup() { - return semigroup(new F2, Option, Option>() { - public Option f(final Option a1, final Option a2) { - return a2.orElse(a1); - } - }); + return semigroup((a1, a2) -> a2.orElse(a1)); } /** @@ -386,11 +286,7 @@ public Option f(final Option a1, final Option a2) { * @return A semigroup for streams. */ public static Semigroup> streamSemigroup() { - return semigroup(new F2, Stream, Stream>() { - public Stream f(final Stream a1, final Stream a2) { - return a1.append(a2); - } - }); + return semigroup((a1, a2) -> a1.append(a2)); } /** @@ -399,11 +295,7 @@ public Stream f(final Stream a1, final Stream a2) { * @return A semigroup for arrays. */ public static Semigroup> arraySemigroup() { - return semigroup(new F2, Array, Array>() { - public Array f(final Array a1, final Array a2) { - return a1.append(a2); - } - }); + return semigroup((a1, a2) -> a1.append(a2)); } /** @@ -413,13 +305,9 @@ public Array f(final Array a1, final Array a2) { * @return A semigroup for unary products. */ public static Semigroup> p1Semigroup(final Semigroup sa) { - return semigroup(new F2, P1, P1>() { - public P1 f(final P1 a1, final P1 a2) { - return new P1() { - public A _1() { - return sa.sum(a1._1(), a2._1()); - } - }; + return semigroup((a1, a2) -> new P1() { + public A _1() { + return sa.sum(a1._1(), a2._1()); } }); } @@ -432,17 +320,13 @@ public A _1() { * @return A semigroup for binary products. */ public static Semigroup> p2Semigroup(final Semigroup sa, final Semigroup sb) { - return semigroup(new F2, P2, P2>() { - public P2 f(final P2 a1, final P2 a2) { - return new P2() { - public A _1() { - return sa.sum(a1._1(), a2._1()); - } - - public B _2() { - return sb.sum(a1._2(), a2._2()); - } - }; + return semigroup((a1, a2) -> new P2() { + public A _1() { + return sa.sum(a1._1(), a2._1()); + } + + public B _2() { + return sb.sum(a1._2(), a2._2()); } }); } @@ -450,11 +334,7 @@ public B _2() { /** * A semigroup for the Unit value. */ - public static final Semigroup unitSemigroup = semigroup(new F2() { - public Unit f(final Unit u1, final Unit u2) { - return Unit.unit(); - } - }); + public static final Semigroup unitSemigroup = semigroup((u1, u2) -> Unit.unit()); /** * A semigroup for sets. @@ -462,11 +342,7 @@ public Unit f(final Unit u1, final Unit u2) { * @return a semigroup for sets. */ public static Semigroup> setSemigroup() { - return semigroup(new F2, Set, Set>() { - public Set f(final Set a, final Set b) { - return a.union(b); - } - }); + return semigroup((a, b) -> a.union(b)); } } From e0778244b42ba80f960d4c48638e3274dd470228 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 16:06:33 +0530 Subject: [PATCH 200/811] Refactoring List type --- core/src/main/java/fj/data/List.java | 252 ++++----------------------- 1 file changed, 37 insertions(+), 215 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 58f3b071..6c2d8911 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -79,15 +79,7 @@ public final Iterator iterator() { * @return The length of this list. */ public final int length() { - return foldLeft(new F>() { - public F f(final Integer i) { - return new F() { - public Integer f(final A a) { - return i + 1; - } - }; - } - }, 0); + return foldLeft(i -> a -> i + 1, 0); } /** @@ -167,15 +159,7 @@ public final Either toEither(final P1 x) { */ public final Stream toStream() { final Stream nil = Stream.nil(); - return foldRight(new F, Stream>>() { - public F, Stream> f(final A a) { - return new F, Stream>() { - public Stream f(final Stream as) { - return as.cons(a); - } - }; - } - }, nil); + return foldRight(a -> as -> as.cons(a), nil); } /** @@ -396,11 +380,7 @@ public final P2, List> span(final F p) { * the given predicate and the second element is the remainder of the list. */ public final P2, List> breakk(final F p) { - return span(new F() { - public Boolean f(final A a) { - return !p.f(a); - } - }); + return span(a -> !p.f(a)); } /** @@ -467,11 +447,7 @@ public final List bind(final List lb, final F2 f) { * @return The given function, promoted to operate on lists. */ public static F, F, List>> liftM2(final F> f) { - return curry(new F2, List, List>() { - public List f(final List as, final List bs) { - return as.bind(bs, f); - } - }); + return curry((as, bs) -> as.bind(bs, f)); } /** @@ -592,11 +568,7 @@ public final List sequence(final List bs) { * @return A new list after applying the given list of functions through this list. */ public final List apply(final List> lf) { - return lf.bind(new F, List>() { - public List f(final F f) { - return map(f); - } - }); + return lf.bind(f -> map(f)); } /** @@ -703,15 +675,7 @@ public final A foldLeft1(final F> f) { * @return A new list that is the reverse of this one. */ public final List reverse() { - return foldLeft(new F, F>>() { - public F> f(final List as) { - return new F>() { - public List f(final A a) { - return cons(a, as); - } - }; - } - }, List.nil()); + return foldLeft(as -> a -> cons(a, as), List.nil()); } /** @@ -774,15 +738,7 @@ public final P2, List> splitAt(final int i) { int c = 0; for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) { final A h = xs.head(); - s = c < i ? s.map1(new F, List>() { - public List f(final List as) { - return as.snoc(h); - } - }) : s.map2(new F, List>() { - public List f(final List as) { - return as.snoc(h); - } - }); + s = c < i ? s.map1(as -> as.snoc(h)) : s.map2(as1 -> as1.snoc(h)); c++; } @@ -801,11 +757,7 @@ public final List> partition(final int n) { throw error("Can't create list partitions shorter than 1 element long."); if (isEmpty()) throw error("Partition on empty list."); - return unfold(new F, Option, List>>>() { - public Option, List>> f(final List as) { - return as.isEmpty() ? Option., List>>none() : some(as.splitAt(n)); - } - }, this); + return unfold(as -> as.isEmpty() ? Option., List>>none() : some(as.splitAt(n)), this); } /** @@ -918,11 +870,7 @@ public final List zipWith(final List bs, final F2 f) { * @return The first-class version of zipWith */ public static F, F, F>, List>>> zipWith() { - return curry(new F3, List, F>, List>() { - public List f(final List as, final List bs, final F> f) { - return as.zipWith(bs, f); - } - }); + return curry((as, bs, f) -> as.zipWith(bs, f)); } /** @@ -943,11 +891,7 @@ public final List> zip(final List bs) { * @return A function that zips the given lists to produce a list of pairs. */ public static F, F, List>>> zip() { - return curry(new F2, List, List>>() { - public List> f(final List as, final List bs) { - return as.zip(bs); - } - }); + return curry((as, bs) -> as.zip(bs)); } /** @@ -956,15 +900,7 @@ public List> f(final List as, final List bs) { * @return A new list with the same length as this list. */ public final List> zipIndex() { - return zipWith(range(0, length()), new F>>() { - public F> f(final A a) { - return new F>() { - public P2 f(final Integer i) { - return p(a, i); - } - }; - } - }); + return zipWith(range(0, length()), a -> i -> p(a, i)); } /** @@ -1057,11 +993,7 @@ public final List nub() { * @return A list without duplicates. */ public final List nub(final Equal eq) { - return isEmpty() ? this : cons(head(), tail().filter(new F() { - public Boolean f(final A a) { - return !eq.eq(a, head()); - } - }).nub(eq)); + return isEmpty() ? this : cons(head(), tail().filter(a -> !eq.eq(a, head())).nub(eq)); } /** @@ -1081,11 +1013,7 @@ public final List nub(final Ord o) { * @return A function that gets the head of a given list. */ public static F, A> head_() { - return new F, A>() { - public A f(final List list) { - return list.head(); - } - }; + return list -> list.head(); } /** @@ -1094,11 +1022,7 @@ public A f(final List list) { * @return A function that gets the tail of a given list. */ public static F, List> tail_() { - return new F, List>() { - public List f(final List list) { - return list.tail(); - } - }; + return list -> list.tail(); } /** @@ -1131,19 +1055,7 @@ public final F> mapM(final F> f) { * @return A possible list of values after binding through the Option monad. */ public final Option> mapMOption(final F> f) { - return foldRight(new F2>, Option>>() { - public Option> f(final A a, final Option> bs) { - return f.f(a).bind(new F>>() { - public Option> f(final B b) { - return bs.map(new F, List>() { - public List f(final List bbs) { - return bbs.cons(b); - } - }); - } - }); - } - }, Option.>some(List.nil())); + return foldRight((a, bs) -> f.f(a).bind(b -> bs.map(bbs -> bbs.cons(b))), Option.>some(List.nil())); } /** @@ -1153,19 +1065,7 @@ public List f(final List bbs) { * @return A list of values in the Trampoline monad. */ public final Trampoline> mapMTrampoline(final F> f) { - return foldRight(new F2>, Trampoline>>() { - public Trampoline> f(final A a, final Trampoline> bs) { - return f.f(a).bind(new F>>() { - public Trampoline> f(final B b) { - return bs.map(new F, List>() { - public List f(final List bbs) { - return bbs.cons(b); - } - }); - } - }); - } - }, Trampoline.>pure(List.nil())); + return foldRight((a, bs) -> f.f(a).bind(b -> bs.map(bbs -> bbs.cons(b))), Trampoline.>pure(List.nil())); } /** @@ -1358,11 +1258,7 @@ public boolean allEqual(final Equal eq) { * @return A function that gets the length of a given list. */ public static F, Integer> length_() { - return new F, Integer>() { - public Integer f(final List a) { - return a.length(); - } - }; + return a -> a.length(); } /** @@ -1479,15 +1375,7 @@ public static List nil() { * @return A function that prepends (cons) an element to a list to produce a new list. */ public static F, List>> cons() { - return new F, List>>() { - public F, List> f(final A a) { - return new F, List>() { - public List f(final List tail) { - return cons(a, tail); - } - }; - } - }; + return a -> tail -> cons(a, tail); } public static F2, List> cons_() { @@ -1501,11 +1389,7 @@ public static F2, List> cons_() { * @return A function that prepends a value to the given list. */ public static F> cons(final List tail) { - return new F>() { - public List f(final A a) { - return tail.cons(a); - } - }; + return a -> tail.cons(a); } /** @@ -1515,11 +1399,7 @@ public List f(final A a) { * @return A function that prepends the given value to a list. */ public static F, List> cons_(final A a) { - return new F, List>() { - public List f(final List as) { - return as.cons(a); - } - }; + return as -> as.cons(a); } /** @@ -1539,11 +1419,7 @@ public static List cons(final A head, final List tail) { * @return A function that determines whether a given list is empty. */ public static F, Boolean> isEmpty_() { - return new F, Boolean>() { - public Boolean f(final List as) { - return as.isEmpty(); - } - }; + return as -> as.isEmpty(); } /** @@ -1552,11 +1428,7 @@ public Boolean f(final List as) { * @return A function that determines whether a given list is not empty. */ public static F, Boolean> isNotEmpty_() { - return new F, Boolean>() { - public Boolean f(final List as) { - return as.isNotEmpty(); - } - }; + return as -> as.isNotEmpty(); } /** @@ -1576,11 +1448,7 @@ public static List join(final List> o) { * @return A function that joins a list of lists using a bind operation. */ public static F>, List> join() { - return new F>, List>() { - public List f(final List> as) { - return join(as); - } - }; + return as -> join(as); } /** @@ -1660,11 +1528,7 @@ public static List fromString(final String s) { * @return A first-class fromString. */ public static F> fromString() { - return new F>() { - public List f(final String s) { - return fromString(s); - } - }; + return s -> fromString(s); } /** @@ -1677,11 +1541,9 @@ public List f(final String s) { public static String asString(final List cs) { final StringBuilder sb = new StringBuilder(); - cs.foreach(new F() { - public Unit f(final Character c) { - sb.append(c); - return unit(); - } + cs.foreach(c -> { + sb.append(c); + return unit(); }); return sb.toString(); } @@ -1692,11 +1554,7 @@ public Unit f(final Character c) { * @return A first-class asString. */ public static F, String> asString() { - return new F, String>() { - public String f(final List cs) { - return asString(cs); - } - }; + return cs -> asString(cs); } /** @@ -1721,16 +1579,8 @@ public static List single(final A a) { */ public static List iterateWhile(final F f, final F p, final A a) { return unfold( - new F>>() { - public Option> f(final A o) { - return Option.iif(new F, Boolean>() { - public Boolean f(final P2 p2) { - return p.f(o); - } - }, P.p(o, f.f(o))); - } - } - , a); + o -> Option.iif(p2 -> p.f(o), P.p(o, f.f(o))) + , a); } /** @@ -1742,11 +1592,7 @@ public Boolean f(final P2 p2) { * @return An associated value with the given key in the list of pairs. */ public static Option lookup(final Equal e, final List> x, final A a) { - return x.find(new F, Boolean>() { - public Boolean f(final P2 p) { - return e.eq(p._1(), a); - } - }).map(P2.__2()); + return x.find(p -> e.eq(p._1(), a)).map(P2.__2()); } /** @@ -1756,11 +1602,7 @@ public Boolean f(final P2 p) { * @return A partially applied version of {@link #lookup(Equal , List, Object)}. */ public static F2>, A, Option> lookup(final Equal e) { - return new F2>, A, Option>() { - public Option f(final List> x, final A a) { - return lookup(e, x, a); - } - }; + return (x, a) -> lookup(e, x, a); } /** @@ -1769,11 +1611,7 @@ public Option f(final List> x, final A a) { * @return The bind function for lists. */ public static F>, F, List>> bind_() { - return curry(new F2>, List, List>() { - public List f(final F> f, final List as) { - return as.bind(f); - } - }); + return curry((f, as) -> as.bind(f)); } /** @@ -1782,11 +1620,7 @@ public List f(final F> f, final List as) { * @return The map function for lists. */ public static F, F, List>> map_() { - return curry(new F2, List, List>() { - public List f(final F f, final List as) { - return as.map(f); - } - }); + return curry((f, as) -> as.map(f)); } /** @@ -1807,11 +1641,7 @@ public static F> sequence_(final List> fs) { * @return The left fold function for lists. */ public static F>, F, B>>> foldLeft() { - return curry(new F3>, B, List, B>() { - public B f(final F> f, final B b, final List as) { - return as.foldLeft(f, b); - } - }); + return curry((f, b, as) -> as.foldLeft(f, b)); } /** @@ -1820,11 +1650,7 @@ public B f(final F> f, final B b, final List as) { * @return First-class version of take. */ public static F, List>> take() { - return curry(new F2, List>() { - public List f(final Integer n, final List as) { - return as.take(n); - } - }); + return curry((n, as) -> as.take(n)); } /** @@ -2005,10 +1831,6 @@ private void copy() { * @return a String representation of the list */ @Override public String toString() { - return Show.listShow( Show.anyShow() ).show( this ).foldLeft( new F2() { - @Override public String f( final String s, final Character c ) { - return s + c; - } - }, "" ); + return Show.listShow( Show.anyShow() ).show( this ).foldLeft((s, c) -> s + c, "" ); } } From 369bf6c86cac701cc75b3b45574bb8e78635b46e Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 16:11:17 +0530 Subject: [PATCH 201/811] Refactoring Ord and Show --- core/src/main/java/fj/Ord.java | 394 +++++++++----------------------- core/src/main/java/fj/Show.java | 190 +++++---------- 2 files changed, 161 insertions(+), 423 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 8ecccfd0..99894105 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -64,11 +64,7 @@ public boolean eq(final A a1, final A a2) { * @return An Equal for this order. */ public Equal equal() { - return Equal.equal(curry(new F2() { - public Boolean f(final A a1, final A a2) { - return eq(a1, a2); - } - })); + return Equal.equal(curry(this::eq)); } /** @@ -114,11 +110,7 @@ public boolean isGreaterThan(final A a1, final A a2) { * @return A function that returns true if its argument is less than the argument to this method. */ public F isLessThan(final A a) { - return new F() { - public Boolean f(final A a2) { - return compare(a2, a) == Ordering.LT; - } - }; + return a2 -> compare(a2, a) == Ordering.LT; } /** @@ -128,11 +120,7 @@ public Boolean f(final A a2) { * @return A function that returns true if its argument is greater than the argument to this method. */ public F isGreaterThan(final A a) { - return new F() { - public Boolean f(final A a2) { - return compare(a2, a) == Ordering.GT; - } - }; + return a2 -> compare(a2, a) == Ordering.GT; } /** @@ -161,20 +149,12 @@ public A min(final A a1, final A a2) { /** * A function that returns the greater of its two arguments. */ - public final F> max = curry(new F2() { - public A f(final A a, final A a1) { - return max(a, a1); - } - }); + public final F> max = curry((a, a1) -> max(a, a1)); /** * A function that returns the lesser of its two arguments. */ - public final F> min = curry(new F2() { - public A f(final A a, final A a1) { - return min(a, a1); - } - }); + public final F> min = curry((a, a1) -> min(a, a1)); /** * Returns an order instance that uses the given equality test and ordering function. @@ -190,151 +170,91 @@ public static Ord ord(final F> f) { * An order instance for the boolean type. */ public static final Ord booleanOrd = new Ord( - new F>() { - public F f(final Boolean a1) { - return new F() { - public Ordering f(final Boolean a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the byte type. */ public static final Ord byteOrd = new Ord( - new F>() { - public F f(final Byte a1) { - return new F() { - public Ordering f(final Byte a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the char type. */ public static final Ord charOrd = new Ord( - new F>() { - public F f(final Character a1) { - return new F() { - public Ordering f(final Character a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the double type. */ public static final Ord doubleOrd = new Ord( - new F>() { - public F f(final Double a1) { - return new F() { - public Ordering f(final Double a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the float type. */ public static final Ord floatOrd = new Ord( - new F>() { - public F f(final Float a1) { - return new F() { - public Ordering f(final Float a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the int type. */ public static final Ord intOrd = new Ord( - new F>() { - public F f(final Integer a1) { - return new F() { - public Ordering f(final Integer a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the BigInteger type. */ public static final Ord bigintOrd = new Ord( - new F>() { - public F f(final BigInteger a1) { - return new F() { - public Ordering f(final BigInteger a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the BigDecimal type. */ public static final Ord bigdecimalOrd = new Ord( - new F>() { - public F f(final BigDecimal a1) { - return new F() { - public Ordering f(final BigDecimal a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the long type. */ public static final Ord longOrd = new Ord( - new F>() { - public F f(final Long a1) { - return new F() { - public Ordering f(final Long a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the short type. */ public static final Ord shortOrd = new Ord( - new F>() { - public F f(final Short a1) { - return new F() { - public Ordering f(final Short a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the {@link Ordering} type. @@ -357,44 +277,22 @@ public Ordering f(final Ordering o1, final Ordering o2) { * An order instance for the {@link String} type. */ public static final Ord stringOrd = new Ord( - new F>() { - public F f(final String a1) { - return new F() { - public Ordering f(final String a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } - }); + a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + }); /** * An order instance for the {@link StringBuffer} type. */ public static final Ord stringBufferOrd = - new Ord(new F>() { - public F f(final StringBuffer a1) { - return new F() { - public Ordering f(final StringBuffer a2) { - return stringOrd.compare(a1.toString(), a2.toString()); - } - }; - } - }); + new Ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); /** * An order instance for the {@link StringBuffer} type. */ public static final Ord stringBuilderOrd = - new Ord(new F>() { - public F f(final StringBuilder a1) { - return new F() { - public Ordering f(final StringBuilder a2) { - return stringOrd.compare(a1.toString(), a2.toString()); - } - }; - } - }); + new Ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); /** * An order instance for the {@link Option} type. @@ -403,21 +301,13 @@ public Ordering f(final StringBuilder a2) { * @return An order instance for the {@link Option} type. */ public static Ord> optionOrd(final Ord oa) { - return new Ord>(new F, F, Ordering>>() { - public F, Ordering> f(final Option o1) { - return new F, Ordering>() { - public Ordering f(final Option o2) { - return o1.isNone() ? - o2.isNone() ? - Ordering.EQ : - Ordering.LT : - o2.isNone() ? - Ordering.GT : - oa.f.f(o1.some()).f(o2.some()); - } - }; - } - }); + return new Ord>(o1 -> o2 -> o1.isNone() ? + o2.isNone() ? + Ordering.EQ : + Ordering.LT : + o2.isNone() ? + Ordering.GT : + oa.f.f(o1.some()).f(o2.some())); } /** @@ -428,21 +318,13 @@ public Ordering f(final Option o2) { * @return An order instance for the {@link Either} type. */ public static Ord> eitherOrd(final Ord oa, final Ord ob) { - return new Ord>(new F, F, Ordering>>() { - public F, Ordering> f(final Either e1) { - return new F, Ordering>() { - public Ordering f(final Either e2) { - return e1.isLeft() ? - e2.isLeft() ? - oa.f.f(e1.left().value()).f(e2.left().value()) : - Ordering.LT : - e2.isLeft() ? - Ordering.GT : - ob.f.f(e1.right().value()).f(e2.right().value()); - } - }; - } - }); + return new Ord>(e1 -> e2 -> e1.isLeft() ? + e2.isLeft() ? + oa.f.f(e1.left().value()).f(e2.left().value()) : + Ordering.LT : + e2.isLeft() ? + Ordering.GT : + ob.f.f(e1.right().value()).f(e2.right().value())); } /** @@ -463,20 +345,14 @@ public static Ord> validationOrd(final Ord oa, final * @return An order instance for the {@link List} type. */ public static Ord> listOrd(final Ord oa) { - return new Ord>(new F, F, Ordering>>() { - public F, Ordering> f(final List l1) { - return new F, Ordering>() { - public Ordering f(final List l2) { - if (l1.isEmpty()) - return l2.isEmpty() ? Ordering.EQ : Ordering.LT; - else if (l2.isEmpty()) - return l1.isEmpty() ? Ordering.EQ : Ordering.GT; - else { - final Ordering c = oa.compare(l1.head(), l2.head()); - return c == Ordering.EQ ? listOrd(oa).f.f(l1.tail()).f(l2.tail()) : c; - } - } - }; + return new Ord>(l1 -> l2 -> { + if (l1.isEmpty()) + return l2.isEmpty() ? Ordering.EQ : Ordering.LT; + else if (l2.isEmpty()) + return l1.isEmpty() ? Ordering.EQ : Ordering.GT; + else { + final Ordering c = oa.compare(l1.head(), l2.head()); + return c == Ordering.EQ ? listOrd(oa).f.f(l1.tail()).f(l2.tail()) : c; } }); } @@ -498,20 +374,14 @@ public static Ord> nonEmptyListOrd(final Ord oa) { * @return An order instance for the {@link Stream} type. */ public static Ord> streamOrd(final Ord oa) { - return new Ord>(new F, F, Ordering>>() { - public F, Ordering> f(final Stream s1) { - return new F, Ordering>() { - public Ordering f(final Stream s2) { - if (s1.isEmpty()) - return s2.isEmpty() ? Ordering.EQ : Ordering.LT; - else if (s2.isEmpty()) - return s1.isEmpty() ? Ordering.EQ : Ordering.GT; - else { - final Ordering c = oa.compare(s1.head(), s2.head()); - return c == Ordering.EQ ? streamOrd(oa).f.f(s1.tail()._1()).f(s2.tail()._1()) : c; - } - } - }; + return new Ord>(s1 -> s2 -> { + if (s1.isEmpty()) + return s2.isEmpty() ? Ordering.EQ : Ordering.LT; + else if (s2.isEmpty()) + return s1.isEmpty() ? Ordering.EQ : Ordering.GT; + else { + final Ordering c = oa.compare(s1.head(), s2.head()); + return c == Ordering.EQ ? streamOrd(oa).f.f(s1.tail()._1()).f(s2.tail()._1()) : c; } }); } @@ -523,27 +393,21 @@ else if (s2.isEmpty()) * @return An order instance for the {@link Array} type. */ public static Ord> arrayOrd(final Ord oa) { - return new Ord>(new F, F, Ordering>>() { - public F, Ordering> f(final Array a1) { - return new F, Ordering>() { - public Ordering f(final Array a2) { - int i = 0; - //noinspection ForLoopWithMissingComponent - for (; i < a1.length() && i < a2.length(); i++) { - final Ordering c = oa.compare(a1.get(i), a2.get(i)); - if (c == Ordering.GT || c == Ordering.LT) - return c; - } - return i == a1.length() ? - i == a2.length() ? - Ordering.EQ : - Ordering.LT : - i == a1.length() ? - Ordering.EQ : - Ordering.GT; - } - }; + return new Ord>(a1 -> a2 -> { + int i = 0; + //noinspection ForLoopWithMissingComponent + for (; i < a1.length() && i < a2.length(); i++) { + final Ordering c = oa.compare(a1.get(i), a2.get(i)); + if (c == Ordering.GT || c == Ordering.LT) + return c; } + return i == a1.length() ? + i == a2.length() ? + Ordering.EQ : + Ordering.LT : + i == a1.length() ? + Ordering.EQ : + Ordering.GT; }); } @@ -554,21 +418,13 @@ public Ordering f(final Array a2) { * @return An order instance for the {@link Set} type. */ public static Ord> setOrd(final Ord oa) { - return streamOrd(oa).comap(new F, Stream>() { - public Stream f(final Set as) { - return as.toStream(); - } - }); + return streamOrd(oa).comap(as -> as.toStream()); } /** * An order instance for the {@link Unit} type. */ - public static final Ord unitOrd = ord(curry(new F2() { - public Ordering f(final Unit u1, final Unit u2) { - return Ordering.EQ; - } - })); + public static final Ord unitOrd = ord(curry((Unit u1, Unit u2) -> Ordering.EQ)); /** * An order instance for a product-1. @@ -589,11 +445,7 @@ public static Ord> p1Ord(final Ord oa) { * @return An order instance for a product-2, with the first factor considered most significant. */ public static Ord> p2Ord(final Ord oa, final Ord ob) { - return ord(curry(new F2, P2, Ordering>() { - public Ordering f(final P2 a, final P2 b) { - return oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1()); - } - })); + return ord(curry((P2 a, P2 b) -> oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1()))); } /** @@ -605,13 +457,9 @@ public Ordering f(final P2 a, final P2 b) { * @return An order instance for a product-3, with the first factor considered most significant. */ public static Ord> p3Ord(final Ord oa, final Ord ob, final Ord oc) { - return ord(curry(new F2, P3, Ordering>() { - public Ordering f(final P3 a, final P3 b) { - return oa.eq(a._1(), b._1()) ? - p2Ord(ob, oc).compare(P.p(a._2(), a._3()), P.p(b._2(), b._3())) - : oa.compare(a._1(), b._1()); - } - })); + return ord(curry((P3 a, P3 b) -> oa.eq(a._1(), b._1()) ? + p2Ord(ob, oc).compare(P.p(a._2(), a._3()), P.p(b._2(), b._3())) + : oa.compare(a._1(), b._1()))); } /** @@ -626,15 +474,9 @@ public Ordering f(final P3 a, final P3 b) { * @return An order instance for the Comparable interface. */ public static > Ord comparableOrd() { - return ord(new F>() { - public F f(final A a1) { - return new F() { - public Ordering f(final A a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } + return ord(a1 -> a2 -> { + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; }); } @@ -647,17 +489,9 @@ public Ordering f(final A a2) { * @see #hashEqualsOrd() */ public static Ord hashOrd() { - return Ord. ord(new F>() { - @Override - public F f(final A a) { - return new F() { - @Override - public Ordering f(final A a2) { - final int x = a.hashCode() - a2.hashCode(); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - } - }; - } + return Ord. ord(a -> a2 -> { + final int x = a.hashCode() - a2.hashCode(); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; }); } @@ -669,17 +503,9 @@ public Ordering f(final A a2) { * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. */ public static Ord hashEqualsOrd() { - return Ord. ord(new F>() { - @Override - public F f(final A a) { - return new F() { - @Override - public Ordering f(final A a2) { - final int x = a.hashCode() - a2.hashCode(); - return x < 0 ? Ordering.LT : x == 0 && a.equals(a2) ? Ordering.EQ : Ordering.GT; - } - }; - } + return Ord. ord(a -> a2 -> { + final int x = a.hashCode() - a2.hashCode(); + return x < 0 ? Ordering.LT : x == 0 && a.equals(a2) ? Ordering.EQ : Ordering.GT; }); } diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 7351d918..28f309d1 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -89,11 +89,7 @@ public String showS(final A a) { * @return the transformation equivalent to this show. */ public F showS_() { - return new F() { - public String f(final A a) { - return showS(a); - } - }; + return a -> showS(a); } /** @@ -164,11 +160,7 @@ public static Show show(final F> f) { * @return A show instance. */ public static Show showS(final F f) { - return new Show(new F>() { - public Stream f(final A a) { - return fromString(f.f(a)); - } - }); + return new Show(a -> fromString(f.f(a))); } /** @@ -177,11 +169,7 @@ public Stream f(final A a) { * @return A show instance that uses {@link Object#toString()} to perform the display rendering. */ public static Show anyShow() { - return new Show(new F>() { - public Stream f(final A a) { - return Stream.fromString((a == null) ? "null" : a.toString()); - } - }); + return new Show(a -> Stream.fromString((a == null) ? "null" : a.toString())); } /** @@ -256,13 +244,9 @@ public Stream f(final A a) { * @return A show instance for the {@link Option} type. */ public static Show> optionShow(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final Option o) { - return o.isNone() ? - fromString("None") : - fromString("Some(").append(sa.f.f(o.some())).append(single(')')); - } - }); + return new Show>(o -> o.isNone() ? + fromString("None") : + fromString("Some(").append(sa.f.f(o.some())).append(single(')'))); } /** @@ -273,13 +257,9 @@ public Stream f(final Option o) { * @return A show instance for the {@link Either} type. */ public static Show> eitherShow(final Show sa, final Show sb) { - return new Show>(new F, Stream>() { - public Stream f(final Either e) { - return e.isLeft() ? - fromString("Left(").append(sa.f.f(e.left().value())).append(single(')')) : - fromString("Right(").append(sb.f.f(e.right().value())).append(single(')')); - } - }); + return new Show>(e -> e.isLeft() ? + fromString("Left(").append(sa.f.f(e.left().value())).append(single(')')) : + fromString("Right(").append(sb.f.f(e.right().value())).append(single(')'))); } /** @@ -290,13 +270,9 @@ public Stream f(final Either e) { * @return A show instance for the {@link Validation} type. */ public static Show> validationShow(final Show sa, final Show sb) { - return new Show>(new F, Stream>() { - public Stream f(final Validation v) { - return v.isFail() ? - fromString("Fail(").append(sa.f.f(v.fail())).append(single(')')) : - fromString("Success(").append(sb.f.f(v.success())).append(single(')')); - } - }); + return new Show>(v -> v.isFail() ? + fromString("Fail(").append(sa.f.f(v.fail())).append(single(')')) : + fromString("Success(").append(sb.f.f(v.success())).append(single(')'))); } /** @@ -306,11 +282,7 @@ public Stream f(final Validation v) { * @return A show instance for the {@link Stream} type. */ public static Show> listShow(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final List as) { - return streamShow(sa).show(as.toStream()); - } - }); + return new Show>(as -> streamShow(sa).show(as.toStream())); } /** @@ -330,13 +302,11 @@ public static Show> nonEmptyListShow(final Show sa) { * @return A show instance for the {@link Tree} type. */ public static Show> treeShow(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final Tree a) { - final Stream b = sa.f.f(a.root()) - .append(p1Show(streamShow(treeShow(sa))).f.f(a.subForest())) - .snoc(')'); - return cons('(', p(b)); - } + return new Show>(a -> { + final Stream b = sa.f.f(a.root()) + .append(p1Show(streamShow(treeShow(sa))).f.f(a.subForest())) + .snoc(')'); + return cons('(', p(b)); }); } @@ -347,11 +317,7 @@ public Stream f(final Tree a) { * @return A show instance for the {@link Stream} type. */ public static Show> streamShow(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final Stream as) { - return join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">")))); - } - }); + return new Show>(as -> join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">"))))); } /** @@ -361,21 +327,19 @@ public Stream f(final Stream as) { * @return A show instance for the {@link Array} type. */ public static Show> arrayShow(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final Array as) { - Stream b = nil(); + return new Show>(as -> { + Stream b = nil(); - for (int i = 0; i < as.length(); i++) { - b = b.append(sa.f.f(as.get(i))); + for (int i = 0; i < as.length(); i++) { + b = b.append(sa.f.f(as.get(i))); - if (i != as.length() - 1) - b = b.snoc(','); - } + if (i != as.length() - 1) + b = b.snoc(','); + } - b = b.snoc('}'); + b = b.snoc('}'); - return cons('{', p(b)); - } + return cons('{', p(b)); }); } @@ -385,11 +349,7 @@ public Stream f(final Array as) { * @return A show instance for the {@link Class} type. */ public static Show> classShow() { - return new Show>(new F, Stream>() { - public Stream f(final Class c) { - return anyShow().show(c.clas()); - } - }); + return new Show>(c -> anyShow().show(c.clas())); } /** @@ -399,11 +359,7 @@ public Stream f(final Class c) { * @return A show instance for the {@link P1 tuple-1} type. */ public static Show> p1Show(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final P1 p) { - return cons('(', p(sa.show(p._1()))).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(')')); } /** @@ -414,11 +370,7 @@ public Stream f(final P1 p) { * @return A show instance for the {@link P2 tuple-2} type. */ public static Show> p2Show(final Show sa, final Show sb) { - return new Show>(new F, Stream>() { - public Stream f(final P2 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')')); } /** @@ -430,12 +382,8 @@ public Stream f(final P2 p) { * @return A show instance for the {@link P3 tuple-3} type. */ public static Show> p3Show(final Show sa, final Show sb, final Show sc) { - return new Show>(new F, Stream>() { - public Stream f(final P3 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') - .append(sc.show(p._3())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + .append(sc.show(p._3())).snoc(')')); } /** @@ -449,12 +397,8 @@ public Stream f(final P3 p) { */ public static Show> p4Show(final Show sa, final Show sb, final Show sc, final Show sd) { - return new Show>(new F, Stream>() { - public Stream f(final P4 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') - .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(')')); } /** @@ -469,12 +413,8 @@ public Stream f(final P4 p) { */ public static Show> p5Show(final Show sa, final Show sb, final Show sc, final Show sd, final Show se) { - return new Show>(new F, Stream>() { - public Stream f(final P5 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') - .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',').append(se.show(p._5())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',').append(se.show(p._5())).snoc(')')); } /** @@ -491,13 +431,9 @@ public Stream f(final P5 p) { public static Show> p6Show(final Show sa, final Show sb, final Show sc, final Show sd, final Show se, final Show sf) { - return new Show>(new F, Stream>() { - public Stream f(final P6 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') - .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') - .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') + .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(')')); } /** @@ -516,13 +452,9 @@ public Stream f(final P6 p) { final Show sc, final Show sd, final Show se, final Show sf, final Show sg) { - return new Show>(new F, Stream>() { - public Stream f(final P7 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') - .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') - .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',').append(sg.show(p._7())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') + .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',').append(sg.show(p._7())).snoc(')')); } /** @@ -542,14 +474,10 @@ public Stream f(final P7 p) { final Show sc, final Show sd, final Show se, final Show sf, final Show sg, final Show sh) { - return new Show>(new F, Stream>() { - public Stream f(final P8 p) { - return cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') - .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') - .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',') - .append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')'); - } - }); + return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') + .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',') + .append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')')); } /** @@ -625,11 +553,7 @@ public static Show> v8Show(final Show ea) { /** * A show instance for natural numbers. */ - public static final Show naturalShow = bigintShow.comap(new F() { - public BigInteger f(final Natural natural) { - return natural.bigIntegerValue(); - } - }); + public static final Show naturalShow = bigintShow.comap(Natural::bigIntegerValue); /** * A show instance for streams that splits into lines. @@ -638,21 +562,13 @@ public BigInteger f(final Natural natural) { * @return A show instance for streams that splits into lines. */ public static Show> unlineShow(final Show sa) { - return new Show>(new F, Stream>() { - public Stream f(final Stream as) { - return join(as.map(sa.show_()).intersperse(fromString("\n"))); - } - }); + return new Show>(as -> join(as.map(sa.show_()).intersperse(fromString("\n")))); } /** * A show instance for lazy strings. */ - public static final Show lazyStringShow = show(new F>() { - public Stream f(final LazyString string) { - return string.toStream(); - } - }); + public static final Show lazyStringShow = show(LazyString::toStream); /** * A show instance for the empty heterogeneous Stream. @@ -667,10 +583,6 @@ public Stream f(final LazyString string) { * @return a show instance for heterogeneous Streams. */ public static > Show> HListShow(final Show e, final Show l) { - return show(new F, Stream>() { - public Stream f(final HList.HCons c) { - return e.show(c.head()).cons('[').append(l.show(c.tail())).snoc(']'); - } - }); + return show(c -> e.show(c.head()).cons('[').append(l.show(c.tail())).snoc(']')); } } From 02528532ff2070a9aedca54006224583423d0cd3 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 16:40:47 +0530 Subject: [PATCH 202/811] Refactoring `Functiona` and `Hash` --- core/src/main/java/fj/Function.java | 476 +++------------------------- core/src/main/java/fj/Hash.java | 196 +++++------- 2 files changed, 127 insertions(+), 545 deletions(-) diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 96f62f85..843c5a55 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -51,11 +51,7 @@ public F f(final F g) { * @return A function that is the composition of the given arguments. */ public static F compose(final F f, final F g) { - return new F() { - public C f(final A a) { - return f.f(g.f(a)); - } - }; + return a -> f.f(g.f(a)); } /** @@ -66,15 +62,7 @@ public C f(final A a) { * @return A function that is the composition of the given arguments. */ public static F> compose2(final F f, final F> g) { - return new F>() { - public F f(final A a) { - return new F() { - public D f(final B b) { - return f.f(g.f(a).f(b)); - } - }; - } - }; + return a -> b -> f.f(g.f(a).f(b)); } @@ -84,15 +72,7 @@ public D f(final B b) { * @return A function that composes two functions to produce a new function. */ public static F, F, F>> andThen() { - return new F, F, F>>() { - public F, F> f(final F g) { - return new F, F>() { - public F f(final F f) { - return Function.andThen(g, f); - } - }; - } - }; + return g -> f -> Function.andThen(g, f); } /** @@ -103,11 +83,7 @@ public F f(final F f) { * @return A function that is the composition of the given arguments. */ public static F andThen(final F g, final F f) { - return new F() { - public C f(final A a) { - return f.f(g.f(a)); - } - }; + return a -> f.f(g.f(a)); } /** @@ -116,11 +92,7 @@ public C f(final A a) { * @return The identity transformation. */ public static F identity() { - return new F() { - public A f(final A a) { - return a; - } - }; + return a -> a; } /** @@ -129,11 +101,7 @@ public A f(final A a) { * @return A function that given an argument, returns a function that ignores its argument. */ public static F> constant() { - return new F>() { - public F f(final B b) { - return constant(b); - } - }; + return b -> constant(b); } /** @@ -143,11 +111,7 @@ public F f(final B b) { * @return A function that ignores its argument to constantly produce the given value. */ public static F constant(final B b) { - return new F() { - public B f(final A a) { - return b; - } - }; + return a -> b; } /** @@ -157,11 +121,7 @@ public B f(final A a) { * @return A co- and contravariant function that invokes f on its argument. */ public static F vary(final F f) { - return new F() { - public B f(final A a) { - return f.f(a); - } - }; + return a -> f.f(a); } /** @@ -170,11 +130,7 @@ public B f(final A a) { * @return A function that varies and covaries a function. */ public static F, F> vary() { - return new F, F>() { - public F f(final F f) { - return Function.vary(f); - } - }; + return f -> Function.vary(f); } /** @@ -183,11 +139,7 @@ public F f(final F f) { * @return A function that takes a function and flips its arguments. */ public static F>, F>> flip() { - return new F>, F>>() { - public F> f(final F> f) { - return flip(f); - } - }; + return f -> flip(f); } /** @@ -197,15 +149,7 @@ public F> f(final F> f) { * @return The given function flipped. */ public static F> flip(final F> f) { - return new F>() { - public F f(final B b) { - return new F() { - public C f(final A a) { - return f.f(a).f(b); - } - }; - } - }; + return b -> a -> f.f(a).f(b); } /** @@ -215,11 +159,7 @@ public C f(final A a) { * @return The given function flipped. */ public static F2 flip(final F2 f) { - return new F2() { - public C f(final B b, final A a) { - return f.f(a, b); - } - }; + return (b, a) -> f.f(a, b); } /** @@ -228,11 +168,7 @@ public C f(final B b, final A a) { * @return A function that flips the arguments of a given function. */ public static F, F2> flip2() { - return new F, F2>() { - public F2 f(final F2 f) { - return flip(f); - } - }; + return f -> flip(f); } /** @@ -244,11 +180,7 @@ public F2 f(final F2 f) { * not apply the value, instead returning an empty optional value. */ public static F> nullable(final F f) { - return new F>() { - public Option f(final A a) { - return a == null ? Option.none() : Option.some(f.f(a)); - } - }; + return a -> a == null ? Option.none() : Option.some(f.f(a)); } /** @@ -258,15 +190,7 @@ public Option f(final A a) { * @return A curried form of the given function. */ public static F> curry(final F2 f) { - return new F>() { - public F f(final A a) { - return new F() { - public C f(final B b) { - return f.f(a, b); - } - }; - } - }; + return a -> b -> f.f(a, b); } /** @@ -286,11 +210,7 @@ public static F curry(final F2 f, final A a) { * @return An uncurried function. */ public static F>, F2> uncurryF2() { - return new F>, F2>() { - public F2 f(final F> f) { - return uncurryF2(f); - } - }; + return f -> uncurryF2(f); } /** @@ -300,11 +220,7 @@ public F2 f(final F> f) { * @return An uncurried function. */ public static F2 uncurryF2(final F> f) { - return new F2() { - public C f(final A a, final B b) { - return f.f(a).f(b); - } - }; + return (a, b) -> f.f(a).f(b); } /** @@ -314,19 +230,7 @@ public C f(final A a, final B b) { * @return A curried form of the given function. */ public static F>> curry(final F3 f) { - return new F>>() { - public F> f(final A a) { - return new F>() { - public F f(final B b) { - return new F() { - public D f(final C c) { - return f.f(a, b, c); - } - }; - } - }; - } - }; + return a -> b -> c -> f.f(a, b, c); } /** @@ -358,11 +262,7 @@ public static F curry(final F3 f, final A a, fina * @return An uncurried function. */ public static F>>, F3> uncurryF3() { - return new F>>, F3>() { - public F3 f(final F>> f) { - return uncurryF3(f); - } - }; + return f -> uncurryF3(f); } /** @@ -372,11 +272,7 @@ public F3 f(final F>> f) { * @return An uncurried function. */ public static F3 uncurryF3(final F>> f) { - return new F3() { - public D f(final A a, final B b, final C c) { - return f.f(a).f(b).f(c); - } - }; + return (a, b, c) -> f.f(a).f(b).f(c); } /** @@ -386,23 +282,7 @@ public D f(final A a, final B b, final C c) { * @return A curried form of the given function. */ public static F>>> curry(final F4 f) { - return new F>>>() { - public F>> f(final A a) { - return new F>>() { - public F> f(final B b) { - return new F>() { - public F f(final C c) { - return new F() { - public E f(final D d) { - return f.f(a, b, c, d); - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> f.f(a, b, c, d); } /** @@ -447,11 +327,7 @@ public static F curry(final F4 f, final A a * @return An uncurried function. */ public static F>>>, F4> uncurryF4() { - return new F>>>, F4>() { - public F4 f(final F>>> f) { - return uncurryF4(f); - } - }; + return f -> uncurryF4(f); } /** @@ -461,11 +337,7 @@ public F4 f(final F>>> f) { * @return An uncurried function. */ public static F4 uncurryF4(final F>>> f) { - return new F4() { - public E f(final A a, final B b, final C c, final D d) { - return f.f(a).f(b).f(c).f(d); - } - }; + return (a, b, c, d) -> f.f(a).f(b).f(c).f(d); } /** @@ -475,27 +347,7 @@ public E f(final A a, final B b, final C c, final D d) { * @return A curried form of the given function. */ public static F>>>> curry(final F5 f) { - return new F>>>>() { - public F>>> f(final A a) { - return new F>>>() { - public F>> f(final B b) { - return new F>>() { - public F> f(final C c) { - return new F>() { - public F f(final D d) { - return new F() { - public F$ f(final E e) { - return f.f(a, b, c, d, e); - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f.f(a, b, c, d, e); } /** @@ -556,11 +408,7 @@ public E f(final A a, final B b, final C c, final D d) { * @return An uncurried function. */ public static F>>>>, F5> uncurryF5() { - return new F>>>>, F5>() { - public F5 f(final F>>>> f) { - return uncurryF5(f); - } - }; + return f -> uncurryF5(f); } /** @@ -570,11 +418,7 @@ public E f(final A a, final B b, final C c, final D d) { * @return An uncurried function. */ public static F5 uncurryF5(final F>>>> f) { - return new F5() { - public F$ f(final A a, final B b, final C c, final D d, final E e) { - return f.f(a).f(b).f(c).f(d).f(e); - } - }; + return (a, b, c, d, e) -> f.f(a).f(b).f(c).f(d).f(e); } /** @@ -584,31 +428,7 @@ public E f(final A a, final B b, final C c, final D d) { * @return A curried form of the given function. */ public static F>>>>> curry(final F6 f) { - return new F>>>>>() { - public F>>>> f(final A a) { - return new F>>>>() { - public F>>> f(final B b) { - return new F>>>() { - public F>> f(final C c) { - return new F>>() { - public F> f(final D d) { - return new F>() { - public F f(final E e) { - return new F() { - public G f(final F$ f$) { - return f.f(a, b, c, d, e, f$); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f$ -> f.f(a, b, c, d, e, f$); } /** @@ -617,11 +437,7 @@ public G f(final F$ f$) { * @return An uncurried function. */ public static F>>>>>, F6> uncurryF6() { - return new F>>>>>, F6>() { - public F6 f(final F>>>>> f) { - return uncurryF6(f); - } - }; + return f -> uncurryF6(f); } /** @@ -632,11 +448,7 @@ public G f(final F$ f$) { */ public static F6 uncurryF6( final F>>>>> f) { - return new F6() { - public G f(final A a, final B b, final C c, final D d, final E e, final F$ f$) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$); - } - }; + return (a, b, c, d, e, f$) -> f.f(a).f(b).f(c).f(d).f(e).f(f$); } /** @@ -647,35 +459,7 @@ public G f(final A a, final B b, final C c, final D d, final E e, final F$ f$) { */ public static F>>>>>> curry( final F7 f) { - return new F>>>>>>() { - public F>>>>> f(final A a) { - return new F>>>>>() { - public F>>>> f(final B b) { - return new F>>>>() { - public F>>> f(final C c) { - return new F>>>() { - public F>> f(final D d) { - return new F>>() { - public F> f(final E e) { - return new F>() { - public F f(final F$ f$) { - return new F() { - public H f(final G g) { - return f.f(a, b, c, d, e, f$, g); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f$ -> g -> f.f(a, b, c, d, e, f$, g); } /** @@ -786,11 +570,7 @@ public H f(final G g) { */ public static F7 uncurryF7( final F>>>>>> f) { - return new F7() { - public H f(final A a, final B b, final C c, final D d, final E e, final F$ f$, final G g) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g); - } - }; + return (a, b, c, d, e, f$, g) -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g); } /** @@ -801,39 +581,7 @@ public H f(final A a, final B b, final C c, final D d, final E e, final F$ f$, f */ public static F>>>>>>> curry( final F8 f) { - return new F>>>>>>>() { - public F>>>>>> f(final A a) { - return new F>>>>>>() { - public F>>>>> f(final B b) { - return new F>>>>>() { - public F>>>> f(final C c) { - return new F>>>>() { - public F>>> f(final D d) { - return new F>>>() { - public F>> f(final E e) { - return new F>>() { - public F> f(final F$ f$) { - return new F>() { - public F f(final G g) { - return new F() { - public I f(final H h) { - return f.f(a, b, c, d, e, f$, g, h); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f$ -> g -> h -> f.f(a, b, c, d, e, f$, g, h); } /** @@ -950,11 +698,7 @@ public I f(final H h) { * @return An uncurried function. */ public static F>>>>>>>, F8> uncurryF8() { - return new F>>>>>>>, F8>() { - public F8 f(final F>>>>>>> f) { - return uncurryF8(f); - } - }; + return f -> uncurryF8(f); } /** @@ -965,11 +709,7 @@ public I f(final H h) { */ public static F8 uncurryF8( final F>>>>>>> f) { - return new F8() { - public I f(final A a, final B b, final C c, final D d, final E e, final F$ f$, final G g, final H h) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h); - } - }; + return (a, b, c, d, e, f$, g, h) -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h); } /** @@ -983,11 +723,7 @@ public I f(final A a, final B b, final C c, final D d, final E e, final F$ f$, f * that is applied to the argument again. */ public static F bind(final F ma, final F> f) { - return new F() { - public B f(final C m) { - return f.f(ma.f(m)).f(m); - } - }; + return m -> f.f(ma.f(m)).f(m); } /** @@ -998,15 +734,7 @@ public B f(final C m) { * @return A new function after applying the given higher-order function to the given function. */ public static F apply(final F> cab, final F ca) { - return bind(cab, new F, F>() { - public F f(final F f) { - return compose(new F() { - public B f(final A a) { - return f.f(a); - } - }, ca); - } - }); + return bind(cab, f -> compose(a -> f.f(a), ca)); } /** @@ -1039,11 +767,7 @@ public static F> on(final F> a, final F f) * @return A function of arity-2 promoted to compose with two functions. */ public static F, F, F>> lift(final F> f) { - return curry(new F2, F, F>() { - public F f(final F ca, final F cb) { - return bind(ca, cb, f); - } - }); + return curry((ca, cb) -> bind(ca, cb, f)); } /** @@ -1066,11 +790,7 @@ public static F join(final F> f) { * @return A new function based on f with its second argument applied. */ public static F partialApply2(final F> f, final B b) { - return new F() { - public C f(final A a) { - return uncurryF2(f).f(a, b); - } - }; + return a -> uncurryF2(f).f(a, b); } /** @@ -1082,15 +802,7 @@ public C f(final A a) { * @return A new function based on f with its third argument applied. */ public static F> partialApply3(final F>> f, final C c) { - return new F>() { - public F f(final A a) { - return new F() { - public D f(final B b) { - return uncurryF3(f).f(a, b, c); - } - }; - } - }; + return a -> b -> uncurryF3(f).f(a, b, c); } /** @@ -1102,19 +814,7 @@ public D f(final B b) { * @return A new function based on f with its fourth argument applied. */ public static F>> partialApply4(final F>>> f, final D d) { - return new F>>() { - public F> f(final A a) { - return new F>() { - public F f(final B b) { - return new F() { - public E f(final C c) { - return uncurryF4(f).f(a, b, c, d); - } - }; - } - }; - } - }; + return a -> b -> c -> uncurryF4(f).f(a, b, c, d); } /** @@ -1127,23 +827,7 @@ public E f(final C c) { */ public static F>>> partialApply5(final F>>>> f, final E e) { - return new F>>>() { - public F>> f(final A a) { - return new F>>() { - public F> f(final B b) { - return new F>() { - public F f(final C c) { - return new F() { - public F$ f(final D d) { - return uncurryF5(f).f(a, b, c, d, e); - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> uncurryF5(f).f(a, b, c, d, e); } /** @@ -1156,27 +840,7 @@ public E f(final C c) { */ public static F>>>> partialApply6( final F>>>>> f, final F$ f$) { - return new F>>>>() { - public F>>> f(final A a) { - return new F>>>() { - public F>> f(final B b) { - return new F>>() { - public F> f(final C c) { - return new F>() { - public F f(final D d) { - return new F() { - public G f(final E e) { - return uncurryF6(f).f(a, b, c, d, e, f$); - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> uncurryF6(f).f(a, b, c, d, e, f$); } /** @@ -1189,31 +853,7 @@ public G f(final E e) { */ public static F>>>>> partialApply7( final F>>>>>> f, final G g) { - return new F>>>>>() { - public F>>>> f(final A a) { - return new F>>>>() { - public F>>> f(final B b) { - return new F>>>() { - public F>> f(final C c) { - return new F>>() { - public F> f(final D d) { - return new F>() { - public F f(final E e) { - return new F() { - public H f(final F$ f$) { - return uncurryF7(f).f(a, b, c, d, e, f$, g); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f$ -> uncurryF7(f).f(a, b, c, d, e, f$, g); } /** @@ -1226,34 +866,6 @@ public H f(final F$ f$) { */ public static F>>>>>> partialApply8( final F>>>>>>> f, final H h) { - return new F>>>>>>() { - public F>>>>> f(final A a) { - return new F>>>>>() { - public F>>>> f(final B b) { - return new F>>>>() { - public F>>> f(final C c) { - return new F>>>() { - public F>> f(final D d) { - return new F>>() { - public F> f(final E e) { - return new F>() { - public F f(final F$ f$) { - return new F() { - public I f(final G g) { - return uncurryF8(f).f(a, b, c, d, e, f$, g, h); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f$ -> g -> uncurryF8(f).f(a, b, c, d, e, f$, g, h); } } diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index d5e80951..9a616023 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -66,11 +66,7 @@ public static Hash hash(final F f) { * @return A hash that uses {@link Object#hashCode()}. */ public static Hash anyHash() { - return new Hash(new F() { - public Integer f(final A a) { - return a.hashCode(); - } - }); + return new Hash(a -> a.hashCode()); } /** @@ -156,11 +152,7 @@ public Integer f(final StringBuilder sb) { * @return A hash instance for the {@link Either} type. */ public static Hash> eitherHash(final Hash ha, final Hash hb) { - return new Hash>(new F, Integer>() { - public Integer f(final Either e) { - return e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value()); - } - }); + return new Hash>(e -> e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value())); } /** @@ -181,19 +173,17 @@ public static Hash> validationHash(final Hash ha, fin * @return A hash instance for the {@link List} type. */ public static Hash> listHash(final Hash ha) { - return new Hash>(new F, Integer>() { - public Integer f(final List as) { - final int p = 419; - int r = 239; - List aas = as; - - while (!aas.isEmpty()) { - r = p * r + ha.hash(aas.head()); - aas = aas.tail(); - } + return new Hash>(as -> { + final int p = 419; + int r = 239; + List aas = as; - return r; + while (!aas.isEmpty()) { + r = p * r + ha.hash(aas.head()); + aas = aas.tail(); } + + return r; }); } @@ -214,11 +204,7 @@ public static Hash> nonEmptyListHash(final Hash ha) { * @return A hash instance for the {@link Option} type. */ public static Hash> optionHash(final Hash ha) { - return new Hash>(new F, Integer>() { - public Integer f(final Option o) { - return o.isNone() ? 0 : ha.hash(o.some()); - } - }); + return new Hash>(o -> o.isNone() ? 0 : ha.hash(o.some())); } /** @@ -228,19 +214,17 @@ public Integer f(final Option o) { * @return A hash instance for the {@link Stream} type. */ public static Hash> streamHash(final Hash ha) { - return new Hash>(new F, Integer>() { - public Integer f(final Stream as) { - final int p = 419; - int r = 239; - Stream aas = as; - - while (!aas.isEmpty()) { - r = p * r + ha.hash(aas.head()); - aas = aas.tail()._1(); - } + return new Hash>(as -> { + final int p = 419; + int r = 239; + Stream aas = as; - return r; + while (!aas.isEmpty()) { + r = p * r + ha.hash(aas.head()); + aas = aas.tail()._1(); } + + return r; }); } @@ -251,17 +235,15 @@ public Integer f(final Stream as) { * @return A hash instance for the {@link Array} type. */ public static Hash> arrayHash(final Hash ha) { - return new Hash>(new F, Integer>() { - public Integer f(final Array as) { - final int p = 419; - int r = 239; - - for (int i = 0; i < as.length(); i++) { - r = p * r + ha.hash(as.get(i)); - } + return new Hash>(as -> { + final int p = 419; + int r = 239; - return r; + for (int i = 0; i < as.length(); i++) { + r = p * r + ha.hash(as.get(i)); } + + return r; }); } @@ -293,16 +275,14 @@ public static Hash> p1Hash(final Hash ha) { * @return A hash instance for a product-2. */ public static Hash> p2Hash(final Hash ha, final Hash hb) { - return new Hash>(new F, Integer>() { - public Integer f(final P2 p2) { - final int p = 419; - int r = 239; + return new Hash>(p2 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p2._1()); - r = p * r + hb.hash(p2._2()); + r = p * r + ha.hash(p2._1()); + r = p * r + hb.hash(p2._2()); - return r; - } + return r; }); } @@ -315,17 +295,15 @@ public Integer f(final P2 p2) { * @return A hash instance for a product-3. */ public static Hash> p3Hash(final Hash ha, final Hash hb, final Hash hc) { - return new Hash>(new F, Integer>() { - public Integer f(final P3 p3) { - final int p = 419; - int r = 239; + return new Hash>(p3 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p3._1()); - r = p * r + hb.hash(p3._2()); - r = p * r + hc.hash(p3._3()); + r = p * r + ha.hash(p3._1()); + r = p * r + hb.hash(p3._2()); + r = p * r + hc.hash(p3._3()); - return r; - } + return r; }); } @@ -367,19 +345,17 @@ public Integer f(final P4 p4) { */ public static Hash> p5Hash(final Hash ha, final Hash hb, final Hash hc, final Hash hd, final Hash he) { - return new Hash>(new F, Integer>() { - public Integer f(final P5 p5) { - final int p = 419; - int r = 239; + return new Hash>(p5 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p5._1()); - r = p * r + hb.hash(p5._2()); - r = p * r + hc.hash(p5._3()); - r = p * r + hd.hash(p5._4()); - r = p * r + he.hash(p5._5()); + r = p * r + ha.hash(p5._1()); + r = p * r + hb.hash(p5._2()); + r = p * r + hc.hash(p5._3()); + r = p * r + hd.hash(p5._4()); + r = p * r + he.hash(p5._5()); - return r; - } + return r; }); } @@ -397,20 +373,18 @@ public Integer f(final P5 p5) { public static Hash> p6Hash(final Hash ha, final Hash hb, final Hash hc, final Hash hd, final Hash he, final Hash hf) { - return new Hash>(new F, Integer>() { - public Integer f(final P6 p6) { - final int p = 419; - int r = 239; + return new Hash>(p6 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p6._1()); - r = p * r + hb.hash(p6._2()); - r = p * r + hc.hash(p6._3()); - r = p * r + hd.hash(p6._4()); - r = p * r + he.hash(p6._5()); - r = p * r + hf.hash(p6._6()); + r = p * r + ha.hash(p6._1()); + r = p * r + hb.hash(p6._2()); + r = p * r + hc.hash(p6._3()); + r = p * r + hd.hash(p6._4()); + r = p * r + he.hash(p6._5()); + r = p * r + hf.hash(p6._6()); - return r; - } + return r; }); } @@ -430,21 +404,19 @@ public Integer f(final P6 p6) { final Hash hc, final Hash hd, final Hash he, final Hash hf, final Hash hg) { - return new Hash>(new F, Integer>() { - public Integer f(final P7 p7) { - final int p = 419; - int r = 239; + return new Hash>(p7 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p7._1()); - r = p * r + hb.hash(p7._2()); - r = p * r + hc.hash(p7._3()); - r = p * r + hd.hash(p7._4()); - r = p * r + he.hash(p7._5()); - r = p * r + hf.hash(p7._6()); - r = p * r + hg.hash(p7._7()); + r = p * r + ha.hash(p7._1()); + r = p * r + hb.hash(p7._2()); + r = p * r + hc.hash(p7._3()); + r = p * r + hd.hash(p7._4()); + r = p * r + he.hash(p7._5()); + r = p * r + hf.hash(p7._6()); + r = p * r + hg.hash(p7._7()); - return r; - } + return r; }); } @@ -465,22 +437,20 @@ public Integer f(final P7 p7) { final Hash hc, final Hash hd, final Hash he, final Hash hf, final Hash hg, final Hash hh) { - return new Hash>(new F, Integer>() { - public Integer f(final P8 p8) { - final int p = 419; - int r = 239; + return new Hash>(p8 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p8._1()); - r = p * r + hb.hash(p8._2()); - r = p * r + hc.hash(p8._3()); - r = p * r + hd.hash(p8._4()); - r = p * r + he.hash(p8._5()); - r = p * r + hf.hash(p8._6()); - r = p * r + hg.hash(p8._7()); - r = p * r + hh.hash(p8._8()); + r = p * r + ha.hash(p8._1()); + r = p * r + hb.hash(p8._2()); + r = p * r + hc.hash(p8._3()); + r = p * r + hd.hash(p8._4()); + r = p * r + he.hash(p8._5()); + r = p * r + hf.hash(p8._6()); + r = p * r + hg.hash(p8._7()); + r = p * r + hh.hash(p8._8()); - return r; - } + return r; }); } From 7a04219032660ffc825fc0666085f6745dc47e05 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 16:47:14 +0530 Subject: [PATCH 203/811] Refactoring `Equal` --- core/src/main/java/fj/Equal.java | 286 ++++++++----------------------- 1 file changed, 74 insertions(+), 212 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index d47e51dd..8ca04ef9 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -44,11 +44,7 @@ public boolean eq(final A a1, final A a2) { * @return A function that returns true if the two given arguments are equal. */ public F2 eq() { - return new F2() { - public Boolean f(final A a, final A a1) { - return eq(a, a1); - } - }; + return (a, a1) -> eq(a, a1); } /** @@ -58,11 +54,7 @@ public Boolean f(final A a, final A a1) { * @return A function that returns true if the given argument equals the argument to this method. */ public F eq(final A a) { - return new F() { - public Boolean f(final A a1) { - return eq(a, a1); - } - }; + return a1 -> eq(a, a1); } /** @@ -93,15 +85,7 @@ public static Equal equal(final F> f) { * equality. */ public static Equal anyEqual() { - return new Equal(new F>() { - public F f(final A a1) { - return new F() { - public Boolean f(final A a2) { - return a1.equals(a2); - } - }; - } - }); + return new Equal(a1 -> a2 -> a1.equals(a2)); } /** @@ -163,40 +147,28 @@ public Boolean f(final A a2) { * An equal instance for the {@link StringBuffer} type. */ public static final Equal stringBufferEqual = - new Equal(new F>() { - public F f(final StringBuffer sb1) { - return new F() { - public Boolean f(final StringBuffer sb2) { - if (sb1.length() == sb2.length()) { - for (int i = 0; i < sb1.length(); i++) - if (sb1.charAt(i) != sb2.charAt(i)) - return false; - return true; - } else - return false; - } - }; - } + new Equal(sb1 -> sb2 -> { + if (sb1.length() == sb2.length()) { + for (int i = 0; i < sb1.length(); i++) + if (sb1.charAt(i) != sb2.charAt(i)) + return false; + return true; + } else + return false; }); /** * An equal instance for the {@link StringBuilder} type. */ public static final Equal stringBuilderEqual = - new Equal(new F>() { - public F f(final StringBuilder sb1) { - return new F() { - public Boolean f(final StringBuilder sb2) { - if (sb1.length() == sb2.length()) { - for (int i = 0; i < sb1.length(); i++) - if (sb1.charAt(i) != sb2.charAt(i)) - return false; - return true; - } else - return false; - } - }; - } + new Equal(sb1 -> sb2 -> { + if (sb1.length() == sb2.length()) { + for (int i = 0; i < sb1.length(); i++) + if (sb1.charAt(i) != sb2.charAt(i)) + return false; + return true; + } else + return false; }); /** @@ -207,16 +179,8 @@ public Boolean f(final StringBuilder sb2) { * @return An equal instance for the {@link Either} type. */ public static Equal> eitherEqual(final Equal ea, final Equal eb) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final Either e1) { - return new F, Boolean>() { - public Boolean f(final Either e2) { - return e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || - e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value()); - } - }; - } - }); + return new Equal>(e1 -> e2 -> e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || + e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value())); } /** @@ -237,25 +201,19 @@ public static Equal> validationEqual(final Equal ea, * @return An equal instance for the {@link List} type. */ public static Equal> listEqual(final Equal ea) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final List a1) { - return new F, Boolean>() { - public Boolean f(final List a2) { - List x1 = a1; - List x2 = a2; - - while (x1.isNotEmpty() && x2.isNotEmpty()) { - if (!ea.eq(x1.head(), x2.head())) - return false; - - x1 = x1.tail(); - x2 = x2.tail(); - } - - return x1.isEmpty() && x2.isEmpty(); - } - }; + return new Equal>(a1 -> a2 -> { + List x1 = a1; + List x2 = a2; + + while (x1.isNotEmpty() && x2.isNotEmpty()) { + if (!ea.eq(x1.head(), x2.head())) + return false; + + x1 = x1.tail(); + x2 = x2.tail(); } + + return x1.isEmpty() && x2.isEmpty(); }); } @@ -276,16 +234,8 @@ public static Equal> nonEmptyListEqual(final Equal ea) { * @return An equal instance for the {@link Option} type. */ public static Equal> optionEqual(final Equal ea) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final Option o1) { - return new F, Boolean>() { - public Boolean f(final Option o2) { - return o1.isNone() && o2.isNone() || - o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some()); - } - }; - } - }); + return new Equal>(o1 -> o2 -> o1.isNone() && o2.isNone() || + o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some())); } /** @@ -295,25 +245,19 @@ public Boolean f(final Option o2) { * @return An equal instance for the {@link Stream} type. */ public static Equal> streamEqual(final Equal ea) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final Stream a1) { - return new F, Boolean>() { - public Boolean f(final Stream a2) { - Stream x1 = a1; - Stream x2 = a2; - - while (x1.isNotEmpty() && x2.isNotEmpty()) { - if (!ea.eq(x1.head(), x2.head())) - return false; - - x1 = x1.tail()._1(); - x2 = x2.tail()._1(); - } - - return x1.isEmpty() && x2.isEmpty(); - } - }; + return new Equal>(a1 -> a2 -> { + Stream x1 = a1; + Stream x2 = a2; + + while (x1.isNotEmpty() && x2.isNotEmpty()) { + if (!ea.eq(x1.head(), x2.head())) + return false; + + x1 = x1.tail()._1(); + x2 = x2.tail()._1(); } + + return x1.isEmpty() && x2.isEmpty(); }); } @@ -324,21 +268,15 @@ public Boolean f(final Stream a2) { * @return An equal instance for the {@link Array} type. */ public static Equal> arrayEqual(final Equal ea) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final Array a1) { - return new F, Boolean>() { - public Boolean f(final Array a2) { - if (a1.length() == a2.length()) { - for (int i = 0; i < a1.length(); i++) { - if (!ea.eq(a1.get(i), a2.get(i))) - return false; - } - return true; - } else - return false; - } - }; - } + return new Equal>(a1 -> a2 -> { + if (a1.length() == a2.length()) { + for (int i = 0; i < a1.length(); i++) { + if (!ea.eq(a1.get(i), a2.get(i))) + return false; + } + return true; + } else + return false; }); } @@ -349,11 +287,7 @@ public Boolean f(final Array a2) { * @return An equal instance for the {@link Tree} type. */ public static Equal> treeEqual(final Equal ea) { - return new Equal>(curry(new F2, Tree, Boolean>() { - public Boolean f(final Tree t1, final Tree t2) { - return ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()); - } - })); + return new Equal>(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); } /** @@ -363,15 +297,7 @@ public Boolean f(final Tree t1, final Tree t2) { * @return An equal instance for a product-1. */ public static Equal> p1Equal(final Equal ea) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P1 p1) { - return new F, Boolean>() { - public Boolean f(final P1 p2) { - return ea.eq(p1._1(), p2._1()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1())); } /** @@ -382,15 +308,7 @@ public Boolean f(final P1 p2) { * @return An equal instance for a product-2. */ public static Equal> p2Equal(final Equal ea, final Equal eb) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P2 p1) { - return new F, Boolean>() { - public Boolean f(final P2 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2())); } /** @@ -402,15 +320,7 @@ public Boolean f(final P2 p2) { * @return An equal instance for a product-3. */ public static Equal> p3Equal(final Equal ea, final Equal eb, final Equal ec) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P3 p1) { - return new F, Boolean>() { - public Boolean f(final P3 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3())); } /** @@ -424,16 +334,8 @@ public Boolean f(final P3 p2) { */ public static Equal> p4Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P4 p1) { - return new F, Boolean>() { - public Boolean f(final P4 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + ed.eq(p1._4(), p2._4())); } /** @@ -449,16 +351,8 @@ public Boolean f(final P4 p2) { public static Equal> p5Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P5 p1) { - return new F, Boolean>() { - public Boolean f(final P5 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5())); } /** @@ -475,16 +369,8 @@ public Boolean f(final P5 p2) { public static Equal> p6Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee, final Equal ef) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P6 p1) { - return new F, Boolean>() { - public Boolean f(final P6 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6())); } /** @@ -503,17 +389,9 @@ public Boolean f(final P6 p2) { final Equal ec, final Equal ed, final Equal ee, final Equal ef, final Equal eg) { - return new Equal>(new F, F, Boolean>>() { - public F, Boolean> f(final P7 p1) { - return new F, Boolean>() { - public Boolean f(final P7 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && - eg.eq(p1._7(), p2._7()); - } - }; - } - }); + return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && + eg.eq(p1._7(), p2._7())); } /** @@ -538,17 +416,9 @@ public Boolean f(final P7 p2) { final Equal eg, final Equal eh) { return new Equal>( - new F, F, Boolean>>() { - public F, Boolean> f(final P8 p1) { - return new F, Boolean>() { - public Boolean f(final P8 p2) { - return ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && - eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8()); - } - }; - } - }); + p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && + eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8())); } /** @@ -639,11 +509,7 @@ public static Equal> v8Equal(final Equal ea) { * @return an equal instance for a heterogeneous list. */ public static > Equal> hListEqual(final Equal e, final Equal l) { - return equal(curry(new F2, HList.HCons, Boolean>() { - public Boolean f(final HList.HCons c1, final HList.HCons c2) { - return e.eq(c1.head(), c2.head()) && l.eq(c1.tail(), c2.tail()); - } - })); + return equal(curry((HList.HCons c1, HList.HCons c2) -> e.eq(c1.head(), c2.head()) && l.eq(c1.tail(), c2.tail()))); } /** @@ -653,11 +519,7 @@ public Boolean f(final HList.HCons c1, final HList.HCons c2) { * @return An equal instance for sets. */ public static Equal> setEqual(final Equal e) { - return equal(curry(new F2, Set, Boolean>() { - public Boolean f(final Set a, final Set b) { - return streamEqual(e).eq(a.toStream(), b.toStream()); - } - })); + return equal(curry((Set a, Set b) -> streamEqual(e).eq(a.toStream(), b.toStream()))); } public static Equal> writerEqual(Equal eq1, Equal eq2) { From 3cec7b7d552f0232851adf13a689313bbaa78d74 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 17:03:39 +0530 Subject: [PATCH 204/811] Refactoring `Class` and `Bottom` --- core/src/main/java/fj/Bottom.java | 18 +++----------- core/src/main/java/fj/Class.java | 41 +++++++++++++------------------ 2 files changed, 21 insertions(+), 38 deletions(-) diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index 6c475bd4..d773bfe2 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -52,10 +52,8 @@ public static P1 error_(final String s) { * @return A function that throws an error using the given message, ignoring its argument. */ public static F errorF(final String s) { - return new F() { - public B f(final A a) { - throw new Error(s); - } + return a -> { + throw new Error(s); }; } @@ -87,11 +85,7 @@ public static Error decons(final java.lang.Class c) { * @return A function that returns the toString for a throwable. */ public static F eToString() { - return new F() { - public String f(final Throwable t) { - return t.toString(); - } - }; + return t -> t.toString(); } /** @@ -100,10 +94,6 @@ public String f(final Throwable t) { * @return A function that returns the getMessage for a throwable. */ public static F eMessage() { - return new F() { - public String f(final Throwable t) { - return t.getMessage(); - } - }; + return t -> t.getMessage(); } } diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index 9e02c4e4..50c7c5a7 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -29,31 +29,24 @@ private Class(final java.lang.Class c) { */ public List> inheritance() { return unfold( - new F, Option, java.lang.Class>>>() { - public Option, java.lang.Class>> f( - final java.lang.Class c) { - if (c == null) - return none(); - else { - final P2, java.lang.Class> p = - new P2, java.lang.Class>() { - public java.lang.Class _1() { - return c; - } + (java.lang.Class c2) -> { + if (c == null) + return none(); + else { + final P2, java.lang.Class> p = + new P2, java.lang.Class>() { + public java.lang.Class _1() { + return c; + } - @SuppressWarnings({"unchecked"}) - public java.lang.Class _2() { - return c.getSuperclass(); - } - }; - return some(p); - } - } - }, c).map(new F, Class>() { - public Class f(final java.lang.Class c) { - return clas(c); - } - }); + @SuppressWarnings({"unchecked"}) + public java.lang.Class _2() { + return c.getSuperclass(); + } + }; + return some(p); + } + }, c).map(c1 -> clas(c1)); } /** From c55531304a11db3ac05098c113de9a3586179601 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 17:11:40 +0530 Subject: [PATCH 205/811] Refactoring `Shrink` and `Variant` --- core/src/main/java/fj/test/Shrink.java | 436 ++++++------------------ core/src/main/java/fj/test/Variant.java | 27 +- 2 files changed, 115 insertions(+), 348 deletions(-) diff --git a/core/src/main/java/fj/test/Shrink.java b/core/src/main/java/fj/test/Shrink.java index 8f43d181..41810843 100644 --- a/core/src/main/java/fj/test/Shrink.java +++ b/core/src/main/java/fj/test/Shrink.java @@ -114,11 +114,7 @@ public Stream shrink(final A a) { * @return A shrink from this shrink and the given symmetric transformations. */ public Shrink map(final F f, final F g) { - return new Shrink(new F>() { - public Stream f(final B b) { - return Shrink.this.f.f(g.f(b)).map(f); - } - }); + return new Shrink(b -> Shrink.this.f.f(g.f(b)).map(f)); } @@ -140,45 +136,27 @@ public static Shrink shrink(final F> f) { * @return A shrink strategy that cannot be reduced further. */ public static Shrink empty() { - return new Shrink(new F>() { - public Stream f(final A a) { - return nil(); - } - }); + return new Shrink(a -> nil()); } /** * A shrink strategy for longs using 0 as the bottom of the shrink. */ - public static final Shrink shrinkLong = new Shrink(new F>() { - public Stream f(final Long i) { - if (i == 0L) - return nil(); - else { - final Stream is = cons(0L, new P1>() { - public Stream _1() { - return iterate(new F() { - public Long f(final Long x) { - return x / 2L; - } - }, i).takeWhile(new F() { - public Boolean f(final Long x) { - return x != 0L; - } - }).map(new F() { - public Long f(final Long x) { - return i - x; - } - }); - } - }); - - return i < 0L ? cons(-i, new P1>() { - public Stream _1() { - return is; - } - }) : is; - } + public static final Shrink shrinkLong = new Shrink(i -> { + if (i == 0L) + return nil(); + else { + final Stream is = cons(0L, new P1>() { + public Stream _1() { + return iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1); + } + }); + + return i < 0L ? cons(-i, new P1>() { + public Stream _1() { + return is; + } + }) : is; } }); @@ -226,17 +204,13 @@ public Stream _1() { * @return A shrink strategy for optional values. */ public static Shrink> shrinkOption(final Shrink sa) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final Option o) { - return o.isNone() ? - Stream.>nil() : - cons(Option.none(), new P1>>() { - public Stream> _1() { - return sa.shrink(o.some()).map(Option.some_()); - } - }); - } - }); + return new Shrink>(o -> o.isNone() ? + Stream.>nil() : + cons(Option.none(), new P1>>() { + public Stream> _1() { + return sa.shrink(o.some()).map(Option.some_()); + } + })); } /** @@ -280,15 +254,7 @@ public Stream> _1() { final List as2 = as.drop(n1); return cons(as2, new P1>>() { public Stream> _1() { - return removeChunks(n1, as1).filter(isNotEmpty).map(new F, List>() { - public List f(final List aas) { - return aas.append(as2); - } - }).interleave(removeChunks(n2, as2).filter(isNotEmpty).map(new F, List>() { - public List f(final List aas) { - return as1.append(aas); - } - })); + return removeChunks(n1, as1).filter(isNotEmpty).map(aas1 -> aas1.append(as2)).interleave(removeChunks(n2, as2).filter(isNotEmpty).map(aas -> as1.append(aas))); } }); } @@ -301,23 +267,13 @@ Stream> shrinkOne(final List as) { if (as.isEmpty()) return nil(); else - return sa.shrink(as.head()).map(new F>() { - public List f(final A a) { - return as.tail().cons(a); - } - }).append(shrinkOne(as.tail()).map(new F, List>() { - public List f(final List aas) { - return aas.cons(as.head()); - } - })); + return sa.shrink(as.head()).map(a -> as.tail().cons(a)).append(shrinkOne(as.tail()).map(aas -> aas.cons(as.head()))); } } - return new Shrink>(new F, Stream>>() { - public Stream> f(final List as) { - final Util u = new Util(); - return u.removeChunks(as.length(), as).append(u.shrinkOne(as)); - } + return new Shrink>(as -> { + final Util u = new Util(); + return u.removeChunks(as.length(), as).append(u.shrinkOne(as)); }); } @@ -366,15 +322,7 @@ public static Shrink> shrinkStream(final Shrink sa) { * @return A shrink strategy for throwables. */ public static Shrink shrinkThrowable(final Shrink ss) { - return ss.map(new F() { - public Throwable f(final String s) { - return new Throwable(s); - } - }, new F() { - public String f(final Throwable t) { - return t.getMessage(); - } - }); + return ss.map(s -> new Throwable(s), t -> t.getMessage()); } /** @@ -404,31 +352,17 @@ public static Shrink> shrinkArrayList(final Shrink sa) { * A shrink strategy for calendars. */ public static final Shrink shrinkCalendar = - shrinkLong.map(new F() { - public Calendar f(final Long i) { - final Calendar c = Calendar.getInstance(); - c.setTimeInMillis(i); - return c; - } - }, new F() { - public Long f(final Calendar c) { - return c.getTime().getTime(); - } - }); + shrinkLong.map(i -> { + final Calendar c = Calendar.getInstance(); + c.setTimeInMillis(i); + return c; + }, c -> c.getTime().getTime()); /** * A shrink strategy for dates. */ public static final Shrink shrinkDate = - shrinkLong.map(new F() { - public Date f(final Long i) { - return new Date(i); - } - }, new F() { - public Long f(final Date d) { - return d.getTime(); - } - }); + shrinkLong.map(i -> new Date(i), d -> d.getTime()); /** * A shrink strategy for enum maps. @@ -438,17 +372,7 @@ public Long f(final Date d) { * @return A shrink strategy for enum maps. */ public static , V> Shrink> shrinkEnumMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, EnumMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public EnumMap f(final Hashtable h) { - return new EnumMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final EnumMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new EnumMap(h), m -> new Hashtable(m)); } /** @@ -465,17 +389,11 @@ public static > Shrink> shrinkEnumSet(final Shrink< * A shrink strategy for gregorian calendars. */ public static final Shrink shrinkGregorianCalendar = - shrinkLong.map(new F() { - public GregorianCalendar f(final Long i) { - final GregorianCalendar c = new GregorianCalendar(); - c.setTimeInMillis(i); - return c; - } - }, new F() { - public Long f(final GregorianCalendar c) { - return c.getTime().getTime(); - } - }); + shrinkLong.map(i -> { + final GregorianCalendar c = new GregorianCalendar(); + c.setTimeInMillis(i); + return c; + }, c -> c.getTime().getTime()); /** * A shrink strategy for hash maps. @@ -485,17 +403,7 @@ public Long f(final GregorianCalendar c) { * @return A shrink strategy for hash maps. */ public static Shrink> shrinkHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, HashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public HashMap f(final Hashtable h) { - return new HashMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final HashMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new HashMap(h), m -> new Hashtable(m)); } /** @@ -517,24 +425,18 @@ public static Shrink> shrinkHashSet(final Shrink sa) { */ @SuppressWarnings({"UseOfObsoleteCollectionType"}) public static Shrink> shrinkHashtable(final Shrink sk, final Shrink sv) { - return shrinkList(shrinkP2(sk, sv)).map(new F>, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final List> kvs) { - final Hashtable h = new Hashtable(); - kvs.foreachDoEffect(kv -> h.put(kv._1(), kv._2())); - return h; - } - }, new F, List>>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public List> f(final Hashtable h) { - List> x = List.nil(); + return shrinkList(shrinkP2(sk, sv)).map(kvs -> { + final Hashtable h = new Hashtable(); + kvs.foreachDoEffect(kv -> h.put(kv._1(), kv._2())); + return h; + }, h -> { + List> x = List.nil(); - for (final K k : h.keySet()) { - x = x.snoc(p(k, h.get(k))); - } - - return x; + for (final K k : h.keySet()) { + x = x.snoc(p(k, h.get(k))); } + + return x; }); } @@ -546,17 +448,7 @@ public List> f(final Hashtable h) { * @return A shrink strategy for identity hash maps. */ public static Shrink> shrinkIdentityHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, IdentityHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public IdentityHashMap f(final Hashtable h) { - return new IdentityHashMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final IdentityHashMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new IdentityHashMap(h), m -> new Hashtable(m)); } /** @@ -567,17 +459,7 @@ public Hashtable f(final IdentityHashMap m) { * @return A shrink strategy for linked hash maps. */ public static Shrink> shrinkLinkedHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, LinkedHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public LinkedHashMap f(final Hashtable h) { - return new LinkedHashMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final LinkedHashMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new LinkedHashMap(h), m -> new Hashtable(m)); } /** @@ -614,28 +496,22 @@ public static Shrink> shrinkPriorityQueue(final Shrink s * A shrink strategy for properties. */ public static final Shrink shrinkProperties = shrinkHashtable(shrinkString, shrinkString) - .map(new F, Properties>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Properties f(final Hashtable h) { - final Properties p = new Properties(); - - for (final String k : h.keySet()) { - p.setProperty(k, h.get(k)); - } + .map(h -> { + final Properties p = new Properties(); - return p; + for (final String k : h.keySet()) { + p.setProperty(k, h.get(k)); } - }, new F>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final Properties p) { - final Hashtable t = new Hashtable(); - for (final Object s : p.keySet()) { - t.put((String) s, p.getProperty((String) s)); - } + return p; + }, p -> { + final Hashtable t = new Hashtable(); - return t; + for (final Object s : p.keySet()) { + t.put((String) s, p.getProperty((String) s)); } + + return t; }); /** @@ -656,17 +532,7 @@ public static Shrink> shrinkStack(final Shrink sa) { * @return A shrink strategy for tree maps. */ public static Shrink> shrinkTreeMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, TreeMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public TreeMap f(final Hashtable h) { - return new TreeMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final TreeMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new TreeMap(h), m -> new Hashtable(m)); } /** @@ -697,17 +563,7 @@ public static Shrink> shrinkVector(final Shrink sa) { * @return A shrink strategy for weak hash maps. */ public static Shrink> shrinkWeakHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, WeakHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public WeakHashMap f(final Hashtable h) { - return new WeakHashMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final WeakHashMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new WeakHashMap(h), m -> new Hashtable(m)); } // END java.util @@ -732,17 +588,7 @@ public static Shrink> shrinkArrayBlockingQueue(final S * @return A shrink strategy for concurrent hash maps. */ public static Shrink> shrinkConcurrentHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(new F, ConcurrentHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public ConcurrentHashMap f(final Hashtable h) { - return new ConcurrentHashMap(h); - } - }, new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Hashtable f(final ConcurrentHashMap m) { - return new Hashtable(m); - } - }); + return shrinkHashtable(sk, sv).map(h -> new ConcurrentHashMap(h), m -> new Hashtable(m)); } /** @@ -823,43 +669,19 @@ public static Shrink> shrinkSynchronousQueue(final Shrin * A shrink strategy for SQL dates. */ public static final Shrink shrinkSQLDate = - shrinkLong.map(new F() { - public java.sql.Date f(final Long i) { - return new java.sql.Date(i); - } - }, new F() { - public Long f(final java.sql.Date c) { - return c.getTime(); - } - }); + shrinkLong.map(i -> new java.sql.Date(i), c -> c.getTime()); /** * A shrink strategy for SQL times. */ public static final Shrink Shrink> shrinkP1(final Shrink sa) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P1 p) { - return sa.shrink(p._1()).map(new F>() { - public P1 f(final A a) { - return p(a); - } - }); - } - }); + return new Shrink>(p -> sa.shrink(p._1()).map(a -> p(a))); } /** @@ -932,11 +734,9 @@ public P1 f(final A a) { * @return a shrinking strategy for product-2 values. */ public static Shrink> shrinkP2(final Shrink sa, final Shrink sb) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P2 p) { - final F>> p2 = p2(); - return sa.shrink(p._1()).bind(sb.shrink(p._2()), p2); - } + return new Shrink>(p -> { + final F>> p2 = p2(); + return sa.shrink(p._1()).bind(sb.shrink(p._2()), p2); }); } @@ -949,11 +749,9 @@ public Stream> f(final P2 p) { * @return a shrinking strategy for product-3 values. */ public static Shrink> shrinkP3(final Shrink sa, final Shrink sb, final Shrink sc) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P3 p) { - final F>>> p3 = p3(); - return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), p3); - } + return new Shrink>(p -> { + final F>>> p3 = p3(); + return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), p3); }); } @@ -968,11 +766,9 @@ public Stream> f(final P3 p) { */ public static Shrink> shrinkP4(final Shrink sa, final Shrink sb, final Shrink sc, final Shrink sd) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P4 p) { - final F>>>> p4 = p4(); - return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), p4); - } + return new Shrink>(p -> { + final F>>>> p4 = p4(); + return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), p4); }); } @@ -989,11 +785,9 @@ public Stream> f(final P4 p) { public static Shrink> shrinkP5(final Shrink sa, final Shrink sb, final Shrink sc, final Shrink sd, final Shrink se) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P5 p) { - final F>>>>> p5 = p5(); - return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), p5); - } + return new Shrink>(p -> { + final F>>>>> p5 = p5(); + return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), p5); }); } @@ -1011,12 +805,10 @@ public Stream> f(final P5 p) { public static Shrink> shrinkP6(final Shrink sa, final Shrink sb, final Shrink sc, final Shrink sd, final Shrink se, final Shrink sf) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P6 p) { - final F>>>>>> p6 = p6(); - return sa.shrink(p._1()) - .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), p6); - } + return new Shrink>(p -> { + final F>>>>>> p6 = p6(); + return sa.shrink(p._1()) + .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), p6); }); } @@ -1037,13 +829,11 @@ public Stream> f(final P5 p) { final Shrink se, final Shrink sf, final Shrink sg) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final P7 p) { - final F>>>>>>> p7 = p7(); - return sa.shrink(p._1()) - .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), + return new Shrink>(p -> { + final F>>>>>>> p7 = p7(); + return sa.shrink(p._1()) + .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), sg.shrink(p._7()), p7); - } }); } @@ -1069,13 +859,11 @@ public Stream> f(final P5 p) { final Shrink sg, final Shrink sh) { return new Shrink>( - new F, Stream>>() { - public Stream> f(final P8 p) { - final F>>>>>>>> p8 = p8(); - return sa.shrink(p._1()) - .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), - sg.shrink(p._7()), sh.shrink(p._8()), p8); - } - }); + p -> { + final F>>>>>>>> p8 = p8(); + return sa.shrink(p._1()) + .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), + sg.shrink(p._7()), sh.shrink(p._8()), p8); + }); } } diff --git a/core/src/main/java/fj/test/Variant.java b/core/src/main/java/fj/test/Variant.java index 54b3c1ab..2612c14a 100644 --- a/core/src/main/java/fj/test/Variant.java +++ b/core/src/main/java/fj/test/Variant.java @@ -53,27 +53,10 @@ public static Gen variant(final long n, final Gen g) { final LongGen p = new LongGen(n, g); final Gen gx = variantMemo.get(p); if(gx == null) { - final Gen t = gen(new F>() { - public F f(final Integer i) { - return new F() { - public A f(final Rand r) { - return g.gen(i, r.reseed(n)); - } - }; - } - }); + final Gen t = gen(i -> r -> g.gen(i, r.reseed(n))); variantMemo.put(p, t); return t; - } else return gen(new F>() { - public F f(final Integer i) { - return new F() { - @SuppressWarnings({"unchecked"}) - public A f(final Rand r) { - return (A)gx.gen(i, r); - } - }; - } - }); + } else return gen(i -> r -> (A)gx.gen(i, r)); } /** @@ -83,11 +66,7 @@ public A f(final Rand r) { * @return A curried version of {@link #variant(long, Gen)}. */ public static F, Gen> variant(final long n) { - return new F, Gen>() { - public Gen f(final Gen g) { - return variant(n, g); - } - }; + return g -> variant(n, g); } } From 0fba01609a96be2ab47d7b3b086891b723dc469a Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 17:19:11 +0530 Subject: [PATCH 206/811] Refactoring `Parser` --- core/src/main/java/fj/parser/Parser.java | 268 +++++------------------ 1 file changed, 51 insertions(+), 217 deletions(-) diff --git a/core/src/main/java/fj/parser/Parser.java b/core/src/main/java/fj/parser/Parser.java index e74c697f..6c89a071 100644 --- a/core/src/main/java/fj/parser/Parser.java +++ b/core/src/main/java/fj/parser/Parser.java @@ -45,15 +45,7 @@ public Validation> parse(final I i) { * @return A parser with the new input type. */ public Parser xmap(final F f, final F g) { - return parser(new F>>() { - public Validation> f(final Z z) { - return parse(g.f(z)).map(new F, Result>() { - public Result f(final Result r) { - return r.mapRest(f); - } - }); - } - }); + return parser(z -> parse(g.f(z)).map(r -> r.mapRest(f))); } /** @@ -63,15 +55,7 @@ public Result f(final Result r) { * @return A parser with the new result type. */ public Parser map(final F f) { - return parser(new F>>() { - public Validation> f(final I i) { - return parse(i).map(new F, Result>() { - public Result f(final Result r) { - return r.mapValue(f); - } - }); - } - }); + return parser(i -> parse(i).map(r -> r.mapValue(f))); } /** @@ -82,18 +66,12 @@ public Result f(final Result r) { * @return A parser that fails with the given error if the result value does not meet the given predicate. */ public Parser filter(final F f, final E e) { - return parser(new F>>() { - public Validation> f(final I i) { - return parse(i).bind(new F, Validation>>() { - public Validation> f(final Result r) { - final A v = r.value(); - return f.f(v) ? - Validation.>success(result(r.rest(), v)) : - Validation.>fail(e); - } - }); - } - }); + return parser(i -> parse(i).bind(r -> { + final A v = r.value(); + return f.f(v) ? + Validation.>success(result(r.rest(), v)) : + Validation.>fail(e); + })); } /** @@ -103,15 +81,7 @@ public Validation> f(final Result r) { * @return A new parser after performing the map, then final join. */ public Parser bind(final F> f) { - return parser(new F>>() { - public Validation> f(final I i) { - return parse(i).bind(new F, Validation>>() { - public Validation> f(final Result r) { - return f.f(r.value()).parse(r.rest()); - } - }); - } - }); + return parser(i -> parse(i).bind(r -> f.f(r.value()).parse(r.rest()))); } /** @@ -233,11 +203,7 @@ public Parser bind(final Parser pb, final Parser Parser sequence(final Parser p) { - return bind(new F>() { - public Parser f(final A a) { - return p; - } - }); + return bind(a -> p); } /** @@ -247,11 +213,7 @@ public Parser f(final A a) { * @return A new parser after function application. */ public Parser apply(final Parser, E> p) { - return p.bind(new F, Parser>() { - public Parser f(final F f) { - return map(f); - } - }); + return p.bind((F, Parser>) f1 -> map(f1)); } /** @@ -261,11 +223,7 @@ public Parser f(final F f) { * @return A parser that tries this parser and if it fails, then tries the given parser. */ public Parser or(final P1> alt) { - return parser(new F>>() { - public Validation> f(final I i) { - return parse(i).f().sequence(alt._1().parse(i)); - } - }); + return parser(i -> parse(i).f().sequence(alt._1().parse(i))); } /** @@ -287,15 +245,7 @@ public Parser or(final Parser alt) { * @return A parser that tries this parser and if it fails, then tries the given parser. */ public Parser or(final P1> alt, final Semigroup s) { - return parser(new F>>() { - public Validation> f(final I i) { - return parse(i).f().bind(new F>>() { - public Validation> f(final E e) { - return alt._1().parse(i).f().map(s.sum(e)); - } - }); - } - }); + return parser(i -> parse(i).f().bind(e -> alt._1().parse(i).f().map(s.sum(e)))); } /** @@ -317,13 +267,9 @@ public Parser or(final Parser alt, final Semigroup s) { * @return A parser that negates this parser. */ public Parser not(final P1 e) { - return parser(new F>>() { - public Validation> f(final I i) { - return parse(i).isFail() ? - Validation.>success(result(i, unit())) : - Validation.>fail(e._1()); - } - }); + return parser(i -> parse(i).isFail() ? + Validation.>success(result(i, unit())) : + Validation.>fail(e._1())); } /** @@ -355,15 +301,11 @@ public Parser, E> _1() { * @return A parser that repeats application of this parser one or many times. */ public Parser, E> repeat1() { - return bind(new F, E>>() { - public Parser, E> f(final A a) { - return repeat().map(new F, Stream>() { - public Stream f(final Stream as) { - return as.cons(a); - } - }); - } - }); + return bind(a -> repeat().map(new F, Stream>() { + public Stream f(final Stream as) { + return as.cons(a); + } + })); } /** @@ -373,11 +315,7 @@ public Stream f(final Stream as) { * @return A new parser with a new error type. */ public Parser mapError(final F f) { - return parser(new F>>() { - public Validation> f(final I i) { - return Parser.this.f.f(i).f().map(f); - } - }); + return parser(i -> Parser.this.f.f(i).f().map(f)); } /** @@ -397,11 +335,7 @@ public static Parser parser(final F Parser value(final A a) { - return parser(new F>>() { - public Validation> f(final I i) { - return success(result(i, a)); - } - }); + return parser(i -> success(result(i, a))); } /** @@ -411,11 +345,7 @@ public Validation> f(final I i) { * @return A parser that always fails with the given error. */ public static Parser fail(final E e) { - return parser(new F>>() { - public Validation> f(final I i) { - return Validation.fail(e); - } - }); + return parser(i -> Validation.fail(e)); } /** @@ -427,11 +357,7 @@ public Validation> f(final I i) { public static Parser, E> sequence(final List> ps) { return ps.isEmpty() ? Parser., E>value(List.nil()) : - ps.head().bind(new F, E>>() { - public Parser, E> f(final A a) { - return sequence(ps.tail()).map(cons_(a)); - } - }); + ps.head().bind(a -> sequence(ps.tail()).map(cons_(a))); } /** @@ -449,13 +375,9 @@ private StreamParser() { * @return A parser that produces an element from the stream if it is available and fails otherwise. */ public static Parser, I, E> element(final P1 e) { - return parser(new F, Validation, I>>>() { - public Validation, I>> f(final Stream is) { - return is.isEmpty() ? - Validation., I>>fail(e._1()) : - Validation., I>>success(result(is.tail()._1(), is.head())); - } - }); + return parser(is -> is.isEmpty() ? + Validation., I>>fail(e._1()) : + Validation., I>>success(result(is.tail()._1(), is.head()))); } /** @@ -478,13 +400,9 @@ public static Parser, I, E> element(final E e) { */ public static Parser, I, E> satisfy(final P1 missing, final F sat, final F f) { - return StreamParser.element(missing).bind(new F, I, E>>() { - public Parser, I, E> f(final I x) { - return f.f(x) ? - Parser., I, E>value(x) : - Parser., I, E>fail(sat.f(x)); - } - }); + return StreamParser.element(missing).bind(x -> f.f(x) ? + Parser., I, E>value(x) : + Parser., I, E>fail(sat.f(x))); } /** @@ -538,11 +456,7 @@ public static Parser, Character, E> character(final E e) { */ public static Parser, Character, E> character(final P1 missing, final F sat, final char c) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character x) { - return x == c; - } - }); + return StreamParser.satisfy(missing, sat, x -> x == c); } /** @@ -622,11 +536,7 @@ public static Parser, Stream, E> characters(fin */ public static Parser, String, E> string(final P1 missing, final F sat, final String s) { - return characters(missing, sat, List.fromString(s).toStream()).map(new F, String>() { - public String f(final Stream cs) { - return List.asString(cs.toList()); - } - }); + return characters(missing, sat, List.fromString(s).toStream()).map(cs -> List.asString(cs.toList())); } /** @@ -650,15 +560,7 @@ public static Parser, String, E> string(final E missing, f * @return A parser that produces a digit (0 to 9). */ public static Parser, Digit, E> digit(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isDigit(c); - } - }).map(new F() { - public Digit f(final Character c) { - return Digit.fromChar(c).some(); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isDigit(c)).map(c1 -> Digit.fromChar(c1).some()); } /** @@ -681,11 +583,7 @@ public static Parser, Digit, E> digit(final E missing, fin * @see Character#isLowerCase(char) */ public static Parser, Character, E> lower(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isLowerCase(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isLowerCase(c)); } /** @@ -709,11 +607,7 @@ public static Parser, Character, E> lower(final E missing, * @see Character#isUpperCase(char) */ public static Parser, Character, E> upper(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isUpperCase(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isUpperCase(c)); } /** @@ -737,11 +631,7 @@ public static Parser, Character, E> upper(final E missing, * @see Character#isDefined(char) */ public static Parser, Character, E> defined(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isDefined(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isDefined(c)); } /** @@ -766,11 +656,7 @@ public static Parser, Character, E> defined(final E missin */ public static Parser, Character, E> highSurrogate(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isHighSurrogate(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isHighSurrogate(c)); } /** @@ -796,11 +682,7 @@ public static Parser, Character, E> highSurrogate(final E */ public static Parser, Character, E> identifierIgnorable(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isIdentifierIgnorable(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isIdentifierIgnorable(c)); } /** @@ -826,11 +708,7 @@ public static Parser, Character, E> identifierIgnorable(fi */ public static Parser, Character, E> isoControl(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isISOControl(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isISOControl(c)); } /** @@ -855,11 +733,7 @@ public static Parser, Character, E> isoControl(final E mis */ public static Parser, Character, E> javaIdentifierPart(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isJavaIdentifierPart(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierPart(c)); } /** @@ -885,11 +759,7 @@ public static Parser, Character, E> javaIdentifierPart(fin */ public static Parser, Character, E> javaIdentifierStart(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isJavaIdentifierStart(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierStart(c)); } /** @@ -914,11 +784,7 @@ public static Parser, Character, E> javaIdentifierStart(fi * @see Character#isLetter(char) */ public static Parser, Character, E> alpha(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isLetter(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isLetter(c)); } /** @@ -942,11 +808,7 @@ public static Parser, Character, E> alpha(final E missing, * @see Character#isLetterOrDigit(char) */ public static Parser, Character, E> alphaNum(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isLetterOrDigit(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isLetterOrDigit(c)); } /** @@ -971,11 +833,7 @@ public static Parser, Character, E> alphaNum(final E missi */ public static Parser, Character, E> lowSurrogate(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isLowSurrogate(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isLowSurrogate(c)); } /** @@ -999,11 +857,7 @@ public static Parser, Character, E> lowSurrogate(final E m * @see Character#isMirrored(char) */ public static Parser, Character, E> mirrored(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isMirrored(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isMirrored(c)); } /** @@ -1027,11 +881,7 @@ public static Parser, Character, E> mirrored(final E missi * @see Character#isSpace(char) */ public static Parser, Character, E> space(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isSpaceChar(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isSpaceChar(c)); } /** @@ -1056,11 +906,7 @@ public static Parser, Character, E> space(final E missing, */ public static Parser, Character, E> titleCase(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isTitleCase(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isTitleCase(c)); } /** @@ -1085,11 +931,7 @@ public static Parser, Character, E> titleCase(final E miss */ public static Parser, Character, E> unicodeIdentiferPart(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isUnicodeIdentifierPart(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isUnicodeIdentifierPart(c)); } /** @@ -1115,11 +957,7 @@ public static Parser, Character, E> unicodeIdentiferPart(f */ public static Parser, Character, E> unicodeIdentiferStart(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isUnicodeIdentifierStart(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isUnicodeIdentifierStart(c)); } /** @@ -1145,11 +983,7 @@ public static Parser, Character, E> unicodeIdentiferStart( */ public static Parser, Character, E> whitespace(final P1 missing, final F sat) { - return StreamParser.satisfy(missing, sat, new F() { - public Boolean f(final Character c) { - return Character.isWhitespace(c); - } - }); + return StreamParser.satisfy(missing, sat, c -> Character.isWhitespace(c)); } /** From 0d3a1c56a54e003727e2a3d85658dec0824192c6 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Tue, 23 Dec 2014 19:05:24 +0530 Subject: [PATCH 207/811] removing parenthesis of single argument lamda expression --- core/src/main/java/fj/F1Functions.java | 80 +++++++++++++------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 14730860..0f57cd3e 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -29,7 +29,7 @@ public class F1Functions { * @return The composed function such that this function is applied last. */ static public F o(final F f, final F g) { - return (c) -> f.f(g.f(c)); + return c -> f.f(g.f(c)); } /** @@ -38,7 +38,7 @@ static public F o(final F f, final F g) { * @return A function that composes this function with another. */ static public F, F> o(final F f) { - return (g) -> o(f, g); + return g -> o(f, g); } /** @@ -58,7 +58,7 @@ static public F andThen(final F f, final F g) { * @return A function that invokes this function and then a given function on the result. */ static public F, F> andThen(final F f) { - return (g) -> andThen(f, g); + return g -> andThen(f, g); } /** @@ -68,7 +68,7 @@ static public F, F> andThen(final F f) { * @return A function that invokes this function on its argument and then the given function on the result. */ static public F bind(final F f, final F> g) { - return (a) -> g.f(f.f(a)).f(a); + return a -> g.f(f.f(a)).f(a); } /** @@ -77,7 +77,7 @@ static public F bind(final F f, final F> g) { * @return A function that binds another function across this function. */ static public F>, F> bind(final F f) { - return (g) -> bind(f, g); + return g -> bind(f, g); } /** @@ -89,7 +89,7 @@ static public F>, F> bind(final F f) { * applied to the result of applying this function to the argument. */ static public F apply(final F f, final F> g) { - return (a) -> g.f(a).f(f.f(a)); + return a -> g.f(a).f(f.f(a)); } /** @@ -98,7 +98,7 @@ static public F apply(final F f, final F> g) { * @return A function that applies a given function within the environment of this function. */ static public F>, F> apply(final F f) { - return (g) -> apply(f, g); + return g -> apply(f, g); } /** @@ -108,9 +108,7 @@ static public F>, F> apply(final F f) { * @return A new function that invokes this function on its arguments before invoking the given function. */ static public F> on(final F f, final F> g) { - return (a1) -> - (a2) -> - g.f(f.f(a1)).f(f.f(a2)); + return a1 -> a2 -> g.f(f.f(a1)).f(f.f(a2)); } @@ -121,7 +119,7 @@ static public F> on(final F f, final F> g) * @return A function that applies this function over the arguments of another function. */ static public F>, F>> on(final F f) { - return (g) -> on(f, g); + return g -> on(f, g); } /** @@ -130,7 +128,7 @@ static public F>, F>> on(final F f) { * @return This function promoted to return its result in a product-1. */ static public F> lazy(final F f) { - return (a) -> new P1(){ + return a -> new P1(){ public B _1() { return f.f(a); } @@ -153,7 +151,7 @@ static public P1 f(final F f, final A a) { * @return This function promoted to map over a product-1. */ static public F, P1> mapP1(final F f) { - return (p) -> p.map(f); + return p -> p.map(f); } /** @@ -162,7 +160,7 @@ static public F, P1> mapP1(final F f) { * @return This function promoted to return its result in an Option. */ static public F> optionK(final F f) { - return (a) -> some(f.f(a)); + return a -> some(f.f(a)); } /** @@ -171,7 +169,7 @@ static public F> optionK(final F f) { * @return This function promoted to map over an optional value. */ static public F, Option> mapOption(final F f) { - return (o) -> o.map(f); + return o -> o.map(f); } /** @@ -180,7 +178,7 @@ static public F, Option> mapOption(final F f) { * @return This function promoted to return its result in a List. */ static public F> listK(final F f) { - return (a) -> List.single(f.f(a)); + return a -> List.single(f.f(a)); } /** @@ -189,7 +187,7 @@ static public F> listK(final F f) { * @return This function promoted to map over a List. */ static public F, List> mapList(final F f) { - return (x) -> x.map(f); + return x -> x.map(f); } /** @@ -198,7 +196,7 @@ static public F, List> mapList(final F f) { * @return This function promoted to return its result in a Stream. */ static public F> streamK(final F f) { - return (a) -> Stream.single(f.f(a)); + return a -> Stream.single(f.f(a)); } /** @@ -207,7 +205,7 @@ static public F> streamK(final F f) { * @return This function promoted to map over a Stream. */ static public F, Stream> mapStream(final F f) { - return (x) -> x.map(f); + return x -> x.map(f); } /** @@ -216,7 +214,7 @@ static public F, Stream> mapStream(final F f) { * @return This function promoted to return its result in a Array. */ static public F> arrayK(final F f) { - return (a) -> Array.single(f.f(a)); + return a -> Array.single(f.f(a)); } @@ -226,7 +224,7 @@ static public F> arrayK(final F f) { * @return This function promoted to map over a Array. */ static public F, Array> mapArray(final F f) { - return (x) -> x.map(f); + return x -> x.map(f); } /** @@ -235,7 +233,7 @@ static public F, Array> mapArray(final F f) { * @return A function that comaps over a given actor. */ static public F, Actor> comapActor(final F f) { - return (a) -> a.comap(f); + return a -> a.comap(f); } /** @@ -254,7 +252,7 @@ static public F> promiseK(final F f, final Strategy F, Promise> mapPromise(final F f) { - return (p) -> p.fmap(f); + return p -> p.fmap(f); } /** @@ -305,7 +303,7 @@ static public F, Either> mapRight(final F f) * @return a function that returns the left side of a given Either, or this function applied to the right side. */ static public F, B> onLeft(final F f) { - return (e) -> e.left().on(f); + return e -> e.left().on(f); } /** @@ -314,7 +312,7 @@ static public F, B> onLeft(final F f) { * @return a function that returns the right side of a given Either, or this function applied to the left side. */ static public F, B> onRight(final F f) { - return (e) -> e.right().on(f); + return e -> e.right().on(f); } /** @@ -353,7 +351,7 @@ static public F> nelK(final F f) { * @return This function promoted to map over a NonEmptyList. */ static public F, NonEmptyList> mapNel(final F f) { - return (list) -> list.map(f); + return list -> list.map(f); } /** @@ -364,7 +362,7 @@ static public F, NonEmptyList> mapNel(final F f) */ static public F> setK(final F f, final Ord o ) { - return (a) -> Set.single(o, f.f(a)); + return a -> Set.single(o, f.f(a)); } /** @@ -374,7 +372,7 @@ static public F> setK(final F f, final Ord o * @return This function promoted to map over a Set. */ static public F, Set> mapSet(final F f, final Ord o) { - return (s) -> s.map(o, f); + return s -> s.map(o, f); } /** @@ -383,7 +381,7 @@ static public F, Set> mapSet(final F f, final Ord o) { * @return This function promoted to return its value in a Tree. */ static public F> treeK(final F f) { - return (a) -> Tree.leaf(f.f(a)); + return a -> Tree.leaf(f.f(a)); } /** @@ -431,7 +429,7 @@ static public F, TreeZipper> mapTreeZipper(final F * @return This function promoted to return its result on the failure side of a Validation. */ static public F> failK(final F f) { - return (a) -> Validation.fail(f.f(a)); + return a -> Validation.fail(f.f(a)); } @@ -442,7 +440,7 @@ static public F> failK(final F f) { * @return This function promoted to return its result on the success side of an Validation. */ static public F> successK(final F f) { - return (a) -> Validation.success(f.f(a)); + return a -> Validation.success(f.f(a)); } /** @@ -451,7 +449,7 @@ static public F> successK(final F f) { * @return This function promoted to map over the failure side of a Validation. */ static public F, Validation> mapFail(final F f) { - return (v) -> v.f().map(f); + return v -> v.f().map(f); } /** @@ -460,7 +458,7 @@ static public F, Validation> mapFail(final F F, Validation> mapSuccess(final F f) { - return (v) -> v.map(f); + return v -> v.map(f); } /** @@ -471,7 +469,7 @@ static public F, Validation> mapSuccess(final F * or this function applied to the success side. */ static public F, B> onFail(final F f) { - return (v) -> v.f().on(f); + return v -> v.f().on(f); } /** @@ -482,7 +480,7 @@ static public F, B> onFail(final F f) { * or this function applied to the failure side. */ static public F, B> onSuccess(final F f) { - return (v) -> v.on(f); + return v -> v.on(f); } /** @@ -491,7 +489,7 @@ static public F, B> onSuccess(final F f) { * @return This function promoted to return its value in a Zipper. */ static public F> zipperK(final F f) { - return andThen(streamK(f), (s) -> fromStream(s).some()); + return andThen(streamK(f), s -> fromStream(s).some()); } /** @@ -500,7 +498,7 @@ static public F> zipperK(final F f) { * @return This function promoted to map over a Zipper. */ static public F, Zipper> mapZipper(final F f) { - return (z) -> z.map(f); + return z -> z.map(f); } /** @@ -509,7 +507,7 @@ static public F, Zipper> mapZipper(final F f) { * @return This function promoted to map over an Equal as a contravariant functor. */ static public F, Equal> comapEqual(final F f) { - return (e) -> e.comap(f); + return e -> e.comap(f); } /** @@ -518,7 +516,7 @@ static public F, Equal> comapEqual(final F f) { * @return This function promoted to map over a Hash as a contravariant functor. */ static public F, Hash> comapHash(final F f) { - return (h) -> h.comap(f); + return h -> h.comap(f); } /** @@ -527,7 +525,7 @@ static public F, Hash> comapHash(final F f) { * @return This function promoted to map over a Show as a contravariant functor. */ static public F, Show> comapShow(final F f) { - return (s) -> s.comap(f); + return s -> s.comap(f); } /** @@ -554,7 +552,7 @@ static public F, P2> mapSnd(final F f) { * @return This function promoted to map over both elements of a pair. */ static public F, P2> mapBoth(final F f) { - return (p2) -> P2.map(f, p2); + return p2 -> P2.map(f, p2); } /** From 09552ee6ce0e9af59bab4b1bbe2fb0d8c22c8da9 Mon Sep 17 00:00:00 2001 From: Paul Horn Date: Wed, 24 Dec 2014 03:22:05 +0100 Subject: [PATCH 208/811] Add some Collectors for Java8 --- java8/src/main/java/fj/data/Collectors.java | 36 +++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 java8/src/main/java/fj/data/Collectors.java diff --git a/java8/src/main/java/fj/data/Collectors.java b/java8/src/main/java/fj/data/Collectors.java new file mode 100644 index 00000000..3f3d7e40 --- /dev/null +++ b/java8/src/main/java/fj/data/Collectors.java @@ -0,0 +1,36 @@ +package fj.data; + +import java.util.stream.Collector; + +public final class Collectors { + + private Collectors() { + } + + public static Collector, List> toList() { + return Collector.of( + List.Buffer::new, + List.Buffer::snoc, + (acc1, acc2) -> acc1.append(acc2.toList()), + List.Buffer::toList + ); + } + + public static Collector, Array> toArray() { + return Collector.of( + List.Buffer::new, + List.Buffer::snoc, + (acc1, acc2) -> acc1.append(acc2.toList()), + (buf) -> Array.iterableArray(buf.toList()) + ); + } + + public static Collector, Stream> toStream() { + return Collector.of( + List.Buffer::new, + List.Buffer::snoc, + (acc1, acc2) -> acc1.append(acc2.toList()), + (buf) -> Stream.iterableStream(buf.toList()) + ); + } +} From eb923587cd1cc15878ca06b7ce930d853b5ae6db Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sat, 27 Dec 2014 19:27:21 +0530 Subject: [PATCH 209/811] Refactoring Control and Data module --- core/src/main/java/fj/control/Trampoline.java | 122 +-- .../main/java/fj/control/parallel/Actor.java | 18 +- .../java/fj/control/parallel/Callables.java | 94 +-- .../java/fj/control/parallel/ParModule.java | 117 +-- .../java/fj/control/parallel/Strategy.java | 130 +--- core/src/main/java/fj/data/HashMap.java | 6 +- core/src/main/java/fj/data/IterableW.java | 68 +- core/src/main/java/fj/data/Iteratee.java | 72 +- core/src/main/java/fj/data/Java.java | 725 +++++------------- core/src/main/java/fj/data/LazyString.java | 24 +- core/src/main/java/fj/data/Natural.java | 60 +- core/src/main/java/fj/data/NonEmptyList.java | 18 +- core/src/main/java/fj/data/Set.java | 54 +- core/src/main/java/fj/data/Stream.java | 211 +---- core/src/main/java/fj/data/Tree.java | 66 +- core/src/main/java/fj/data/TreeMap.java | 6 +- core/src/main/java/fj/data/TreeZipper.java | 118 +-- core/src/main/java/fj/data/Validation.java | 66 +- core/src/main/java/fj/data/Zipper.java | 48 +- 19 files changed, 413 insertions(+), 1610 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 70f29f9b..fad6be90 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -50,57 +50,21 @@ public R fold(final F, R> n, // The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the // continuations. public Trampoline bind(final F> f) { - return codense(sub, new F>() { - public Trampoline f(final Object o) { - return suspend(new P1>() { - public Trampoline _1() { - return cont.f(o).bind(f); - } - }); + return codense(sub, o -> suspend(new P1>() { + public Trampoline _1() { + return cont.f(o).bind(f); } - }); + })); } // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result // gets shifted into the continuation. public Either>, A> resume() { - return left(sub.resume().either(new F>, P1>>() { - public P1> f(final P1> p) { - return p.map(new F, Trampoline>() { - public Trampoline f(final Trampoline ot) { - return ot.fold(new F, Trampoline>() { - public Trampoline f(final Normal o) { - return o.foldNormal(new F>() { - public Trampoline f(final Object o) { - return cont.f(o); - } - }, new F>, Trampoline>() { - public Trampoline f(final P1> t) { - return t._1().bind(cont); - } - } - ); - } - }, new F, Trampoline>() { - public Trampoline f(final Codense c) { - return codense(c.sub, new F>() { - public Trampoline f(final Object o) { - return c.cont.f(o).bind(cont); - } - }); - } - } - ); - } - }); - } - }, new F>>() { - public P1> f(final Object o) { - return new P1>() { - public Trampoline _1() { - return cont.f(o); - } - }; + return left(sub.resume().either(p -> p.map(ot -> ot.fold(o1 -> o1.foldNormal(o2 -> cont.f(o2), t -> t._1().bind(cont) + ), c -> codense(c.sub, o -> c.cont.f(o).bind(cont)) + )), o3 -> new P1>() { + public Trampoline _1() { + return cont.f(o3); } } )); @@ -159,11 +123,7 @@ protected static Codense codense(final Normal a, final F F> pure() { - return new F>() { - public Trampoline f(final A a) { - return pure(a); - } - }; + return a -> pure(a); } /** @@ -190,11 +150,7 @@ public static Trampoline suspend(final P1> a) { * @return The first-class version of `suspend`. */ public static F>, Trampoline> suspend_() { - return new F>, Trampoline>() { - public Trampoline f(final P1> trampolineP1) { - return suspend(trampolineP1); - } - }; + return trampolineP1 -> suspend(trampolineP1); } protected abstract R fold(final F, R> n, final F, R> gs); @@ -221,41 +177,21 @@ public final Trampoline map(final F f) { * @return The first-class version of `bind`. */ public static F>, F, Trampoline>> bind_() { - return new F>, F, Trampoline>>() { - public F, Trampoline> f(final F> f) { - return new F, Trampoline>() { - public Trampoline f(final Trampoline a) { - return a.bind(f); - } - }; - } - }; + return f -> a -> a.bind(f); } /** * @return The first-class version of `map`. */ public static F, F, Trampoline>> map_() { - return new F, F, Trampoline>>() { - public F, Trampoline> f(final F f) { - return new F, Trampoline>() { - public Trampoline f(final Trampoline a) { - return a.map(f); - } - }; - } - }; + return f -> a -> a.map(f); } /** * @return The first-class version of `resume`. */ public static F, Either>, A>> resume_() { - return new F, Either>, A>>() { - public Either>, A> f(final Trampoline aTrampoline) { - return aTrampoline.resume(); - } - }; + return aTrampoline -> aTrampoline.resume(); } /** @@ -291,11 +227,7 @@ public A run() { * @return A new Trampoline after applying the given function through this Trampoline. */ public final Trampoline apply(final Trampoline> lf) { - return lf.bind(new F, Trampoline>() { - public Trampoline f(final F f) { - return map(f); - } - }); + return lf.bind(f -> map(f)); } /** @@ -317,11 +249,7 @@ public final Trampoline bind(final Trampoline lb, final F F, F, Trampoline>> liftM2(final F> f) { - return curry(new F2, Trampoline, Trampoline>() { - public Trampoline f(final Trampoline as, final Trampoline bs) { - return as.bind(bs, f); - } - }); + return curry((as, bs) -> as.bind(bs, f)); } /** @@ -337,22 +265,14 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry(new F2, Trampoline, Trampoline>() { - public Trampoline f(final Trampoline ta, final Trampoline tb) { - return suspend(new P1>() { - public Trampoline _1() { - return ta.zipWith(tb, f); - } - }); + return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(new P1>() { + public Trampoline _1() { + return ta.zipWith(tb, f); } - }))); + })))); } for (final B y : eb.right()) { - return suspend(x.map(new F, Trampoline>() { - public Trampoline f(final Trampoline ta) { - return ta.map(F2Functions.f(F2Functions.flip(f), y)); - } - })); + return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); } } for (final A x : ea.right()) { diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 86201147..91ee72d0 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -79,11 +79,7 @@ protected void work() { private Actor(final Strategy s, final F> e) { this.s = s; - f = new F>() { - public P1 f(final A a) { - return s.par(e.f(a)); - } - }; + f = a -> s.par(e.f(a)); } /** @@ -127,11 +123,7 @@ public P1 act(final A a) { * @return A new actor which passes its messages through the given function, to this actor. */ public Actor comap(final F f) { - return actor(s, new F>() { - public P1 f(final B b) { - return act(f.f(b)); - } - }); + return actor(s, (B b) -> act(f.f(b))); } /** @@ -140,11 +132,7 @@ public P1 f(final B b) { * @return A new actor, equivalent to this actor, that acts on promises. */ public Actor> promise() { - return actor(s, new Effect1>() { - public void f(final Promise b) { - b.to(Actor.this); - } - }); + return actor(s, (Promise b) -> b.to(Actor.this)); } } diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index b011a0a6..658908cc 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -31,11 +31,7 @@ private Callables() { * @return A Callable that yields the argument when called. */ public static Callable callable(final A a) { - return new Callable() { - public A call() throws Exception { - return a; - } - }; + return () -> a; } /** @@ -45,10 +41,8 @@ public A call() throws Exception { * @return A callable that always throws the given exception. */ public static Callable callable(final Exception e) { - return new Callable() { - public A call() throws Exception { - throw e; - } + return () -> { + throw e; }; } @@ -58,11 +52,7 @@ public A call() throws Exception { * @return A function from a value to a Callable that completely preserves that value. */ public static F> callable() { - return new F>() { - public Callable f(final A a) { - return callable(a); - } - }; + return a -> callable(a); } /** @@ -73,15 +63,7 @@ public Callable f(final A a) { * @return The equivalent function whose return value is wrapped in a Callable. */ public static F> callable(final F f) { - return new F>() { - public Callable f(final A a) { - return new Callable() { - public B call() { - return f.f(a); - } - }; - } - }; + return a -> () -> f.f(a); } /** @@ -91,11 +73,7 @@ public B call() { * @return A transformation from a function to the equivalent Callable-valued function. */ public static F, F>> arrow() { - return new F, F>>() { - public F> f(final F f) { - return callable(f); - } - }; + return f -> callable(f); } /** @@ -106,11 +84,7 @@ public F> f(final F f) { * @return The result of applying the function in the second argument to the value of the Callable in the first. */ public static Callable bind(final Callable a, final F> f) { - return new Callable() { - public B call() throws Exception { - return f.f(a.call()).call(); - } - }; + return () -> f.f(a.call()).call(); } /** @@ -120,11 +94,7 @@ public B call() throws Exception { * @return That function lifted to a function on Callables. */ public static F, Callable> fmap(final F f) { - return new F, Callable>() { - public Callable f(final Callable a) { - return Callables.bind(a, callable(f)); - } - }; + return a -> Callables.bind(a, callable(f)); } /** @@ -135,11 +105,7 @@ public Callable f(final Callable a) { * @return A new callable after applying the given callable function to the first argument. */ public static Callable apply(final Callable ca, final Callable> cf) { - return bind(cf, new F, Callable>() { - public Callable f(final F f) { - return fmap(f).f(ca); - } - }); + return bind(cf, f -> fmap(f).f(ca)); } /** @@ -171,11 +137,7 @@ public static Callable join(final Callable> a) { * @return A function of arity-2 promoted to map over callables. */ public static F, F, Callable>> liftM2(final F> f) { - return curry(new F2, Callable, Callable>() { - public Callable f(final Callable ca, final Callable cb) { - return bind(ca, cb, f); - } - }); + return curry((ca, cb) -> bind(ca, cb, f)); } /** @@ -195,11 +157,7 @@ public static Callable> sequence(final List> as) { * @return A function from a List of Callables to a single Callable of a List. */ public static F>, Callable>> sequence_() { - return new F>, Callable>>() { - public Callable> f(final List> as) { - return sequence(as); - } - }; + return as -> sequence(as); } /** @@ -227,11 +185,7 @@ public Option _1() { * @return a function that turns a Callable into an optional value. */ public static F, P1>> option() { - return new F, P1>>() { - public P1> f(final Callable a) { - return option(a); - } - }; + return a -> option(a); } /** @@ -258,11 +212,7 @@ public Either _1() { * @return a function that turns a Callable into an Either. */ public static F, P1>> either() { - return new F, P1>>() { - public P1> f(final Callable a) { - return either(a); - } - }; + return a -> either(a); } /** @@ -289,11 +239,7 @@ public A call() throws Exception { * @return a function that turns an Either into a Callable. */ public static F>, Callable> fromEither() { - return new F>, Callable>() { - public Callable f(final P1> e) { - return fromEither(e); - } - }; + return e -> fromEither(e); } /** @@ -321,11 +267,7 @@ public A call() throws Exception { * or throws an exception in the case of no value. */ public static F>, Callable> fromOption() { - return new F>, Callable>() { - public Callable f(final P1> o) { - return fromOption(o); - } - }; + return o -> fromOption(o); } /** @@ -349,11 +291,7 @@ public static Callable normalise(final Callable a) { * @return A function that normalises the given Callable by calling it and wrapping the result in a new Callable. */ public static F, Callable> normalise() { - return new F, Callable>() { - public Callable f(final Callable a) { - return normalise(a); - } - }; + return a -> normalise(a); } } diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 9d04fc7a..e6f37228 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -56,11 +56,7 @@ public Promise promise(final P1 p) { * @return a function that evaluates a given product concurrently and returns a Promise of the result. */ public F, Promise> promise() { - return new F, Promise>() { - public Promise f(final P1 ap1) { - return promise(ap1); - } - }; + return ap1 -> promise(ap1); } /** @@ -81,11 +77,7 @@ public F> promise(final F f) { * @return A higher-order function that takes pure functions to promise-valued functions. */ public F, F>> promisePure() { - return new F, F>>() { - public F> f(final F abf) { - return promise(abf); - } - }; + return abf -> promise(abf); } /** @@ -118,11 +110,7 @@ public Actor effect(final Effect1 e) { * @return A function that takes an effect and returns a concurrent effect. */ public F, Actor> effect() { - return new F, Actor>() { - public Actor f(final Effect1 effect) { - return effect(effect); - } - }; + return effect -> effect(effect); } /** @@ -141,11 +129,7 @@ public Actor actor(final Effect1 e) { * @return A function that takes an effect and returns an actor that processes messages in some order. */ public F, Actor> actor() { - return new F, Actor>() { - public Actor f(final Effect1 effect) { - return actor(effect); - } - }; + return effect -> actor(effect); } /** @@ -164,11 +148,7 @@ public Promise> sequence(final List> ps) { * @return A first-class function that traverses a list inside a promise. */ public F>, Promise>> sequenceList() { - return new F>, Promise>>() { - public Promise> f(final List> list) { - return sequence(list); - } - }; + return list -> sequence(list); } /** @@ -187,11 +167,7 @@ public Promise> sequence(final Stream> ps) { * @return A first-class function that traverses a stream inside a promise. */ public F>, Promise>> sequenceStream() { - return new F>, Promise>>() { - public Promise> f(final Stream> stream) { - return sequence(stream); - } - }; + return stream -> sequence(stream); } /** @@ -222,11 +198,7 @@ public Promise> mapM(final List as, final F> f) * @return a function that maps a concurrent function over a List inside a promise. */ public F>, F, Promise>>> mapList() { - return curry(new F2>, List, Promise>>() { - public Promise> f(final F> f, final List list) { - return mapM(list, f); - } - }); + return curry((f, list) -> mapM(list, f)); } /** @@ -247,11 +219,7 @@ public Promise> mapM(final Stream as, final F> * @return a function that maps a concurrent function over a Stream inside a promise. */ public F>, F, Promise>>> mapStream() { - return curry(new F2>, Stream, Promise>>() { - public Promise> f(final F> f, final Stream stream) { - return mapM(stream, f); - } - }); + return curry((f, stream) -> mapM(stream, f)); } /** @@ -282,11 +250,7 @@ public Promise> parMap(final List as, final F f) { * @return A function that maps another function across a list in parallel. */ public F, F, Promise>>> parMapList() { - return curry(new F2, List, Promise>>() { - public Promise> f(final F abf, final List list) { - return parMap(list, abf); - } - }); + return curry((abf, list) -> parMap(list, abf)); } /** @@ -297,11 +261,7 @@ public Promise> f(final F abf, final List list) { * @return A Promise of a new NonEmptyList with the given function applied to each element. */ public Promise> parMap(final NonEmptyList as, final F f) { - return mapM(as.toList(), promise(f)).fmap(new F, NonEmptyList>() { - public NonEmptyList f(final List list) { - return NonEmptyList.fromList(list).some(); - } - }); + return mapM(as.toList(), promise(f)).fmap((F, NonEmptyList>) list -> NonEmptyList.fromList(list).some()); } /** @@ -321,11 +281,7 @@ public Promise> parMap(final Stream as, final F f) { * @return A function that maps another function across a stream in parallel. */ public F, F, Promise>>> parMapStream() { - return curry(new F2, Stream, Promise>>() { - public Promise> f(final F abf, final Stream stream) { - return parMap(stream, abf); - } - }); + return curry((abf, stream) -> parMap(stream, abf)); } /** @@ -346,11 +302,7 @@ public Promise> parMap(final Iterable as, final F f) * @return A function that maps another function across an iterable in parallel. */ public F, F, Promise>>> parMapIterable() { - return curry(new F2, Iterable, Promise>>() { - public Promise> f(final F abf, final Iterable iterable) { - return parMap(iterable, abf); - } - }); + return curry((abf, iterable) -> parMap(iterable, abf)); } /** @@ -361,11 +313,7 @@ public Promise> f(final F abf, final Iterable iterable) { * @return A Promise of a new Array with the given function applied to each element. */ public Promise> parMap(final Array as, final F f) { - return parMap(as.toStream(), f).fmap(new F, Array>() { - public Array f(final Stream stream) { - return stream.toArray(); - } - }); + return parMap(as.toStream(), f).fmap(stream -> stream.toArray()); } /** @@ -374,11 +322,7 @@ public Array f(final Stream stream) { * @return A function that maps another function across an array in parallel. */ public F, F, Promise>>> parMapArray() { - return curry(new F2, Array, Promise>>() { - public Promise> f(final F abf, final Array array) { - return parMap(array, abf); - } - }); + return curry((abf, array) -> parMap(array, abf)); } /** @@ -411,11 +355,7 @@ public Promise> parMap(final Tree ta, final F f) { * @return A function that maps a given function across a Tree in parallel. */ public F, F, Promise>>> parMapTree() { - return curry(new F2, Tree, Promise>>() { - public Promise> f(final F abf, final Tree tree) { - return parMap(tree, abf); - } - }); + return curry((abf, tree) -> parMap(tree, abf)); } /** @@ -429,13 +369,8 @@ public Promise> parMap(final TreeZipper za, final F, Tree> tf = Tree.fmap_().f(f); final P4, Stream>, Stream>, Stream>, A, Stream>>>> p = za.p(); return mapM(p._4(), - new F>, A, Stream>>, Promise>, B, Stream>>>>() { - public Promise>, B, Stream>>> f( - final P3>, A, Stream>> p3) { - return parMap(p3._3(), tf).apply(promise(f).f(p3._2()).apply( - parMap(p3._1(), tf).fmap(P.>, B, Stream>>p3()))); - } - }).apply(parMap(za.rights(), tf).apply( + p3 -> parMap(p3._3(), tf).apply(promise(f).f(p3._2()).apply( + parMap(p3._1(), tf).fmap(P.>, B, Stream>>p3())))).apply(parMap(za.rights(), tf).apply( parMap(za.lefts(), tf).apply(parMap(p._1(), f).fmap(TreeZipper.treeZipper())))); } @@ -565,11 +500,7 @@ public Promise parFoldMap(final Stream as, final F map, final */ public Promise parFoldMap(final Stream as, final F map, final Monoid reduce, final F, P2, Stream>> chunking) { - return parMap(Stream.unfold(new F, Option, Stream>>>() { - public Option, Stream>> f(final Stream stream) { - return stream.isEmpty() ? Option., Stream>>none() : some(chunking.f(stream)); - } - }, as), Stream.map_().f(map)).bind(new F>, Promise>() { + return parMap(Stream.unfold(stream -> stream.isEmpty() ? Option., Stream>>none() : some(chunking.f(stream)), as), Stream.map_().f(map)).bind(new F>, Promise>() { public Promise f(final Stream> stream) { return parMap(stream, reduce.sumLeftS()).fmap(reduce.sumLeftS()); } @@ -591,15 +522,9 @@ public Promise f(final Stream> stream) { */ public Promise parFoldMap(final Iterable as, final F map, final Monoid reduce, final F, P2, Iterable>> chunking) { - return parFoldMap(iterableStream(as), map, reduce, new F, P2, Stream>>() { - public P2, Stream> f(final Stream stream) { - final F, Stream> is = new F, Stream>() { - public Stream f(final Iterable iterable) { - return iterableStream(iterable); - } - }; - return chunking.f(stream).map1(is).map2(is); - } + return parFoldMap(iterableStream(as), map, reduce, (Stream stream) -> { + final F, Stream> is = iterable -> iterableStream(iterable); + return chunking.f(stream).map1(is).map2(is); }); } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index daf8098e..1002ae03 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -82,11 +82,7 @@ public F> concurry(final F f) { * @return A function that executes concurrently when called, yielding a product-1 that returns the value. */ public F>> concurry(final F2 f) { - return new F>>() { - public F> f(final B b) { - return concurry(curry(f).f(b)); - } - }; + return b -> concurry(curry(f).f(b)); } /** @@ -164,11 +160,7 @@ public Array parMap1(final F f, final Array bs) { * @return The function transformed into a parallel function on lists. */ public F, P1>> parMapList(final F f) { - return new F, P1>>() { - public P1> f(final List as) { - return parMap(f, as); - } - }; + return as -> parMap(f, as); } /** @@ -177,11 +169,7 @@ public P1> f(final List as) { * @return A function that promotes another function to a parallel function on lists. */ public F, F, P1>>> parMapList() { - return new F, F, P1>>>() { - public F, P1>> f(final F f) { - return parMapList(f); - } - }; + return f1 -> parMapList(f1); } /** @@ -190,15 +178,7 @@ public F, P1>> f(final F f) { * @return A function that promotes another function to a blocking parallel function on lists. */ public F, F, List>> parMapList1() { - return new F, F, List>>() { - public F, List> f(final F f) { - return new F, List>() { - public List f(final List bs) { - return parMap1(f, bs); - } - }; - } - }; + return f1 -> bs -> parMap1(f1, bs); } /** @@ -208,11 +188,7 @@ public List f(final List bs) { * @return The function transformed into a parallel function on arrays. */ public F, P1>> parMapArray(final F f) { - return new F, P1>>() { - public P1> f(final Array as) { - return parMap(f, as); - } - }; + return as -> parMap(f, as); } /** @@ -221,11 +197,7 @@ public P1> f(final Array as) { * @return A function that promotes another function to a parallel function on arrays. */ public F, F, P1>>> parMapArray() { - return new F, F, P1>>>() { - public F, P1>> f(final F f) { - return parMapArray(f); - } - }; + return f1 -> parMapArray(f1); } /** @@ -234,15 +206,7 @@ public F, P1>> f(final F f) { * @return A function that promotes another function to a blocking parallel function on arrays. */ public F, F, Array>> parMapArray1() { - return new F, F, Array>>() { - public F, Array> f(final F f) { - return new F, Array>() { - public Array f(final Array bs) { - return parMap1(f, bs); - } - }; - } - }; + return f1 -> bs -> parMap1(f1, bs); } /** @@ -328,11 +292,7 @@ public P1> parZipWith(final F2 f, final Array bs, fi * @return A transformation that zips two lists using the argument function, in parallel. */ public F2, List, P1>> parZipListWith(final F2 f) { - return new F2, List, P1>>() { - public P1> f(final List bs, final List cs) { - return parZipWith(f, bs, cs); - } - }; + return (bs, cs) -> parZipWith(f, bs, cs); } /** @@ -343,11 +303,7 @@ public P1> f(final List bs, final List cs) { * @return A transformation that zips two arrays using the argument function, in parallel. */ public F2, Array, P1>> parZipArrayWith(final F2 f) { - return new F2, Array, P1>>() { - public P1> f(final Array bs, final Array cs) { - return parZipWith(f, bs, cs); - } - }; + return (bs, cs) -> parZipWith(f, bs, cs); } /** @@ -356,11 +312,7 @@ public P1> f(final Array bs, final Array cs) { * @return A function which, given a Future, yields a product-1 that waits for it. */ public static F, P1> obtain() { - return new F, P1>() { - public P1 f(final Future t) { - return obtain(t); - } - }; + return t -> obtain(t); } /** @@ -390,10 +342,8 @@ public A _1() { * @return An effect, which, given a Future, waits for it to obtain a value, discarding the value. */ public static Effect1> discard() { - return new Effect1>() { - public void f(final Future a) { - Strategy.obtain().f(a)._1(); - } + return a -> { + Strategy.obtain().f(a)._1(); }; } @@ -405,12 +355,10 @@ public void f(final Future a) { * every evaluation. */ public static Strategy simpleThreadStrategy() { - return strategy(new F, P1>() { - public P1 f(final P1 p) { - final FutureTask t = new FutureTask(Java.P1_Callable().f(p)); - new Thread(t).start(); - return obtain(t); - } + return strategy(p -> { + final FutureTask t = new FutureTask(Java.P1_Callable().f(p)); + new Thread(t).start(); + return obtain(t); }); } @@ -423,11 +371,7 @@ public P1 f(final P1 p) { * of parallelism. */ public static Strategy executorStrategy(final ExecutorService s) { - return strategy(new F, P1>() { - public P1 f(final P1 p) { - return obtain(s.submit(Java.P1_Callable().f(p))); - } - }); + return strategy(p -> obtain(s.submit(Java.P1_Callable().f(p)))); } /** @@ -439,11 +383,7 @@ public P1 f(final P1 p) { * and notifies the service of task completion. */ public static Strategy completionStrategy(final CompletionService s) { - return strategy(new F, P1>() { - public P1 f(final P1 p) { - return obtain(s.submit(Java.P1_Callable().f(p))); - } - }); + return strategy(p -> obtain(s.submit(Java.P1_Callable().f(p)))); } /** @@ -452,11 +392,7 @@ public P1 f(final P1 p) { * @return A strategy that performs sequential (non-concurrent) evaluation of its argument. */ public static Strategy seqStrategy() { - return strategy(new F, P1>() { - public P1 f(final P1 a) { - return P.p(a._1()); - } - }); + return strategy(a -> P.p(a._1())); } /** @@ -519,19 +455,15 @@ public Strategy errorStrategy(final Effect1 e) { * @return A strategy that captures any runtime errors with a side-effect. */ public static Strategy errorStrategy(final Strategy s, final Effect1 e) { - return s.comap(new F, P1>() { - public P1 f(final P1 a) { - return new P1() { - public A _1() { - try { - return a._1(); - } catch (Throwable t) { - final Error error = new Error(t); - e.f(error); - throw error; - } - } - }; + return s.comap(a -> new P1() { + public A _1() { + try { + return a._1(); + } catch (Throwable t) { + final Error error = new Error(t); + e.f(error); + throw error; + } } }); } @@ -543,11 +475,7 @@ public A _1() { * @return A new strategy that fully evaluates Callables, using the given strategy. */ public static Strategy> callableStrategy(final Strategy> s) { - return s.comap(new F>, P1>>() { - public P1> f(final P1> a) { - return P1.curry(Callables.normalise()).f(a._1()); - } - }); + return s.comap(a -> P1.curry(Callables.normalise()).f(a._1())); } } diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index f2a3189b..0b2215c6 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -300,11 +300,7 @@ public void foreach(F, Unit> function) { } public List> toList() { - return keys().map(new F>() { - public P2 f(final K k) { - return p(k, get(k).some()); - } - }); + return keys().map(k -> p(k, get(k).some())); } /** diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 5a3aa66e..2474d72b 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -44,11 +44,7 @@ public static IterableW wrap(final Iterable a) { * @return A function that returns the given iterable, wrapped. */ public static > F> wrap() { - return new F>() { - public IterableW f(final T a) { - return wrap(a); - } - }; + return a -> wrap(a); } /** @@ -69,11 +65,7 @@ public static IterableW iterable(final A a) { * @return The equivalent function whose return value is iterable. */ public static F> iterable(final F f) { - return new F>() { - public IterableW f(final A a) { - return iterable(f.f(a)); - } - }; + return a -> iterable(f.f(a)); } /** @@ -83,11 +75,7 @@ public IterableW f(final A a) { * @return A transformation from a function to the equivalent Iterable-valued function. */ public static F, F>> arrow() { - return new F, F>>() { - public F> f(final F f) { - return iterable(f); - } - }; + return f -> iterable(f); } /** @@ -97,11 +85,7 @@ public F> f(final F f) { * @return an iterable result of binding the given function over the wrapped Iterable. */ public > IterableW bind(final F f) { - return wrap(iterableStream(this).bind(new F>() { - public Stream f(final A a) { - return iterableStream(f.f(a)); - } - })); + return wrap(iterableStream(this).bind(a -> iterableStream(f.f(a)))); } /** @@ -111,11 +95,7 @@ public Stream f(final A a) { * @return A new iterable after applying the given iterable function to the wrapped iterable. */ public IterableW apply(final Iterable> f) { - return wrap(f).bind(new F, Iterable>() { - public Iterable f(final F f) { - return map(f); - } - }); + return wrap(f).bind(f1 -> map(f1)); } /** @@ -137,11 +117,7 @@ public static IterableW bind(final Iterable a, final Iterable * @return A function of arity-2 promoted to map over iterables. */ public static F, F, IterableW>> liftM2(final F> f) { - return curry(new F2, Iterable, IterableW>() { - public IterableW f(final Iterable ca, final Iterable cb) { - return bind(ca, cb, f); - } - }); + return curry((ca, cb) -> bind(ca, cb, f)); } /** @@ -176,15 +152,7 @@ public Stream _1() { * @return a function that binds a given function across a given iterable. */ public static > F, F, IterableW>> bind() { - return new F, F, IterableW>>() { - public F, IterableW> f(final IterableW a) { - return new F, IterableW>() { - public IterableW f(final F f) { - return a.bind(f); - } - }; - } - }; + return a -> f -> a.bind(f); } /** @@ -204,11 +172,7 @@ public static > IterableW join(final Iterable as) * @return a function that joins an Iterable of Iterables into a single Iterable. */ public static > F, IterableW> join() { - return new F, IterableW>() { - public IterableW f(final Iterable a) { - return join(a); - } - }; + return a -> join(a); } /** @@ -227,15 +191,7 @@ public IterableW map(final F f) { * @return a function that promotes any function so that it operates on Iterables. */ public static F, F, IterableW>> map() { - return new F, F, IterableW>>() { - public F, IterableW> f(final F f) { - return new F, IterableW>() { - public IterableW f(final IterableW a) { - return a.map(f); - } - }; - } - }; + return f -> a -> a.map(f); } /** @@ -284,11 +240,7 @@ public A foldLeft1(final F> f) { */ public B foldRight(final F2 f, final B z) { final F id = identity(); - return foldLeft(curry(new F3, A, B, B>() { - public B f(final F k, final A a, final B b) { - return k.f(f.f(a, b)); - } - }), id).f(z); + return foldLeft(curry((k, a, b) -> k.f(f.f(a, b))), id).f(z); } /** diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index 7d3cc503..7b5961cd 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -92,12 +92,7 @@ public Option f(final IterV i) { }; final F>, A> done = P2.>__1(); final F, IterV>, A> cont = - new F, IterV>, A>() { - @Override - public A f(final F, IterV> k) { - return runCont.f(k.f(Input.eof())).valueE("diverging iteratee"); //$NON-NLS-1$ - } - }; + k -> runCont.f(k.f(Input.eof())).valueE("diverging iteratee"); return fold(done, cont); } @@ -109,36 +104,18 @@ public final IterV bind(final F> f) { public IterV f(final P2> xe) { final Input e = xe._2(); final F>, IterV> done = - new F>, IterV>() { - @Override - public IterV f(final P2> y_) { - final B y = y_._1(); - return done(y, e); - } - }; + y_ -> { + final B y = y_._1(); + return done(y, e); + }; final F, IterV>, IterV> cont = - new F, IterV>, IterV>() { - @Override - public IterV f(final F, IterV> k) { - return k.f(e); - } - }; + k -> k.f(e); final A x = xe._1(); return f.f(x).fold(done, cont); } }; final F, IterV>, IterV> cont = - new F, IterV>, IterV>() { - @Override - public IterV f(final F, IterV> k) { - return cont(new F, IterV>() { - @Override - public IterV f(final Input e) { - return k.f(e).bind(f); - } - }); - } - }; + k -> cont(e -> k.f(e).bind(f)); return this.fold(done, cont); } @@ -171,12 +148,7 @@ public IterV _1() { return done(acc, Input.eof()); } }; - return new F, IterV>() { - @Override - public IterV f(final Input s) { - return s.apply(empty, el, eof); - } - }; + return s -> s.apply(empty, el, eof); } }; return cont(step.f(0)); @@ -237,12 +209,7 @@ public IterV> _1() { new P1>>>() { @Override public F>> _1() { - return new F>>() { - @Override - public IterV> f(final E e) { - return done(Option.some(e), Input.empty()); - } - }; + return e -> done(Option.some(e), Input.empty()); } }; final P1>> eof = @@ -278,12 +245,7 @@ public IterV> _1() { new P1>>>() { @Override public F>> _1() { - return new F>>() { - @Override - public IterV> f(final E e) { - return done(Option.some(e), Input.el(e)); - } - }; + return e -> done(Option.some(e), Input.el(e)); } }; final P1>> eof = @@ -322,12 +284,7 @@ public IterV> _1() { new P1>>>() { @Override public F>> _1() { - return new F>>() { - @Override - public IterV> f(final E e) { - return cont(step.f(acc.cons(e))); - } - }; + return e -> cont(step.f(acc.cons(e))); } }; final P1>> eof = @@ -337,12 +294,7 @@ public IterV> _1() { return done(acc, Input.eof()); } }; - return new F, IterV>>() { - @Override - public IterV> f(final Input s) { - return s.apply(empty, el, eof); - } - }; + return s -> s.apply(empty, el, eof); } }; return cont(step.f(List. nil())); diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 4c62b0ad..2e5650c7 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -56,26 +56,18 @@ private Java() { * @return A function that converts lists to array lists. */ public static F, ArrayList> List_ArrayList() { - return new F, ArrayList>() { - public ArrayList f(final List as) { - return new ArrayList(as.toCollection()); - } - }; + return as -> new ArrayList(as.toCollection()); } /** * A function that converts lists to bit sets. */ - public static final F, BitSet> List_BitSet = new F, BitSet>() { - public BitSet f(final List bs) { - final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(new Effect1>() { - public void f(final P2 bi) { - s.set(bi._2(), bi._1()); - } - }); - return s; - } + public static final F, BitSet> List_BitSet = bs -> { + final BitSet s = new BitSet(bs.length()); + bs.zipIndex().foreachDoEffect(bi -> { + s.set(bi._2(), bi._1()); + }); + return s; }; /** @@ -84,11 +76,7 @@ public void f(final P2 bi) { * @return A function that converts lists to enum sets. */ public static > F, EnumSet> List_EnumSet() { - return new F, EnumSet>() { - public EnumSet f(final List as) { - return copyOf(as.toCollection()); - } - }; + return as -> copyOf(as.toCollection()); } /** @@ -97,11 +85,7 @@ public EnumSet f(final List as) { * @return A function that converts lists to hash sets. */ public static F, HashSet> List_HashSet() { - return new F, HashSet>() { - public HashSet f(final List as) { - return new HashSet(as.toCollection()); - } - }; + return as -> new HashSet(as.toCollection()); } /** @@ -110,11 +94,7 @@ public HashSet f(final List as) { * @return A function that converts lists to linked hash sets. */ public static F, LinkedHashSet> List_LinkedHashSet() { - return new F, LinkedHashSet>() { - public LinkedHashSet f(final List as) { - return new LinkedHashSet(as.toCollection()); - } - }; + return as -> new LinkedHashSet(as.toCollection()); } /** @@ -123,11 +103,7 @@ public LinkedHashSet f(final List as) { * @return A function that converts lists to linked lists. */ public static F, LinkedList> List_LinkedList() { - return new F, LinkedList>() { - public LinkedList f(final List as) { - return new LinkedList(as.toCollection()); - } - }; + return as -> new LinkedList(as.toCollection()); } /** @@ -136,11 +112,7 @@ public LinkedList f(final List as) { * @return A function that converts lists to priority queues. */ public static F, PriorityQueue> List_PriorityQueue() { - return new F, PriorityQueue>() { - public PriorityQueue f(final List as) { - return new PriorityQueue(as.toCollection()); - } - }; + return as -> new PriorityQueue(as.toCollection()); } /** @@ -149,12 +121,10 @@ public PriorityQueue f(final List as) { * @return A function that converts lists to stacks. */ public static F, Stack> List_Stack() { - return new F, Stack>() { - public Stack f(final List as) { - final Stack s = new Stack(); - s.addAll(as.toCollection()); - return s; - } + return as -> { + final Stack s = new Stack(); + s.addAll(as.toCollection()); + return s; }; } @@ -164,11 +134,7 @@ public Stack f(final List as) { * @return A function that converts lists to stacks. */ public static F, TreeSet> List_TreeSet() { - return new F, TreeSet>() { - public TreeSet f(final List as) { - return new TreeSet(as.toCollection()); - } - }; + return as -> new TreeSet(as.toCollection()); } /** @@ -177,12 +143,7 @@ public TreeSet f(final List as) { * @return A function that converts lists to vectors. */ public static F, Vector> List_Vector() { - return new F, Vector>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Vector f(final List as) { - return new Vector(as.toCollection()); - } - }; + return as -> new Vector(as.toCollection()); } /** @@ -192,11 +153,7 @@ public Vector f(final List as) { * @return A function that converts lists to array blocking queue. */ public static F, ArrayBlockingQueue> List_ArrayBlockingQueue(final boolean fair) { - return new F, ArrayBlockingQueue>() { - public ArrayBlockingQueue f(final List as) { - return new ArrayBlockingQueue(as.length(), fair, as.toCollection()); - } - }; + return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); } /** @@ -205,11 +162,7 @@ public ArrayBlockingQueue f(final List as) { * @return A function that converts lists to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> List_ConcurrentLinkedQueue() { - return new F, ConcurrentLinkedQueue>() { - public ConcurrentLinkedQueue f(final List as) { - return new ConcurrentLinkedQueue(as.toCollection()); - } - }; + return as -> new ConcurrentLinkedQueue(as.toCollection()); } /** @@ -218,11 +171,7 @@ public ConcurrentLinkedQueue f(final List as) { * @return A function that converts lists to copy on write array lists. */ public static F, CopyOnWriteArrayList> List_CopyOnWriteArrayList() { - return new F, CopyOnWriteArrayList>() { - public CopyOnWriteArrayList f(final List as) { - return new CopyOnWriteArrayList(as.toCollection()); - } - }; + return as -> new CopyOnWriteArrayList(as.toCollection()); } /** @@ -231,11 +180,7 @@ public CopyOnWriteArrayList f(final List as) { * @return A function that converts lists to copy on write array sets. */ public static F, CopyOnWriteArraySet> List_CopyOnWriteArraySet() { - return new F, CopyOnWriteArraySet>() { - public CopyOnWriteArraySet f(final List as) { - return new CopyOnWriteArraySet(as.toCollection()); - } - }; + return as -> new CopyOnWriteArraySet(as.toCollection()); } /** @@ -244,11 +189,7 @@ public CopyOnWriteArraySet f(final List as) { * @return A function that converts lists to delay queues. */ public static F, DelayQueue> List_DelayQueue() { - return new F, DelayQueue>() { - public DelayQueue f(final List as) { - return new DelayQueue(as.toCollection()); - } - }; + return as -> new DelayQueue(as.toCollection()); } /** @@ -257,11 +198,7 @@ public DelayQueue f(final List as) { * @return A function that converts lists to linked blocking queues. */ public static F, LinkedBlockingQueue> List_LinkedBlockingQueue() { - return new F, LinkedBlockingQueue>() { - public LinkedBlockingQueue f(final List as) { - return new LinkedBlockingQueue(as.toCollection()); - } - }; + return as -> new LinkedBlockingQueue(as.toCollection()); } /** @@ -270,11 +207,7 @@ public LinkedBlockingQueue f(final List as) { * @return A function that converts lists to priority blocking queues. */ public static F, PriorityBlockingQueue> List_PriorityBlockingQueue() { - return new F, PriorityBlockingQueue>() { - public PriorityBlockingQueue f(final List as) { - return new PriorityBlockingQueue(as.toCollection()); - } - }; + return as -> new PriorityBlockingQueue(as.toCollection()); } /** @@ -284,12 +217,10 @@ public PriorityBlockingQueue f(final List as) { * @return A function that converts lists to synchronous queues. */ public static F, SynchronousQueue> List_SynchronousQueue(final boolean fair) { - return new F, SynchronousQueue>() { - public SynchronousQueue f(final List as) { - final SynchronousQueue q = new SynchronousQueue(fair); - q.addAll(as.toCollection()); - return q; - } + return as -> { + final SynchronousQueue q = new SynchronousQueue(fair); + q.addAll(as.toCollection()); + return q; }; } @@ -303,27 +234,19 @@ public SynchronousQueue f(final List as) { * @return A function that converts arrays to array lists. */ public static F, ArrayList> Array_ArrayList() { - return new F, ArrayList>() { - public ArrayList f(final Array as) { - return new ArrayList(as.toCollection()); - } - }; + return as -> new ArrayList(as.toCollection()); } /** * A function that converts arrays to bit sets. */ - public static final F, BitSet> Array_BitSet = new F, BitSet>() { - public BitSet f(final Array bs) { - final BitSet s = new BitSet(bs.length()); + public static final F, BitSet> Array_BitSet = bs -> { + final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(new Effect1>() { - public void f(final P2 bi) { - s.set(bi._2(), bi._1()); - } - }); - return s; - } + bs.zipIndex().foreachDoEffect(bi -> { + s.set(bi._2(), bi._1()); + }); + return s; }; /** @@ -332,11 +255,7 @@ public void f(final P2 bi) { * @return A function that converts arrays to enum sets. */ public static > F, EnumSet> Array_EnumSet() { - return new F, EnumSet>() { - public EnumSet f(final Array as) { - return copyOf(as.toCollection()); - } - }; + return as -> copyOf(as.toCollection()); } /** @@ -345,11 +264,7 @@ public EnumSet f(final Array as) { * @return A function that converts arrays to hash sets. */ public static F, HashSet> Array_HashSet() { - return new F, HashSet>() { - public HashSet f(final Array as) { - return new HashSet(as.toCollection()); - } - }; + return as -> new HashSet(as.toCollection()); } /** @@ -358,11 +273,7 @@ public HashSet f(final Array as) { * @return A function that converts arrays to linked hash sets. */ public static F, LinkedHashSet> Array_LinkedHashSet() { - return new F, LinkedHashSet>() { - public LinkedHashSet f(final Array as) { - return new LinkedHashSet(as.toCollection()); - } - }; + return as -> new LinkedHashSet(as.toCollection()); } /** @@ -371,11 +282,7 @@ public LinkedHashSet f(final Array as) { * @return A function that converts arrays to linked lists. */ public static F, LinkedList> Array_LinkedList() { - return new F, LinkedList>() { - public LinkedList f(final Array as) { - return new LinkedList(as.toCollection()); - } - }; + return as -> new LinkedList(as.toCollection()); } /** @@ -384,11 +291,7 @@ public LinkedList f(final Array as) { * @return A function that converts arrays to priority queues. */ public static F, PriorityQueue> Array_PriorityQueue() { - return new F, PriorityQueue>() { - public PriorityQueue f(final Array as) { - return new PriorityQueue(as.toCollection()); - } - }; + return as -> new PriorityQueue(as.toCollection()); } /** @@ -397,12 +300,10 @@ public PriorityQueue f(final Array as) { * @return A function that converts arrays to stacks. */ public static F, Stack> Array_Stack() { - return new F, Stack>() { - public Stack f(final Array as) { - final Stack s = new Stack(); - s.addAll(as.toCollection()); - return s; - } + return as -> { + final Stack s = new Stack(); + s.addAll(as.toCollection()); + return s; }; } @@ -412,11 +313,7 @@ public Stack f(final Array as) { * @return A function that converts arrays to tree sets. */ public static F, TreeSet> Array_TreeSet() { - return new F, TreeSet>() { - public TreeSet f(final Array as) { - return new TreeSet(as.toCollection()); - } - }; + return as -> new TreeSet(as.toCollection()); } /** @@ -425,12 +322,7 @@ public TreeSet f(final Array as) { * @return A function that converts arrays to vectors. */ public static F, Vector> Array_Vector() { - return new F, Vector>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Vector f(final Array as) { - return new Vector(as.toCollection()); - } - }; + return as -> new Vector(as.toCollection()); } /** @@ -440,11 +332,7 @@ public Vector f(final Array as) { * @return A function that converts arrays to array blocking queues. */ public static F, ArrayBlockingQueue> Array_ArrayBlockingQueue(final boolean fair) { - return new F, ArrayBlockingQueue>() { - public ArrayBlockingQueue f(final Array as) { - return new ArrayBlockingQueue(as.length(), fair, as.toCollection()); - } - }; + return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); } /** @@ -453,11 +341,7 @@ public ArrayBlockingQueue f(final Array as) { * @return A function that converts arrays to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Array_ConcurrentLinkedQueue() { - return new F, ConcurrentLinkedQueue>() { - public ConcurrentLinkedQueue f(final Array as) { - return new ConcurrentLinkedQueue(as.toCollection()); - } - }; + return as -> new ConcurrentLinkedQueue(as.toCollection()); } /** @@ -466,11 +350,7 @@ public ConcurrentLinkedQueue f(final Array as) { * @return A function that converts arrays to copy on write array lists. */ public static F, CopyOnWriteArrayList> Array_CopyOnWriteArrayList() { - return new F, CopyOnWriteArrayList>() { - public CopyOnWriteArrayList f(final Array as) { - return new CopyOnWriteArrayList(as.toCollection()); - } - }; + return as -> new CopyOnWriteArrayList(as.toCollection()); } /** @@ -479,11 +359,7 @@ public CopyOnWriteArrayList f(final Array as) { * @return A function that converts arrays to copy on write array sets. */ public static F, CopyOnWriteArraySet> Array_CopyOnWriteArraySet() { - return new F, CopyOnWriteArraySet>() { - public CopyOnWriteArraySet f(final Array as) { - return new CopyOnWriteArraySet(as.toCollection()); - } - }; + return as -> new CopyOnWriteArraySet(as.toCollection()); } /** @@ -492,11 +368,7 @@ public CopyOnWriteArraySet f(final Array as) { * @return A function that converts arrays to delay queues. */ public static F, DelayQueue> Array_DelayQueue() { - return new F, DelayQueue>() { - public DelayQueue f(final Array as) { - return new DelayQueue(as.toCollection()); - } - }; + return as -> new DelayQueue(as.toCollection()); } /** @@ -505,11 +377,7 @@ public DelayQueue f(final Array as) { * @return A function that converts arrays to linked blocking queues. */ public static F, LinkedBlockingQueue> Array_LinkedBlockingQueue() { - return new F, LinkedBlockingQueue>() { - public LinkedBlockingQueue f(final Array as) { - return new LinkedBlockingQueue(as.toCollection()); - } - }; + return as -> new LinkedBlockingQueue(as.toCollection()); } /** @@ -518,11 +386,7 @@ public LinkedBlockingQueue f(final Array as) { * @return A function that converts arrays to priority blocking queues. */ public static F, PriorityBlockingQueue> Array_PriorityBlockingQueue() { - return new F, PriorityBlockingQueue>() { - public PriorityBlockingQueue f(final Array as) { - return new PriorityBlockingQueue(as.toCollection()); - } - }; + return as -> new PriorityBlockingQueue(as.toCollection()); } /** @@ -532,12 +396,10 @@ public PriorityBlockingQueue f(final Array as) { * @return A function that converts arrays to synchronous queues. */ public static F, SynchronousQueue> Array_SynchronousQueue(final boolean fair) { - return new F, SynchronousQueue>() { - public SynchronousQueue f(final Array as) { - final SynchronousQueue q = new SynchronousQueue(fair); - q.addAll(as.toCollection()); - return q; - } + return as -> { + final SynchronousQueue q = new SynchronousQueue(fair); + q.addAll(as.toCollection()); + return q; }; } @@ -551,31 +413,27 @@ public SynchronousQueue f(final Array as) { * @return A function that converts streams to iterable. */ public static F, Iterable> Stream_Iterable() { - return new F, Iterable>() { - public Iterable f(final Stream as) { - return new Iterable() { - public Iterator iterator() { - return new Iterator() { - private Stream x = as; - - public boolean hasNext() { - return x.isNotEmpty(); - } - - public A next() { - if (x.isEmpty()) - throw new NoSuchElementException("Empty iterator"); - else { - final A a = x.head(); - x = x.tail()._1(); - return a; - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; + return as -> new Iterable() { + public Iterator iterator() { + return new Iterator() { + private Stream x = as; + + public boolean hasNext() { + return x.isNotEmpty(); + } + + public A next() { + if (x.isEmpty()) + throw new NoSuchElementException("Empty iterator"); + else { + final A a = x.head(); + x = x.tail()._1(); + return a; + } + } + + public void remove() { + throw new UnsupportedOperationException(); } }; } @@ -588,26 +446,18 @@ public void remove() { * @return A function that converts streams to array lists. */ public static F, ArrayList> Stream_ArrayList() { - return new F, ArrayList>() { - public ArrayList f(final Stream as) { - return new ArrayList(as.toCollection()); - } - }; + return as -> new ArrayList(as.toCollection()); } /** * A function that converts streams to bit sets. */ - public static final F, BitSet> Stream_BitSet = new F, BitSet>() { - public BitSet f(final Stream bs) { - final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(new Effect1>() { - public void f(final P2 bi) { - s.set(bi._2(), bi._1()); - } - }); - return s; - } + public static final F, BitSet> Stream_BitSet = bs -> { + final BitSet s = new BitSet(bs.length()); + bs.zipIndex().foreachDoEffect(bi -> { + s.set(bi._2(), bi._1()); + }); + return s; }; /** @@ -616,11 +466,7 @@ public void f(final P2 bi) { * @return A function that converts streams to enum sets. */ public static > F, EnumSet> Stream_EnumSet() { - return new F, EnumSet>() { - public EnumSet f(final Stream as) { - return copyOf(as.toCollection()); - } - }; + return as -> copyOf(as.toCollection()); } /** @@ -629,11 +475,7 @@ public EnumSet f(final Stream as) { * @return A function that converts streams to hash sets. */ public static F, HashSet> Stream_HashSet() { - return new F, HashSet>() { - public HashSet f(final Stream as) { - return new HashSet(as.toCollection()); - } - }; + return as -> new HashSet(as.toCollection()); } /** @@ -642,11 +484,7 @@ public HashSet f(final Stream as) { * @return A function that converts streams to linked hash sets. */ public static F, LinkedHashSet> Stream_LinkedHashSet() { - return new F, LinkedHashSet>() { - public LinkedHashSet f(final Stream as) { - return new LinkedHashSet(as.toCollection()); - } - }; + return as -> new LinkedHashSet(as.toCollection()); } /** @@ -655,11 +493,7 @@ public LinkedHashSet f(final Stream as) { * @return A function that converts streams to linked lists. */ public static F, LinkedList> Stream_LinkedList() { - return new F, LinkedList>() { - public LinkedList f(final Stream as) { - return new LinkedList(as.toCollection()); - } - }; + return as -> new LinkedList(as.toCollection()); } /** @@ -668,11 +502,7 @@ public LinkedList f(final Stream as) { * @return A function that converts streams to priority queues. */ public static F, PriorityQueue> Stream_PriorityQueue() { - return new F, PriorityQueue>() { - public PriorityQueue f(final Stream as) { - return new PriorityQueue(as.toCollection()); - } - }; + return as -> new PriorityQueue(as.toCollection()); } /** @@ -681,12 +511,10 @@ public PriorityQueue f(final Stream as) { * @return A function that converts streams to stacks. */ public static F, Stack> Stream_Stack() { - return new F, Stack>() { - public Stack f(final Stream as) { - final Stack s = new Stack(); - s.addAll(as.toCollection()); - return s; - } + return as -> { + final Stack s = new Stack(); + s.addAll(as.toCollection()); + return s; }; } @@ -696,11 +524,7 @@ public Stack f(final Stream as) { * @return A function that converts streams to tree sets. */ public static F, TreeSet> Stream_TreeSet() { - return new F, TreeSet>() { - public TreeSet f(final Stream as) { - return new TreeSet(as.toCollection()); - } - }; + return as -> new TreeSet(as.toCollection()); } /** @@ -709,12 +533,7 @@ public TreeSet f(final Stream as) { * @return A function that converts streams to vectors. */ public static F, Vector> Stream_Vector() { - return new F, Vector>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Vector f(final Stream as) { - return new Vector(as.toCollection()); - } - }; + return as -> new Vector(as.toCollection()); } /** @@ -724,11 +543,7 @@ public Vector f(final Stream as) { * @return A function that converts streams to array blocking queues. */ public static F, ArrayBlockingQueue> Stream_ArrayBlockingQueue(final boolean fair) { - return new F, ArrayBlockingQueue>() { - public ArrayBlockingQueue f(final Stream as) { - return new ArrayBlockingQueue(as.length(), fair, as.toCollection()); - } - }; + return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); } /** @@ -737,11 +552,7 @@ public ArrayBlockingQueue f(final Stream as) { * @return A function that converts streams to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Stream_ConcurrentLinkedQueue() { - return new F, ConcurrentLinkedQueue>() { - public ConcurrentLinkedQueue f(final Stream as) { - return new ConcurrentLinkedQueue(as.toCollection()); - } - }; + return as -> new ConcurrentLinkedQueue(as.toCollection()); } /** @@ -750,11 +561,7 @@ public ConcurrentLinkedQueue f(final Stream as) { * @return A function that converts streams to copy on write array lists. */ public static F, CopyOnWriteArrayList> Stream_CopyOnWriteArrayList() { - return new F, CopyOnWriteArrayList>() { - public CopyOnWriteArrayList f(final Stream as) { - return new CopyOnWriteArrayList(as.toCollection()); - } - }; + return as -> new CopyOnWriteArrayList(as.toCollection()); } /** @@ -763,11 +570,7 @@ public CopyOnWriteArrayList f(final Stream as) { * @return A function that converts streams to copy on write array sets. */ public static F, CopyOnWriteArraySet> Stream_CopyOnWriteArraySet() { - return new F, CopyOnWriteArraySet>() { - public CopyOnWriteArraySet f(final Stream as) { - return new CopyOnWriteArraySet(as.toCollection()); - } - }; + return as -> new CopyOnWriteArraySet(as.toCollection()); } /** @@ -776,11 +579,7 @@ public CopyOnWriteArraySet f(final Stream as) { * @return A function that converts streams to delay queues. */ public static F, DelayQueue> Stream_DelayQueue() { - return new F, DelayQueue>() { - public DelayQueue f(final Stream as) { - return new DelayQueue(as.toCollection()); - } - }; + return as -> new DelayQueue(as.toCollection()); } /** @@ -789,11 +588,7 @@ public DelayQueue f(final Stream as) { * @return A function that converts streams to linked blocking queues. */ public static F, LinkedBlockingQueue> Stream_LinkedBlockingQueue() { - return new F, LinkedBlockingQueue>() { - public LinkedBlockingQueue f(final Stream as) { - return new LinkedBlockingQueue(as.toCollection()); - } - }; + return as -> new LinkedBlockingQueue(as.toCollection()); } /** @@ -802,11 +597,7 @@ public LinkedBlockingQueue f(final Stream as) { * @return A function that converts streams to priority blocking queues. */ public static F, PriorityBlockingQueue> Stream_PriorityBlockingQueue() { - return new F, PriorityBlockingQueue>() { - public PriorityBlockingQueue f(final Stream as) { - return new PriorityBlockingQueue(as.toCollection()); - } - }; + return as -> new PriorityBlockingQueue(as.toCollection()); } /** @@ -816,12 +607,10 @@ public PriorityBlockingQueue f(final Stream as) { * @return A function that converts streams to synchronous queues. */ public static F, SynchronousQueue> Stream_SynchronousQueue(final boolean fair) { - return new F, SynchronousQueue>() { - public SynchronousQueue f(final Stream as) { - final SynchronousQueue q = new SynchronousQueue(fair); - q.addAll(as.toCollection()); - return q; - } + return as -> { + final SynchronousQueue q = new SynchronousQueue(fair); + q.addAll(as.toCollection()); + return q; }; } @@ -835,28 +624,20 @@ public SynchronousQueue f(final Stream as) { * @return A function that converts options to array lists. */ public static F, ArrayList> Option_ArrayList() { - return new F, ArrayList>() { - public ArrayList f(final Option as) { - return new ArrayList(as.toCollection()); - } - }; + return as -> new ArrayList(as.toCollection()); } /** * A function that converts options to bit sets. */ - public static final F, BitSet> Option_BitSet = new F, BitSet>() { - public BitSet f(final Option bs) { - final BitSet s = new BitSet(bs.length()); + public static final F, BitSet> Option_BitSet = bs -> { + final BitSet s = new BitSet(bs.length()); - bs.foreachDoEffect(new Effect1() { - public void f(final Boolean b) { - if (b) - s.set(0); - } - }); - return s; - } + bs.foreachDoEffect(b -> { + if (b) + s.set(0); + }); + return s; }; /** @@ -865,11 +646,7 @@ public void f(final Boolean b) { * @return A function that converts options to enum sets. */ public static > F, EnumSet> Option_EnumSet() { - return new F, EnumSet>() { - public EnumSet f(final Option as) { - return copyOf(as.toCollection()); - } - }; + return as -> copyOf(as.toCollection()); } /** @@ -878,11 +655,7 @@ public EnumSet f(final Option as) { * @return A function that converts options to hash sets. */ public static F, HashSet> Option_HashSet() { - return new F, HashSet>() { - public HashSet f(final Option as) { - return new HashSet(as.toCollection()); - } - }; + return as -> new HashSet(as.toCollection()); } /** @@ -891,11 +664,7 @@ public HashSet f(final Option as) { * @return A function that converts options to linked hash sets. */ public static F, LinkedHashSet> Option_LinkedHashSet() { - return new F, LinkedHashSet>() { - public LinkedHashSet f(final Option as) { - return new LinkedHashSet(as.toCollection()); - } - }; + return as -> new LinkedHashSet(as.toCollection()); } /** @@ -904,11 +673,7 @@ public LinkedHashSet f(final Option as) { * @return A function that converts options to linked lists. */ public static F, LinkedList> Option_LinkedList() { - return new F, LinkedList>() { - public LinkedList f(final Option as) { - return new LinkedList(as.toCollection()); - } - }; + return as -> new LinkedList(as.toCollection()); } /** @@ -917,11 +682,7 @@ public LinkedList f(final Option as) { * @return A function that converts options to priority queues. */ public static F, PriorityQueue> Option_PriorityQueue() { - return new F, PriorityQueue>() { - public PriorityQueue f(final Option as) { - return new PriorityQueue(as.toCollection()); - } - }; + return as -> new PriorityQueue(as.toCollection()); } /** @@ -930,12 +691,10 @@ public PriorityQueue f(final Option as) { * @return A function that converts options to stacks. */ public static F, Stack> Option_Stack() { - return new F, Stack>() { - public Stack f(final Option as) { - final Stack s = new Stack(); - s.addAll(as.toCollection()); - return s; - } + return as -> { + final Stack s = new Stack(); + s.addAll(as.toCollection()); + return s; }; } @@ -945,11 +704,7 @@ public Stack f(final Option as) { * @return A function that converts options to tree sets. */ public static F, TreeSet> Option_TreeSet() { - return new F, TreeSet>() { - public TreeSet f(final Option as) { - return new TreeSet(as.toCollection()); - } - }; + return as -> new TreeSet(as.toCollection()); } /** @@ -958,12 +713,7 @@ public TreeSet f(final Option as) { * @return A function that converts options to vectors. */ public static F, Vector> Option_Vector() { - return new F, Vector>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public Vector f(final Option as) { - return new Vector(as.toCollection()); - } - }; + return as -> new Vector(as.toCollection()); } /** @@ -973,11 +723,7 @@ public Vector f(final Option as) { * @return A function that converts options to array blocking queues. */ public static F, ArrayBlockingQueue> Option_ArrayBlockingQueue(final boolean fair) { - return new F, ArrayBlockingQueue>() { - public ArrayBlockingQueue f(final Option as) { - return new ArrayBlockingQueue(as.length(), fair, as.toCollection()); - } - }; + return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); } /** @@ -986,11 +732,7 @@ public ArrayBlockingQueue f(final Option as) { * @return A function that converts options to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Option_ConcurrentLinkedQueue() { - return new F, ConcurrentLinkedQueue>() { - public ConcurrentLinkedQueue f(final Option as) { - return new ConcurrentLinkedQueue(as.toCollection()); - } - }; + return as -> new ConcurrentLinkedQueue(as.toCollection()); } /** @@ -999,11 +741,7 @@ public ConcurrentLinkedQueue f(final Option as) { * @return A function that converts options to copy on write array lists. */ public static F, CopyOnWriteArrayList> Option_CopyOnWriteArrayList() { - return new F, CopyOnWriteArrayList>() { - public CopyOnWriteArrayList f(final Option as) { - return new CopyOnWriteArrayList(as.toCollection()); - } - }; + return as -> new CopyOnWriteArrayList(as.toCollection()); } /** @@ -1012,11 +750,7 @@ public CopyOnWriteArrayList f(final Option as) { * @return A function that converts options to copy on write array sets. */ public static F, CopyOnWriteArraySet> Option_CopyOnWriteArraySet() { - return new F, CopyOnWriteArraySet>() { - public CopyOnWriteArraySet f(final Option as) { - return new CopyOnWriteArraySet(as.toCollection()); - } - }; + return as -> new CopyOnWriteArraySet(as.toCollection()); } /** @@ -1025,11 +759,7 @@ public CopyOnWriteArraySet f(final Option as) { * @return A function that converts options to delay queues. */ public static F, DelayQueue> Option_DelayQueue() { - return new F, DelayQueue>() { - public DelayQueue f(final Option as) { - return new DelayQueue(as.toCollection()); - } - }; + return as -> new DelayQueue(as.toCollection()); } /** @@ -1038,11 +768,7 @@ public DelayQueue f(final Option as) { * @return A function that converts options to linked blocking queues. */ public static F, LinkedBlockingQueue> Option_LinkedBlockingQueue() { - return new F, LinkedBlockingQueue>() { - public LinkedBlockingQueue f(final Option as) { - return new LinkedBlockingQueue(as.toCollection()); - } - }; + return as -> new LinkedBlockingQueue(as.toCollection()); } /** @@ -1051,11 +777,7 @@ public LinkedBlockingQueue f(final Option as) { * @return A function that converts options to priority blocking queues. */ public static F, PriorityBlockingQueue> Option_PriorityBlockingQueue() { - return new F, PriorityBlockingQueue>() { - public PriorityBlockingQueue f(final Option as) { - return new PriorityBlockingQueue(as.toCollection()); - } - }; + return as -> new PriorityBlockingQueue(as.toCollection()); } /** @@ -1065,12 +787,10 @@ public PriorityBlockingQueue f(final Option as) { * @return A function that converts options to synchronous queues. */ public static F, SynchronousQueue> Option_SynchronousQueue(final boolean fair) { - return new F, SynchronousQueue>() { - public SynchronousQueue f(final Option as) { - final SynchronousQueue q = new SynchronousQueue(fair); - q.addAll(as.toCollection()); - return q; - } + return as -> { + final SynchronousQueue q = new SynchronousQueue(fair); + q.addAll(as.toCollection()); + return q; }; } @@ -1740,12 +1460,7 @@ public List f(final ArrayList as) { * @return A function that converts Java lists to lists. */ public static F, List> JUList_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final java.util.List as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // BEGIN BitSet -> @@ -1753,17 +1468,9 @@ public List f(final java.util.List as) { /** * A function that converts bit sets to lists. */ - public static final F> BitSet_List = new F>() { - public List f(final BitSet s) { - return List.unfold(new F>>() { - public Option> f(final Integer i) { - return i == s.length() ? - Option.>none() : - some(p(s.get(i), i + 1)); - } - }, 0); - } - }; + public static final F> BitSet_List = s -> List.unfold(i -> i == s.length() ? + Option.>none() : + some(p(s.get(i), i + 1)), 0); // todo @@ -1777,12 +1484,7 @@ public Option> f(final Integer i) { * @return A function that converts enum sets to lists. */ public static > F, List> EnumSet_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final EnumSet as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } public static List Collection_List(Collection c) { @@ -1810,12 +1512,7 @@ private static E[] array(int length, E... array) { * @return A function that converts hash sets to lists. */ public static F, List> HashSet_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final HashSet as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1830,12 +1527,7 @@ public List f(final HashSet as) { * @return A function that converts linked hash sets to lists. */ public static F, List> LinkedHashSet_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final LinkedHashSet as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1850,12 +1542,7 @@ public List f(final LinkedHashSet as) { * @return A function that converts linked lists to lists. */ public static F, List> LinkedList_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final LinkedList as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1870,12 +1557,7 @@ public List f(final LinkedList as) { * @return A function that converts priority queues to lists. */ public static F, List> PriorityQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final PriorityQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1890,12 +1572,7 @@ public List f(final PriorityQueue as) { * @return A function that converts stacks to lists. */ public static F, List> Stack_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final Stack as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1910,12 +1587,7 @@ public List f(final Stack as) { * @return A function that converts tree sets to lists. */ public static F, List> TreeSet_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final TreeSet as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1930,12 +1602,7 @@ public List f(final TreeSet as) { * @return A function that converts vectors to lists. */ public static F, List> Vector_List() { - return new F, List>() { - @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"}) - public List f(final Vector as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1950,12 +1617,7 @@ public List f(final Vector as) { * @return A function that converts array blocking queues to lists. */ public static F, List> ArrayBlockingQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final ArrayBlockingQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1970,12 +1632,7 @@ public List f(final ArrayBlockingQueue as) { * @return A function that converts concurrent linked queues to lists. */ public static F, List> ConcurrentLinkedQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final ConcurrentLinkedQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1990,12 +1647,7 @@ public List f(final ConcurrentLinkedQueue as) { * @return A function that converts copy on write array lists to lists. */ public static F, List> CopyOnWriteArrayList_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final CopyOnWriteArrayList as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -2010,12 +1662,7 @@ public List f(final CopyOnWriteArrayList as) { * @return A function that converts copy on write array sets to lists. */ public static F, List> CopyOnWriteArraySet_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final CopyOnWriteArraySet as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -2030,12 +1677,7 @@ public List f(final CopyOnWriteArraySet as) { * @return A function that converts delay queues to lists. */ public static F, List> DelayQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final DelayQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -2050,12 +1692,7 @@ public List f(final DelayQueue as) { * @return A function that converts linked blocking queues to lists. */ public static F, List> LinkedBlockingQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final LinkedBlockingQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -2070,12 +1707,7 @@ public List f(final LinkedBlockingQueue as) { * @return A function that converts priority blocking queues to lists. */ public static F, List> PriorityBlockingQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final PriorityBlockingQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -2090,12 +1722,7 @@ public List f(final PriorityBlockingQueue as) { * @return A function that converts synchronous queues to lists. */ public static F, List> SynchronousQueue_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final SynchronousQueue as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -2105,13 +1732,9 @@ public List f(final SynchronousQueue as) { // BEGIN Callable -> public static F, Callable> P1_Callable() { - return new F, Callable>() { - public Callable f(final P1 a) { - return new Callable() { - public A call() { - return a._1(); - } - }; + return a -> new Callable() { + public A call() { + return a._1(); } }; } @@ -2121,21 +1744,17 @@ public A call() { // BEGIN Future -> public static F, P1>> Future_P1() { - return new F, P1>>() { - public P1> f(final Future a) { - return new P1>() { - @SuppressWarnings({"OverlyBroadCatchBlock"}) - public Either _1() { - Either r; - try { - r = Either.right(a.get()); - } - catch (Exception e) { - r = Either.left(e); - } - return r; - } - }; + return a -> new P1>() { + @SuppressWarnings({"OverlyBroadCatchBlock"}) + public Either _1() { + Either r; + try { + r = Either.right(a.get()); + } + catch (Exception e) { + r = Either.left(e); + } + return r; } }; } diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index ae375828..5ce04e36 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -168,11 +168,7 @@ public boolean startsWith(final LazyString cs) { * @return A function that yields true if the first argument is a prefix of the second. */ public static F> startsWith() { - return curry(new F2() { - public Boolean f(final LazyString needle, final LazyString haystack) { - return haystack.startsWith(needle); - } - }); + return curry((needle, haystack) -> haystack.startsWith(needle)); } /** @@ -310,31 +306,19 @@ public static LazyString unwords(final Stream str) { * First-class conversion from lazy strings to streams. */ public static final F> toStream = - new F>() { - public Stream f(final LazyString string) { - return string.toStream(); - } - }; + string -> string.toStream(); /** * First-class conversion from lazy strings to String. */ public static final F toString = - new F() { - public String f(final LazyString string) { - return string.toString(); - } - }; + string -> string.toString(); /** * First-class conversion from character streams to lazy strings. */ public static final F, LazyString> fromStream = - new F, LazyString>() { - public LazyString f(final Stream s) { - return fromStream(s); - } - }; + s -> fromStream(s); private static final Equal> eqS = streamEqual(charEqual); diff --git a/core/src/main/java/fj/data/Natural.java b/core/src/main/java/fj/data/Natural.java index 98dddb25..25cd11d5 100644 --- a/core/src/main/java/fj/data/Natural.java +++ b/core/src/main/java/fj/data/Natural.java @@ -40,11 +40,7 @@ public static Option natural(final BigInteger i) { * A function that returns the natural number equal to a given BigInteger */ public static final F> fromBigInt = - new F>() { - public Option f(final BigInteger i) { - return natural(i); - } - }; + i -> natural(i); /** * Returns the natural number equal to the given long @@ -81,11 +77,7 @@ public Natural succ() { * @return A function that returns the successor of a given natural number. */ public static F succ_() { - return new F() { - public Natural f(final Natural natural) { - return natural.succ(); - } - }; + return natural -> natural.succ(); } /** @@ -103,11 +95,7 @@ public Option pred() { * @return A function that returns the predecessor of a given natural number, or None if it's zero. */ public static F> pred_() { - return new F>() { - public Option f(final Natural natural) { - return natural.pred(); - } - }; + return natural -> natural.pred(); } /** @@ -123,11 +111,7 @@ public Natural add(final Natural n) { /** * A function that adds two natural numbers. */ - public static final F> add = curry(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n1.add(n2); - } - }); + public static final F> add = curry((n1, n2) -> n1.add(n2)); /** @@ -144,11 +128,7 @@ public Option subtract(final Natural n) { * A function that subtracts its first argument from its second. */ public static final F>> subtract = - curry(new F2>() { - public Option f(final Natural o, final Natural o1) { - return o1.subtract(o); - } - }); + curry((o, o1) -> o1.subtract(o)); /** * Multiply a natural number by another. @@ -163,22 +143,14 @@ public Natural multiply(final Natural n) { /** * A function that multiplies a natural number by another. */ - public static final F> multiply = curry(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n1.multiply(n2); - } - }); + public static final F> multiply = curry((n1, n2) -> n1.multiply(n2)); /** * A function that divides its second argument by its first. */ public static final F> divide = - curry(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n2.divide(n1); - } - }); + curry((n1, n2) -> n2.divide(n1)); /** * Divide a natural number by another. @@ -205,11 +177,7 @@ public Natural mod(final Natural n) { * A function that yields the remainder of division of its second argument by its first. */ public static final F> mod = - curry(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n2.mod(n1); - } - }); + curry((n1, n2) -> n2.mod(n1)); /** * Divide a natural number by another yielding both the quotient and the remainder. @@ -226,11 +194,7 @@ public V2 divmod(final Natural n) { * A function that divides its second argument by its first, yielding both the quotient and the remainder. */ public static final F>> divmod = - curry(new F2>() { - public V2 f(final Natural n1, final Natural n2) { - return n2.divmod(n1); - } - }); + curry((n1, n2) -> n2.divmod(n1)); /** @@ -281,11 +245,7 @@ public int intValue() { /** * A function that returns the BigInteger value of a given Natural. */ - public static final F bigIntegerValue = new F() { - public BigInteger f(final Natural n) { - return n.bigIntegerValue(); - } - }; + public static final F bigIntegerValue = n -> n.bigIntegerValue(); /** * Sums a stream of natural numbers. diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 1c14c535..fdf69815 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -108,11 +108,7 @@ public void f(final A a) { public NonEmptyList> sublists() { return fromList( somes(toList().toStream().substreams() - .map(F1Functions.o(new F, Option>>() { - public Option> f(final List list) { - return fromList(list); - } - }, Conversions.Stream_List())).toList())).some(); + .map(F1Functions.o(list -> fromList(list), Conversions.Stream_List())).toList())).some(); } /** @@ -163,11 +159,7 @@ public Collection toCollection() { * @return A function that takes a non-empty list to a list. */ public static F, List> toList_() { - return new F, List>() { - public List f(final NonEmptyList as) { - return as.toList(); - } - }; + return as -> as.toList(); } /** @@ -197,11 +189,7 @@ public static NonEmptyList nel(final A head) { * @return A function that puts an element into a non-empty list. */ public static F> nel() { - return new F>() { - public NonEmptyList f(final A a) { - return nel(a); - } - }; + return a -> nel(a); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 56a27ba4..81fc0106 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -121,32 +121,20 @@ public Set r() { public final P2> update(final A a, final F f) { return isEmpty() ? P.p(false, this) - : tryUpdate(a, f).either(new F>>() { - public P2> f(final A a2) { - return P.p(true, delete(a).insert(a2)); - } - }, Function.>>identity()); + : tryUpdate(a, f).either(a2 -> P.p(true, delete(a).insert(a2)), Function.>>identity()); } private Either>> tryUpdate(final A a, final F f) { if (isEmpty()) return right(P.p(false, this)); else if (ord.isLessThan(a, head())) - return l().tryUpdate(a, f).right().map(new F>, P2>>() { - public P2> f(final P2> set) { - return set._1() ? P.p(true, (Set) new Tree(ord, color(), set._2(), head(), r())) : set; - } - }); + return l().tryUpdate(a, f).right().map(set -> set._1() ? P.p(true, (Set) new Tree(ord, color(), set._2(), head(), r())) : set); else if (ord.eq(a, head())) { final A h = f.f(head()); return ord.eq(head(), h) ? Either .>>right(P.p(true, (Set) new Tree(ord, color(), l(), h, r()))) : Either.>>left(h); - } else return r().tryUpdate(a, f).right().map(new F>, P2>>() { - public P2> f(final P2> set) { - return set._1() ? P.p(true, (Set) new Tree(ord, color(), l(), head(), set._2())) : set; - } - }); + } else return r().tryUpdate(a, f).right().map(set -> set._1() ? P.p(true, (Set) new Tree(ord, color(), l(), head(), set._2())) : set); } /** @@ -176,11 +164,7 @@ public final boolean member(final A x) { * @return A function that returns true if the given element if a member of the given set. */ public static F, F> member() { - return curry(new F2, A, Boolean>() { - public Boolean f(final Set s, final A a) { - return s.member(a); - } - }); + return curry((s, a) -> s.member(a)); } /** @@ -199,11 +183,7 @@ public final Set insert(final A x) { * @return A function that inserts a given element into a given set. */ public static F, Set>> insert() { - return curry(new F2, Set>() { - public Set f(final A a, final Set set) { - return set.insert(a); - } - }); + return curry((a, set) -> set.insert(a)); } private Set ins(final A x) { @@ -326,11 +306,7 @@ public final Set union(final Set s) { * @see #union(Set) */ public static F, F, Set>> union() { - return curry(new F2, Set, Set>() { - public Set f(final Set s1, final Set s2) { - return s1.union(s2); - } - }); + return curry((s1, s2) -> s1.union(s2)); } /** @@ -360,11 +336,7 @@ public final Set delete(final A a) { * @return A function that deletes a given element from a given set. */ public final F, Set>> delete() { - return curry(new F2, Set>() { - public Set f(final A a, final Set set) { - return set.delete(a); - } - }); + return curry((a, set) -> set.delete(a)); } /** @@ -384,11 +356,7 @@ public final Set intersect(final Set s) { * @see #intersect(Set) */ public static F, F, Set>> intersect() { - return curry(new F2, Set, Set>() { - public Set f(final Set s1, final Set s2) { - return s1.intersect(s2); - } - }); + return curry((s1, s2) -> s1.intersect(s2)); } /** @@ -408,11 +376,7 @@ public final Set minus(final Set s) { * @see #minus(Set) */ public static F, F, Set>> minus() { - return curry(new F2, Set, Set>() { - public Set f(final Set s1, final Set s2) { - return s1.minus(s2); - } - }); + return curry((s1, s2) -> s1.minus(s2)); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index f04249e6..0538cdcd 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -263,15 +263,7 @@ public Stream _1() { * @return A function that maps a given function across a given stream. */ public static F, F, Stream>> map_() { - return new F, F, Stream>>() { - public F, Stream> f(final F f) { - return new F, Stream>() { - public Stream f(final Stream as) { - return as.map(f); - } - }; - } - }; + return f -> as -> as.map(f); } /** @@ -371,15 +363,7 @@ public final Stream removeAll(final F f) { * and returns a stream of the results. */ public static F> sequence_(final Stream> fs) { - return fs.foldRight(new F2, P1>>, F>>() { - public F> f(final F baf, final P1>> p1) { - return Function.bind(baf, p1._1(), Function.curry(new F2, Stream>() { - public Stream f(final A a, final Stream stream) { - return cons(a, p(stream)); - } - })); - } - }, Function + return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), Function.curry((a, stream) -> cons(a, p(stream)))), Function .>constant(Stream.nil())); } @@ -402,15 +386,12 @@ public final F> mapM(final F> f) { * @return A new stream after performing the map, then final join. */ public final Stream bind(final F> f) { - return map(f).foldLeft(new F2, Stream, Stream>() { - @Override - public Stream f(Stream accumulator, Stream element) { - Stream result = accumulator; - for (B single : element) { - result = result.cons(single); - } - return result; + return map(f).foldLeft((accumulator, element) -> { + Stream result = accumulator; + for (B single : element) { + result = result.cons(single); } + return result; }, Stream.nil()).reverse(); } @@ -558,15 +539,7 @@ public final Stream sequence(final Stream bs) { * @return A new stream after applying the given stream of functions through this stream. */ public final Stream apply(final Stream> sf) { - return sf.bind(new F, Stream>() { - public Stream f(final F f) { - return map(new F() { - public B f(final A a) { - return f.f(a); - } - }); - } - }); + return sf.bind(f -> map(a -> f.f(a))); } /** @@ -663,11 +636,7 @@ private Promise> qs(final Ord o, final Strategy s) { } private static F, Promise>> qs_(final Ord o, final Strategy s) { - return new F, Promise>>() { - public Promise> f(final Stream xs) { - return xs.qs(o, s); - } - }; + return xs -> xs.qs(o, s); } private static F, Promise>> flt(final Ord o, @@ -741,12 +710,8 @@ public Stream _1() { */ public static Stream stream(final A... as) { return as.length == 0 ? Stream.nil() - : unfold(P2.tuple(new F2>>>() { - public Option>> f(final A[] as, final Integer i) { - return i >= as.length ? Option.>>none() - : some(P.p(as[i], P.p(as, i + 1))); - } - }), P.p(as, 0)); + : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.>>none() + : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0)); } /** @@ -775,11 +740,7 @@ public static Stream forever(final Enumerator e, final A from) { public static Stream forever(final Enumerator e, final A from, final long step) { return cons(from, new P1>() { public Stream _1() { - return e.plus(from, step).map(new F>() { - public Stream f(final A a) { - return forever(e, a, step); - } - }).orSome(Stream.nil()); + return e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil()); } }); } @@ -813,15 +774,9 @@ public static Stream range(final Enumerator e, final A from, final A t final Ordering o = e.order().compare(from, to); return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, new P1>() { public Stream _1() { - return Stream.join(e.plus(from, step).filter(new F() { - public Boolean f(final A a) { - return !(o == LT ? e.order().isLessThan(to, a) : e.order().isGreaterThan(to, a)); - } - }).map(new F>() { - public Stream f(final A a) { - return range(e, a, to, step); - } - }).toStream()); + return Stream.join(e.plus(from, step).filter(a -> !(o == LT + ? e.order().isLessThan(to, a) + : e.order().isGreaterThan(to, a))).map(a1 -> range(e, a1, to, step)).toStream()); } }); } @@ -846,11 +801,7 @@ public Stream _1() { * @return a function that filters a given stream using a given predicate. */ public static F, F, Stream>> filter() { - return curry(new F2, Stream, Stream>() { - public Stream f(final F f, final Stream as) { - return as.filter(f); - } - }); + return curry((f, as) -> as.filter(f)); } /** @@ -906,11 +857,7 @@ public final Stream zipWith(final Stream bs, final F2 f) { * @return A function that zips a given stream with this stream using the given function. */ public final F, Stream> zipWith(final F> f) { - return new F, Stream>() { - public Stream f(final Stream stream) { - return zipWith(stream, f); - } - }; + return stream -> zipWith(stream, f); } /** @@ -933,11 +880,7 @@ public final Stream> zip(final Stream bs) { * @return A new stream with the same length as this stream. */ public final Stream> zipIndex() { - return zipWith(range(0), new F2>() { - public P2 f(final A a, final Integer i) { - return p(a, i); - } - }); + return zipWith(range(0), (a, i) -> p(a, i)); } /** @@ -1219,18 +1162,12 @@ public final P2, Stream> split(final F p) { * @return A new stream that is the reverse of this one. */ public final Stream reverse() { - return foldLeft(new F, F>>() { - public F> f(final Stream as) { - return new F>() { - public Stream f(final A a) { - return cons(a, new P1>() { - public Stream _1() { + return foldLeft(as -> { + return a -> cons(a, new P1>() { + public Stream _1() { return as; - } - }); - } - }; - } + } + }); }, Stream.nil()); } @@ -1374,11 +1311,7 @@ public Stream> _1() { * @return a stream of the infixes of this stream. */ public final Stream> substreams() { - return tails().bind(new F, Stream>>() { - public Stream> f(final Stream stream) { - return stream.inits(); - } - }); + return tails().bind(stream -> stream.inits()); } /** @@ -1388,11 +1321,7 @@ public Stream> f(final Stream stream) { * @return the position of the first element matching the given predicate, if any. */ public final Option indexOf(final F p) { - return zipIndex().find(new F, Boolean>() { - public Boolean f(final P2 p2) { - return p.f(p2._1()); - } - }).map(P2.__2()); + return zipIndex().find(p2 -> p.f(p2._1())).map(P2.__2()); } /** @@ -1417,11 +1346,7 @@ public Stream _1() { * @return A function from natural numbers to values with the corresponding position in this stream. */ public final F toFunction() { - return new F() { - public A f(final Integer i) { - return index(i); - } - }; + return i -> index(i); } /** @@ -1462,11 +1387,9 @@ public Stream _1() { * @return A stream of first components and a stream of second components. */ public static P2, Stream> unzip(final Stream> xs) { - return xs.foldRight(new F2, P1, Stream>>, P2, Stream>>() { - public P2, Stream> f(final P2 p, final P1, Stream>> ps) { - final P2, Stream> pp = ps._1(); - return P.p(cons(p._1(), P.p(pp._1())), cons(p._2(), P.p(pp._2()))); - } + return xs.foldRight((p, ps) -> { + final P2, Stream> pp = ps._1(); + return P.p(cons(p._1(), P.p(pp._1())), cons(p._2(), P.p(pp._2()))); }, P.p(Stream.nil(), Stream.nil())); } @@ -1476,11 +1399,7 @@ public P2, Stream> f(final P2 p, final P1, Strea * @return a function that zips two given streams with a given function. */ public static F, F, F>, Stream>>> zipWith() { - return curry(new F3, Stream, F>, Stream>() { - public Stream f(final Stream as, final Stream bs, final F> f) { - return as.zipWith(bs, f); - } - }); + return curry((as, bs, f) -> as.zipWith(bs, f)); } private static final class Nil extends Stream { @@ -1518,15 +1437,7 @@ public P1> tail() { * @return A function that prepends (cons) an element to a stream to produce a new stream. */ public static F>, Stream>> cons() { - return new F>, Stream>>() { - public F>, Stream> f(final A a) { - return new F>, Stream>() { - public Stream f(final P1> list) { - return cons(a, list); - } - }; - } - }; + return a -> list -> cons(a, list); } /** @@ -1535,11 +1446,7 @@ public Stream f(final P1> list) { * @return A function that prepends (cons) an element to a stream to produce a new stream. */ public static F, Stream>> cons_() { - return curry(new F2, Stream>() { - public Stream f(final A a, final Stream as) { - return as.cons(a); - } - }); + return curry((a, as) -> as.cons(a)); } /** @@ -1570,11 +1477,7 @@ public Stream _1() { * @return A function that determines whether a given stream is empty. */ public static F, Boolean> isEmpty_() { - return new F, Boolean>() { - public Boolean f(final Stream as) { - return as.isEmpty(); - } - }; + return as -> as.isEmpty(); } /** @@ -1583,11 +1486,7 @@ public Boolean f(final Stream as) { * @return A function that determines whether a given stream is not empty. */ public static F, Boolean> isNotEmpty_() { - return new F, Boolean>() { - public Boolean f(final Stream as) { - return as.isNotEmpty(); - } - }; + return as -> as.isNotEmpty(); } /** @@ -1610,11 +1509,7 @@ public Stream _1() { * @return a function that yields a stream containing its argument. */ public static F> single() { - return new F>() { - public Stream f(final A a) { - return single(a); - } - }; + return a -> single(a); } /** @@ -1644,11 +1539,7 @@ public static Stream join(final Stream> o) { * @return A function that joins a stream of streams using a bind operation. */ public static F>, Stream> join() { - return new F>, Stream>() { - public Stream f(final Stream> as) { - return join(as); - } - }; + return as -> join(as); } /** @@ -1685,16 +1576,8 @@ public Stream _1() { */ public static Stream iterateWhile(final F f, final F p, final A a) { return unfold( - new F>>() { - public Option> f(final A o) { - return Option.iif(new F, Boolean>() { - public Boolean f(final P2 p2) { - return p.f(o); - } - }, P.p(o, f.f(o))); - } - } - , a); + o -> Option.iif(p2 -> p.f(o), P.p(o, f.f(o))) + , a); } /** @@ -1774,11 +1657,7 @@ public Stream _1() { * starting at a given value. */ public static F, F>> iterate() { - return curry(new F2, A, Stream>() { - public Stream f(final F f, final A a) { - return iterate(f, a); - } - }); + return curry((f, a) -> iterate(f, a)); } /** @@ -1787,11 +1666,7 @@ public Stream f(final F f, final A a) { * @return A function that binds a given function across a given stream, joining the resulting streams. */ public static F>, F, Stream>> bind_() { - return curry(new F2>, Stream, Stream>() { - public Stream f(final F> f, final Stream as) { - return as.bind(f); - } - }); + return curry((f, as) -> as.bind(f)); } /** @@ -1800,10 +1675,6 @@ public Stream f(final F> f, final Stream as) { * @return A function that folds a given stream with a given function. */ public static F, B>>, F, B>>> foldRight() { - return curry(new F3, B>>, B, Stream, B>() { - public B f(final F, B>> f, final B b, final Stream as) { - return as.foldRight(f, b); - } - }); + return curry((f, b, as) -> as.foldRight(f, b)); } } diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 8c3cd8b1..fbdb0ea4 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -86,11 +86,7 @@ public static Tree node(final A root, final List> forest) { * @return A function that constructs an n-ary tree given a root and a subforest or length n. */ public static F>>, Tree>> node() { - return curry(new F2>>, Tree>() { - public Tree f(final A a, final P1>> p1) { - return node(a, p1); - } - }); + return curry((a, p1) -> node(a, p1)); } /** @@ -117,11 +113,7 @@ public P1>> subForest() { * @return A transformation from a tree to its root. */ public static F, A> root_() { - return new F, A>() { - public A f(final Tree a) { - return a.root(); - } - }; + return a -> a.root(); } /** @@ -130,11 +122,7 @@ public A f(final Tree a) { * @return A transformation from a tree to its subforest. */ public static F, P1>>> subForest_() { - return new F, P1>>>() { - public P1>> f(final Tree a) { - return a.subForest(); - } - }; + return a -> a.subForest(); } /** @@ -160,11 +148,7 @@ public Stream f(final Tree t, final P1> xs) { * @return The elements of the tree in pre-order. */ public static F, Stream> flatten_() { - return new F, Stream>() { - public Stream f(final Tree t) { - return t.flatten(); - } - }; + return t -> t.flatten(); } /** @@ -195,15 +179,7 @@ public Tree fmap(final F f) { * @return A transformation to lift any function so that it maps over Trees. */ public static F, F, Tree>> fmap_() { - return new F, F, Tree>>() { - public F, Tree> f(final F f) { - return new F, Tree>() { - public Tree f(final Tree a) { - return a.fmap(f); - } - }; - } - }; + return f -> a -> a.fmap(f); } /** @@ -234,11 +210,7 @@ public Collection toCollection() { * @return A function that, given a tree, folds it with the given monoid. */ public static F, B> foldMap_(final F f, final Monoid m) { - return new F, B>() { - public B f(final Tree t) { - return t.foldMap(f, m); - } - }; + return t -> t.foldMap(f, m); } /** @@ -248,11 +220,9 @@ public B f(final Tree t) { * @return A function which, given a seed value, yields a tree. */ public static F> unfoldTree(final F>>> f) { - return new F>() { - public Tree f(final B b) { - final P2>> p = f.f(b); - return node(p._1(), p._2().map(Stream.>map_().f(unfoldTree(f)))); - } + return b -> { + final P2>> p = f.f(b); + return node(p._1(), p._2().map(Stream.>map_().f(unfoldTree(f)))); }; } @@ -265,11 +235,7 @@ public Tree f(final B b) { * root's children are labels of the root's subforest, etc. */ public Tree cobind(final F, B> f) { - return unfoldTree(new F, P2>>>>() { - public P2>>> f(final Tree t) { - return P.p(f.f(t), t.subForest()); - } - }).f(this); + return unfoldTree((Tree t) -> P.p(f.f(t), t.subForest())).f(this); } /** @@ -316,11 +282,7 @@ public String draw(final Show s) { * @return a show instance that draws a 2-dimensional representation of a tree. */ public static Show> show2D(final Show s) { - return Show.showS(new F, String>() { - public String f(final Tree tree) { - return tree.draw(s); - } - }); + return Show.showS(tree -> tree.draw(s)); } /** @@ -369,11 +331,7 @@ public static Tree bottomUp(Tree t, final F>, B> f) * @return a function getting the root of a Tree */ private static F, A> getRoot() { - return new F, A>() { - @Override public A f(Tree a) { - return a.root(); - } - }; + return a -> a.root(); } } \ No newline at end of file diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 636dce7b..ca8568c1 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -164,11 +164,7 @@ public static TreeMap fromMutableMap(final Ord ord, final Map> get() { - return new F>() { - public Option f(final K k) { - return get(k); - } - }; + return k -> get(k); } /** diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 860d7e80..96874799 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -81,14 +81,7 @@ public static TreeZipper treeZipper(final Tree tree, F, F>, F>, F>, A, Stream>>>, TreeZipper>>>> treeZipper() { return curry( - new F4, Stream>, Stream>, Stream>, A, Stream>>>, TreeZipper>() { - public TreeZipper f(final Tree tree, - final Stream> lefts, - final Stream> rights, - final Stream>, A, Stream>>> parents) { - return treeZipper(tree, lefts, rights, parents); - } - }); + (tree, lefts, rights, parents) -> treeZipper(tree, lefts, rights, parents)); } /** @@ -107,20 +100,7 @@ public P4, Stream>, Stream>, Stream>, */ public static F, P4, Stream>, Stream>, Stream>, A, Stream>>>>> p_() { - return new F< - TreeZipper, - P4, - Stream>, - Stream>, - Stream>, A, Stream>>>>>() { - public P4< - Tree, - Stream>, - Stream>, - Stream>, A, Stream>>>> f(final TreeZipper a) { - return a.p(); - } - }; + return a -> a.p(); } /** @@ -187,11 +167,7 @@ public TreeZipper root() { * @return A function that returns a new tree-zipper focused on the root of the given tree zipper's tree. */ public static F, TreeZipper> root_() { - return new F, TreeZipper>() { - public TreeZipper f(final TreeZipper a) { - return a.root(); - } - }; + return a -> a.root(); } /** @@ -459,11 +435,7 @@ public TreeZipper modifyLabel(final F f) { * @return A new tree zipper with the focused node's label replaced by the given value. */ public TreeZipper setLabel(final A v) { - return modifyTree(new F, Tree>() { - public Tree f(final Tree t) { - return Tree.node(v, t.subForest()); - } - }); + return modifyTree(t -> Tree.node(v, t.subForest())); } /** @@ -546,11 +518,7 @@ public Option> delete() { else if (lefts.isNotEmpty()) r = some(treeZipper(lefts.head(), lefts.tail()._1(), rights, parents)); else for (final TreeZipper loc : parent()) - r = some(loc.modifyTree(new F, Tree>() { - public Tree f(final Tree t) { - return node(t.root(), Stream.>nil()); - } - })); + r = some(loc.modifyTree(t -> node(t.root(), Stream.>nil()))); return r; } @@ -576,11 +544,7 @@ public TreeZipper map(final F f) { final F, Tree> g = Tree.fmap_().f(f); final F>, Stream>> h = Stream., Tree>map_().f(g); return treeZipper(tree.fmap(f), lefts.map(g), rights.map(g), parents.map( - new F>, A, Stream>>, P3>, B, Stream>>>() { - public P3>, B, Stream>> f(final P3>, A, Stream>> p) { - return p.map1(h).map2(f).map3(h); - } - })); + p -> p.map1(h).map2(f).map3(h))); } /** @@ -589,11 +553,7 @@ public P3>, B, Stream>> f(final P3>, A, St * @return A function that takes a tree to its tree zipper representation. */ public static F, TreeZipper> fromTree() { - return new F, TreeZipper>() { - public TreeZipper f(final Tree t) { - return fromTree(t); - } - }; + return t -> fromTree(t); } /** @@ -602,11 +562,7 @@ public TreeZipper f(final Tree t) { * @return A function that focuses the given tree zipper on its left sibling. */ public static F, Option>> left_() { - return new F, Option>>() { - public Option> f(final TreeZipper z) { - return z.left(); - } - }; + return z -> z.left(); } /** @@ -615,11 +571,7 @@ public Option> f(final TreeZipper z) { * @return A function that focuses the given tree zipper on its right sibling. */ public static F, Option>> right_() { - return new F, Option>>() { - public Option> f(final TreeZipper z) { - return z.right(); - } - }; + return z -> z.right(); } /** @@ -654,39 +606,31 @@ Option>>> f(final Option> o) { private Stream>> uf(final F, Option>> f) { return unfold( - new F>, Option>, Option>>>>() { - public Option>, Option>>> f(final Option> o) { - Option>, Option>>> r = none(); - for (final TreeZipper c : o) { - r = some(P.p(unfoldTree(TreeZipper.dwn()).f(c), f.f(c))); - } - return r; - } - }, f.f(this)); + o -> { + Option>, Option>>> r = none(); + for (final TreeZipper c : o) { + r = some(P.p(unfoldTree(TreeZipper.dwn()).f(c), f.f(c))); + } + return r; + }, f.f(this)); } private static F, P2, P1>>>> dwn() { - return new F, P2, P1>>>>() { - public P2, P1>>> f(final TreeZipper tz) { - return P., P1>>>p(tz, new P1>>() { - private F>, Option, Option>>>> fwd() { - return new F>, Option, Option>>>>() { - public Option, Option>>> f(final Option> o) { - Option, Option>>> r = none(); - for (final TreeZipper c : o) { - r = some(P.p(c, c.right())); - } - return r; - } - }; + return tz -> P., P1>>>p(tz, new P1>>() { + private F>, Option, Option>>>> fwd() { + return o -> { + Option, Option>>> r = none(); + for (final TreeZipper c : o) { + r = some(P.p(c, c.right())); } + return r; + }; + } - public Stream> _1() { - return unfold(fwd(), tz.firstChild()); - } - }); + public Stream> _1() { + return unfold(fwd(), tz.firstChild()); } - }; + }); } /** @@ -706,11 +650,7 @@ public TreeZipper cobind(final F, B> f) { * @return a function that finds the first child, of a given tree zipper, that matches a given predicate. */ public static F2, Boolean>, TreeZipper, Option>> findChild() { - return new F2, Boolean>, TreeZipper, Option>>() { - public Option> f(final F, Boolean> f, final TreeZipper az) { - return az.findChild(f); - } - }; + return (f, az) -> az.findChild(f); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 7716b269..a9f71df0 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -342,11 +342,7 @@ public Validation accumulate(final Semigroup s, final Validation * None. */ public Option accumulate(final Semigroup s, final Validation va) { - return accumulate(s, va, new F2() { - public Unit f(final T t, final A a) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, (t, a) -> unit()).f().toOption(); } /** @@ -391,11 +387,7 @@ public Validation accumulate(final Semigroup s, final Validat * None. */ public Option accumulate(final Semigroup s, final Validation va, final Validation vb) { - return accumulate(s, va, vb, new F3() { - public Unit f(final T t, final A a, final B b) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, vb, (t, a, b) -> unit()).f().toOption(); } /** @@ -446,11 +438,7 @@ public Validation accumulate(final Semigroup s, final Vali */ public Option accumulate(final Semigroup s, final Validation va, final Validation vb, final Validation vc) { - return accumulate(s, va, vb, vc, new F4() { - public Unit f(final T t, final A a, final B b, final C c) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, vb, vc, (t, a, b, c) -> unit()).f().toOption(); } /** @@ -505,11 +493,7 @@ public Unit f(final T t, final A a, final B b, final C c) { */ public Option accumulate(final Semigroup s, final Validation va, final Validation vb, final Validation vc, final Validation vd) { - return accumulate(s, va, vb, vc, vd, new F5() { - public Unit f(final T t, final A a, final B b, final C c, final D d) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, vb, vc, vd, (t, a, b, c, d) -> unit()).f().toOption(); } /** @@ -569,11 +553,7 @@ public Unit f(final T t, final A a, final B b, final C c, final D d) { public Option accumulate(final Semigroup s, final Validation va, final Validation vb, final Validation vc, final Validation vd, final Validation ve) { - return accumulate(s, va, vb, vc, vd, ve, new F6() { - public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, vb, vc, vd, ve, (t, a, b, c, d, e1) -> unit()).f().toOption(); } /** @@ -639,11 +619,7 @@ public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e) final Validation vb, final Validation vc, final Validation vd, final Validation ve, final Validation vf) { - return accumulate(s, va, vb, vc, vd, ve, vf, new F7() { - public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e, final F$ f) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, vb, vc, vd, ve, vf, (t, a, b, c, d, e1, f) -> unit()).f().toOption(); } /** @@ -712,11 +688,7 @@ public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e, final Validation vb, final Validation vc, final Validation vd, final Validation ve, final Validation vf, final Validation vg) { - return accumulate(s, va, vb, vc, vd, ve, vf, vg, new F8() { - public Unit f(final T t, final A a, final B b, final C c, final D d, final E$ e, final F$ f, final G g) { - return unit(); - } - }).f().toOption(); + return accumulate(s, va, vb, vc, vd, ve, vf, vg, (t, a, b, c, d, e1, f, g) -> unit()).f().toOption(); } /** @@ -958,11 +930,7 @@ public Validation bind(final F> f) { * @return A new validation value after the final join. */ public Validation sequence(final Validation v) { - return bind(new F>() { - public Validation f(final E e) { - return v; - } - }); + return bind(e1 -> v); } @@ -989,11 +957,7 @@ public Option> filter(final F f) { * @return The result of function application in validation. */ public Validation apply(final Validation, T> v) { - return v.f().bind(new F, Validation>() { - public Validation f(final F f) { - return map(f); - } - }); + return v.f().bind(f -> map(f)); } /** @@ -1094,11 +1058,7 @@ public static Validation validation(final Either e) { * @return A function that constructs a validation with an either. */ public static F, Validation> validation() { - return new F, Validation>() { - public Validation f(final Either e) { - return validation(e); - } - }; + return e1 -> validation(e1); } /** @@ -1107,11 +1067,7 @@ public Validation f(final Either e) { * @return A function that constructs an either with a validation. */ public static F, Either> either() { - return new F, Either>() { - public Either f(final Validation v) { - return v.toEither(); - } - }; + return v -> v.toEither(); } /** diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index c94a8129..c4219a4d 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -75,11 +75,7 @@ public static Zipper zipper(final P3, A, Stream> p) { * @return A function that yields a new zipper given streams on the left and right and a focus element. */ public static F3, A, Stream, Zipper> zipper() { - return new F3, A, Stream, Zipper>() { - public Zipper f(final Stream l, final A a, final Stream r) { - return zipper(l, a, r); - } - }; + return (l, a, r) -> zipper(l, a, r); } /** @@ -97,11 +93,7 @@ public P3, A, Stream> p() { * @return A first-class function that yields the product-3 representation of a given Zipper. */ public static F, P3, A, Stream>> p_() { - return new F, P3, A, Stream>>() { - public P3, A, Stream> f(final Zipper a) { - return a.p(); - } - }; + return a -> a.p(); } /** @@ -264,11 +256,7 @@ public Zipper tryPrevious() { * @return A function that moves the given zipper's focus to the next element. */ public static F, Option>> next_() { - return new F, Option>>() { - public Option> f(final Zipper as) { - return as.next(); - } - }; + return as -> as.next(); } /** @@ -277,11 +265,7 @@ public Option> f(final Zipper as) { * @return A function that moves the given zipper's focus to the previous element. */ public static F, Option>> previous_() { - return new F, Option>>() { - public Option> f(final Zipper as) { - return as.previous(); - } - }; + return as -> as.previous(); } /** @@ -382,17 +366,9 @@ public boolean atEnd() { */ public Zipper> positions() { final Stream> left = Stream.unfold( - new F, Option, Zipper>>>() { - public Option, Zipper>> f(final Zipper p) { - return p.previous().map(join(P., Zipper>p2())); - } - }, this); + p -> p.previous().map(join(P., Zipper>p2())), this); final Stream> right = Stream.unfold( - new F, Option, Zipper>>>() { - public Option, Zipper>> f(final Zipper p) { - return p.next().map(join(P., Zipper>p2())); - } - }, this); + p -> p.next().map(join(P., Zipper>p2())), this); return zipper(left, this, right); } @@ -445,11 +421,7 @@ else if (rl >= n) * @return A function that moves the focus of the given zipper to the given index. */ public static F, Option>>> move() { - return curry(new F2, Option>>() { - public Option> f(final Integer i, final Zipper a) { - return a.move(i); - } - }); + return curry((i, a) -> a.move(i)); } /** @@ -463,11 +435,7 @@ public Option> find(final F p) { return some(this); else { final Zipper> ps = positions(); - return ps.lefts().interleave(ps.rights()).find(new F, Boolean>() { - public Boolean f(final Zipper zipper) { - return p.f(zipper.focus()); - } - }); + return ps.lefts().interleave(ps.rights()).find(zipper -> p.f(zipper.focus())); } } From 06477884918f48d35a538d86b6e0948c41abfb2c Mon Sep 17 00:00:00 2001 From: AlexeyMz Date: Mon, 29 Dec 2014 15:48:57 +0300 Subject: [PATCH 210/811] Made Seq.empty() and List.nil() return singleton instances --- core/src/main/java/fj/data/List.java | 6 ++++-- core/src/main/java/fj/data/Seq.java | 14 ++++++++++---- .../main/java/fj/data/fingertrees/MakeTree.java | 4 +++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 58f3b071..5ca6d156 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -2,7 +2,6 @@ import static fj.Bottom.error; import fj.F2Functions; -import fj.Effect; import fj.Equal; import fj.F; import fj.F2; @@ -1423,6 +1422,8 @@ public int size() { } private static final class Nil extends List { + public static final Nil INSTANCE = new Nil(); + public A head() { throw error("head on empty list"); } @@ -1469,8 +1470,9 @@ public static List list(final A... as) { * * @return An empty list. */ + @SuppressWarnings("unchecked") public static List nil() { - return new Nil(); + return (Nil) Nil.INSTANCE; } /** diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index ec48086b..8cc595fb 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -2,7 +2,6 @@ import fj.F; import fj.F2; -import fj.F2Functions; import fj.Function; import static fj.Bottom.error; import static fj.Monoid.intAdditionMonoid; @@ -17,8 +16,13 @@ * the head and tail, as well as O(log n) random access and concatenation of sequences. */ public final class Seq { + private static final Measured ELEM_MEASURED = measured(intAdditionMonoid, Function.constant(1)); + private static final MakeTree MK_TREE = FingerTree.mkTree(ELEM_MEASURED); + private static final Seq EMPTY = new Seq(MK_TREE.empty()); + + @SuppressWarnings("unchecked") private static MakeTree mkTree() { - return FingerTree.mkTree(Seq.elemMeasured()); + return (MakeTree) MK_TREE; } private final FingerTree ftree; @@ -27,8 +31,9 @@ private Seq(final FingerTree ftree) { this.ftree = ftree; } + @SuppressWarnings("unchecked") private static Measured elemMeasured() { - return measured(intAdditionMonoid, Function.constant(1)); + return (Measured) ELEM_MEASURED; } /** @@ -36,8 +41,9 @@ private static Measured elemMeasured() { * * @return A sequence with no elements. */ + @SuppressWarnings("unchecked") public static Seq empty() { - return new Seq(Seq.mkTree().empty()); + return (Seq) EMPTY; } /** diff --git a/core/src/main/java/fj/data/fingertrees/MakeTree.java b/core/src/main/java/fj/data/fingertrees/MakeTree.java index 84ed7655..b435d955 100644 --- a/core/src/main/java/fj/data/fingertrees/MakeTree.java +++ b/core/src/main/java/fj/data/fingertrees/MakeTree.java @@ -10,9 +10,11 @@ */ public final class MakeTree { private final Measured m; + private final Empty empty; MakeTree(final Measured m) { this.m = m; + this.empty = new Empty(m); } // Tree constructors @@ -23,7 +25,7 @@ public final class MakeTree { * @return The empty tree. */ public FingerTree empty() { - return new Empty(m); + return empty; } /** From 05ec1cd7b35fc209881889b43e7dc157bf1c033d Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Sat, 3 Jan 2015 22:07:45 -0800 Subject: [PATCH 211/811] Add toInt and fromInt to fj.Ordering. --- core/src/main/java/fj/Ordering.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Ordering.java b/core/src/main/java/fj/Ordering.java index 1b510678..3e938181 100644 --- a/core/src/main/java/fj/Ordering.java +++ b/core/src/main/java/fj/Ordering.java @@ -20,5 +20,10 @@ public enum Ordering { /** * Greater than. */ - GT + GT; + + public int toInt() { return ordinal() - 1 ; } + public static Ordering fromInt(int cmp) { + return cmp == 0 ? EQ : cmp > 0 ? GT : LT; + } } From f7334d32fb4ad1b7662920cb8a503a417026fc9e Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Sat, 3 Jan 2015 22:09:59 -0800 Subject: [PATCH 212/811] Use Ordering.fromInt() instead of a ternary operator in Ord.comparableOrd(). --- core/src/main/java/fj/Ord.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 8ecccfd0..8300989c 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -630,8 +630,7 @@ public static > Ord comparableOrd() { public F f(final A a1) { return new F() { public Ordering f(final A a2) { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + return Ordering.fromInt(a1.compareTo(a2)); } }; } From 3bff9bb5f95683ecd9a91057eaf7ece2fc169546 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Sat, 3 Jan 2015 22:15:16 -0800 Subject: [PATCH 213/811] Add MANIFEST.MF so this project can be used as an eclipse plugin. --- META-INF/MANIFEST.MF | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 META-INF/MANIFEST.MF diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 00000000..24770b25 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,21 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Functional Java +Bundle-SymbolicName: org.functionaljava +Bundle-Version: 4.3.0.qualifier +Export-Package: fj, + fj.control, + fj.control.db, + fj.control.parallel, + fj.data, + fj.data.fingertrees, + fj.data.hlist, + fj.data.vector, + fj.demo, + fj.demo.concurrent, + fj.demo.euler, + fj.demo.test, + fj.function, + fj.parser +Bundle-ActivationPolicy: lazy +Bundle-Vendor: functionaljava.org From 7acc2227897dd1e13f3004868a0086b1232c2659 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Wed, 7 Jan 2015 14:40:51 +0530 Subject: [PATCH 214/811] Removing traverse tests --- core/src/main/java/fj/data/List.java | 6 +- core/src/test/java/fj/data/OptionTests.java | 63 --------------------- 2 files changed, 4 insertions(+), 65 deletions(-) delete mode 100644 core/src/test/java/fj/data/OptionTests.java diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 6c2d8911..1253e406 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1036,7 +1036,9 @@ public final List minus(final Equal eq, final List xs) { return removeAll(compose(Monoid.disjunctionMonoid.sumLeft(), xs.mapM(curry(eq.eq())))); } - /** + + + /** * Maps the given function of arity-2 across this list and returns a function that applies all the resulting * functions to a given argument. * @@ -1188,7 +1190,7 @@ public final TreeMap> groupBy( final F keyFunction, final F valueFunction, final Ord keyOrd) { - return this.groupBy(keyFunction, valueFunction, List.nil(), List::cons, keyOrd); + return this.>groupBy(keyFunction, valueFunction, List.nil(), List::cons, keyOrd); } /** diff --git a/core/src/test/java/fj/data/OptionTests.java b/core/src/test/java/fj/data/OptionTests.java deleted file mode 100644 index f69806d6..00000000 --- a/core/src/test/java/fj/data/OptionTests.java +++ /dev/null @@ -1,63 +0,0 @@ -package fj.data; - -import fj.F; -import org.junit.Assert; -import org.junit.Test; - -import static fj.data.List.list; -import static fj.data.Option.none; -import static fj.data.Option.some; - -/** - * Created by amar on 28/12/14. - */ -public class OptionTests { - - @Test - public void ShouldTraverseListWithGivenFunction(){ - List strings = list("some1", "some2", "some3", "not_some", " "); - F> f = s -> { - if(s.startsWith("some")) - return some(s); - else - return Option.none(); - }; - - Option> optStr = Option.traverse(strings, f); - Assert.assertEquals("optStr should be none", Option.none(), optStr); - } - - @Test - public void ShouldTraverseListWithGivenFunction2(){ - List strings = list("some1", "some2", "some3"); - F> f = s -> { - if(s.startsWith("some")) - return some(s); - else - return Option.none(); - }; - - Option> optStr = Option.traverse(strings, f); - Assert.assertEquals("optStr should be some", optStr.isSome(), true); - Assert.assertArrayEquals(optStr.some().toArray().array(), new String[]{"some1", "some2", "some3"}); - } - - @Test - public void ShouldSequenceListOfOptionalContexts(){ - List> strings = list(some("some1"), some("some2"), some("some3")); - - - Option> optStr = Option.sequence(strings); - Assert.assertEquals("should be some", optStr.isSome(), true); - Assert.assertArrayEquals(optStr.some().toArray().array(), new String[]{"some1", "some2", "some3"}); - } - - @Test - public void ShouldSequenceListOfOptionalContexts2(){ - List> strings = list(some("some1"), some("some2"), none()); - - - Option> optStr = Option.sequence(strings); - Assert.assertEquals("should be some", optStr.isNone(), true); - } -} From 1c257a3a7e5259ed75905bac45129de6f97e13a5 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sat, 10 Jan 2015 14:10:02 +0530 Subject: [PATCH 215/811] using static methods to gain inference --- core/src/main/java/fj/Bottom.java | 4 +- core/src/main/java/fj/Effect.java | 9 +- core/src/main/java/fj/Equal.java | 34 ++-- core/src/main/java/fj/F1Functions.java | 6 +- core/src/main/java/fj/Hash.java | 124 +++++++------- core/src/main/java/fj/Ord.java | 158 +++++++++--------- core/src/main/java/fj/Show.java | 42 ++--- core/src/main/java/fj/control/Trampoline.java | 41 ++--- .../java/fj/control/parallel/Strategy.java | 13 +- core/src/main/java/fj/data/Java.java | 70 +++----- core/src/main/java/fj/parser/Parser.java | 21 +-- core/src/main/java/fj/test/Shrink.java | 83 ++++----- 12 files changed, 260 insertions(+), 345 deletions(-) diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index d773bfe2..28de5b7d 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -52,9 +52,7 @@ public static P1 error_(final String s) { * @return A function that throws an error using the given message, ignoring its argument. */ public static F errorF(final String s) { - return a -> { - throw new Error(s); - }; + return a -> {throw new Error(s);}; } /** diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 3e9cbc93..884e7399 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -93,15 +93,12 @@ public static F5 f(Effect5 z * @return An effect after a contra-variant map. */ public final Effect1 comap(Effect1 e1, final F f) { - return b -> { - e1.f(f.f(b)); - }; + return b -> e1.f(f.f(b)); } public static Effect1 lazy(final F f) { - return a -> { - f.f(a); - }; + return a -> f.f(a); + } // public static void f(Effect1 ) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 8ca04ef9..3cfa4b1e 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -85,7 +85,7 @@ public static Equal equal(final F> f) { * equality. */ public static Equal anyEqual() { - return new Equal(a1 -> a2 -> a1.equals(a2)); + return equal(a1 -> a2 -> a1.equals(a2)); } /** @@ -147,7 +147,7 @@ public static Equal anyEqual() { * An equal instance for the {@link StringBuffer} type. */ public static final Equal stringBufferEqual = - new Equal(sb1 -> sb2 -> { + Equal.equal(sb1 -> sb2 -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -161,7 +161,7 @@ public static Equal anyEqual() { * An equal instance for the {@link StringBuilder} type. */ public static final Equal stringBuilderEqual = - new Equal(sb1 -> sb2 -> { + Equal.equal(sb1 -> sb2 -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -179,7 +179,7 @@ public static Equal anyEqual() { * @return An equal instance for the {@link Either} type. */ public static Equal> eitherEqual(final Equal ea, final Equal eb) { - return new Equal>(e1 -> e2 -> e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || + return Equal.equal(e1 -> e2 -> e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value())); } @@ -201,7 +201,7 @@ public static Equal> validationEqual(final Equal ea, * @return An equal instance for the {@link List} type. */ public static Equal> listEqual(final Equal ea) { - return new Equal>(a1 -> a2 -> { + return Equal.equal(a1 -> a2 -> { List x1 = a1; List x2 = a2; @@ -234,7 +234,7 @@ public static Equal> nonEmptyListEqual(final Equal ea) { * @return An equal instance for the {@link Option} type. */ public static Equal> optionEqual(final Equal ea) { - return new Equal>(o1 -> o2 -> o1.isNone() && o2.isNone() || + return Equal.equal(o1 -> o2 -> o1.isNone() && o2.isNone() || o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some())); } @@ -245,7 +245,7 @@ public static Equal> optionEqual(final Equal ea) { * @return An equal instance for the {@link Stream} type. */ public static Equal> streamEqual(final Equal ea) { - return new Equal>(a1 -> a2 -> { + return Equal.equal(a1 -> a2 -> { Stream x1 = a1; Stream x2 = a2; @@ -268,7 +268,7 @@ public static Equal> streamEqual(final Equal ea) { * @return An equal instance for the {@link Array} type. */ public static Equal> arrayEqual(final Equal ea) { - return new Equal>(a1 -> a2 -> { + return Equal.equal(a1 -> a2 -> { if (a1.length() == a2.length()) { for (int i = 0; i < a1.length(); i++) { if (!ea.eq(a1.get(i), a2.get(i))) @@ -287,7 +287,7 @@ public static Equal> arrayEqual(final Equal ea) { * @return An equal instance for the {@link Tree} type. */ public static Equal> treeEqual(final Equal ea) { - return new Equal>(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); + return Equal.>equal(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); } /** @@ -297,7 +297,7 @@ public static Equal> treeEqual(final Equal ea) { * @return An equal instance for a product-1. */ public static Equal> p1Equal(final Equal ea) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1())); + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1())); } /** @@ -308,7 +308,7 @@ public static Equal> p1Equal(final Equal ea) { * @return An equal instance for a product-2. */ public static Equal> p2Equal(final Equal ea, final Equal eb) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2())); + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2())); } /** @@ -320,7 +320,7 @@ public static Equal> p2Equal(final Equal ea, final Equal e * @return An equal instance for a product-3. */ public static Equal> p3Equal(final Equal ea, final Equal eb, final Equal ec) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3())); + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3())); } /** @@ -334,7 +334,7 @@ public static Equal> p3Equal(final Equal ea, final Equa */ public static Equal> p4Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4())); } @@ -351,7 +351,7 @@ public static Equal> p4Equal(final Equal ea, fina public static Equal> p5Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5())); } @@ -369,7 +369,7 @@ public static Equal> p5Equal(final Equal ea public static Equal> p6Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee, final Equal ef) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6())); } @@ -389,7 +389,7 @@ public static Equal> p5Equal(final Equal ea final Equal ec, final Equal ed, final Equal ee, final Equal ef, final Equal eg) { - return new Equal>(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && eg.eq(p1._7(), p2._7())); } @@ -415,7 +415,7 @@ public static Equal> p5Equal(final Equal ea final Equal ef, final Equal eg, final Equal eh) { - return new Equal>( + return Equal.equal( p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8())); diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 0f57cd3e..dc3b4378 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -128,11 +128,7 @@ static public F>, F>> on(final F f) { * @return This function promoted to return its result in a product-1. */ static public F> lazy(final F f) { - return a -> new P1(){ - public B _1() { - return f.f(a); - } - }; + return a -> P.lazy(u -> f.f(a)); } /** diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 9a616023..a391a693 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -47,7 +47,7 @@ public int hash(final A a) { * @return A new hash. */ public Hash comap(final F g) { - return new Hash(compose(f, g)); + return hash(compose(f, g)); } /** @@ -57,7 +57,7 @@ public Hash comap(final F g) { * @return A hash that uses the given function. */ public static Hash hash(final F f) { - return new Hash(f); + return new Hash<>(f); } /** @@ -66,7 +66,7 @@ public static Hash hash(final F f) { * @return A hash that uses {@link Object#hashCode()}. */ public static Hash anyHash() { - return new Hash(a -> a.hashCode()); + return hash(a -> a.hashCode()); } /** @@ -117,31 +117,27 @@ public static Hash anyHash() { /** * A hash instance for the {@link StringBuffer} type. */ - public static final Hash stringBufferHash = new Hash(new F() { - public Integer f(final StringBuffer sb) { + public static final Hash stringBufferHash = hash(sb -> { final int p = 419; int r = 239; for (int i = 0; i < sb.length(); i++) - r = p * r + sb.charAt(i); + r = p * r + sb.charAt(i); return r; - } }); /** * A hash instance for the {@link StringBuilder} type. */ - public static final Hash stringBuilderHash = new Hash(new F() { - public Integer f(final StringBuilder sb) { + public static final Hash stringBuilderHash = hash(sb -> { final int p = 419; int r = 239; for (int i = 0; i < sb.length(); i++) - r = p * r + sb.charAt(i); + r = p * r + sb.charAt(i); return r; - } }); /** @@ -152,7 +148,7 @@ public Integer f(final StringBuilder sb) { * @return A hash instance for the {@link Either} type. */ public static Hash> eitherHash(final Hash ha, final Hash hb) { - return new Hash>(e -> e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value())); + return hash(e -> e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value())); } /** @@ -173,17 +169,17 @@ public static Hash> validationHash(final Hash ha, fin * @return A hash instance for the {@link List} type. */ public static Hash> listHash(final Hash ha) { - return new Hash>(as -> { - final int p = 419; - int r = 239; - List aas = as; + return hash(as -> { + final int p = 419; + int r = 239; + List aas = as; - while (!aas.isEmpty()) { - r = p * r + ha.hash(aas.head()); - aas = aas.tail(); - } + while (!aas.isEmpty()) { + r = p * r + ha.hash(aas.head()); + aas = aas.tail(); + } - return r; + return r; }); } @@ -204,7 +200,7 @@ public static Hash> nonEmptyListHash(final Hash ha) { * @return A hash instance for the {@link Option} type. */ public static Hash> optionHash(final Hash ha) { - return new Hash>(o -> o.isNone() ? 0 : ha.hash(o.some())); + return hash(o -> o.isNone() ? 0 : ha.hash(o.some())); } /** @@ -214,17 +210,17 @@ public static Hash> optionHash(final Hash ha) { * @return A hash instance for the {@link Stream} type. */ public static Hash> streamHash(final Hash ha) { - return new Hash>(as -> { - final int p = 419; - int r = 239; - Stream aas = as; + return hash(as -> { + final int p = 419; + int r = 239; + Stream aas = as; - while (!aas.isEmpty()) { - r = p * r + ha.hash(aas.head()); - aas = aas.tail()._1(); - } + while (!aas.isEmpty()) { + r = p * r + ha.hash(aas.head()); + aas = aas.tail()._1(); + } - return r; + return r; }); } @@ -235,15 +231,15 @@ public static Hash> streamHash(final Hash ha) { * @return A hash instance for the {@link Array} type. */ public static Hash> arrayHash(final Hash ha) { - return new Hash>(as -> { - final int p = 419; - int r = 239; + return hash(as -> { + final int p = 419; + int r = 239; - for (int i = 0; i < as.length(); i++) { - r = p * r + ha.hash(as.get(i)); - } + for (int i = 0; i < as.length(); i++) { + r = p * r + ha.hash(as.get(i)); + } - return r; + return r; }); } @@ -275,14 +271,14 @@ public static Hash> p1Hash(final Hash ha) { * @return A hash instance for a product-2. */ public static Hash> p2Hash(final Hash ha, final Hash hb) { - return new Hash>(p2 -> { - final int p = 419; - int r = 239; + return hash(p2 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p2._1()); - r = p * r + hb.hash(p2._2()); + r = p * r + ha.hash(p2._1()); + r = p * r + hb.hash(p2._2()); - return r; + return r; }); } @@ -295,15 +291,15 @@ public static Hash> p2Hash(final Hash ha, final Hash hb) { * @return A hash instance for a product-3. */ public static Hash> p3Hash(final Hash ha, final Hash hb, final Hash hc) { - return new Hash>(p3 -> { - final int p = 419; - int r = 239; + return hash(p3 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p3._1()); - r = p * r + hb.hash(p3._2()); - r = p * r + hc.hash(p3._3()); + r = p * r + ha.hash(p3._1()); + r = p * r + hb.hash(p3._2()); + r = p * r + hc.hash(p3._3()); - return r; + return r; }); } @@ -318,18 +314,16 @@ public static Hash> p3Hash(final Hash ha, final Hash */ public static Hash> p4Hash(final Hash ha, final Hash hb, final Hash hc, final Hash hd) { - return new Hash>(new F, Integer>() { - public Integer f(final P4 p4) { - final int p = 419; - int r = 239; + return hash(p4 -> { + final int p = 419; + int r = 239; - r = p * r + ha.hash(p4._1()); - r = p * r + hb.hash(p4._2()); - r = p * r + hc.hash(p4._3()); - r = p * r + hd.hash(p4._4()); + r = p * r + ha.hash(p4._1()); + r = p * r + hb.hash(p4._2()); + r = p * r + hc.hash(p4._3()); + r = p * r + hd.hash(p4._4()); - return r; - } + return r; }); } @@ -345,7 +339,7 @@ public Integer f(final P4 p4) { */ public static Hash> p5Hash(final Hash ha, final Hash hb, final Hash hc, final Hash hd, final Hash he) { - return new Hash>(p5 -> { + return hash(p5 -> { final int p = 419; int r = 239; @@ -373,7 +367,7 @@ public static Hash> p5Hash(final Hash ha, f public static Hash> p6Hash(final Hash ha, final Hash hb, final Hash hc, final Hash hd, final Hash he, final Hash hf) { - return new Hash>(p6 -> { + return hash(p6 -> { final int p = 419; int r = 239; @@ -404,7 +398,7 @@ public static Hash> p5Hash(final Hash ha, f final Hash hc, final Hash hd, final Hash he, final Hash hf, final Hash hg) { - return new Hash>(p7 -> { + return hash(p7 -> { final int p = 419; int r = 239; @@ -437,7 +431,7 @@ public static Hash> p5Hash(final Hash ha, f final Hash hc, final Hash hd, final Hash he, final Hash hf, final Hash hg, final Hash hh) { - return new Hash>(p8 -> { + return hash(p8 -> { final int p = 419; int r = 239; diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 3ea2ce4c..81ad92a8 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -169,7 +169,7 @@ public static Ord ord(final F> f) { /** * An order instance for the boolean type. */ - public static final Ord booleanOrd = new Ord( + public static final Ord booleanOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -178,7 +178,7 @@ public static Ord ord(final F> f) { /** * An order instance for the byte type. */ - public static final Ord byteOrd = new Ord( + public static final Ord byteOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -187,7 +187,7 @@ public static Ord ord(final F> f) { /** * An order instance for the char type. */ - public static final Ord charOrd = new Ord( + public static final Ord charOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -196,7 +196,7 @@ public static Ord ord(final F> f) { /** * An order instance for the double type. */ - public static final Ord doubleOrd = new Ord( + public static final Ord doubleOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -205,7 +205,7 @@ public static Ord ord(final F> f) { /** * An order instance for the float type. */ - public static final Ord floatOrd = new Ord( + public static final Ord floatOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -214,7 +214,7 @@ public static Ord ord(final F> f) { /** * An order instance for the int type. */ - public static final Ord intOrd = new Ord( + public static final Ord intOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -223,7 +223,7 @@ public static Ord ord(final F> f) { /** * An order instance for the BigInteger type. */ - public static final Ord bigintOrd = new Ord( + public static final Ord bigintOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -232,7 +232,7 @@ public static Ord ord(final F> f) { /** * An order instance for the BigDecimal type. */ - public static final Ord bigdecimalOrd = new Ord( + public static final Ord bigdecimalOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -241,7 +241,7 @@ public static Ord ord(final F> f) { /** * An order instance for the long type. */ - public static final Ord longOrd = new Ord( + public static final Ord longOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -250,7 +250,7 @@ public static Ord ord(final F> f) { /** * An order instance for the short type. */ - public static final Ord shortOrd = new Ord( + public static final Ord shortOrd = ord( a1 -> a2 -> { final int x = a1.compareTo(a2); return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; @@ -259,40 +259,36 @@ public static Ord ord(final F> f) { /** * An order instance for the {@link Ordering} type. */ - public static final Ord orderingOrd = new Ord(curry(new F2() { - public Ordering f(final Ordering o1, final Ordering o2) { - return o1 == o2 ? - Ordering.EQ : - o1 == Ordering.LT ? - Ordering.LT : - o2 == Ordering.LT ? - Ordering.GT : - o1 == Ordering.EQ ? - Ordering.LT : - Ordering.GT; - } - })); + public static final Ord orderingOrd = Ord.ord(curry((o1, o2) -> o1 == o2 ? + Ordering.EQ : + o1 == Ordering.LT ? + Ordering.LT : + o2 == Ordering.LT ? + Ordering.GT : + o1 == Ordering.EQ ? + Ordering.LT : + Ordering.GT)); /** * An order instance for the {@link String} type. */ - public static final Ord stringOrd = new Ord( + public static final Ord stringOrd = ord( a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + final int x = a1.compareTo(a2); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; }); /** * An order instance for the {@link StringBuffer} type. */ public static final Ord stringBufferOrd = - new Ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); + ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); /** * An order instance for the {@link StringBuffer} type. */ public static final Ord stringBuilderOrd = - new Ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); + ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); /** * An order instance for the {@link Option} type. @@ -301,13 +297,13 @@ public Ordering f(final Ordering o1, final Ordering o2) { * @return An order instance for the {@link Option} type. */ public static Ord> optionOrd(final Ord oa) { - return new Ord>(o1 -> o2 -> o1.isNone() ? - o2.isNone() ? - Ordering.EQ : - Ordering.LT : - o2.isNone() ? - Ordering.GT : - oa.f.f(o1.some()).f(o2.some())); + return ord(o1 -> o2 -> o1.isNone() ? + o2.isNone() ? + Ordering.EQ : + Ordering.LT : + o2.isNone() ? + Ordering.GT : + oa.f.f(o1.some()).f(o2.some())); } /** @@ -318,13 +314,13 @@ public static Ord> optionOrd(final Ord oa) { * @return An order instance for the {@link Either} type. */ public static Ord> eitherOrd(final Ord oa, final Ord ob) { - return new Ord>(e1 -> e2 -> e1.isLeft() ? - e2.isLeft() ? - oa.f.f(e1.left().value()).f(e2.left().value()) : - Ordering.LT : - e2.isLeft() ? - Ordering.GT : - ob.f.f(e1.right().value()).f(e2.right().value())); + return ord(e1 -> e2 -> e1.isLeft() ? + e2.isLeft() ? + oa.f.f(e1.left().value()).f(e2.left().value()) : + Ordering.LT : + e2.isLeft() ? + Ordering.GT : + ob.f.f(e1.right().value()).f(e2.right().value())); } /** @@ -345,15 +341,15 @@ public static Ord> validationOrd(final Ord oa, final * @return An order instance for the {@link List} type. */ public static Ord> listOrd(final Ord oa) { - return new Ord>(l1 -> l2 -> { - if (l1.isEmpty()) - return l2.isEmpty() ? Ordering.EQ : Ordering.LT; - else if (l2.isEmpty()) - return l1.isEmpty() ? Ordering.EQ : Ordering.GT; - else { - final Ordering c = oa.compare(l1.head(), l2.head()); - return c == Ordering.EQ ? listOrd(oa).f.f(l1.tail()).f(l2.tail()) : c; - } + return ord(l1 -> l2 -> { + if (l1.isEmpty()) + return l2.isEmpty() ? Ordering.EQ : Ordering.LT; + else if (l2.isEmpty()) + return l1.isEmpty() ? Ordering.EQ : Ordering.GT; + else { + final Ordering c = oa.compare(l1.head(), l2.head()); + return c == Ordering.EQ ? listOrd(oa).f.f(l1.tail()).f(l2.tail()) : c; + } }); } @@ -374,15 +370,15 @@ public static Ord> nonEmptyListOrd(final Ord oa) { * @return An order instance for the {@link Stream} type. */ public static Ord> streamOrd(final Ord oa) { - return new Ord>(s1 -> s2 -> { - if (s1.isEmpty()) - return s2.isEmpty() ? Ordering.EQ : Ordering.LT; - else if (s2.isEmpty()) - return s1.isEmpty() ? Ordering.EQ : Ordering.GT; - else { - final Ordering c = oa.compare(s1.head(), s2.head()); - return c == Ordering.EQ ? streamOrd(oa).f.f(s1.tail()._1()).f(s2.tail()._1()) : c; - } + return ord(s1 -> s2 -> { + if (s1.isEmpty()) + return s2.isEmpty() ? Ordering.EQ : Ordering.LT; + else if (s2.isEmpty()) + return s1.isEmpty() ? Ordering.EQ : Ordering.GT; + else { + final Ordering c = oa.compare(s1.head(), s2.head()); + return c == Ordering.EQ ? streamOrd(oa).f.f(s1.tail()._1()).f(s2.tail()._1()) : c; + } }); } @@ -393,21 +389,21 @@ else if (s2.isEmpty()) * @return An order instance for the {@link Array} type. */ public static Ord> arrayOrd(final Ord oa) { - return new Ord>(a1 -> a2 -> { - int i = 0; - //noinspection ForLoopWithMissingComponent - for (; i < a1.length() && i < a2.length(); i++) { - final Ordering c = oa.compare(a1.get(i), a2.get(i)); - if (c == Ordering.GT || c == Ordering.LT) - return c; - } - return i == a1.length() ? - i == a2.length() ? - Ordering.EQ : - Ordering.LT : - i == a1.length() ? - Ordering.EQ : - Ordering.GT; + return ord(a1 -> a2 -> { + int i = 0; + //noinspection ForLoopWithMissingComponent + for (; i < a1.length() && i < a2.length(); i++) { + final Ordering c = oa.compare(a1.get(i), a2.get(i)); + if (c == Ordering.GT || c == Ordering.LT) + return c; + } + return i == a1.length() ? + i == a2.length() ? + Ordering.EQ : + Ordering.LT : + i == a1.length() ? + Ordering.EQ : + Ordering.GT; }); } @@ -487,9 +483,9 @@ public static > Ord comparableOrd() { * @see #hashEqualsOrd() */ public static Ord hashOrd() { - return Ord. ord(a -> a2 -> { - final int x = a.hashCode() - a2.hashCode(); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + return ord(a -> a2 -> { + final int x = a.hashCode() - a2.hashCode(); + return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; }); } @@ -501,9 +497,9 @@ public static Ord hashOrd() { * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. */ public static Ord hashEqualsOrd() { - return Ord. ord(a -> a2 -> { - final int x = a.hashCode() - a2.hashCode(); - return x < 0 ? Ordering.LT : x == 0 && a.equals(a2) ? Ordering.EQ : Ordering.GT; + return ord(a -> a2 -> { + final int x = a.hashCode() - a2.hashCode(); + return x < 0 ? Ordering.LT : x == 0 && a.equals(a2) ? Ordering.EQ : Ordering.GT; }); } diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 28f309d1..2a30817e 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -150,7 +150,7 @@ public void printlnE(final A a) { * @return A show instance. */ public static Show show(final F> f) { - return new Show(f); + return new Show<>(f); } /** @@ -160,7 +160,7 @@ public static Show show(final F> f) { * @return A show instance. */ public static Show showS(final F f) { - return new Show(a -> fromString(f.f(a))); + return show(a -> fromString(f.f(a))); } /** @@ -169,7 +169,7 @@ public static Show showS(final F f) { * @return A show instance that uses {@link Object#toString()} to perform the display rendering. */ public static Show anyShow() { - return new Show(a -> Stream.fromString((a == null) ? "null" : a.toString())); + return show(a -> Stream.fromString((a == null) ? "null" : a.toString())); } /** @@ -244,7 +244,7 @@ public static Show anyShow() { * @return A show instance for the {@link Option} type. */ public static Show> optionShow(final Show sa) { - return new Show>(o -> o.isNone() ? + return show(o -> o.isNone() ? fromString("None") : fromString("Some(").append(sa.f.f(o.some())).append(single(')'))); } @@ -257,7 +257,7 @@ public static Show> optionShow(final Show sa) { * @return A show instance for the {@link Either} type. */ public static Show> eitherShow(final Show sa, final Show sb) { - return new Show>(e -> e.isLeft() ? + return show(e -> e.isLeft() ? fromString("Left(").append(sa.f.f(e.left().value())).append(single(')')) : fromString("Right(").append(sb.f.f(e.right().value())).append(single(')'))); } @@ -270,7 +270,7 @@ public static Show> eitherShow(final Show sa, final Show< * @return A show instance for the {@link Validation} type. */ public static Show> validationShow(final Show sa, final Show sb) { - return new Show>(v -> v.isFail() ? + return show(v -> v.isFail() ? fromString("Fail(").append(sa.f.f(v.fail())).append(single(')')) : fromString("Success(").append(sb.f.f(v.success())).append(single(')'))); } @@ -282,7 +282,7 @@ public static Show> validationShow(final Show sa, fin * @return A show instance for the {@link Stream} type. */ public static Show> listShow(final Show sa) { - return new Show>(as -> streamShow(sa).show(as.toStream())); + return show(as -> streamShow(sa).show(as.toStream())); } /** @@ -302,9 +302,9 @@ public static Show> nonEmptyListShow(final Show sa) { * @return A show instance for the {@link Tree} type. */ public static Show> treeShow(final Show sa) { - return new Show>(a -> { + return show(a -> { final Stream b = sa.f.f(a.root()) - .append(p1Show(streamShow(treeShow(sa))).f.f(a.subForest())) + .append(p1Show(streamShow(Show.treeShow(sa))).f.f(a.subForest())) .snoc(')'); return cons('(', p(b)); }); @@ -317,7 +317,7 @@ public static Show> treeShow(final Show sa) { * @return A show instance for the {@link Stream} type. */ public static Show> streamShow(final Show sa) { - return new Show>(as -> join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">"))))); + return show(as -> join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">"))))); } /** @@ -327,7 +327,7 @@ public static Show> streamShow(final Show sa) { * @return A show instance for the {@link Array} type. */ public static Show> arrayShow(final Show sa) { - return new Show>(as -> { + return show(as -> { Stream b = nil(); for (int i = 0; i < as.length(); i++) { @@ -349,7 +349,7 @@ public static Show> arrayShow(final Show sa) { * @return A show instance for the {@link Class} type. */ public static Show> classShow() { - return new Show>(c -> anyShow().show(c.clas())); + return show(c -> anyShow().show(c.clas())); } /** @@ -359,7 +359,7 @@ public static Show> classShow() { * @return A show instance for the {@link P1 tuple-1} type. */ public static Show> p1Show(final Show sa) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(')')); + return show(p -> cons('(', p(sa.show(p._1()))).snoc(')')); } /** @@ -370,7 +370,7 @@ public static Show> p1Show(final Show sa) { * @return A show instance for the {@link P2 tuple-2} type. */ public static Show> p2Show(final Show sa, final Show sb) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')')); + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')')); } /** @@ -382,7 +382,7 @@ public static Show> p2Show(final Show sa, final Show sb) { * @return A show instance for the {@link P3 tuple-3} type. */ public static Show> p3Show(final Show sa, final Show sb, final Show sc) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') .append(sc.show(p._3())).snoc(')')); } @@ -397,7 +397,7 @@ public static Show> p3Show(final Show sa, final Show */ public static Show> p4Show(final Show sa, final Show sb, final Show sc, final Show sd) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(')')); } @@ -413,7 +413,7 @@ public static Show> p4Show(final Show sa, final S */ public static Show> p5Show(final Show sa, final Show sb, final Show sc, final Show sd, final Show se) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',').append(se.show(p._5())).snoc(')')); } @@ -431,7 +431,7 @@ public static Show> p5Show(final Show sa, f public static Show> p6Show(final Show sa, final Show sb, final Show sc, final Show sd, final Show se, final Show sf) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(')')); } @@ -452,7 +452,7 @@ public static Show> p5Show(final Show sa, f final Show sc, final Show sd, final Show se, final Show sf, final Show sg) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',').append(sg.show(p._7())).snoc(')')); } @@ -474,7 +474,7 @@ public static Show> p5Show(final Show sa, f final Show sc, final Show sd, final Show se, final Show sf, final Show sg, final Show sh) { - return new Show>(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') + return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(',') .append(sc.show(p._3())).snoc(',').append(sd.show(p._4())).snoc(',') .append(se.show(p._5())).snoc(',').append(sf.show(p._6())).snoc(',') .append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')')); @@ -562,7 +562,7 @@ public static Show> v8Show(final Show ea) { * @return A show instance for streams that splits into lines. */ public static Show> unlineShow(final Show sa) { - return new Show>(as -> join(as.map(sa.show_()).intersperse(fromString("\n")))); + return show(as -> join(as.map(sa.show_()).intersperse(fromString("\n")))); } /** diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index fad6be90..30c3a429 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -1,12 +1,8 @@ package fj.control; -import fj.Bottom; -import fj.F; -import fj.F1Functions; -import fj.F2; -import fj.P1; +import fj.*; import fj.data.Either; -import fj.F2Functions; + import static fj.Function.curry; import static fj.data.Either.left; import static fj.data.Either.right; @@ -50,24 +46,19 @@ public R fold(final F, R> n, // The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the // continuations. public Trampoline bind(final F> f) { - return codense(sub, o -> suspend(new P1>() { - public Trampoline _1() { - return cont.f(o).bind(f); - } - })); + return codense(sub, o -> suspend(P.lazy(u -> cont.f(o).bind(f)))); } // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result // gets shifted into the continuation. public Either>, A> resume() { - return left(sub.resume().either(p -> p.map(ot -> ot.fold(o1 -> o1.foldNormal(o2 -> cont.f(o2), t -> t._1().bind(cont) - ), c -> codense(c.sub, o -> c.cont.f(o).bind(cont)) - )), o3 -> new P1>() { - public Trampoline _1() { - return cont.f(o3); - } - } - )); + return left( + sub.resume().either( + p -> p.map(ot -> ot.fold(o1 -> o1.foldNormal(o2 -> cont.f(o2), t -> t._1().bind(cont)), + c -> codense(c.sub, o -> c.cont.f(o).bind(cont)))), + o3 -> P.lazy(u -> cont.f(o3)) + ) + ); } } @@ -265,11 +256,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(new P1>() { - public Trampoline _1() { - return ta.zipWith(tb, f); - } - })))); + return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.>lazy(u -> ta.zipWith(tb, f)))))); } for (final B y : eb.right()) { return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); @@ -277,11 +264,7 @@ public Trampoline _1() { } for (final A x : ea.right()) { for (final B y : eb.right()) { - return suspend(new P1>() { - public Trampoline _1() { - return pure(f.f(x, y)); - } - }); + return suspend(P.lazy(u -> pure(f.f(x, y)))); } for (final P1> y : eb.left()) { return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index 1002ae03..3582545d 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -322,8 +322,7 @@ public static F, P1> obtain() { * @return A product-1 that waits for the given future to obtain a value. */ public static P1 obtain(final Future t) { - return new P1() { - public A _1() { + return P.lazy(u -> { try { return t.get(); } catch (InterruptedException e) { @@ -332,8 +331,7 @@ public A _1() { } catch (ExecutionException e) { throw new Error(e); } - } - }; + }); } /** @@ -455,8 +453,7 @@ public Strategy errorStrategy(final Effect1 e) { * @return A strategy that captures any runtime errors with a side-effect. */ public static Strategy errorStrategy(final Strategy s, final Effect1 e) { - return s.comap(a -> new P1() { - public A _1() { + return s.comap(a -> P.lazy(u -> { try { return a._1(); } catch (Throwable t) { @@ -464,8 +461,8 @@ public A _1() { e.f(error); throw error; } - } - }); + }) + ); } /** diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 2e5650c7..45da97b1 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1,11 +1,9 @@ package fj.data; -import fj.F; +import fj.*; + import static fj.P.p; -import fj.Function; -import fj.P1; -import fj.P2; import fj.function.Effect1; import static fj.data.List.list; @@ -413,29 +411,25 @@ public static F, SynchronousQueue> Array_SynchronousQueue(final * @return A function that converts streams to iterable. */ public static F, Iterable> Stream_Iterable() { - return as -> new Iterable() { - public Iterator iterator() { - return new Iterator() { - private Stream x = as; - - public boolean hasNext() { - return x.isNotEmpty(); - } - - public A next() { - if (x.isEmpty()) - throw new NoSuchElementException("Empty iterator"); - else { - final A a = x.head(); - x = x.tail()._1(); - return a; - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; + return as -> () -> new Iterator() { + private Stream x = as; + + public boolean hasNext() { + return x.isNotEmpty(); + } + + public A next() { + if (x.isEmpty()) + throw new NoSuchElementException("Empty iterator"); + else { + final A a = x.head(); + x = x.tail()._1(); + return a; + } + } + + public void remove() { + throw new UnsupportedOperationException(); } }; } @@ -1442,12 +1436,7 @@ public static F> StringBuilder_Synchr * @return A function that converts array lists to lists. */ public static F, List> ArrayList_List() { - return new F, List>() { - @SuppressWarnings({"unchecked"}) - public List f(final ArrayList as) { - return Collection_List(as); - } - }; + return as -> Collection_List(as); } // todo @@ -1492,7 +1481,7 @@ public static List Collection_List(Collection c) { } public static F, List> Collection_List() { - return c -> list(c.toArray(array(c.size()))); + return c -> List.list(c.toArray(array(c.size()))); } @SafeVarargs @@ -1732,11 +1721,7 @@ public static F, List> SynchronousQueue_List() { // BEGIN Callable -> public static F, Callable> P1_Callable() { - return a -> new Callable() { - public A call() { - return a._1(); - } - }; + return a -> () -> a._1(); } // END Callable -> @@ -1744,9 +1729,7 @@ public A call() { // BEGIN Future -> public static F, P1>> Future_P1() { - return a -> new P1>() { - @SuppressWarnings({"OverlyBroadCatchBlock"}) - public Either _1() { + return a -> P.lazy(u -> { Either r; try { r = Either.right(a.get()); @@ -1755,8 +1738,7 @@ public Either _1() { r = Either.left(e); } return r; - } - }; + }); } // END Future -> diff --git a/core/src/main/java/fj/parser/Parser.java b/core/src/main/java/fj/parser/Parser.java index 6c89a071..b974b73b 100644 --- a/core/src/main/java/fj/parser/Parser.java +++ b/core/src/main/java/fj/parser/Parser.java @@ -1,11 +1,8 @@ package fj.parser; -import fj.F; +import fj.*; + import static fj.P.p; -import fj.P1; -import fj.Semigroup; -import fj.Unit; -import fj.Digit; import static fj.Unit.unit; import fj.data.List; import static fj.data.List.cons_; @@ -288,11 +285,7 @@ public Parser not(final E e) { * @return A parser that repeats application of this parser zero or many times. */ public Parser, E> repeat() { - return repeat1().or(new P1, E>>() { - public Parser, E> _1() { - return value(Stream.nil()); - } - }); + return repeat1().or(P.lazy(u -> value(Stream.nil()))); } /** @@ -301,11 +294,7 @@ public Parser, E> _1() { * @return A parser that repeats application of this parser one or many times. */ public Parser, E> repeat1() { - return bind(a -> repeat().map(new F, Stream>() { - public Stream f(final Stream as) { - return as.cons(a); - } - })); + return bind(a -> repeat().map(as -> as.cons(a))); } /** @@ -325,7 +314,7 @@ public Parser mapError(final F f) { * @return A parser that computes using the given function. */ public static Parser parser(final F>> f) { - return new Parser(f); + return new Parser<>(f); } /** diff --git a/core/src/main/java/fj/test/Shrink.java b/core/src/main/java/fj/test/Shrink.java index 41810843..c51da04e 100644 --- a/core/src/main/java/fj/test/Shrink.java +++ b/core/src/main/java/fj/test/Shrink.java @@ -1,6 +1,7 @@ package fj.test; -import fj.F; +import fj.*; + import static fj.P.p; import static fj.P.p2; import static fj.P.p3; @@ -10,15 +11,6 @@ import static fj.P.p7; import static fj.P.p8; -import fj.Function; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.P4; -import fj.P5; -import fj.P6; -import fj.P7; -import fj.P8; import static fj.Primitive.Byte_Long; import static fj.Primitive.Character_Long; import static fj.Primitive.Double_Long; @@ -114,7 +106,7 @@ public Stream shrink(final A a) { * @return A shrink from this shrink and the given symmetric transformations. */ public Shrink map(final F f, final F g) { - return new Shrink(b -> Shrink.this.f.f(g.f(b)).map(f)); + return shrink(b -> Shrink.this.f.f(g.f(b)).map(f)); } @@ -136,27 +128,19 @@ public static Shrink shrink(final F> f) { * @return A shrink strategy that cannot be reduced further. */ public static Shrink empty() { - return new Shrink(a -> nil()); + return shrink(a -> nil()); } /** * A shrink strategy for longs using 0 as the bottom of the shrink. */ - public static final Shrink shrinkLong = new Shrink(i -> { + public static final Shrink shrinkLong = shrink(i -> { if (i == 0L) return nil(); else { - final Stream is = cons(0L, new P1>() { - public Stream _1() { - return iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1); - } - }); + final Stream is = cons(0L, P.lazy(u -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1))); - return i < 0L ? cons(-i, new P1>() { - public Stream _1() { - return is; - } - }) : is; + return i < 0L ? cons(-i, P.lazy(u -> is)) : is; } }); @@ -204,7 +188,7 @@ public Stream _1() { * @return A shrink strategy for optional values. */ public static Shrink> shrinkOption(final Shrink sa) { - return new Shrink>(o -> o.isNone() ? + return shrink(o -> o.isNone() ? Stream.>nil() : cons(Option.none(), new P1>>() { public Stream> _1() { @@ -221,13 +205,9 @@ public Stream> _1() { * @return A shrink strategy for either values. */ public static Shrink> shrinkEither(final Shrink sa, final Shrink sb) { - return new Shrink>(new F, Stream>>() { - public Stream> f(final Either e) { - return e.isLeft() ? - sa.shrink(e.left().value()).map(Either.left_()) : - sb.shrink(e.right().value()).map(Either.right_()); - } - }); + return shrink(e -> e.isLeft() ? + sa.shrink(e.left().value()).map(Either.left_()) : + sb.shrink(e.right().value()).map(Either.right_())); } /** @@ -249,16 +229,19 @@ else if (as.tail().isEmpty()) final List as1 = as.take(n1); final F, Boolean> isNotEmpty = isNotEmpty_(); - return cons(as1, new P1>>() { - public Stream> _1() { - final List as2 = as.drop(n1); - return cons(as2, new P1>>() { - public Stream> _1() { - return removeChunks(n1, as1).filter(isNotEmpty).map(aas1 -> aas1.append(as2)).interleave(removeChunks(n2, as2).filter(isNotEmpty).map(aas -> as1.append(aas))); - } - }); - } - }); + return cons( + as1, + P.lazy(u -> + { + final List as2 = as.drop(n1); + return cons(as2, P.lazy(u1 -> removeChunks(n1, as1) + .filter(isNotEmpty) + .map(aas1 -> aas1.append(as2)) + .interleave(removeChunks(n2, as2) + .filter(isNotEmpty) + .map(aas -> as1.append(aas))))); + }) + ); } } @@ -271,7 +254,7 @@ Stream> shrinkOne(final List as) { } } - return new Shrink>(as -> { + return shrink(as -> { final Util u = new Util(); return u.removeChunks(as.length(), as).append(u.shrinkOne(as)); }); @@ -723,7 +706,7 @@ public static Shrink> shrinkSynchronousQueue(final Shrin * @return a shrinking strategy for product-1 values. */ public static Shrink> shrinkP1(final Shrink sa) { - return new Shrink>(p -> sa.shrink(p._1()).map(a -> p(a))); + return shrink(p -> sa.shrink(p._1()).map(a -> p(a))); } /** @@ -734,7 +717,7 @@ public static Shrink> shrinkP1(final Shrink sa) { * @return a shrinking strategy for product-2 values. */ public static Shrink> shrinkP2(final Shrink sa, final Shrink sb) { - return new Shrink>(p -> { + return shrink(p -> { final F>> p2 = p2(); return sa.shrink(p._1()).bind(sb.shrink(p._2()), p2); }); @@ -749,7 +732,7 @@ public static Shrink> shrinkP2(final Shrink sa, final Shrink< * @return a shrinking strategy for product-3 values. */ public static Shrink> shrinkP3(final Shrink sa, final Shrink sb, final Shrink sc) { - return new Shrink>(p -> { + return shrink(p -> { final F>>> p3 = p3(); return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), p3); }); @@ -766,7 +749,7 @@ public static Shrink> shrinkP3(final Shrink sa, final S */ public static Shrink> shrinkP4(final Shrink sa, final Shrink sb, final Shrink sc, final Shrink sd) { - return new Shrink>(p -> { + return shrink(p -> { final F>>>> p4 = p4(); return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), p4); }); @@ -785,7 +768,7 @@ public static Shrink> shrinkP4(final Shrink sa, f public static Shrink> shrinkP5(final Shrink sa, final Shrink sb, final Shrink sc, final Shrink sd, final Shrink se) { - return new Shrink>(p -> { + return shrink(p -> { final F>>>>> p5 = p5(); return sa.shrink(p._1()).bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), p5); }); @@ -805,7 +788,7 @@ public static Shrink> shrinkP5(final Shrink public static Shrink> shrinkP6(final Shrink sa, final Shrink sb, final Shrink sc, final Shrink sd, final Shrink se, final Shrink sf) { - return new Shrink>(p -> { + return shrink(p -> { final F>>>>>> p6 = p6(); return sa.shrink(p._1()) .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), p6); @@ -829,7 +812,7 @@ public static Shrink> shrinkP5(final Shrink final Shrink se, final Shrink sf, final Shrink sg) { - return new Shrink>(p -> { + return shrink(p -> { final F>>>>>>> p7 = p7(); return sa.shrink(p._1()) .bind(sb.shrink(p._2()), sc.shrink(p._3()), sd.shrink(p._4()), se.shrink(p._5()), sf.shrink(p._6()), @@ -858,7 +841,7 @@ public static Shrink> shrinkP5(final Shrink final Shrink sf, final Shrink sg, final Shrink sh) { - return new Shrink>( + return shrink( p -> { final F>>>>>>>> p8 = p8(); return sa.shrink(p._1()) From 216ccd96168ccb676fcb00ee42fe4652bdf0f310 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sat, 10 Jan 2015 14:22:45 +0530 Subject: [PATCH 216/811] removing ipr file. --- core/src/main/java/fj/Bottom.java | 4 +- functionaljava.ipr | 190 ------------------------------ 2 files changed, 3 insertions(+), 191 deletions(-) delete mode 100644 functionaljava.ipr diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index 28de5b7d..6c6588fd 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -52,7 +52,9 @@ public static P1 error_(final String s) { * @return A function that throws an error using the given message, ignoring its argument. */ public static F errorF(final String s) { - return a -> {throw new Error(s);}; + return a -> { + throw new Error(s); + }; } /** diff --git a/functionaljava.ipr b/functionaljava.ipr deleted file mode 100644 index 9e637fb5..00000000 --- a/functionaljava.ipr +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From a1db04dfca14901260965f6107ac498968ac54e3 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sat, 10 Jan 2015 14:31:45 +0530 Subject: [PATCH 217/811] removing unnecessary class references --- core/src/main/java/fj/Equal.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 3cfa4b1e..216991d3 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -147,7 +147,7 @@ public static Equal anyEqual() { * An equal instance for the {@link StringBuffer} type. */ public static final Equal stringBufferEqual = - Equal.equal(sb1 -> sb2 -> { + equal(sb1 -> sb2 -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -161,7 +161,7 @@ public static Equal anyEqual() { * An equal instance for the {@link StringBuilder} type. */ public static final Equal stringBuilderEqual = - Equal.equal(sb1 -> sb2 -> { + equal(sb1 -> sb2 -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -179,7 +179,7 @@ public static Equal anyEqual() { * @return An equal instance for the {@link Either} type. */ public static Equal> eitherEqual(final Equal ea, final Equal eb) { - return Equal.equal(e1 -> e2 -> e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || + return equal(e1 -> e2 -> e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value())); } @@ -201,7 +201,7 @@ public static Equal> validationEqual(final Equal ea, * @return An equal instance for the {@link List} type. */ public static Equal> listEqual(final Equal ea) { - return Equal.equal(a1 -> a2 -> { + return equal(a1 -> a2 -> { List x1 = a1; List x2 = a2; @@ -234,7 +234,7 @@ public static Equal> nonEmptyListEqual(final Equal ea) { * @return An equal instance for the {@link Option} type. */ public static Equal> optionEqual(final Equal ea) { - return Equal.equal(o1 -> o2 -> o1.isNone() && o2.isNone() || + return equal(o1 -> o2 -> o1.isNone() && o2.isNone() || o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some())); } @@ -245,7 +245,7 @@ public static Equal> optionEqual(final Equal ea) { * @return An equal instance for the {@link Stream} type. */ public static Equal> streamEqual(final Equal ea) { - return Equal.equal(a1 -> a2 -> { + return equal(a1 -> a2 -> { Stream x1 = a1; Stream x2 = a2; @@ -268,7 +268,7 @@ public static Equal> streamEqual(final Equal ea) { * @return An equal instance for the {@link Array} type. */ public static Equal> arrayEqual(final Equal ea) { - return Equal.equal(a1 -> a2 -> { + return equal(a1 -> a2 -> { if (a1.length() == a2.length()) { for (int i = 0; i < a1.length(); i++) { if (!ea.eq(a1.get(i), a2.get(i))) @@ -287,7 +287,7 @@ public static Equal> arrayEqual(final Equal ea) { * @return An equal instance for the {@link Tree} type. */ public static Equal> treeEqual(final Equal ea) { - return Equal.>equal(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); + return Equal.>equal(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(Equal.treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); } /** @@ -415,7 +415,7 @@ public static Equal> p5Equal(final Equal ea final Equal ef, final Equal eg, final Equal eh) { - return Equal.equal( + return equal( p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8())); @@ -523,7 +523,7 @@ public static Equal> setEqual(final Equal e) { } public static Equal> writerEqual(Equal eq1, Equal eq2) { - return new Equal>(w1 -> w2 -> Equal.p2Equal(eq1, eq2).eq(w1.run(), w2.run())); + return equal(w1 -> w2 -> p2Equal(eq1, eq2).eq(w1.run(), w2.run())); } } From 62d793254c69f2fb680d0a10e594c3445f1c92ab Mon Sep 17 00:00:00 2001 From: daneko <3a3k.web+github@gmail.com> Date: Fri, 9 Jan 2015 19:08:35 +0900 Subject: [PATCH 218/811] fix Option#fromNull javadoc --- core/src/main/java/fj/data/Option.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index c952133c..46eb5f29 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -695,7 +695,7 @@ public static Option none() { * return none, otherwise, return the given value in some. * * @param t The unsafe nullable value. - * @return If t == null then return it in some, otherwise, return none. + * @return If t == null then return none, otherwise, return it in some. */ public static Option fromNull(final T t) { return t == null ? Option.none() : some(t); @@ -705,7 +705,7 @@ public static Option fromNull(final T t) { * Turns an unsafe nullable value into a safe optional value. If t == null then * return none, otherwise, return the given value in some. * - * @return If t == null then return it in some, otherwise, return none. + * @return If t == null then return none, otherwise, return it in some. */ public static F> fromNull() { return new F>() { From 2ea0d2d03846467223b799d608d91b4b200c47c4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 10 Jan 2015 23:26:22 +1000 Subject: [PATCH 219/811] #76: Workaround compiler bug introduced by #67 --- core/src/main/java/fj/control/Trampoline.java | 17 ++++++++++------- core/src/main/java/fj/data/List.java | 5 ++++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 30c3a429..c245e021 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -52,13 +52,16 @@ public Trampoline bind(final F> f) { // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result // gets shifted into the continuation. public Either>, A> resume() { - return left( - sub.resume().either( - p -> p.map(ot -> ot.fold(o1 -> o1.foldNormal(o2 -> cont.f(o2), t -> t._1().bind(cont)), - c -> codense(c.sub, o -> c.cont.f(o).bind(cont)))), - o3 -> P.lazy(u -> cont.f(o3)) - ) - ); + return left(sub.resume().either(p -> { + return p.map(ot -> { + // WARNING: In JDK 8, update 25 (current version) the following code is a + // workaround for an internal JDK compiler error, likely due to + // https:bugs.openjdk.java.net/browse/JDK-8062253. + F, Trampoline> f = o -> o.foldNormal(o1 -> cont.f(o1), t -> t._1().bind(cont)); + F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); + return ot.fold(f, g); + }); + }, o -> P.lazy(u -> cont.f(o)))); } } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index cd4fa22f..5f5782ed 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -78,7 +78,10 @@ public final Iterator iterator() { * @return The length of this list. */ public final int length() { - return foldLeft(i -> a -> i + 1, 0); + // WARNING: In JDK 8, update 25 (current version) the following code triggers an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. + // return foldLeft(i -> a -> i + 1, 0); + F2 f = (i, a) -> i + 1; + return foldLeft(f, 0); } /** From f8af461afee9fa584c140615e8a74f187e3576b5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 11 Jan 2015 19:45:05 +1000 Subject: [PATCH 220/811] #77: Improved show for list, tree, set, treemap, stream, array, V arity 2 to 8, HList --- core/src/main/java/fj/Show.java | 108 +++++++++++++++---- core/src/main/java/fj/data/Stream.java | 28 ++--- core/src/test/java/fj/data/TestRngState.java | 15 +-- 3 files changed, 112 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 2a30817e..3a22864a 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -8,6 +8,8 @@ import fj.data.NonEmptyList; import fj.data.Option; import fj.data.Stream; +import fj.data.Set; +import fj.data.TreeMap; import fj.data.Tree; import fj.data.Validation; import fj.data.hlist.HList; @@ -282,7 +284,7 @@ public static Show> validationShow(final Show sa, fin * @return A show instance for the {@link Stream} type. */ public static Show> listShow(final Show sa) { - return show(as -> streamShow(sa).show(as.toStream())); + return show(as -> streamShow(sa, "List(", ",", ")").show(as.toStream())); } /** @@ -303,13 +305,63 @@ public static Show> nonEmptyListShow(final Show sa) { */ public static Show> treeShow(final Show sa) { return show(a -> { - final Stream b = sa.f.f(a.root()) - .append(p1Show(streamShow(Show.treeShow(sa))).f.f(a.subForest())) - .snoc(')'); - return cons('(', p(b)); + Stream result = sa.f.f(a.root()); + if (!a.subForest()._1().isEmpty()) { + result = result.append(fromString(",")).append(streamShow(treeShow(sa), "", ",", "").f.f(a.subForest()._1())); + } + return fromString("Tree(").append(p(result)).append(fromString(")")); }); } + /** + * A show instance for the {@link Set} type. + * + * @param sa Show for the elements of the set. + * @return A show instance for the {@link Set} type. + */ + public static Show> setShow(final Show sa) { + return show(s -> streamShow(sa, "Set(", ",", ")").show(s.toStream())); + } + + /** + * A show instance for the {@link TreeMap} type. + * + * @param sk Show for the keys of the TreeMap. + * @param sv Show for the values of the TreeMap. + * @return A show instance for the {@link TreeMap} type. + */ + public static Show> treeMapShow(final Show sk, final Show sv) { + return show(tm -> { + Stream> stream = Stream.iteratorStream(tm.iterator()); + return streamShow(Show.p2MapShow(sk, sv), "TreeMap(", ",", ")").show(stream); + }); + } + + /** + * A show instance for the {@link P2 tuple-2} type in the style of a mapping from A to B. + * + * @param sa Show for the first element of the tuple. + * @param sb Show for the second element of the tuple. + * @return A show instance for the {@link P2 tuple-2} type. + */ + public static Show> p2MapShow(final Show sa, final Show sb) { + return p2Show(sa, sb, "(", ":", ")"); + } + + /** + * A show instance for the {@link P2 tuple-2} type. + * + * @param sa Show for the first element of the tuple. + * @param sb Show for the second element of the tuple. + * @param start Prefix string for the show. + * @param sep Separator string between elements of the tuple. + * @param end Suffix string for the show. + * @return A show instance for the {@link P2 tuple-2} type. + */ + public static Show> p2Show(final Show sa, final Show sb, String start, String sep, String end) { + return show(p -> fromString(start).append(p(sa.show(p._1()))).append(fromString(sep)).append(sb.show(p._2())).append(fromString(end))); + } + /** * A show instance for the {@link Stream} type. * @@ -317,7 +369,27 @@ public static Show> treeShow(final Show sa) { * @return A show instance for the {@link Stream} type. */ public static Show> streamShow(final Show sa) { - return show(as -> join(as.map(sa.show_()).intersperse(fromString(",")).cons(fromString("<")).snoc(p(fromString(">"))))); + return streamShow(sa, "Stream(", ",", ")"); + } + + /** + * A show instance for the {@link Stream} type. + * + * @param sa Show for the first element of the tuple. + * @param start Prefix string for the show. + * @param sep Separator string between elements of the stream. + * @param end Suffix string for the show. + * @return A show instance for the {@link Stream} type. + */ + public static Show> streamShow(final Show sa, String start, String sep, String end) { + return show(streamShow_(sa, start, sep, end)); + } + + /** + * Returns the transformation equivalent for the stream show. + */ + public static F, Stream> streamShow_(final Show sa, String start, String sep, String end) { + return as -> join(as.map(sa.show_()).intersperse(fromString(sep)).cons(fromString(start)).snoc(p(fromString(end)))); } /** @@ -334,12 +406,12 @@ public static Show> arrayShow(final Show sa) { b = b.append(sa.f.f(as.get(i))); if (i != as.length() - 1) - b = b.snoc(','); + b = b.append(fromString(",")); } - b = b.snoc('}'); + b = b.append(fromString("Array(")); - return cons('{', p(b)); + return fromString(")").append(p(b)); }); } @@ -370,7 +442,7 @@ public static Show> p1Show(final Show sa) { * @return A show instance for the {@link P2 tuple-2} type. */ public static Show> p2Show(final Show sa, final Show sb) { - return show(p -> cons('(', p(sa.show(p._1()))).snoc(',').append(sb.show(p._2())).snoc(')')); + return p2Show(sa, sb, "(", ",", ")"); } /** @@ -487,7 +559,7 @@ public static Show> p5Show(final Show sa, f * @return A show instance for a vector-2. */ public static Show> v2Show(final Show ea) { - return streamShow(ea).comap(V2.toStream_()); + return streamShow(ea, "V2(", ",", ")").comap(V2.toStream_()); } /** @@ -497,7 +569,7 @@ public static Show> v2Show(final Show ea) { * @return A show instance for a vector-3. */ public static Show> v3Show(final Show ea) { - return streamShow(ea).comap(V3.toStream_()); + return streamShow(ea, "V3(", ",", ")").comap(V3.toStream_()); } /** @@ -507,7 +579,7 @@ public static Show> v3Show(final Show ea) { * @return A show instance for a vector-4. */ public static Show> v4Show(final Show ea) { - return streamShow(ea).comap(V4.toStream_()); + return streamShow(ea, "V4(", ",", ")").comap(V4.toStream_()); } /** @@ -517,7 +589,7 @@ public static Show> v4Show(final Show ea) { * @return A show instance for a vector-5. */ public static Show> v5Show(final Show ea) { - return streamShow(ea).comap(V5.toStream_()); + return streamShow(ea, "V5(", ",", ")").comap(V5.toStream_()); } /** @@ -527,7 +599,7 @@ public static Show> v5Show(final Show ea) { * @return A show instance for a vector-6. */ public static Show> v6Show(final Show ea) { - return streamShow(ea).comap(V6.toStream_()); + return streamShow(ea, "V6(", ",", ")").comap(V6.toStream_()); } /** @@ -537,7 +609,7 @@ public static Show> v6Show(final Show ea) { * @return A show instance for a vector-7. */ public static Show> v7Show(final Show ea) { - return streamShow(ea).comap(V7.toStream_()); + return streamShow(ea, "V7(", ",", ")").comap(V7.toStream_()); } /** @@ -547,7 +619,7 @@ public static Show> v7Show(final Show ea) { * @return A show instance for a vector-8. */ public static Show> v8Show(final Show ea) { - return streamShow(ea).comap(V8.toStream_()); + return streamShow(ea, "V8(", ",", ")").comap(V8.toStream_()); } /** @@ -583,6 +655,6 @@ public static Show> unlineShow(final Show sa) { * @return a show instance for heterogeneous Streams. */ public static > Show> HListShow(final Show e, final Show l) { - return show(c -> e.show(c.head()).cons('[').append(l.show(c.tail())).snoc(']')); + return show(c -> fromString("HList(").append(e.show(c.head())).append(l.show(c.tail())).append(fromString(")"))); } } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 0538cdcd..136ba841 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1587,21 +1587,21 @@ public static Stream iterateWhile(final F f, final F p, * @return A stream from the given iterable. */ public static Stream iterableStream(final Iterable i) { - final class Util { - public Stream iteratorStream(final Iterator i) { - if (i.hasNext()) { - final A a = i.next(); - return cons(a, new P1>() { - public Stream _1() { - return iteratorStream(i); - } - }); - } else - return nil(); - } - } + return iteratorStream(i.iterator()); + } - return new Util().iteratorStream(i.iterator()); + /** + * Takes the given iterator to a stream. + * + * @param i The iterator to take to a stream. + * @return A stream from the given iterator. + */ + public static Stream iteratorStream(final Iterator i) { + if (i.hasNext()) { + final A a = i.next(); + return cons(a, P.lazy(u -> iteratorStream(i))); + } else + return nil(); } /** diff --git a/core/src/test/java/fj/data/TestRngState.java b/core/src/test/java/fj/data/TestRngState.java index 0deac432..b8a17494 100644 --- a/core/src/test/java/fj/data/TestRngState.java +++ b/core/src/test/java/fj/data/TestRngState.java @@ -22,8 +22,9 @@ */ public class TestRngState { - static String expected1 = "<4,4,2,2,2,5,3,3,1,5>"; + static List expected1 = List.list(4,4,2,2,2,5,3,3,1,5); static int size = 10; + static final Equal> listIntEqual = Equal.listEqual(Equal.intEqual); static Rng defaultRng() { return new LcgRng(1); @@ -48,10 +49,10 @@ static P2 num(Rng r, int x) { @Test public void testUnfold() { Stream s = unfold(r -> some(num(r).swap()), defaultRng()); - Assert.assertTrue(s.take(size).toList().toString().equals(expected1)); + Assert.assertTrue(listIntEqual.eq(s.take(size).toList(), expected1)); } - @Test + @Test public void testTransitions() { P2>, State> p = List.replicate(size, nextState()).foldLeft( (P2>, State> p2, F, State> f) -> { @@ -61,21 +62,21 @@ public void testTransitions() { , P.p(List.nil(), defaultState()) ); List ints = p._1().map(s -> s.eval(defaultRng())); - Assert.assertTrue(ints.toString().equals(expected1)); + Assert.assertTrue(listIntEqual.eq(ints, expected1)); } @Test public void testSequence() { List list = State.sequence(List.replicate(size, defaultState())).eval(defaultRng()); - Assert.assertTrue(list.toString().equals(expected1)); + Assert.assertTrue(listIntEqual.eq(list, expected1)); } @Test public void testTraverse() { List list = State.traverse(List.range(1, 10), a -> (State.unit((Rng s) -> num(s, a)))).eval(defaultRng()); // System.out.println(list.toString()); - String expected = "<1,2,3,5,6,7,7,9,10>"; - Assert.assertTrue(list.toString().equals(expected)); + List expected = List.list(1,2,3,5,6,7,7,9,10); + Assert.assertTrue(listIntEqual.eq(list, expected)); } public static Arbitrary> arbState() { From 5147cdf483ee3880e5f92a437376a4cd3ae914d0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 11 Jan 2015 20:56:19 +1000 Subject: [PATCH 221/811] #4: Demonstrate how TreeMap.split is broken --- core/src/main/java/fj/data/Set.java | 14 +++++++ core/src/main/java/fj/data/TreeMap.java | 26 +++++++++++++ core/src/test/java/fj/data/TreeMapTest.java | 41 +++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 core/src/test/java/fj/data/TreeMapTest.java diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 81fc0106..1fdd262a 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -474,4 +474,18 @@ public static Set set(final Ord o, final A ... as) { return s; } + /** + * Constructs a set from the given elements. + * + * @param o An order for the elements of the new set. + * @param list The elements to add to a set. + * @return A new set containing the elements of the given list. + */ + public static Set set(final Ord o, List list) { + Set s = empty(o); + for (final A a : list) + s = s.insert(a); + return s; + } + } diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index ca8568c1..12e2b394 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -40,6 +40,32 @@ public static TreeMap empty(final Ord keyOrd) { return new TreeMap(Set.empty(TreeMap.>ord(keyOrd))); } + /** + * Constructs a tree map from the given elements. + * + * @param keyOrd An order for the keys of the tree map. + * @param p2s The elements to construct the tree map with. + * @return a TreeMap with the given elements. + */ + public static TreeMap map(final Ord keyOrd, final P2 ... p2s) { + return map(keyOrd, List.list(p2s)); + } + + /** + * Constructs a tree map from the given elements. + * + * @param keyOrd An order for the keys of the tree map. + * @param list The elements to construct the tree map with. + * @return a TreeMap with the given elements. + */ + public static TreeMap map(final Ord keyOrd, final List> list) { + TreeMap tm = empty(keyOrd); + for (final P2 p2 : list) { + tm = tm.set(p2._1(), p2._2()); + } + return tm; + } + /** * Returns a potential value that the given key maps to. * diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java new file mode 100644 index 00000000..824566a8 --- /dev/null +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -0,0 +1,41 @@ +package fj.data; + +import fj.Equal; +import fj.Ord; +import fj.P3; +import fj.Show; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by MarkPerry on 11/01/2015. + */ +public class TreeMapTest { + + @Test + public void split() { + int pivot = 4; + List l = List.range(1, 6); + TreeMap m2 = TreeMap.map(Ord.intOrd, l.zip(l.map(i -> i.toString()))); + P3, Option, Set> p = m2.split(pivot); + Show> st = Show.treeMapShow(Show.intShow, Show.stringShow); + Show> ss = Show.setShow(Show.stringShow); + Show> so = Show.optionShow(Show.stringShow); + Show, Option, Set>> sp3 = Show.p3Show(ss, so, ss); + + st.println(m2); + sp3.println(p); + + Equal> eq = Equal.setEqual(Equal.stringEqual); + Set left = toSetString(List.list(1, 2, 3)); + Set right = toSetString(List.list(5)); + Assert.assertTrue("Left side of split unexpected", eq.eq(left, p._1())); + Assert.assertTrue(eq.eq(right, p._1())); + Assert.assertTrue(Equal.optionEqual(Equal.stringEqual).eq(p._2(), Option.some(Integer.toString(pivot)))); + } + + private static Set toSetString(List list) { + return Set.set(Ord.stringOrd, list.map(i -> i.toString())); + } + +} From 0645ad91db08567ffc96a4a1daba6dac9aefbc55 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 11 Jan 2015 21:49:48 +1000 Subject: [PATCH 222/811] Issue #4: Fixed TreeMap.split and added splitLookup --- core/src/main/java/fj/Equal.java | 4 ++ core/src/main/java/fj/data/TreeMap.java | 46 ++++++++++++++-- core/src/test/java/fj/data/TreeMapTest.java | 59 +++++++++++++++++---- 3 files changed, 95 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 216991d3..0e3f1f26 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -522,6 +522,10 @@ public static Equal> setEqual(final Equal e) { return equal(curry((Set a, Set b) -> streamEqual(e).eq(a.toStream(), b.toStream()))); } + public static Equal> treeMapEqual(Equal k, Equal v) { + return equal(t1 -> t2 -> Equal.streamEqual(p2Equal(k, v)).eq(t1.toStream(), t2.toStream())); + } + public static Equal> writerEqual(Equal eq1, Equal eq2) { return equal(w1 -> w2 -> p2Equal(eq1, eq2).eq(w1.run(), w2.run())); } diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 12e2b394..4de7c455 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -169,6 +169,9 @@ public Map toMutableMap() { return m; } + public Stream> toStream() { + return Stream.iteratorStream(iterator()); + } /** * An immutable projection of the given mutable map. * @@ -234,13 +237,50 @@ public TreeMap update(final K k, final F f, final V v) { * key in this map, all the elements in the second set are mapped to keys greater than the given key, * and the optional value is the value associated with the given key if present, otherwise None. */ - public P3, Option, Set> split(final K k) { - final F>>, Set> getSome = F1Functions.mapSet(F1Functions.o(Option.fromSome(), P2.>__2()) - , tree.ord().comap(F1Functions.o(P.>p2().f(k), Option.some_()))); + public P3, Option, Set> split(Ord ord, final K k) { + final F>>, Set> getSome = F1Functions.mapSet(F1Functions.o(Option.fromSome(), P2.>__2()), ord); return tree.split(p(k, Option.none())).map1(getSome).map3(getSome) .map2(F1Functions.o(Option.join(), F1Functions.mapOption(P2.>__2()))); } + /** + * Internal construction of a TreeMap from the given set. + * @param ord An order for the keys of the tree map. + * @param s The elements to construct the tree map with. + * @return a TreeMap with the given elements. + */ + private static TreeMap map(Ord ord, Set>> s) { + TreeMap empty = TreeMap.empty(ord); + TreeMap tree = s.toList().foldLeft((tm, p2) -> { + Option opt = p2._2(); + if (opt.isSome()) { + return tm.set(p2._1(), opt.some()); + } + return tm; + }, empty); + return tree; + } + + /** + * Splits this TreeMap at the given key. Returns a triple of: + *
    + *
  • A tree map containing all the values of this map associated with keys less than the given key.
  • + *
  • An option of a value mapped to the given key, if it exists in this map, otherwise None. + *
  • A tree map containing all the values of this map associated with keys greater than the given key.
  • + *
+ * + * @param k A key at which to split this map. + * @return Two tree maps and an optional value, where all keys in the first tree map are mapped + * to keys less than the given key in this map, all the keys in the second tree map are mapped + * to keys greater than the given key, and the optional value is the value associated with the + * given key if present, otherwise None. + */ + public P3, Option, TreeMap> splitLookup(final K k) { + P3>>, Option>>, Set>>> p3 = tree.split(P.p(k, get(k))); + Ord o = tree.ord().comap(k2 -> P.p(k2, Option.none())); + return P.p(map(o, p3._1()), get(k), map(o, p3._3())); + } + /** * Maps the given function across the values of this TreeMap. * diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 824566a8..153ab43c 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -4,9 +4,13 @@ import fj.Ord; import fj.P3; import fj.Show; +import fj.P; import org.junit.Assert; import org.junit.Test; +import static fj.data.Option.some; +import static org.junit.Assert.assertTrue; + /** * Created by MarkPerry on 11/01/2015. */ @@ -14,28 +18,61 @@ public class TreeMapTest { @Test public void split() { + // do the split int pivot = 4; - List l = List.range(1, 6); + int max = 5; + List l = List.range(1, max + 1); TreeMap m2 = TreeMap.map(Ord.intOrd, l.zip(l.map(i -> i.toString()))); - P3, Option, Set> p = m2.split(pivot); + P3, Option, Set> p = m2.split(Ord.stringOrd, pivot); + + // print debug info Show> st = Show.treeMapShow(Show.intShow, Show.stringShow); Show> ss = Show.setShow(Show.stringShow); Show> so = Show.optionShow(Show.stringShow); Show, Option, Set>> sp3 = Show.p3Show(ss, so, ss); + if (true) { + st.println(m2); + sp3.println(p); + } - st.println(m2); - sp3.println(p); - - Equal> eq = Equal.setEqual(Equal.stringEqual); - Set left = toSetString(List.list(1, 2, 3)); - Set right = toSetString(List.list(5)); - Assert.assertTrue("Left side of split unexpected", eq.eq(left, p._1())); - Assert.assertTrue(eq.eq(right, p._1())); - Assert.assertTrue(Equal.optionEqual(Equal.stringEqual).eq(p._2(), Option.some(Integer.toString(pivot)))); + // assert equals + Equal> seq = Equal.setEqual(Equal.stringEqual); + Set left = toSetString(List.range(1, pivot)); + Set right = toSetString(List.range(pivot + 1, max + 1)); + P3, Option, Set> expected = P.p(left, some(Integer.toString(pivot)), right); + assertTrue(Equal.p3Equal(seq, Equal.optionEqual(Equal.stringEqual), seq).eq(p, expected)); } private static Set toSetString(List list) { return Set.set(Ord.stringOrd, list.map(i -> i.toString())); } + @Test + public void splitLookup() { + // do the split + int pivot = 4; + int max = 5; + List l = List.range(1, max + 1); + TreeMap m2 = TreeMap.map(Ord.intOrd, l.zip(l.map(i -> i.toString()))); + P3, Option, TreeMap> p3 = m2.splitLookup(pivot); + + // create expected output + List leftList = List.range(1, pivot); + TreeMap leftMap = TreeMap.map(Ord.intOrd, leftList.zip(leftList.map(i -> i.toString()))); + List rightList = List.range(pivot + 1, max + 1); + TreeMap rightMap = TreeMap.map(Ord.intOrd, rightList.zip(rightList.map(i -> i.toString()))); + + // debug info + if (true) { + Show> st = Show.treeMapShow(Show.intShow, Show.stringShow); + Show, Option, TreeMap>> sp3 = Show.p3Show(st, Show.optionShow(Show.stringShow), st); + sp3.println(p3); + } + + // do the assert + Equal> tme = Equal.treeMapEqual(Equal.intEqual, Equal.stringEqual); + Equal, Option, TreeMap>> eq = Equal.p3Equal(tme, Equal.optionEqual(Equal.stringEqual), tme); + assertTrue(eq.eq(p3, P.p(leftMap, some(Integer.toString(pivot)), rightMap))); + } + } From 2abd6bb4bce07ec260907161651dc8ac0e89329e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 11 Jan 2015 21:53:12 +1000 Subject: [PATCH 223/811] Issue #4: Renamed static constructor TreeMap.map to treeMap --- core/src/main/java/fj/data/TreeMap.java | 10 +++++----- core/src/test/java/fj/data/TreeMapTest.java | 9 ++++----- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 4de7c455..24055c66 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -47,8 +47,8 @@ public static TreeMap empty(final Ord keyOrd) { * @param p2s The elements to construct the tree map with. * @return a TreeMap with the given elements. */ - public static TreeMap map(final Ord keyOrd, final P2 ... p2s) { - return map(keyOrd, List.list(p2s)); + public static TreeMap treeMap(final Ord keyOrd, final P2... p2s) { + return treeMap(keyOrd, List.list(p2s)); } /** @@ -58,7 +58,7 @@ public static TreeMap map(final Ord keyOrd, final P2 ... p * @param list The elements to construct the tree map with. * @return a TreeMap with the given elements. */ - public static TreeMap map(final Ord keyOrd, final List> list) { + public static TreeMap treeMap(final Ord keyOrd, final List> list) { TreeMap tm = empty(keyOrd); for (final P2 p2 : list) { tm = tm.set(p2._1(), p2._2()); @@ -249,7 +249,7 @@ public P3, Option, Set> split(Ord ord, final K k) { * @param s The elements to construct the tree map with. * @return a TreeMap with the given elements. */ - private static TreeMap map(Ord ord, Set>> s) { + private static TreeMap treeMap(Ord ord, Set>> s) { TreeMap empty = TreeMap.empty(ord); TreeMap tree = s.toList().foldLeft((tm, p2) -> { Option opt = p2._2(); @@ -278,7 +278,7 @@ private static TreeMap map(Ord ord, Set>> s) { public P3, Option, TreeMap> splitLookup(final K k) { P3>>, Option>>, Set>>> p3 = tree.split(P.p(k, get(k))); Ord o = tree.ord().comap(k2 -> P.p(k2, Option.none())); - return P.p(map(o, p3._1()), get(k), map(o, p3._3())); + return P.p(treeMap(o, p3._1()), get(k), treeMap(o, p3._3())); } /** diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 153ab43c..0f8651b7 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -5,7 +5,6 @@ import fj.P3; import fj.Show; import fj.P; -import org.junit.Assert; import org.junit.Test; import static fj.data.Option.some; @@ -22,7 +21,7 @@ public void split() { int pivot = 4; int max = 5; List l = List.range(1, max + 1); - TreeMap m2 = TreeMap.map(Ord.intOrd, l.zip(l.map(i -> i.toString()))); + TreeMap m2 = TreeMap.treeMap(Ord.intOrd, l.zip(l.map(i -> i.toString()))); P3, Option, Set> p = m2.split(Ord.stringOrd, pivot); // print debug info @@ -53,14 +52,14 @@ public void splitLookup() { int pivot = 4; int max = 5; List l = List.range(1, max + 1); - TreeMap m2 = TreeMap.map(Ord.intOrd, l.zip(l.map(i -> i.toString()))); + TreeMap m2 = TreeMap.treeMap(Ord.intOrd, l.zip(l.map(i -> i.toString()))); P3, Option, TreeMap> p3 = m2.splitLookup(pivot); // create expected output List leftList = List.range(1, pivot); - TreeMap leftMap = TreeMap.map(Ord.intOrd, leftList.zip(leftList.map(i -> i.toString()))); + TreeMap leftMap = TreeMap.treeMap(Ord.intOrd, leftList.zip(leftList.map(i -> i.toString()))); List rightList = List.range(pivot + 1, max + 1); - TreeMap rightMap = TreeMap.map(Ord.intOrd, rightList.zip(rightList.map(i -> i.toString()))); + TreeMap rightMap = TreeMap.treeMap(Ord.intOrd, rightList.zip(rightList.map(i -> i.toString()))); // debug info if (true) { From e9c7a1c4cf8beff3e17fb4b7bca8b1400b2b2220 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Thu, 15 Jan 2015 00:28:50 -0800 Subject: [PATCH 224/811] Add setAll() method to TreeMap, to combine two TreeMap instances. --- core/src/main/java/fj/data/TreeMap.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 24055c66..254ec8af 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -295,4 +295,20 @@ public TreeMap map(final F f) { return new TreeMap(tree.map(TreeMap.>ord(o), g)); } + /** + * Extend this TreeMap to include all mapping from another TreeMap. Where a + * mapping exists in both this TreeMap and the other one, the value from the + * other one will replace the value in this one. + * + * @param other + * @return + */ + public Object setAll(TreeMap other) { + TreeMap result = this; + for(P2 p : other) { + result = result.set(p._1(), p._2()); + } + return result; + } + } From fd3951b80427df20e3c82ff2277910aaecd08f4b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 16 Jan 2015 00:30:18 +1000 Subject: [PATCH 225/811] Added traverse family of methods to Option --- core/src/main/java/fj/data/Option.java | 43 ++++++++++++++++++++++ core/src/test/java/fj/data/OptionTest.java | 30 +++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 core/src/test/java/fj/data/OptionTest.java diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 64ddebf9..0d3b9db5 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -17,6 +17,8 @@ import fj.Unit; import fj.Show; import fj.function.Effect1; +import fj.Equal; +import fj.Ord; import static fj.Function.*; import static fj.P.p; @@ -415,6 +417,47 @@ public final Option sequence(final Option o) { return bind(c); } + public Either> traverseEither(F> f) { + return map(a -> f.f(a).right().map(b -> some(b))).orSome(Either.right(none())); + } + + public IO> traverseIO(F> f) { + return map(a -> IOFunctions.map(f.f(a), b -> some(b))).orSome(IOFunctions.lazy(u -> none())); + } + + public List> traverseList(F> f) { + return map(a -> f.f(a).map(b -> some(b))).orSome(List.list()); + } + + public Option> traverseOption(F> f) { + return map(f); + } + + public Stream> traverseStream(F> f) { + return map(a -> f.f(a).map(b -> some(b))).orSome(Stream.nil()); + } + + public P1> traverseP1(F> f) { + return map(a -> f.f(a).map(b -> some(b))).orSome(P.p(none())); + } + + public Seq> traverseSeq(F> f) { + return map(a -> f.f(a).map(b -> some(b))).orSome(Seq.empty()); + } + + public Set> traverseSet(Ord ord, F> f) { + Ord> optOrd = Ord.optionOrd(ord); + return map(a -> f.f(a).map(optOrd, b -> some(b))).orSome(Set.empty(optOrd)); + } + + public F2, F>, Set>> traverseSet() { + return (o, f) -> traverseSet(o, f); + } + + public Validation> traverseValidation(F> f) { + return map(a -> f.f(a).map(b -> some(b))).orSome(Validation.success(none())); + } + /** * Performs function application within an optional value (applicative functor pattern). * diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java new file mode 100644 index 00000000..5d2778e5 --- /dev/null +++ b/core/src/test/java/fj/data/OptionTest.java @@ -0,0 +1,30 @@ +package fj.data; + +import org.junit.Assert; +import org.junit.Test; + +import static fj.data.Option.some; +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 15/01/2015. + */ +public class OptionTest { + + @Test + public void equals() { + int max = 4; + assertTrue(some(1).equals(some(1))); + assertTrue(some(List.range(1, max)).equals(some(List.range(1, max)))); + } + + @Test + public void traverseList() { + int max = 3; + List> actual = some(max).traverseList(a -> List.range(1, a + 1)); + List> expected = List.range(1, max + 1).map(i -> some(i)); + System.out.println(String.format("actual: %s, expected: %s", actual.toString(), expected.toString())); + assertTrue(actual.equals(expected)); + } + +} From abaf0ada4350204b05c05b53a3078e70fcc4b9bb Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Thu, 15 Jan 2015 22:20:01 -0800 Subject: [PATCH 226/811] Add List.isSingle() --- core/src/main/java/fj/data/List.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 5f5782ed..867bed3d 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1840,4 +1840,11 @@ private void copy() { @Override public String toString() { return Show.listShow( Show.
anyShow() ).show( this ).foldLeft((s, c) -> s + c, "" ); } + + /** + * True if and only if the list has one element. Runs in constant time. + */ + public boolean isSingle() { + return isNotEmpty() && tail().isEmpty(); + } } From e0c4efa5af0d6fea0b23e45fd77f70ecfe5f24e1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 17 Jan 2015 01:28:04 +1000 Subject: [PATCH 227/811] #75: Added equals, hashCode and toString to classes P's, Array, Either, List, Option, Seq, Set, Stream, Tree, TreeMap, Validation --- core/src/main/java/fj/Equal.java | 20 ++++++ core/src/main/java/fj/Hash.java | 21 ++++--- core/src/main/java/fj/P1.java | 13 ++++ core/src/main/java/fj/P2.java | 11 ++++ core/src/main/java/fj/P3.java | 11 ++++ core/src/main/java/fj/P4.java | 12 ++++ core/src/main/java/fj/P5.java | 11 ++++ core/src/main/java/fj/P6.java | 13 ++++ core/src/main/java/fj/P7.java | 11 ++++ core/src/main/java/fj/P8.java | 12 ++++ core/src/main/java/fj/Show.java | 17 ++--- core/src/main/java/fj/Unit.java | 6 ++ core/src/main/java/fj/data/Array.java | 20 ++++++ core/src/main/java/fj/data/Either.java | 21 +++++-- core/src/main/java/fj/data/List.java | 10 +-- core/src/main/java/fj/data/Option.java | 73 +++++++--------------- core/src/main/java/fj/data/Seq.java | 34 +++++++++- core/src/main/java/fj/data/Set.java | 26 +++++--- core/src/main/java/fj/data/Stream.java | 18 ++++++ core/src/main/java/fj/data/Tree.java | 26 +++++--- core/src/main/java/fj/data/TreeMap.java | 23 +++++-- core/src/main/java/fj/data/Validation.java | 12 ++++ core/src/test/java/fj/data/ListTest.java | 27 ++++++++ core/src/test/java/fj/data/SeqTest.java | 23 +++++++ core/src/test/java/fj/data/UnitTest.java | 19 ++++++ 25 files changed, 383 insertions(+), 107 deletions(-) create mode 100644 core/src/test/java/fj/data/ListTest.java create mode 100644 core/src/test/java/fj/data/SeqTest.java create mode 100644 core/src/test/java/fj/data/UnitTest.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 0e3f1f26..d1e7c21b 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -238,6 +238,10 @@ public static Equal> optionEqual(final Equal ea) { o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some())); } + public static Equal> seqEqual(final Equal e) { + return equal(s1 -> s2 -> streamEqual(e).eq(s1.toStream(), s2.toStream())); + } + /** * An equal instance for the {@link Stream} type. * @@ -530,4 +534,20 @@ public static Equal> writerEqual(Equal eq1, Equal eq2) return equal(w1 -> w2 -> p2Equal(eq1, eq2).eq(w1.run(), w2.run())); } + /** + * Can the objects be checked for equality? + * @return True if the objects are not null and are an instance of the provided class. + */ + public static boolean equalsValidationCheck(Object o1, Object o2) { + java.lang.Class c = o1.getClass(); + if (o1 == null || !c.isInstance(o1)) { + return false; + } + if (o2 == null || !c.isInstance(o2)) { + return false; + } + return true; + + } + } diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index a391a693..fee25e0a 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -2,14 +2,7 @@ import static fj.Function.compose; -import fj.data.Array; -import fj.data.Either; -import fj.data.List; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Stream; -import fj.data.Tree; -import fj.data.Validation; +import fj.data.*; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; @@ -203,6 +196,14 @@ public static Hash> optionHash(final Hash ha) { return hash(o -> o.isNone() ? 0 : ha.hash(o.some())); } + public static Hash> seqHash(final Hash h) { + return hash(s -> streamHash(h).hash(s.toStream())); + } + + public static Hash> setHash(final Hash h) { + return hash(s -> streamHash(h).hash(s.toStream())); + } + /** * A hash instance for the {@link Stream} type. * @@ -253,6 +254,10 @@ public static Hash> treeHash(final Hash ha) { return streamHash(ha).comap(Tree.flatten_()); } + public static Hash> treeMapHash(final Hash h, final Hash v) { + return hash(t -> streamHash(Hash.p2Hash(h, v)).hash(t.toStream())); + } + /** * A hash instance for a product-1. * diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index dcdeb77a..737431dd 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -232,7 +232,20 @@ public A f(final B b) { }; } + @Override public String toString() { return Show.p1Show(Show.anyShow()).showS(this); } + + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other); + } + + @Override + public int hashCode() { + return Hash.p1Hash(Hash.anyHash()).hash(this); + } + } diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 25eeed7d..7c966126 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -24,6 +24,16 @@ public abstract class P2 { */ public abstract B _2(); + @Override + public boolean equals(Object other) { + return Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual()).eq(this, (P2) other); + } + + @Override + public int hashCode() { + return Hash.p2Hash(Hash.anyHash(), Hash.anyHash()).hash(this); + } + /** * Swaps the elements around in this product. * @@ -344,6 +354,7 @@ public C f(final A a, final B b) { }; } + @Override public String toString() { return Show.p2Show(Show.anyShow(), Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 06babb9c..88d077cc 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -185,9 +185,20 @@ public C f(final P3 p) { }; } + @Override public String toString() { return Show.p3Show(Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P3) other); + } + + @Override + public int hashCode() { + return Hash.p3Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } } diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 5cfac53e..13b423c3 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -258,8 +258,20 @@ public D f(final P4 p) { }; } + @Override public String toString() { return Show.p4Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P4) other); + } + + @Override + public int hashCode() { + return Hash.p4Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } + } diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index ed300f41..741b42f5 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -337,9 +337,20 @@ public E f(final P5 p) { }; } + @Override public String toString() { return Show.p5Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P5) other); + } + + @Override + public int hashCode() { + return Hash.p5Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } } diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 772003c7..d276687f 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -427,8 +427,21 @@ public E f(final P6 p) { }; } + @Override public String toString() { return Show.p6Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } + + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P6) other); + } + + @Override + public int hashCode() { + return Hash.p6Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } + } diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 7fa413e4..e887df79 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -522,9 +522,20 @@ public G f(final P7 p) { }; } + @Override public String toString() { return Show.p7Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P7) other); + } + + @Override + public int hashCode() { + return Hash.p7Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } } diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index 9e471c7f..087efa5a 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -628,8 +628,20 @@ public H f(final P8 p) { }; } + @Override public String toString() { return Show.p8Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P8) other); + } + + @Override + public int hashCode() { + return Hash.p8Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } + } diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 3a22864a..fe1efe32 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -1,17 +1,6 @@ package fj; -import fj.data.Array; -import fj.data.Either; -import fj.data.LazyString; -import fj.data.List; -import fj.data.Natural; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Stream; -import fj.data.Set; -import fj.data.TreeMap; -import fj.data.Tree; -import fj.data.Validation; +import fj.data.*; import fj.data.hlist.HList; import fj.data.vector.V2; import fj.data.vector.V3; @@ -313,6 +302,10 @@ public static Show> treeShow(final Show sa) { }); } + public static Show> seqShow(final Show sa) { + return show(s -> streamShow(sa, "Seq(", ",", ")").show(s.toStream())); + } + /** * A show instance for the {@link Set} type. * diff --git a/core/src/main/java/fj/Unit.java b/core/src/main/java/fj/Unit.java index 60ef3750..c7471f21 100644 --- a/core/src/main/java/fj/Unit.java +++ b/core/src/main/java/fj/Unit.java @@ -20,4 +20,10 @@ private Unit() { public static Unit unit() { return u; } + + @Override + public String toString() { + return "unit"; + } + } diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index ce9be167..93cf7048 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -6,6 +6,9 @@ import fj.P; import fj.P1; import fj.P2; +import fj.Equal; +import fj.Show; +import fj.Hash; import fj.Unit; import fj.function.Effect1; @@ -57,6 +60,11 @@ public A get(final int index) { return (A) a[index]; } + @Override + public int hashCode() { + return Hash.arrayHash(Hash.anyHash()).hash(this); + } + /** * Sets the element at the given index to the given value. * @@ -173,6 +181,11 @@ public Option> f(final Integer o) { }, 0); } + @Override + public String toString() { + return Show.arrayShow(Show.anyShow()).showS(this); + } + /** * Maps the given function across this array. * @@ -668,6 +681,13 @@ public boolean exists(final F f) { return false; } + @Override + public boolean equals(Object o) { + return ! + Equal.equalsValidationCheck(this, o) ? false : + Equal.arrayEqual(Equal.anyEqual()).eq(this, (Array) o); + } + /** * Finds the first occurrence of an element that matches the given predicate or no value if no * elements match. diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 281f4411..1196f321 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -1,15 +1,12 @@ package fj.data; import static fj.Bottom.error; -import fj.Effect; -import fj.F; + +import fj.*; + import static fj.Function.identity; import static fj.P.p; -import fj.Show; -import fj.Function; -import fj.P1; -import fj.Unit; import fj.function.Effect1; import static fj.Unit.unit; @@ -80,6 +77,18 @@ public final X either(final F left, final F right) { right.f(right().value()); } + @Override + public boolean equals(Object other) { + + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Either) other); + } + + @Override + public int hashCode() { + return Hash.eitherHash(Hash.anyHash(), Hash.anyHash()).hash(this); + } + /** * If this is a left, then return the left value in right, or vice versa. * diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 867bed3d..e4ed119f 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1814,11 +1814,12 @@ private void copy() { //Suppress the warning for cast to List because the type is checked in the previous line. @SuppressWarnings({ "unchecked" }) @Override public boolean equals( final Object obj ) { - if ( obj == null || !( obj instanceof List ) ) { return false; } //Casting to List here does not cause a runtime exception even if the type arguments don't match. //The cast is done to avoid the compiler warning "raw use of parameterized class 'List'" - return Equal.listEqual( Equal.anyEqual() ).eq( this, (List) obj ); + + return !Equal.equalsValidationCheck(this, obj) ? false : + Equal.listEqual(Equal.anyEqual()).eq(this, (List) obj); } /** @@ -1827,7 +1828,8 @@ private void copy() { * * @return the hash code for this list. */ - @Override public int hashCode() { + @Override + public int hashCode() { return Hash.listHash( Hash.anyHash() ).hash( this ); } @@ -1838,7 +1840,7 @@ private void copy() { * @return a String representation of the list */ @Override public String toString() { - return Show.listShow( Show.anyShow() ).show( this ).foldLeft((s, c) -> s + c, "" ); + return Show.listShow(Show.anyShow()).showS(this); } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 0ca44994..e9581c91 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -19,6 +19,7 @@ import fj.function.Effect1; import fj.Equal; import fj.Ord; +import fj.Hash; import static fj.Function.*; import static fj.P.p; @@ -48,9 +49,9 @@ private Option() { } + @Override public String toString() { - final Show s = anyShow(); - return optionShow(s).showS(this); + return optionShow(Show.anyShow()).showS(this); } /** @@ -625,6 +626,12 @@ public final boolean exists(final F f) { return isSome() && f.f(some()); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.optionEqual(Equal.anyEqual()).eq(this, (Option) other); + } + /** * Projects an immutable collection of this optional value. * @@ -638,61 +645,20 @@ private static final class None extends Option { public A some() { throw error("some on None"); } - - @Override - public int hashCode() { - return 31; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - return true; - } } - private static final class Some extends Option { - private final A a; - - Some(final A a) { - this.a = a; - } + private static final class Some extends Option { + private final A a; - public A some() { - return a; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((a == null) ? 0 : a.hashCode()); - return result; - } + Some(final A a) { + this.a = a; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Some other = (Some) obj; - if (a == null) { - if (other.a != null) - return false; - } else if (!a.equals(other.a)) - return false; - return true; + public A some() { + return a; + } } - } public static F> some_() { return t -> some(t); @@ -849,6 +815,11 @@ public static Option fromString(final String s) { }); } + @Override + public int hashCode() { + return Hash.optionHash(Hash.anyHash()).hash(this); + } + /** * Returns a function that transforms a string to an optional non-empty string, * or no value if the string is empty. diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 8cc595fb..00292f17 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -1,8 +1,7 @@ package fj.data; -import fj.F; -import fj.F2; -import fj.Function; +import fj.*; + import static fj.Bottom.error; import static fj.Monoid.intAdditionMonoid; import static fj.data.fingertrees.FingerTree.measured; @@ -46,6 +45,13 @@ public static Seq empty() { return (Seq) EMPTY; } + @Override + public boolean equals(Object other) { + + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.seqEqual(Equal.anyEqual()).eq(this, (Seq) other); + } + /** * A singleton sequence. * @@ -56,6 +62,14 @@ public static Seq single(final A a) { return new Seq(Seq.mkTree().single(a)); } + public static Seq seq(final A... as) { + return seq(List.list(as)); + } + + public static Seq seq(final List list) { + return list.foldLeft((b, a) -> b.snoc(a), Seq.empty()); + } + /** * Inserts the given element at the front of this sequence. * @@ -76,6 +90,15 @@ public Seq snoc(final A a) { return new Seq(ftree.snoc(a)); } + public Stream toStream() { + return ftree.foldLeft((b, a) -> b.cons(a), Stream.nil()).reverse(); + } + + @Override + public String toString() { + return Show.seqShow(Show.anyShow()).showS(this); + } + /** * Appends the given sequence to this sequence. * @@ -124,6 +147,11 @@ public B foldRight(final F2 f, final B z) { return ftree.foldRight(f, z); } + @Override + public int hashCode() { + return Hash.seqHash(Hash.anyHash()).hash(this); + } + public Seq map(F f) { return new Seq(ftree.map(f, Seq.elemMeasured())); } diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 1fdd262a..860c34ca 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -1,19 +1,12 @@ package fj.data; -import fj.F; -import fj.F2; -import fj.Function; -import fj.Monoid; -import fj.Ord; -import fj.P; -import fj.P2; -import fj.P3; +import fj.*; + import static fj.Function.*; import static fj.data.Either.right; import static fj.data.Option.some; import static fj.function.Booleans.not; -import fj.Ordering; import static fj.Ordering.GT; import static fj.Ordering.LT; @@ -147,6 +140,21 @@ public static Set empty(final Ord ord) { return new Empty(ord); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : Equal.setEqual(Equal.anyEqual()).eq(this, (Set) other); + } + + @Override + public int hashCode() { + return Hash.setHash(Hash.anyHash()).hash(this); + } + + @Override + public String toString() { + return Show.setShow(Show.anyShow()).showS(this); + } + /** * Checks if the given element is a member of this set. * diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 136ba841..8f33ad2a 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -2,6 +2,8 @@ import fj.Effect; import fj.Equal; +import fj.Hash; +import fj.Show; import fj.F; import fj.F2; import fj.F3; @@ -1235,6 +1237,22 @@ public final boolean forall(final F f) { return isEmpty() || f.f(head()) && tail()._1().forall(f); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other); + } + + @Override + public int hashCode() { + return Hash.streamHash(Hash.anyHash()).hash(this); + } + + @Override + public String toString() { + return Show.streamShow(Show.anyShow()).showS(this); + } + /** * Returns true if the predicate holds for at least one of the elements of this * stream, false otherwise (false for the empty stream). diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index fbdb0ea4..2e0319c2 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -1,15 +1,9 @@ package fj.data; -import fj.F; -import fj.F2; -import fj.F2Functions; -import fj.P; -import fj.P1; -import fj.P2; +import fj.*; + import static fj.Function.*; import static fj.data.Stream.*; -import fj.Monoid; -import fj.Show; import java.util.Collection; import java.util.Iterator; @@ -265,6 +259,22 @@ private Stream drawTree(final Show s) { return drawSubTrees(s, subForest._1()).cons(s.showS(root)); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.treeEqual(Equal.anyEqual()).eq(this, (Tree) other); + } + + @Override + public int hashCode() { + return Hash.treeHash(Hash.anyHash()).hash(this); + } + + @Override + public String toString() { + return Show.treeShow(Show.anyShow()).showS(this); + } + /** * Draws a 2-dimensional representation of a tree. * diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 24055c66..066b60d5 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -1,11 +1,6 @@ package fj.data; -import fj.F; -import fj.F1Functions; -import fj.P; -import fj.P2; -import fj.P3; -import fj.Ord; +import fj.*; import java.util.Iterator; import java.util.Map; @@ -40,6 +35,22 @@ public static TreeMap empty(final Ord keyOrd) { return new TreeMap(Set.empty(TreeMap.>ord(keyOrd))); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (TreeMap) other); + } + + @Override + public int hashCode() { + return Hash.treeMapHash(Hash.anyHash(), Hash.anyHash()).hash(this); + } + + @Override + public String toString() { + return Show.treeMapShow(Show.anyShow(), Show.anyShow()).showS(this); + } + /** * Constructs a tree map from the given elements. * diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index a9f71df0..0f5eb642 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -249,6 +249,17 @@ public boolean exists(final F f) { return e.right().exists(f); } + @Override + public boolean equals(Object other) { + return !Equal.equalsValidationCheck(this, other) ? false : + Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Validation) other); + } + + @Override + public int hashCode() { + return Hash.validationHash(Hash.anyHash(), Hash.anyHash()).hash(this); + } + /** * Returns a single element list if this is a success value, otherwise an empty list. * @@ -1251,6 +1262,7 @@ public Validation f(final String s) { } }; + @Override public String toString() { return Show.validationShow(Show.anyShow(), Show.anyShow()).showS(this); } diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java new file mode 100644 index 00000000..15d2f0bd --- /dev/null +++ b/core/src/test/java/fj/data/ListTest.java @@ -0,0 +1,27 @@ +package fj.data; + +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 16/01/2015. + */ +public class ListTest { + + @Test + public void objectMethods() { + + int max = 5; + List list = List.range(1, max); + assertTrue(list.equals(List.range(1, max))); + assertFalse(list.equals(List.single(1))); + assertFalse(list.equals(true)); + + assertTrue(List.list(1, 2).toString().equals("List(1,2)")); + + } + +} diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java new file mode 100644 index 00000000..9339a52a --- /dev/null +++ b/core/src/test/java/fj/data/SeqTest.java @@ -0,0 +1,23 @@ +package fj.data; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 16/01/2015. + */ +public class SeqTest { + + @Test + public void objectMethods() { + Seq s1 = Seq.seq(1, 2, 3); + Seq s2 = Seq.seq(1, 2, 3); + assertTrue(s1.toString().equals("Seq(1,2,3)")); + assertTrue(s1.equals(s2)); + assertFalse(s1 == s2); + + } + +} diff --git a/core/src/test/java/fj/data/UnitTest.java b/core/src/test/java/fj/data/UnitTest.java new file mode 100644 index 00000000..eef15887 --- /dev/null +++ b/core/src/test/java/fj/data/UnitTest.java @@ -0,0 +1,19 @@ +package fj.data; + +import fj.Unit; +import org.junit.Assert; +import org.junit.Test; + +/** + * Created by MarkPerry on 17/01/2015. + */ +public class UnitTest { + + @Test + public void objectMethods() { + Assert.assertTrue(Unit.unit().equals(Unit.unit())); + Assert.assertFalse(Unit.unit().equals(3)); + Assert.assertTrue(Unit.unit().toString().equals("unit")); + } + +} From 697a1b279b45d575c7c0d49f2f1f85aaee7789c1 Mon Sep 17 00:00:00 2001 From: daneko <3a3k.web+github@gmail.com> Date: Sun, 18 Jan 2015 01:31:01 +0900 Subject: [PATCH 228/811] fix Try javadoc --- core/src/main/java/fj/Try.java | 36 ++++++++++++------------ core/src/main/java/fj/function/Try0.java | 2 +- core/src/main/java/fj/function/Try1.java | 2 +- core/src/main/java/fj/function/Try2.java | 2 +- core/src/main/java/fj/function/Try3.java | 2 +- core/src/main/java/fj/function/Try4.java | 2 +- core/src/main/java/fj/function/Try5.java | 2 +- core/src/main/java/fj/function/Try6.java | 2 +- core/src/main/java/fj/function/Try7.java | 2 +- core/src/main/java/fj/function/Try8.java | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index 0d881b8f..d8cb2034 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -16,9 +16,9 @@ public class Try { /** - * Promotes the TryCatch0 to a Validation that returns an Exception on the failure side and its result on the success side. + * Promotes the Try0 to a Validation that returns an Exception on the failure side and its result on the success side. * - * @param t A TryCatch0 to promote + * @param t A Try0 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ static public P1> f(final Try0 t) { @@ -32,9 +32,9 @@ static public P1> f(final Try0 t } /** - * Promotes the TryCatch1 to a Validation that returns an Exception on the failure side and its result on the success side. + * Promotes the Try1 to a Validation that returns an Exception on the failure side and its result on the success side. * - * @param t A TryCatch1 to promote + * @param t A Try1 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ static public F> f(final Try1 t) { @@ -48,9 +48,9 @@ static public F> f(final Try1 F2> f(final Try2 t) { @@ -64,9 +64,9 @@ static public F2> f(final } /** - * Promotes the TryCatch3 to a Validation that returns an Exception on the failure side and its result on the success side. + * Promotes the Try3 to a Validation that returns an Exception on the failure side and its result on the success side. * - * @param t A TryCatch3 to promote + * @param t A Try3 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ static public F3> f(final Try3 t) { @@ -80,9 +80,9 @@ static public F3> f( } /** - * Promotes the TryCatch4 to a Validation that returns an Exception on the failure side and its result on the success side. + * Promotes the Try4 to a Validation that returns an Exception on the failure side and its result on the success side. * - * @param t A TryCatch4 to promote + * @param t A Try4 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ static public F4> f(final Try4 t) { @@ -96,9 +96,9 @@ static public F4 F5> f(final Try5 t) { @@ -112,9 +112,9 @@ static public F5 F6> f(final Try6 t) { @@ -128,9 +128,9 @@ static public F6 F7> f(final Try7 t) { @@ -144,9 +144,9 @@ static public F7 F8> f(final Try8 t) { diff --git a/core/src/main/java/fj/function/Try0.java b/core/src/main/java/fj/function/Try0.java index 9898e2af..e218f0a7 100644 --- a/core/src/main/java/fj/function/Try0.java +++ b/core/src/main/java/fj/function/Try0.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to a P1. * - * @see fj.Try#f + * @see fj.Try#f(Try0) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try1.java b/core/src/main/java/fj/function/Try1.java index 9bf3d068..b626890b 100644 --- a/core/src/main/java/fj/function/Try1.java +++ b/core/src/main/java/fj/function/Try1.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F. * - * @see fj.Try#f + * @see fj.Try#f(Try1) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try2.java b/core/src/main/java/fj/function/Try2.java index 15dc25fe..94438ccb 100644 --- a/core/src/main/java/fj/function/Try2.java +++ b/core/src/main/java/fj/function/Try2.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F2. * - * @see fj.Try#f + * @see fj.Try#f(Try2) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try3.java b/core/src/main/java/fj/function/Try3.java index 4d3ed383..7464c013 100644 --- a/core/src/main/java/fj/function/Try3.java +++ b/core/src/main/java/fj/function/Try3.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F3. * - * @see fj.Try#f + * @see fj.Try#f(Try3) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try4.java b/core/src/main/java/fj/function/Try4.java index f919ccbb..a7d969ed 100644 --- a/core/src/main/java/fj/function/Try4.java +++ b/core/src/main/java/fj/function/Try4.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F4. * - * @see fj.Try#f + * @see fj.Try#f(Try4) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try5.java b/core/src/main/java/fj/function/Try5.java index cd9fb31f..b9855fd7 100644 --- a/core/src/main/java/fj/function/Try5.java +++ b/core/src/main/java/fj/function/Try5.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F5. * - * @see fj.Try#f + * @see fj.Try#f(Try5) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try6.java b/core/src/main/java/fj/function/Try6.java index c12d1672..b66775c6 100644 --- a/core/src/main/java/fj/function/Try6.java +++ b/core/src/main/java/fj/function/Try6.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F6. * - * @see fj.Try#f + * @see fj.Try#f(Try6) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try7.java b/core/src/main/java/fj/function/Try7.java index 69c4dddd..3bc09cd9 100644 --- a/core/src/main/java/fj/function/Try7.java +++ b/core/src/main/java/fj/function/Try7.java @@ -6,7 +6,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F7. * - * @see fj.Try#f + * @see fj.Try#f(Try7) * @version %build.number% */ diff --git a/core/src/main/java/fj/function/Try8.java b/core/src/main/java/fj/function/Try8.java index 51e61990..5b2f1b55 100644 --- a/core/src/main/java/fj/function/Try8.java +++ b/core/src/main/java/fj/function/Try8.java @@ -5,7 +5,7 @@ * * Used to instantiate a lambda that may throw an Exception before converting to an F8. * - * @see fj.Try#f + * @see fj.Try#f(Try8) * @version %build.number% */ From 84f945ee7962c71c3c1c2bdbc374d1d653c92a0d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 18 Jan 2015 23:15:13 +1000 Subject: [PATCH 229/811] Added releases notes for versions as asciidoc --- etc/release-notes.md | 64 ++++++++++++++++++++++- etc/release-notes/release-notes-2.22.adoc | 7 +++ etc/release-notes/release-notes-2.23.adoc | 6 +++ etc/release-notes/release-notes-3.0.adoc | 7 +++ etc/release-notes/release-notes-3.1.adoc | 33 ++++++++++++ etc/release-notes/release-notes-3.2.adoc | 10 ++++ etc/release-notes/release-notes-4.0.adoc | 8 +++ etc/release-notes/release-notes-4.1.adoc | 7 +++ etc/release-notes/release-notes-4.2.adoc | 47 +++++++++++++++++ etc/release-notes/release-notes-4.3.adoc | 12 +++++ 10 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 etc/release-notes/release-notes-2.22.adoc create mode 100644 etc/release-notes/release-notes-2.23.adoc create mode 100644 etc/release-notes/release-notes-3.0.adoc create mode 100644 etc/release-notes/release-notes-3.1.adoc create mode 100644 etc/release-notes/release-notes-3.2.adoc create mode 100644 etc/release-notes/release-notes-4.0.adoc create mode 100644 etc/release-notes/release-notes-4.1.adoc create mode 100644 etc/release-notes/release-notes-4.2.adoc create mode 100644 etc/release-notes/release-notes-4.3.adoc diff --git a/etc/release-notes.md b/etc/release-notes.md index c1649f01..21db503a 100644 --- a/etc/release-notes.md +++ b/etc/release-notes.md @@ -84,10 +84,58 @@ Released: 30 May, 2014 === Released: May 2012 +Administrivia: + +* Sources have been moved to GitHub: https://github.com/functionaljava/functionaljava +* Built has been converted to SBT + +New features: + +* List.mapMOption - list traversal in the Option monad. +* List.allEqual - Returns whether or not all elements in the list are equal. +* Added a monoid for Double. +* Tree.bottomUp - Grows a tree from another tree by folding it from the bottom up. +* Strings.isNotNullOrEmpty - does what it says. +* Ord.hashOrd - an order instance that uses hashCode() for the order. +* Ord.hashEqualsOrd - same as above but also uses .equals() +* Set.set - A vararg Set factory method. +* Added first-class functions for Set intersect, union, and minus. +* First-class LazyString.toString. +* Added hashCode() and equals() to Option. +* Iteratees and an IO monad. +* Trampoline - a general solution for tail-call elimination in Java. +* List.equals(), List.hashCode(), and List.toString(). + +Bug fixes: + +* Stream.inits should always be nonempty. +* Stream was not compiling in Eclipse. +* Stream.length is now tail-recursive. +* TreeZipper.delete was flipping lefts and rights. +* Fixed naturalOrd Javadoc. + 3.0 === Released: Jun 2010 +A crucial change has been made to the F interfaces, which are now abstract classes and containing useful methods. This means some other methods (fj.Function) are redundant and will be removed in a release soon (perhaps with a @Deprecated first). + +There are other minor additions and bug fixes. + +2.23 +==== +Released: TODO + +Changes: TODO + +2.22 +==== +Released: March 2010 + +* Bug fixes +* Documentation fixes +* Built against JDK 1.5 (not 1.6) + 2.21 ==== Released Feb, 2010 @@ -97,7 +145,21 @@ Released Feb, 2010 2.20 === -Unknown +Released: July 2009 + +The highlight of this release is a parallel module built on top of +actors for doing some very clever and high-level parallel programming. +e.g. An implementation of the parallel map/reduce algorithm +(parFoldMap) and APIs for making use of actors easier for you, the user. + +Other new bits includes: + +* A heap of bug fixes, particularly on Stream (and therefore, many of +its dependencies) +* LazyString -- a lazy sequence of characters +* Function Wrappers +* Improvements to the Tree and Zipper implementations +* Other tidbits and additional APIs 2.19 === diff --git a/etc/release-notes/release-notes-2.22.adoc b/etc/release-notes/release-notes-2.22.adoc new file mode 100644 index 00000000..f0df973e --- /dev/null +++ b/etc/release-notes/release-notes-2.22.adoc @@ -0,0 +1,7 @@ += Release 2.22 + +Released: March 2010 + +* Bug fixes +* Documentation fixes +* Built against JDK 1.5 (not 1.6) diff --git a/etc/release-notes/release-notes-2.23.adoc b/etc/release-notes/release-notes-2.23.adoc new file mode 100644 index 00000000..fbcdb436 --- /dev/null +++ b/etc/release-notes/release-notes-2.23.adoc @@ -0,0 +1,6 @@ += Release 2.23 + +Released: TODO + +Changes: TODO + diff --git a/etc/release-notes/release-notes-3.0.adoc b/etc/release-notes/release-notes-3.0.adoc new file mode 100644 index 00000000..a685b98a --- /dev/null +++ b/etc/release-notes/release-notes-3.0.adoc @@ -0,0 +1,7 @@ += Release 3.0 + +Released: Jun 2010 + +A crucial change has been made to the F interfaces, which are now abstract classes and containing useful methods. This means some other methods (fj.Function) are redundant and will be removed in a release soon (perhaps with a @Deprecated first). + +There are other minor additions and bug fixes. diff --git a/etc/release-notes/release-notes-3.1.adoc b/etc/release-notes/release-notes-3.1.adoc new file mode 100644 index 00000000..0c7e1071 --- /dev/null +++ b/etc/release-notes/release-notes-3.1.adoc @@ -0,0 +1,33 @@ += Release 3.1 + +Released: May 2012 + +Administrivia: + +* Sources have been moved to GitHub: https://github.com/functionaljava/functionaljava +* Built has been converted to SBT + +New features: + +* List.mapMOption - list traversal in the Option monad. +* List.allEqual - Returns whether or not all elements in the list are equal. +* Added a monoid for Double. +* Tree.bottomUp - Grows a tree from another tree by folding it from the bottom up. +* Strings.isNotNullOrEmpty - does what it says. +* Ord.hashOrd - an order instance that uses hashCode() for the order. +* Ord.hashEqualsOrd - same as above but also uses .equals() +* Set.set - A vararg Set factory method. +* Added first-class functions for Set intersect, union, and minus. +* First-class LazyString.toString. +* Added hashCode() and equals() to Option. +* Iteratees and an IO monad. +* Trampoline - a general solution for tail-call elimination in Java. +* List.equals(), List.hashCode(), and List.toString(). + +Bug fixes: + +* Stream.inits should always be nonempty. +* Stream was not compiling in Eclipse. +* Stream.length is now tail-recursive. +* TreeZipper.delete was flipping lefts and rights. +* Fixed naturalOrd Javadoc. diff --git a/etc/release-notes/release-notes-3.2.adoc b/etc/release-notes/release-notes-3.2.adoc new file mode 100644 index 00000000..7c10f6fb --- /dev/null +++ b/etc/release-notes/release-notes-3.2.adoc @@ -0,0 +1,10 @@ += Release 3.2 + +Released: 30 May, 2014 + +* Added methods to HashMap: toList, toStream, toOption, toArray, map, mapKeys, foreach, convert to/from java.util.Map. +* Convert from java.util.List to List. +* Fixed findChild method in TreeZipper to handle empty stream. +* Fixed stack overflow when sorting and zipping. +* Fixed stack overflow in Stream's bind method. +* Small Javadoc fixes. diff --git a/etc/release-notes/release-notes-4.0.adoc b/etc/release-notes/release-notes-4.0.adoc new file mode 100644 index 00000000..e685d91d --- /dev/null +++ b/etc/release-notes/release-notes-4.0.adoc @@ -0,0 +1,8 @@ + += Release 4.0 + +Released: 30 May, 2014 + +* Merged changes from 3.2 +* Minimal changes to support Java 8. +* Changed abstract classes to interfaces with default methods (P1, F1 to F8). diff --git a/etc/release-notes/release-notes-4.1.adoc b/etc/release-notes/release-notes-4.1.adoc new file mode 100644 index 00000000..484c9e8e --- /dev/null +++ b/etc/release-notes/release-notes-4.1.adoc @@ -0,0 +1,7 @@ + += Release 4.1 + +Released: 30 May, 2014 + +* Support Java 7 by removing default methods. Methods on class C with default methods moved to static methods on new class ${C}Functions. + diff --git a/etc/release-notes/release-notes-4.2.adoc b/etc/release-notes/release-notes-4.2.adoc new file mode 100644 index 00000000..a0400a27 --- /dev/null +++ b/etc/release-notes/release-notes-4.2.adoc @@ -0,0 +1,47 @@ + += Release 4.2 + +Released: 20 December, 2014 + +== Enhancements + +* Added Java 8 examples +* Added new website +* Added Option.none_() +* Gradle 2.2.1 support with wrapper +* Added to Strings: isNullOrEmpty, isNullOrBlank and isNotNullOrBlank +* Added Try with arity 0-8 for lambdas that throw exceptions +* Added Effect with arity 0-8 for lambdas with a void return +* Added TryEffect with arity 0-8 for lambdas with a void return that throw an Exception. +* Conversion from Java 8 types to Functional Java types and vice-versa +* Added monadic IO methods +* Support instantiation of IO with lambdas +* Added first class cons_ for List +* Added partial application of first parameter for F 1-8 +* Added SafeIO that encodes IOExceptions into Validations +* Added simple RNG +* Added Reader, Writer and State +* Deprecated $._ +* Added Array.scan family of methods +* Support instantiating P1 values using lambdas to P.lazy +* Added toString for Validation, P arities 1 to 8, Either +* Added vending machine demo +* Added Option.toValidation +* Added map and contramap for F and F2. +* Added partial application for F1. +* Added filter and uncurried foldLeft and foldRight to FingerTree. +* Added foldLeft, foldRight and map to Seq. +* Accumulate Validation errors in a List. +* Convert from fj.data.Stream to java.util.Stream and vice versa. +* Added groupBy on List. + +== Fixes + +* Various Javadoc issues +* Large inserts into TreeMap +* Javadoc support for Java 8 +* Null parameter NullPointerException for Show.anyShow +* Exception propagation in test data generators +* Product memoisation for arities 1 to 8 +* ClassCastException in class fj.data.Java +* Fixed performance of Set.member. diff --git a/etc/release-notes/release-notes-4.3.adoc b/etc/release-notes/release-notes-4.3.adoc new file mode 100644 index 00000000..75e5bca0 --- /dev/null +++ b/etc/release-notes/release-notes-4.3.adoc @@ -0,0 +1,12 @@ + += Release 4.3 + +Released: Unreleased + +== Enhancements + +TODO + +== Fixes + +TODO From 97278b42a24d402092950309fa97cd15ce363099 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 22 Jan 2015 01:43:00 +1000 Subject: [PATCH 230/811] Introduced F0 interface for lazy values equivalent to P1 --- core/src/main/java/fj/F0.java | 10 ++++++++++ core/src/main/java/fj/P.java | 8 ++++++-- core/src/main/java/fj/P1.java | 7 ++++++- .../main/java/fj/control/parallel/Promise.java | 15 +++------------ .../main/java/fj/demo/concurrent/MapReduce.java | 11 ++--------- 5 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 core/src/main/java/fj/F0.java diff --git a/core/src/main/java/fj/F0.java b/core/src/main/java/fj/F0.java new file mode 100644 index 00000000..e85689da --- /dev/null +++ b/core/src/main/java/fj/F0.java @@ -0,0 +1,10 @@ +package fj; + +/** + * Created by MarkPerry on 21/01/2015. + */ +public interface F0 { + + public A f(); + +} diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 9347c060..d0e99bb4 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -675,15 +675,19 @@ public H _8() { }; } - public static P1 lazy(F f) { + public static P1 lazy(F0 f) { return new P1() { @Override public A _1() { - return f.f(unit()); + return f.f(); } }; } + public static P1 lazy(F f) { + return lazy(() -> f.f(unit())); + } + public static P2 lazy(F fa, F fb) { return new P2() { @Override diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 737431dd..b53e6269 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -8,7 +8,12 @@ import fj.data.Validation; import fj.function.Try0; -public abstract class P1 { +public abstract class P1 implements F0 { + + @Override + public A f() { + return _1(); + } /** * Access the first element of the product. diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 81389e26..d74e6522 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -1,12 +1,7 @@ package fj.control.parallel; -import fj.Effect; -import fj.F; -import fj.F2; -import fj.P; -import fj.P1; -import fj.P2; -import fj.Unit; +import fj.*; + import static fj.P.p; import static fj.Function.curry; import static fj.Function.identity; @@ -353,11 +348,7 @@ public static F, Promise> foldRightS(final Strategy s, return new F, Promise>() { public Promise f(final Stream as) { return as.isEmpty() ? promise(s, P.p(b)) : liftM2(f).f(promise(s, P.p(as.head()))).f( - Promise.>join(s, new P1>>() { - public Promise> _1() { - return f(as.tail()._1()).fmap(P.p1()); - } - })); + Promise.>join(s, P.lazy(u -> f(as.tail()._1()).fmap(P.p1())))); } }; } diff --git a/demo/src/main/java/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java index 72e68391..fd8b5282 100644 --- a/demo/src/main/java/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -1,9 +1,6 @@ package fj.demo.concurrent; -import fj.F; -import fj.F1Functions; -import fj.P1; -import fj.Unit; +import fj.*; import fj.control.parallel.ParModule; import static fj.control.parallel.ParModule.parModule; import fj.control.parallel.Promise; @@ -58,11 +55,7 @@ public Stream f(final BufferedReader reader) { throw new Error(e); } if (s.isSome()) - return fromString(s.some()).append(new P1>() { - public Stream _1() { - return f(reader); - } - }); + return fromString(s.some()).append(P.lazy(sc -> f(reader))); else { try { reader.close(); From ce64104805b90cd4e05050499e04a4f047a41e14 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 22 Jan 2015 23:11:55 +1000 Subject: [PATCH 231/811] Implement F2W, but returns interface --- core/src/main/java/fj/F1W.java | 673 +++++++++++++++++++++++++++++++++ core/src/main/java/fj/F2W.java | 7 + 2 files changed, 680 insertions(+) create mode 100644 core/src/main/java/fj/F1W.java create mode 100644 core/src/main/java/fj/F2W.java diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java new file mode 100644 index 00000000..54bcea74 --- /dev/null +++ b/core/src/main/java/fj/F1W.java @@ -0,0 +1,673 @@ +package fj; + +import fj.control.parallel.Actor; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.*; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.PriorityQueue; +import java.util.TreeSet; +import java.util.concurrent.*; + +import static fj.data.Option.some; +import static fj.data.Stream.iterableStream; +import static fj.data.Zipper.fromStream; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F1W implements F { + + /** + * Function composition + * + * @param g A function to compose with this one. + * @return The composed function such that this function is applied last. + */ + public F o(final F g) { + return F1Functions.o(this, g); + } + + /** + * First-class function composition + * + * @return A function that composes this function with another. + */ + public F, F> o() { + return F1Functions.o(this); + } + + /** + * Function composition flipped. + * + * @param g A function with which to compose this one. + * @return The composed function such that this function is applied first. + */ + @SuppressWarnings({"unchecked"}) + public F andThen(final F g) { + return F1Functions.andThen(this, g); + } + + /** + * First-class composition flipped. + * + * @return A function that invokes this function and then a given function on the result. + */ + public F, F> andThen() { + return F1Functions.andThen(this); + } + + /** + * Binds a given function across this function (Reader Monad). + * + * @param g A function that takes the return value of this function as an argument, yielding a new function. + * @return A function that invokes this function on its argument and then the given function on the result. + */ + public F bind(final F> g) { + return F1Functions.bind(this, g); + } + + + /** + * First-class function binding. + * + * @return A function that binds another function across this function. + */ + public F>, F> bind() { + return F1Functions.bind(this); + } + + /** + * Function application in an environment (Applicative Functor). + * + * @param g A function with the same argument type as this function, yielding a function that takes the return + * value of this function. + * @return A new function that invokes the given function on its argument, yielding a new function that is then + * applied to the result of applying this function to the argument. + */ + public F apply(final F> g) { + return F1Functions.apply(this, g); + } + + + /** + * First-class function application in an environment. + * + * @return A function that applies a given function within the environment of this function. + */ + public F>, F> apply() { + return F1Functions.apply(this); + } + + /** + * Applies this function over the arguments of another function. + * + * @param g The function over whose arguments to apply this function. + * @return A new function that invokes this function on its arguments before invoking the given function. + */ + public F> on(final F> g) { + return F1Functions.on(this, g); + } + + + /** + * Applies this function over the arguments of another function. + * + * @return A function that applies this function over the arguments of another function. + */ + public F>, F>> on() { + return F1Functions.on(this); + } + + /** + * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1. + * + * @return This function promoted to return its result in a product-1. + */ + public F> lazy() { + return F1Functions.lazy(this); + } + + + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument to return a lazy value. + */ + public P1 lazy(final A a) { + return F1Functions.f(this, a); + } + + /** + * Promotes this function to map over a product-1. + * + * @return This function promoted to map over a product-1. + */ + public F, P1> mapP1() { + return F1Functions.mapP1(this); + } + + /** + * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option. + * + * @return This function promoted to return its result in an Option. + */ + public F> optionK() { + return F1Functions.optionK(this); + } + + + /** + * Promotes this function to map over an optional value. + * + * @return This function promoted to map over an optional value. + */ + public F, Option> mapOption() { + return F1Functions.mapOption(this); + } + + /** + * Promotes this function so that it returns its result in a List. Kleisli arrow for List. + * + * @return This function promoted to return its result in a List. + */ + public F> listK() { + return F1Functions.listK(this); + } + + /** + * Promotes this function to map over a List. + * + * @return This function promoted to map over a List. + */ + public F, List> mapList() { + return F1Functions.mapList(this); + } + + /** + * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream. + * + * @return This function promoted to return its result in a Stream. + */ + public F> streamK() { + return F1Functions.streamK(this); + } + + /** + * Promotes this function to map over a Stream. + * + * @return This function promoted to map over a Stream. + */ + public F, Stream> mapStream() { + return F1Functions.mapStream(this); + } + + /** + * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array. + * + * @return This function promoted to return its result in a Array. + */ + public F> arrayK() { + return F1Functions.arrayK(this); + + } + + /** + * Promotes this function to map over a Array. + * + * @return This function promoted to map over a Array. + */ + public F, Array> mapArray() { + return F1Functions.mapArray(this); + } + + /** + * Returns a function that comaps over a given actor. + * + * @return A function that comaps over a given actor. + */ + public F, Actor> comapActor() { + return F1Functions.comapActor(this); + } + + /** + * Promotes this function to a concurrent function that returns a Promise of a value. + * + * @param s A parallel strategy for concurrent execution. + * @return A concurrent function that returns a Promise of a value. + */ + public F> promiseK(final Strategy s) { + return F1Functions.promiseK(this, s); + } + + /** + * Promotes this function to map over a Promise. + * + * @return This function promoted to map over Promises. + */ + public F, Promise> mapPromise() { + return F1Functions.mapPromise(this); + } + + /** + * Promotes this function so that it returns its result on the left side of an Either. + * Kleisli arrow for the Either left projection. + * + * @return This function promoted to return its result on the left side of an Either. + */ + @SuppressWarnings({"unchecked"}) + public F> eitherLeftK() { + return F1Functions.eitherLeftK(this); + } + + /** + * Promotes this function so that it returns its result on the right side of an Either. + * Kleisli arrow for the Either right projection. + * + * @return This function promoted to return its result on the right side of an Either. + */ + @SuppressWarnings({"unchecked"}) + public F> eitherRightK() { + return F1Functions.eitherRightK(this); + } + + /** + * Promotes this function to map over the left side of an Either. + * + * @return This function promoted to map over the left side of an Either. + */ + @SuppressWarnings({"unchecked"}) + public F, Either> mapLeft() { + return F1Functions.mapLeft(this); + } + + /** + * Promotes this function to map over the right side of an Either. + * + * @return This function promoted to map over the right side of an Either. + */ + @SuppressWarnings({"unchecked"}) + public F, Either> mapRight() { + return F1Functions.mapRight(this); + } + + /** + * Returns a function that returns the left side of a given Either, or this function applied to the right side. + * + * @return a function that returns the left side of a given Either, or this function applied to the right side. + */ + public F, B> onLeft() { + return F1Functions.onLeft(this); + } + + /** + * Returns a function that returns the right side of a given Either, or this function applied to the left side. + * + * @return a function that returns the right side of a given Either, or this function applied to the left side. + */ + public F, B> onRight() { + return F1Functions.onRight(this); + } + + /** + * Promotes this function to return its value in an Iterable. + * + * @return This function promoted to return its value in an Iterable. + */ + @SuppressWarnings({"unchecked"}) + public F> iterableK() { + return F1Functions.iterableK(this); + } + + /** + * Promotes this function to map over Iterables. + * + * @return This function promoted to map over Iterables. + */ + @SuppressWarnings({"unchecked"}) + public F, IterableW> mapIterable() { + return F1Functions.mapIterable(this); + } + + /** + * Promotes this function to return its value in a NonEmptyList. + * + * @return This function promoted to return its value in a NonEmptyList. + */ + @SuppressWarnings({"unchecked"}) + public F> nelK() { + return F1Functions.nelK(this); + } + + /** + * Promotes this function to map over a NonEmptyList. + * + * @return This function promoted to map over a NonEmptyList. + */ + public F, NonEmptyList> mapNel() { + return F1Functions.mapNel(this); + } + + /** + * Promotes this function to return its value in a Set. + * + * @param o An order for the set. + * @return This function promoted to return its value in a Set. + */ + public F> setK(final Ord o) { + return F1Functions.setK(this, o); + } + + /** + * Promotes this function to map over a Set. + * + * @param o An order for the resulting set. + * @return This function promoted to map over a Set. + */ + public F, Set> mapSet(final Ord o) { + return F1Functions.mapSet(this, o); + } + + /** + * Promotes this function to return its value in a Tree. + * + * @return This function promoted to return its value in a Tree. + */ + public F> treeK() { + return F1Functions.treeK(this); + } + + /** + * Promotes this function to map over a Tree. + * + * @return This function promoted to map over a Tree. + */ + @SuppressWarnings({"unchecked"}) + public F, Tree> mapTree() { + return F1Functions.mapTree(this); + } + + /** + * Returns a function that maps this function over a tree and folds it with the given monoid. + * + * @param m The monoid with which to fold the mapped tree. + * @return a function that maps this function over a tree and folds it with the given monoid. + */ + public F, B> foldMapTree(final Monoid m) { + return F1Functions.foldMapTree(this, m); + } + + /** + * Promotes this function to return its value in a TreeZipper. + * + * @return This function promoted to return its value in a TreeZipper. + */ + public F> treeZipperK() { + return F1Functions.treeZipperK(this); + } + + /** + * Promotes this function to map over a TreeZipper. + * + * @return This function promoted to map over a TreeZipper. + */ + public F, TreeZipper> mapTreeZipper() { + return F1Functions.mapTreeZipper(this); + } + + /** + * Promotes this function so that it returns its result on the failure side of a Validation. + * Kleisli arrow for the Validation failure projection. + * + * @return This function promoted to return its result on the failure side of a Validation. + */ + public F> failK() { + return F1Functions.failK(this); + } + + /** + * Promotes this function so that it returns its result on the success side of an Validation. + * Kleisli arrow for the Validation success projection. + * + * @return This function promoted to return its result on the success side of an Validation. + */ + public F> successK() { + return F1Functions.successK(this); + } + + /** + * Promotes this function to map over the failure side of a Validation. + * + * @return This function promoted to map over the failure side of a Validation. + */ + public F, Validation> mapFail() { + return F1Functions.mapFail(this); + } + + /** + * Promotes this function to map over the success side of a Validation. + * + * @return This function promoted to map over the success side of a Validation. + */ + public F, Validation> mapSuccess() { + return F1Functions.mapSuccess(this); + } + + /** + * Returns a function that returns the failure side of a given Validation, + * or this function applied to the success side. + * + * @return a function that returns the failure side of a given Validation, + * or this function applied to the success side. + */ + public F, B> onFail() { + return F1Functions.onFail(this); + } + + /** + * Returns a function that returns the success side of a given Validation, + * or this function applied to the failure side. + * + * @return a function that returns the success side of a given Validation, + * or this function applied to the failure side. + */ + public F, B> onSuccess() { + return F1Functions.onSuccess(this); + } + + /** + * Promotes this function to return its value in a Zipper. + * + * @return This function promoted to return its value in a Zipper. + */ + public F> zipperK() { + return F1Functions.zipperK(this); + } + + /** + * Promotes this function to map over a Zipper. + * + * @return This function promoted to map over a Zipper. + */ + public F, Zipper> mapZipper() { + return F1Functions.mapZipper(this); + } + + /** + * Promotes this function to map over an Equal as a contravariant functor. + * + * @return This function promoted to map over an Equal as a contravariant functor. + */ + public F, Equal> comapEqual() { + return F1Functions.comapEqual(this); + } + + /** + * Promotes this function to map over a Hash as a contravariant functor. + * + * @return This function promoted to map over a Hash as a contravariant functor. + */ + public F, Hash> comapHash() { + return F1Functions.comapHash(this); + } + + /** + * Promotes this function to map over a Show as a contravariant functor. + * + * @return This function promoted to map over a Show as a contravariant functor. + */ + public F, Show> comapShow() { + return F1Functions.comapShow(this); + } + + /** + * Promotes this function to map over the first element of a pair. + * + * @return This function promoted to map over the first element of a pair. + */ + public F, P2> mapFst() { + return F1Functions.mapFst(this); + } + + /** + * Promotes this function to map over the second element of a pair. + * + * @return This function promoted to map over the second element of a pair. + */ + public F, P2> mapSnd() { + return F1Functions.mapSnd(this); + } + + /** + * Promotes this function to map over both elements of a pair. + * + * @return This function promoted to map over both elements of a pair. + */ + public F, P2> mapBoth() { + return F1Functions.mapBoth(this); + } + + /** + * Maps this function over a SynchronousQueue. + * + * @param as A SynchronousQueue to map this function over. + * @return A new SynchronousQueue with this function applied to each element. + */ + public SynchronousQueue mapJ(final SynchronousQueue as) { + return F1Functions.mapJ(this, as); + } + + + /** + * Maps this function over a PriorityBlockingQueue. + * + * @param as A PriorityBlockingQueue to map this function over. + * @return A new PriorityBlockingQueue with this function applied to each element. + */ + public PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over a LinkedBlockingQueue. + * + * @param as A LinkedBlockingQueue to map this function over. + * @return A new LinkedBlockingQueue with this function applied to each element. + */ + public LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over a CopyOnWriteArraySet. + * + * @param as A CopyOnWriteArraySet to map this function over. + * @return A new CopyOnWriteArraySet with this function applied to each element. + */ + public CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over a CopyOnWriteArrayList. + * + * @param as A CopyOnWriteArrayList to map this function over. + * @return A new CopyOnWriteArrayList with this function applied to each element. + */ + public CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over a ConcurrentLinkedQueue. + * + * @param as A ConcurrentLinkedQueue to map this function over. + * @return A new ConcurrentLinkedQueue with this function applied to each element. + */ + public ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over an ArrayBlockingQueue. + * + * @param as An ArrayBlockingQueue to map this function over. + * @return A new ArrayBlockingQueue with this function applied to each element. + */ + public ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { + return F1Functions.mapJ(this, as); + } + + + /** + * Maps this function over a TreeSet. + * + * @param as A TreeSet to map this function over. + * @return A new TreeSet with this function applied to each element. + */ + public TreeSet mapJ(final TreeSet as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over a PriorityQueue. + * + * @param as A PriorityQueue to map this function over. + * @return A new PriorityQueue with this function applied to each element. + */ + public PriorityQueue mapJ(final PriorityQueue as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over a LinkedList. + * + * @param as A LinkedList to map this function over. + * @return A new LinkedList with this function applied to each element. + */ + public LinkedList mapJ(final LinkedList as) { + return F1Functions.mapJ(this, as); + } + + /** + * Maps this function over an ArrayList. + * + * @param as An ArrayList to map this function over. + * @return A new ArrayList with this function applied to each element. + */ + public ArrayList mapJ(final ArrayList as) { + return F1Functions.mapJ(this, as); + } + + public F map(F f) { + return F1Functions.map(this, f); + } + + public F contramap(F f) { + return F1Functions.contramap(this, f); + } + +} diff --git a/core/src/main/java/fj/F2W.java b/core/src/main/java/fj/F2W.java new file mode 100644 index 00000000..fefffc28 --- /dev/null +++ b/core/src/main/java/fj/F2W.java @@ -0,0 +1,7 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F2W implements F2 { +} From 0ca6e3e1a2b1ad3bf04f2b1db1f08cd6629e44cf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 23 Jan 2015 00:01:04 +1000 Subject: [PATCH 232/811] Made F1W return wrapper functions --- core/src/main/java/fj/F1W.java | 242 ++++++++++++++++++--------------- 1 file changed, 130 insertions(+), 112 deletions(-) diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java index 54bcea74..a0522bab 100644 --- a/core/src/main/java/fj/F1W.java +++ b/core/src/main/java/fj/F1W.java @@ -26,8 +26,8 @@ public abstract class F1W implements F { * @param g A function to compose with this one. * @return The composed function such that this function is applied last. */ - public F o(final F g) { - return F1Functions.o(this, g); + public F1W o(final F g) { + return lift(F1Functions.o(this, g)); } /** @@ -35,8 +35,8 @@ public F o(final F g) { * * @return A function that composes this function with another. */ - public F, F> o() { - return F1Functions.o(this); + public F1W, F> o() { + return lift(F1Functions.o(this)); } /** @@ -46,8 +46,8 @@ public F, F> o() { * @return The composed function such that this function is applied first. */ @SuppressWarnings({"unchecked"}) - public F andThen(final F g) { - return F1Functions.andThen(this, g); + public F1W andThen(final F g) { + return lift(F1Functions.andThen(this, g)); } /** @@ -55,8 +55,8 @@ public F andThen(final F g) { * * @return A function that invokes this function and then a given function on the result. */ - public F, F> andThen() { - return F1Functions.andThen(this); + public F1W, F> andThen() { + return lift( F1Functions.andThen(this)); } /** @@ -65,8 +65,8 @@ public F, F> andThen() { * @param g A function that takes the return value of this function as an argument, yielding a new function. * @return A function that invokes this function on its argument and then the given function on the result. */ - public F bind(final F> g) { - return F1Functions.bind(this, g); + public F1W bind(final F> g) { + return lift(F1Functions.bind(this, g)); } @@ -75,8 +75,8 @@ public F bind(final F> g) { * * @return A function that binds another function across this function. */ - public F>, F> bind() { - return F1Functions.bind(this); + public F1W>, F> bind() { + return lift(F1Functions.bind(this)); } /** @@ -87,8 +87,8 @@ public F>, F> bind() { * @return A new function that invokes the given function on its argument, yielding a new function that is then * applied to the result of applying this function to the argument. */ - public F apply(final F> g) { - return F1Functions.apply(this, g); + public F1W apply(final F> g) { + return lift(F1Functions.apply(this, g)); } @@ -97,8 +97,8 @@ public F apply(final F> g) { * * @return A function that applies a given function within the environment of this function. */ - public F>, F> apply() { - return F1Functions.apply(this); + public F1W>, F> apply() { + return lift(F1Functions.apply(this)); } /** @@ -107,8 +107,8 @@ public F>, F> apply() { * @param g The function over whose arguments to apply this function. * @return A new function that invokes this function on its arguments before invoking the given function. */ - public F> on(final F> g) { - return F1Functions.on(this, g); + public F1W> on(final F> g) { + return lift(F1Functions.on(this, g)); } @@ -117,8 +117,8 @@ public F> on(final F> g) { * * @return A function that applies this function over the arguments of another function. */ - public F>, F>> on() { - return F1Functions.on(this); + public F1W>, F>> on() { + return lift(F1Functions.on(this)); } /** @@ -126,8 +126,8 @@ public F>, F>> on() { * * @return This function promoted to return its result in a product-1. */ - public F> lazy() { - return F1Functions.lazy(this); + public F1W> lazy() { + return lift(F1Functions.lazy(this)); } @@ -146,8 +146,8 @@ public P1 lazy(final A a) { * * @return This function promoted to map over a product-1. */ - public F, P1> mapP1() { - return F1Functions.mapP1(this); + public F1W, P1> mapP1() { + return lift(F1Functions.mapP1(this)); } /** @@ -155,8 +155,8 @@ public F, P1> mapP1() { * * @return This function promoted to return its result in an Option. */ - public F> optionK() { - return F1Functions.optionK(this); + public F1W> optionK() { + return lift(F1Functions.optionK(this)); } @@ -165,8 +165,8 @@ public F> optionK() { * * @return This function promoted to map over an optional value. */ - public F, Option> mapOption() { - return F1Functions.mapOption(this); + public F1W, Option> mapOption() { + return lift(F1Functions.mapOption(this)); } /** @@ -174,8 +174,8 @@ public F, Option> mapOption() { * * @return This function promoted to return its result in a List. */ - public F> listK() { - return F1Functions.listK(this); + public F1W> listK() { + return lift( F1Functions.listK(this)); } /** @@ -183,8 +183,8 @@ public F> listK() { * * @return This function promoted to map over a List. */ - public F, List> mapList() { - return F1Functions.mapList(this); + public F1W, List> mapList() { + return lift(F1Functions.mapList(this)); } /** @@ -192,8 +192,8 @@ public F, List> mapList() { * * @return This function promoted to return its result in a Stream. */ - public F> streamK() { - return F1Functions.streamK(this); + public F1W> streamK() { + return lift(F1Functions.streamK(this)); } /** @@ -201,8 +201,8 @@ public F> streamK() { * * @return This function promoted to map over a Stream. */ - public F, Stream> mapStream() { - return F1Functions.mapStream(this); + public F1W, Stream> mapStream() { + return lift(F1Functions.mapStream(this)); } /** @@ -210,8 +210,8 @@ public F, Stream> mapStream() { * * @return This function promoted to return its result in a Array. */ - public F> arrayK() { - return F1Functions.arrayK(this); + public F1W> arrayK() { + return lift(F1Functions.arrayK(this)); } @@ -220,8 +220,8 @@ public F> arrayK() { * * @return This function promoted to map over a Array. */ - public F, Array> mapArray() { - return F1Functions.mapArray(this); + public F1W, Array> mapArray() { + return lift(F1Functions.mapArray(this)); } /** @@ -229,8 +229,8 @@ public F, Array> mapArray() { * * @return A function that comaps over a given actor. */ - public F, Actor> comapActor() { - return F1Functions.comapActor(this); + public F1W, Actor> comapActor() { + return lift(F1Functions.comapActor(this)); } /** @@ -239,8 +239,8 @@ public F, Actor> comapActor() { * @param s A parallel strategy for concurrent execution. * @return A concurrent function that returns a Promise of a value. */ - public F> promiseK(final Strategy s) { - return F1Functions.promiseK(this, s); + public F1W> promiseK(final Strategy s) { + return lift(F1Functions.promiseK(this, s)); } /** @@ -248,8 +248,8 @@ public F> promiseK(final Strategy s) { * * @return This function promoted to map over Promises. */ - public F, Promise> mapPromise() { - return F1Functions.mapPromise(this); + public F1W, Promise> mapPromise() { + return lift(F1Functions.mapPromise(this)); } /** @@ -259,8 +259,8 @@ public F, Promise> mapPromise() { * @return This function promoted to return its result on the left side of an Either. */ @SuppressWarnings({"unchecked"}) - public F> eitherLeftK() { - return F1Functions.eitherLeftK(this); + public F1W> eitherLeftK() { + return lift(F1Functions.eitherLeftK(this)); } /** @@ -270,8 +270,8 @@ public F> eitherLeftK() { * @return This function promoted to return its result on the right side of an Either. */ @SuppressWarnings({"unchecked"}) - public F> eitherRightK() { - return F1Functions.eitherRightK(this); + public F1W> eitherRightK() { + return lift(F1Functions.eitherRightK(this)); } /** @@ -280,8 +280,8 @@ public F> eitherRightK() { * @return This function promoted to map over the left side of an Either. */ @SuppressWarnings({"unchecked"}) - public F, Either> mapLeft() { - return F1Functions.mapLeft(this); + public F1W, Either> mapLeft() { + return lift(F1Functions.mapLeft(this)); } /** @@ -290,8 +290,8 @@ public F, Either> mapLeft() { * @return This function promoted to map over the right side of an Either. */ @SuppressWarnings({"unchecked"}) - public F, Either> mapRight() { - return F1Functions.mapRight(this); + public F1W, Either> mapRight() { + return lift(F1Functions.mapRight(this)); } /** @@ -299,8 +299,8 @@ public F, Either> mapRight() { * * @return a function that returns the left side of a given Either, or this function applied to the right side. */ - public F, B> onLeft() { - return F1Functions.onLeft(this); + public F1W, B> onLeft() { + return lift(F1Functions.onLeft(this)); } /** @@ -308,8 +308,8 @@ public F, B> onLeft() { * * @return a function that returns the right side of a given Either, or this function applied to the left side. */ - public F, B> onRight() { - return F1Functions.onRight(this); + public F1W, B> onRight() { + return lift(F1Functions.onRight(this)); } /** @@ -318,8 +318,8 @@ public F, B> onRight() { * @return This function promoted to return its value in an Iterable. */ @SuppressWarnings({"unchecked"}) - public F> iterableK() { - return F1Functions.iterableK(this); + public F1W> iterableK() { + return lift( F1Functions.iterableK(this)); } /** @@ -328,8 +328,8 @@ public F> iterableK() { * @return This function promoted to map over Iterables. */ @SuppressWarnings({"unchecked"}) - public F, IterableW> mapIterable() { - return F1Functions.mapIterable(this); + public F1W, IterableW> mapIterable() { + return lift( F1Functions.mapIterable(this)); } /** @@ -338,8 +338,8 @@ public F, IterableW> mapIterable() { * @return This function promoted to return its value in a NonEmptyList. */ @SuppressWarnings({"unchecked"}) - public F> nelK() { - return F1Functions.nelK(this); + public F1W> nelK() { + return lift(F1Functions.nelK(this)); } /** @@ -347,8 +347,8 @@ public F> nelK() { * * @return This function promoted to map over a NonEmptyList. */ - public F, NonEmptyList> mapNel() { - return F1Functions.mapNel(this); + public F1W, NonEmptyList> mapNel() { + return lift(F1Functions.mapNel(this)); } /** @@ -357,8 +357,8 @@ public F, NonEmptyList> mapNel() { * @param o An order for the set. * @return This function promoted to return its value in a Set. */ - public F> setK(final Ord o) { - return F1Functions.setK(this, o); + public F1W> setK(final Ord o) { + return lift(F1Functions.setK(this, o)); } /** @@ -367,8 +367,8 @@ public F> setK(final Ord o) { * @param o An order for the resulting set. * @return This function promoted to map over a Set. */ - public F, Set> mapSet(final Ord o) { - return F1Functions.mapSet(this, o); + public F1W, Set> mapSet(final Ord o) { + return lift(F1Functions.mapSet(this, o)); } /** @@ -376,8 +376,8 @@ public F, Set> mapSet(final Ord o) { * * @return This function promoted to return its value in a Tree. */ - public F> treeK() { - return F1Functions.treeK(this); + public F1W> treeK() { + return lift(F1Functions.treeK(this)); } /** @@ -386,8 +386,8 @@ public F> treeK() { * @return This function promoted to map over a Tree. */ @SuppressWarnings({"unchecked"}) - public F, Tree> mapTree() { - return F1Functions.mapTree(this); + public F1W, Tree> mapTree() { + return lift(F1Functions.mapTree(this)); } /** @@ -396,8 +396,8 @@ public F, Tree> mapTree() { * @param m The monoid with which to fold the mapped tree. * @return a function that maps this function over a tree and folds it with the given monoid. */ - public F, B> foldMapTree(final Monoid m) { - return F1Functions.foldMapTree(this, m); + public F1W, B> foldMapTree(final Monoid m) { + return lift(F1Functions.foldMapTree(this, m)); } /** @@ -405,8 +405,8 @@ public F, B> foldMapTree(final Monoid m) { * * @return This function promoted to return its value in a TreeZipper. */ - public F> treeZipperK() { - return F1Functions.treeZipperK(this); + public F1W> treeZipperK() { + return lift(F1Functions.treeZipperK(this)); } /** @@ -414,8 +414,8 @@ public F> treeZipperK() { * * @return This function promoted to map over a TreeZipper. */ - public F, TreeZipper> mapTreeZipper() { - return F1Functions.mapTreeZipper(this); + public F1W, TreeZipper> mapTreeZipper() { + return lift(F1Functions.mapTreeZipper(this)); } /** @@ -424,8 +424,8 @@ public F, TreeZipper> mapTreeZipper() { * * @return This function promoted to return its result on the failure side of a Validation. */ - public F> failK() { - return F1Functions.failK(this); + public F1W> failK() { + return lift(F1Functions.failK(this)); } /** @@ -434,8 +434,8 @@ public F> failK() { * * @return This function promoted to return its result on the success side of an Validation. */ - public F> successK() { - return F1Functions.successK(this); + public F1W> successK() { + return lift( F1Functions.successK(this)); } /** @@ -443,8 +443,8 @@ public F> successK() { * * @return This function promoted to map over the failure side of a Validation. */ - public F, Validation> mapFail() { - return F1Functions.mapFail(this); + public F1W, Validation> mapFail() { + return lift(F1Functions.mapFail(this)); } /** @@ -452,8 +452,8 @@ public F, Validation> mapFail() { * * @return This function promoted to map over the success side of a Validation. */ - public F, Validation> mapSuccess() { - return F1Functions.mapSuccess(this); + public F1W, Validation> mapSuccess() { + return lift(F1Functions.mapSuccess(this)); } /** @@ -463,8 +463,8 @@ public F, Validation> mapSuccess() { * @return a function that returns the failure side of a given Validation, * or this function applied to the success side. */ - public F, B> onFail() { - return F1Functions.onFail(this); + public F1W, B> onFail() { + return lift(F1Functions.onFail(this)); } /** @@ -474,8 +474,8 @@ public F, B> onFail() { * @return a function that returns the success side of a given Validation, * or this function applied to the failure side. */ - public F, B> onSuccess() { - return F1Functions.onSuccess(this); + public F1W, B> onSuccess() { + return lift(F1Functions.onSuccess(this)); } /** @@ -483,8 +483,8 @@ public F, B> onSuccess() { * * @return This function promoted to return its value in a Zipper. */ - public F> zipperK() { - return F1Functions.zipperK(this); + public F1W> zipperK() { + return lift(F1Functions.zipperK(this)); } /** @@ -492,8 +492,8 @@ public F> zipperK() { * * @return This function promoted to map over a Zipper. */ - public F, Zipper> mapZipper() { - return F1Functions.mapZipper(this); + public F1W, Zipper> mapZipper() { + return lift(F1Functions.mapZipper(this)); } /** @@ -501,8 +501,8 @@ public F, Zipper> mapZipper() { * * @return This function promoted to map over an Equal as a contravariant functor. */ - public F, Equal> comapEqual() { - return F1Functions.comapEqual(this); + public F1W, Equal> comapEqual() { + return lift(F1Functions.comapEqual(this)); } /** @@ -510,8 +510,8 @@ public F, Equal> comapEqual() { * * @return This function promoted to map over a Hash as a contravariant functor. */ - public F, Hash> comapHash() { - return F1Functions.comapHash(this); + public F1W, Hash> comapHash() { + return lift(F1Functions.comapHash(this)); } /** @@ -519,8 +519,8 @@ public F, Hash> comapHash() { * * @return This function promoted to map over a Show as a contravariant functor. */ - public F, Show> comapShow() { - return F1Functions.comapShow(this); + public F1W, Show> comapShow() { + return lift(F1Functions.comapShow(this)); } /** @@ -528,8 +528,8 @@ public F, Show> comapShow() { * * @return This function promoted to map over the first element of a pair. */ - public F, P2> mapFst() { - return F1Functions.mapFst(this); + public F1W, P2> mapFst() { + return lift(F1Functions.mapFst(this)); } /** @@ -537,8 +537,8 @@ public F, P2> mapFst() { * * @return This function promoted to map over the second element of a pair. */ - public F, P2> mapSnd() { - return F1Functions.mapSnd(this); + public F1W, P2> mapSnd() { + return lift(F1Functions.mapSnd(this)); } /** @@ -546,8 +546,8 @@ public F, P2> mapSnd() { * * @return This function promoted to map over both elements of a pair. */ - public F, P2> mapBoth() { - return F1Functions.mapBoth(this); + public F1W, P2> mapBoth() { + return lift(F1Functions.mapBoth(this)); } /** @@ -662,12 +662,30 @@ public ArrayList mapJ(final ArrayList as) { return F1Functions.mapJ(this, as); } - public F map(F f) { - return F1Functions.map(this, f); + public F1W map(F f) { + return lift(F1Functions.map(this, f)); } - public F contramap(F f) { - return F1Functions.contramap(this, f); + public F1W contramap(F f) { + return lift(F1Functions.contramap(this, f)); } + public static class F1WFunc extends F1W { + final F func; + public F1WFunc(F f) { + func = f; + } + + @Override + public B f(A a) { + return func.f(a); + } + } + + /** + * Lifts the function into the fully featured function wrapper + */ + public static F1W lift(final F f) { + return new F1WFunc(f); + } } From d7d02f303df418ee18bbe35ef224b2023da3b6f5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 23 Jan 2015 00:01:29 +1000 Subject: [PATCH 233/811] Added function 2 wrapper --- core/src/main/java/fj/F2W.java | 256 ++++++++++++++++++++++++++++++++- 1 file changed, 255 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/F2W.java b/core/src/main/java/fj/F2W.java index fefffc28..7a2f6e19 100644 --- a/core/src/main/java/fj/F2W.java +++ b/core/src/main/java/fj/F2W.java @@ -1,7 +1,261 @@ package fj; +import fj.control.parallel.Promise; +import fj.data.*; + +import static fj.P.p; +import static fj.data.IterableW.wrap; +import static fj.data.Set.iterableSet; +import static fj.data.Tree.node; +import static fj.data.TreeZipper.treeZipper; +import static fj.data.Zipper.zipper; + /** * Created by MarkPerry on 22/01/2015. */ -public abstract class F2W implements F2 { +public abstract class F2W implements F2 { + + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument. + */ + public F1W f(final A a) { + return F1W.lift(F2Functions.f(this, a)); + } + + /** + * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function. + * + * @return a wrapped function of arity-1 that returns another wrapped function. + */ + public F1W> curry() { + return F1W.lift(F2Functions.curry(this)); + } + + /** + * Flips the arguments of this function. + * + * @return A new function with the arguments of this function flipped. + */ + public F2W flip() { + return lift(F2Functions.flip(this)); + } + + /** + * Uncurries this function to a function on tuples. + * + * @return A new function that calls this function with the elements of a given tuple. + */ + public F1W, C> tuple() { + return F1W.lift(F2Functions.tuple(this)); + } + + /** + * Promotes this function to a function on Arrays. + * + * @return This function promoted to transform Arrays. + */ + public F2W, Array, Array> arrayM() { + return lift(F2Functions.arrayM(this)); + } + + /** + * Promotes this function to a function on Promises. + * + * @return This function promoted to transform Promises. + */ + public F2W, Promise, Promise> promiseM() { + return lift(F2Functions.promiseM(this)); + } + + /** + * Promotes this function to a function on Iterables. + * + * @return This function promoted to transform Iterables. + */ + public F2W, Iterable, IterableW> iterableM() { + return lift(F2Functions.iterableM(this)); + } + + /** + * Promotes this function to a function on Lists. + * + * @return This function promoted to transform Lists. + */ + public F2W, List, List> listM() { + return lift(F2Functions.listM(this)); + } + + /** + * Promotes this function to a function on non-empty lists. + * + * @return This function promoted to transform non-empty lists. + */ + public F2W, NonEmptyList, NonEmptyList> nelM() { + return lift(F2Functions.nelM(this)); + } + + /** + * Promotes this function to a function on Options. + * + * @return This function promoted to transform Options. + */ + public F2W, Option, Option> optionM() { + return lift(F2Functions.optionM(this)); + } + + /** + * Promotes this function to a function on Sets. + * + * @param o An ordering for the result of the promoted function. + * @return This function promoted to transform Sets. + */ + public F2W, Set, Set> setM(final Ord o) { + return lift(F2Functions.setM(this, o)); + } + + /** + * Promotes this function to a function on Streams. + * + * @return This function promoted to transform Streams. + */ + public F2W, Stream, Stream> streamM() { + return lift(F2Functions.streamM(this)); + } + + /** + * Promotes this function to a function on Trees. + * + * @return This function promoted to transform Trees. + */ + public F2W, Tree, Tree> treeM() { + return lift(F2Functions.treeM(this)); + } + + /** + * Promotes this function to zip two arrays, applying the function lock-step over both Arrays. + * + * @return A function that zips two arrays with this function. + */ + public F2W, Array, Array> zipArrayM() { + return lift(F2Functions.zipArrayM(this)); + } + + /** + * Promotes this function to zip two iterables, applying the function lock-step over both iterables. + * + * @return A function that zips two iterables with this function. + */ + public F2W, Iterable, Iterable> zipIterableM() { + return lift(F2Functions.zipIterableM(this)); + } + + /** + * Promotes this function to zip two lists, applying the function lock-step over both lists. + * + * @return A function that zips two lists with this function. + */ + public F2W, List, List> zipListM() { + return lift(F2Functions.zipListM(this)); + } + + + /** + * Promotes this function to zip two streams, applying the function lock-step over both streams. + * + * @return A function that zips two streams with this function. + */ + public F2W, Stream, Stream> zipStreamM() { + return lift(F2Functions.zipStreamM(this)); + } + + /** + * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists. + * + * @return A function that zips two non-empty lists with this function. + */ + public F2W, NonEmptyList, NonEmptyList> zipNelM() { + return lift(F2Functions.zipNelM(this)); + } + + /** + * Promotes this function to zip two sets, applying the function lock-step over both sets. + * + * @param o An ordering for the resulting set. + * @return A function that zips two sets with this function. + */ + public F2W, Set, Set> zipSetM(final Ord o) { + return lift(F2Functions.zipSetM(this, o)); + } + + /** + * Promotes this function to zip two trees, applying the function lock-step over both trees. + * The structure of the resulting tree is the structural intersection of the two trees. + * + * @return A function that zips two trees with this function. + */ + public F2W, Tree, Tree> zipTreeM() { + return lift(F2Functions.zipTreeM(this)); + } + + /** + * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions. + * The structure of the resulting zipper is the structural intersection of the two zippers. + * + * @return A function that zips two zippers with this function. + */ + public F2W, Zipper, Zipper> zipZipperM() { + return lift(F2Functions.zipZipperM(this)); + } + + /** + * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions. + * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. + * + * @return A function that zips two TreeZippers with this function. + */ + public F2W, TreeZipper, TreeZipper> zipTreeZipperM() { + return lift(F2Functions.zipTreeZipperM(this)); + } + + public F2W contramapFirst(F f) { + return lift(F2Functions.contramapFirst(this, f)); + } + + public F2W contramapSecond(F f) { + return lift(F2Functions.contramapSecond(this, f)); + } + + public F2W contramap(F f, F g) { + return lift(F2Functions.contramap(this, f, g)); + } + + public F2W map(F f) { + return lift(F2Functions.map(this, f)); + } + + + public static class F2WFunc extends F2W { + final F2 func; + public F2WFunc(F2 f) { + func = f; + } + + @Override + public C f(A a, B b) { + return func.f(a, b); + } + } + + /** + * Lifts the function into the fully featured function wrapper + */ + public static F2W lift(final F2 f) { + return new F2WFunc<>(f); + } + + + } From 74429e69909ed2946c2c00eb8b16d1b42d3b64d0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 23 Jan 2015 00:01:56 +1000 Subject: [PATCH 234/811] Added placeholder wrappers for the other function arities (3-8). --- core/src/main/java/fj/F3W.java | 8 ++++++++ core/src/main/java/fj/F4W.java | 9 +++++++++ core/src/main/java/fj/F5W.java | 9 +++++++++ core/src/main/java/fj/F6W.java | 9 +++++++++ core/src/main/java/fj/F7W.java | 9 +++++++++ core/src/main/java/fj/F8W.java | 9 +++++++++ 6 files changed, 53 insertions(+) create mode 100644 core/src/main/java/fj/F3W.java create mode 100644 core/src/main/java/fj/F4W.java create mode 100644 core/src/main/java/fj/F5W.java create mode 100644 core/src/main/java/fj/F6W.java create mode 100644 core/src/main/java/fj/F7W.java create mode 100644 core/src/main/java/fj/F8W.java diff --git a/core/src/main/java/fj/F3W.java b/core/src/main/java/fj/F3W.java new file mode 100644 index 00000000..d6ffa80b --- /dev/null +++ b/core/src/main/java/fj/F3W.java @@ -0,0 +1,8 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F3W implements F3 { + +} diff --git a/core/src/main/java/fj/F4W.java b/core/src/main/java/fj/F4W.java new file mode 100644 index 00000000..3cc92e55 --- /dev/null +++ b/core/src/main/java/fj/F4W.java @@ -0,0 +1,9 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F4W implements F4 { + + +} diff --git a/core/src/main/java/fj/F5W.java b/core/src/main/java/fj/F5W.java new file mode 100644 index 00000000..5fa407cd --- /dev/null +++ b/core/src/main/java/fj/F5W.java @@ -0,0 +1,9 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F5W implements F5 { + + +} diff --git a/core/src/main/java/fj/F6W.java b/core/src/main/java/fj/F6W.java new file mode 100644 index 00000000..adaf723f --- /dev/null +++ b/core/src/main/java/fj/F6W.java @@ -0,0 +1,9 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F6W implements F6 { + + +} diff --git a/core/src/main/java/fj/F7W.java b/core/src/main/java/fj/F7W.java new file mode 100644 index 00000000..fdcec3d5 --- /dev/null +++ b/core/src/main/java/fj/F7W.java @@ -0,0 +1,9 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F7W implements F7 { + + +} diff --git a/core/src/main/java/fj/F8W.java b/core/src/main/java/fj/F8W.java new file mode 100644 index 00000000..d0a9f861 --- /dev/null +++ b/core/src/main/java/fj/F8W.java @@ -0,0 +1,9 @@ +package fj; + +/** + * Created by MarkPerry on 22/01/2015. + */ +public abstract class F8W implements F8 { + + +} From 5a1f465e15f6c86ecea6b02aace55cbe2c9c5d1f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 23 Jan 2015 01:53:38 +1000 Subject: [PATCH 235/811] Reviewed implementation of equals --- core/src/main/java/fj/Equal.java | 24 +++++++++++----------- core/src/main/java/fj/P1.java | 5 +---- core/src/main/java/fj/P2.java | 2 +- core/src/main/java/fj/P3.java | 3 +-- core/src/main/java/fj/P4.java | 3 +-- core/src/main/java/fj/P5.java | 3 +-- core/src/main/java/fj/P6.java | 3 +-- core/src/main/java/fj/P7.java | 3 +-- core/src/main/java/fj/P8.java | 3 +-- core/src/main/java/fj/data/Array.java | 5 +---- core/src/main/java/fj/data/Either.java | 3 +-- core/src/main/java/fj/data/List.java | 4 +--- core/src/main/java/fj/data/Option.java | 5 +---- core/src/main/java/fj/data/Seq.java | 3 +-- core/src/main/java/fj/data/Set.java | 2 +- core/src/main/java/fj/data/Stream.java | 5 +---- core/src/main/java/fj/data/Tree.java | 3 +-- core/src/main/java/fj/data/TreeMap.java | 3 +-- core/src/main/java/fj/data/Validation.java | 3 +-- core/src/test/java/fj/data/ListTest.java | 6 ++++++ 20 files changed, 36 insertions(+), 55 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index d1e7c21b..cd719e8c 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -535,19 +535,19 @@ public static Equal> writerEqual(Equal eq1, Equal eq2) } /** - * Can the objects be checked for equality? - * @return True if the objects are not null and are an instance of the provided class. - */ - public static boolean equalsValidationCheck(Object o1, Object o2) { - java.lang.Class c = o1.getClass(); - if (o1 == null || !c.isInstance(o1)) { - return false; - } - if (o2 == null || !c.isInstance(o2)) { - return false; + * @return Returns none if no equality can be determined by checking the nullity and reference values, else the equality + */ + public static Option shallowEqualsO(Object o1, Object o2) { + if (o1 == null && o2 == null) { + return Option.some(true); + } else if (o1 == o2) { + return Option.some(true); + } else if (o1 != null && o2 != null) { + java.lang.Class c = o1.getClass(); + return c.isInstance(o2) ? Option.none() : Option.some(false); + } else { + return Option.some(false); } - return true; - } } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index b53e6269..9105279e 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -5,8 +5,6 @@ import fj.data.Array; import fj.data.List; import fj.data.Stream; -import fj.data.Validation; -import fj.function.Try0; public abstract class P1 implements F0 { @@ -244,8 +242,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other))); } @Override diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 7c966126..e44b38f0 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -26,7 +26,7 @@ public abstract class P2 { @Override public boolean equals(Object other) { - return Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual()).eq(this, (P2) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual()).eq(this, (P2) other))); } @Override diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 88d077cc..e2c7aa26 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -192,8 +192,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P3) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P3) other))); } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 13b423c3..267e4d86 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -265,8 +265,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P4) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P4) other))); } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 741b42f5..b5f62f4b 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -344,8 +344,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P5) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P5) other))); } @Override diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index d276687f..40802b0b 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -435,8 +435,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P6) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P6) other))); } @Override diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index e887df79..cdff75ce 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -529,8 +529,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P7) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P7) other))); } @Override diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index 087efa5a..ffd9081a 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -635,8 +635,7 @@ public String toString() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P8) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P8) other))); } @Override diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 93cf7048..ea9c2026 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -1,6 +1,5 @@ package fj.data; -import fj.Effect; import fj.F; import fj.F2; import fj.P; @@ -683,9 +682,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object o) { - return ! - Equal.equalsValidationCheck(this, o) ? false : - Equal.arrayEqual(Equal.anyEqual()).eq(this, (Array) o); + return Equal.shallowEqualsO(this, o).orSome(P.lazy(u -> Equal.arrayEqual(Equal.anyEqual()).eq(this, (Array) o))); } /** diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 1196f321..95c19e6b 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -80,8 +80,7 @@ public final X either(final F left, final F right) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Either) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Either) other))); } @Override diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index e4ed119f..014124b8 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -5,7 +5,6 @@ import fj.Equal; import fj.F; import fj.F2; -import fj.F3; import fj.Function; import fj.Hash; import fj.Monoid; @@ -1818,8 +1817,7 @@ private void copy() { //Casting to List here does not cause a runtime exception even if the type arguments don't match. //The cast is done to avoid the compiler warning "raw use of parameterized class 'List'" - return !Equal.equalsValidationCheck(this, obj) ? false : - Equal.listEqual(Equal.anyEqual()).eq(this, (List) obj); + return Equal.shallowEqualsO(this, obj).orSome(P.lazy(u -> Equal.listEqual(Equal.anyEqual()).eq(this, (List) obj))); } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index e9581c91..90a88b9d 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -2,7 +2,6 @@ import static fj.Bottom.error; -import fj.Effect; import fj.F; import fj.F2; import fj.P; @@ -33,7 +32,6 @@ import static fj.data.Validation.parseLong; import static fj.data.Validation.parseShort; import static fj.Show.optionShow; -import static fj.Show.anyShow; import java.util.Collection; import java.util.Iterator; @@ -628,8 +626,7 @@ public final boolean exists(final F f) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.optionEqual(Equal.anyEqual()).eq(this, (Option) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.optionEqual(Equal.anyEqual()).eq(this, (Option) other))); } /** diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 00292f17..d696e497 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -48,8 +48,7 @@ public static Seq empty() { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.seqEqual(Equal.anyEqual()).eq(this, (Seq) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.seqEqual(Equal.anyEqual()).eq(this, (Seq) other))); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 860c34ca..7bb868aa 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -142,7 +142,7 @@ public static Set empty(final Ord ord) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : Equal.setEqual(Equal.anyEqual()).eq(this, (Set) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.setEqual(Equal.anyEqual()).eq(this, (Set) other))); } @Override diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 8f33ad2a..3ef65941 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1,12 +1,10 @@ package fj.data; -import fj.Effect; import fj.Equal; import fj.Hash; import fj.Show; import fj.F; import fj.F2; -import fj.F3; import fj.Function; import fj.Monoid; import fj.Ord; @@ -1239,8 +1237,7 @@ public final boolean forall(final F f) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other))); } @Override diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 2e0319c2..f0e19602 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -261,8 +261,7 @@ private Stream drawTree(final Show s) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.treeEqual(Equal.anyEqual()).eq(this, (Tree) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.treeEqual(Equal.anyEqual()).eq(this, (Tree) other))); } @Override diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 066b60d5..ec51a0d0 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -37,8 +37,7 @@ public static TreeMap empty(final Ord keyOrd) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (TreeMap) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (TreeMap) other))); } @Override diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 0f5eb642..a6889bd3 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -251,8 +251,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object other) { - return !Equal.equalsValidationCheck(this, other) ? false : - Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Validation) other); + return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Validation) other))); } @Override diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 15d2f0bd..27b0b71b 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -16,9 +16,15 @@ public void objectMethods() { int max = 5; List list = List.range(1, max); + + assertTrue(list.equals(list)); assertTrue(list.equals(List.range(1, max))); + assertFalse(list.equals(List.single(1))); assertFalse(list.equals(true)); + assertFalse(list.equals(null)); + + assertTrue(List.list(1, 2).toString().equals("List(1,2)")); From 2269c7462c6338e6f2ed51f24f13edddc5bf79fa Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 23 Jan 2015 20:42:52 +1000 Subject: [PATCH 236/811] Merged #80: Added traverse method family --- core/src/main/java/fj/P1.java | 124 ++++----- core/src/main/java/fj/P2.java | 72 +++--- core/src/main/java/fj/data/Either.java | 235 +++++++++++++----- core/src/main/java/fj/data/IOFunctions.java | 10 - core/src/main/java/fj/data/List.java | 53 +++- core/src/main/java/fj/data/Validation.java | 46 +++- .../java/fj/data/List_Traverse_Tests.java | 46 ++++ 7 files changed, 396 insertions(+), 190 deletions(-) create mode 100644 core/src/test/java/fj/data/List_Traverse_Tests.java diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 9105279e..711b1436 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -5,6 +5,11 @@ import fj.data.Array; import fj.data.List; import fj.data.Stream; +import fj.data.Either; +import fj.data.Option; +import fj.data.Validation; +//import fj.data.*; +import fj.function.Try0; public abstract class P1 implements F0 { @@ -26,11 +31,7 @@ public A f() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return new F, A>() { - public A f(final P1 p) { - return p._1(); - } - }; + return p -> p._1(); } /** @@ -40,11 +41,7 @@ public A f(final P1 p) { * @return A function promoted to operate on P1s. */ public static F, P1> fmap(final F f) { - return new F, P1>() { - public P1 f(final P1 a) { - return a.map(f); - } - }; + return a -> a.map(f); } /** @@ -55,11 +52,7 @@ public P1 f(final P1 a) { */ public P1 bind(final F> f) { P1 self = this; - return new P1() { - public B _1() { - return f.f(self._1())._1(); - } - }; + return P.lazy(u -> f.f(self._1())._1()); } /** @@ -69,15 +62,7 @@ public B _1() { * @return A function whose result is wrapped in a P1. */ public static F> curry(final F f) { - return new F>() { - public P1 f(final A a) { - return new P1() { - public B _1() { - return f.f(a); - } - }; - } - }; + return a -> P.lazy(u -> f.f(a)); } /** @@ -88,11 +73,7 @@ public B _1() { */ public P1 apply(final P1> cf) { P1 self = this; - return cf.bind(new F, P1>() { - public P1 f(final F f) { - return fmap(f).f(self); - } - }); + return cf.bind(f -> fmap(f).f(self)); } /** @@ -123,11 +104,7 @@ public static P1 join(final P1> a) { * @return A function of arity-2 promoted to map over P1s. */ public static F, F, P1>> liftM2(final F> f) { - return Function.curry(new F2, P1, P1>() { - public P1 f(final P1 pa, final P1 pb) { - return pa.bind(pb, f); - } - }); + return Function.curry((pa, pb) -> pa.bind(pb, f)); } /** @@ -146,11 +123,7 @@ public static P1> sequence(final List> as) { * @return A function from a List of P1s to a single P1 of a List. */ public static F>, P1>> sequenceList() { - return new F>, P1>>() { - public P1> f(final List> as) { - return sequence(as); - } - }; + return as -> sequence(as); } /** @@ -170,11 +143,57 @@ public static P1> sequence(final Stream> as) { * @return A single P1 for the given array. */ public static P1> sequence(final Array> as) { - return new P1>() { - public Array _1() { - return as.map(P1.__1()); - } - }; + return P.lazy(u -> as.map(P1.__1())); + } + + /** + * Traversable instance of P1 for List + * + * @param f The function that takes A and produces a List (non-deterministic result) + * @return A List of P1 + */ + public List> traverseList(final F> f){ + return f.f(_1()).map(b -> P.p(b)); + } + + /** + * Traversable instance of P1 for Either + * + * @param f The function produces Either + * @return An Either of P1 + */ + public Either> traverseEither(final F> f){ + return f.f(_1()).right().map(b -> P.p(b)); + } + + /** + * Traversable instance of P1 for Option + * + * @param f The function that produces Option + * @return An Option of P1 + */ + public Option> traverseOption(final F> f){ + return f.f(_1()).map(b -> P.p(b)); + } + + /** + * Traversable instance of P1 for Validation + * + * @param f The function might produces Validation + * @return An Validation of P1 + */ + public Validation> traverseValidation(final F> f){ + return f.f(_1()).map(b -> P.p(b)); + } + + /** + * Traversable instance of P1 for Stream + * + * @param f The function that produces Stream + * @return An Stream of P1 + */ + public Stream> traverseStream(final F> f){ + return f.f(_1()).map(b -> P.p(b)); } /** @@ -185,11 +204,7 @@ public Array _1() { */ public P1 map(final F f) { final P1 self = this; - return new P1() { - public X _1() { - return f.f(self._1()); - } - }; + return P.lazy(u -> f.f(self._1())); } /** @@ -198,12 +213,12 @@ public X _1() { * @return A P1 that calls this P1 once and remembers the value for subsequent calls. */ public P1 memo() { - final P1 self = this; + final P1 self = this; return new P1() { private final Object latch = new Object(); @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) private volatile SoftReference v; - + public A _1() { A a = v != null ? v.get() : null; if (a == null) @@ -228,11 +243,7 @@ static P1 memo(F f) { */ public F constant() { - return new F() { - public A f(final B b) { - return P1.this._1(); - } - }; + return b -> P1.this._1(); } @Override @@ -240,6 +251,7 @@ public String toString() { return Show.p1Show(Show.anyShow()).showS(this); } + @SuppressWarnings("unchecked") @Override public boolean equals(Object other) { return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other))); diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index e44b38f0..cab07c3e 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -1,8 +1,8 @@ package fj; import static fj.Function.*; -import fj.data.List; -import fj.data.Stream; + +import fj.data.*; /** * A product-2. @@ -156,6 +156,26 @@ public final List sequenceW(final List, C>> fs) { return cs.toList(); } + public final List> traverseList(final F> f) { + return f.f(_2()).map(x -> P.p(_1(), x)); + } + + public final Stream> traverseStream(final F> f) { + return f.f(_2()).map(x -> P.p(_1(), x)); + } + + public final IO> traverseIO(final F> f) { + return IOFunctions.map(f.f(_2()), x -> P.p(_1(), x)); + } + + public final Option> traverseOption(final F> f) { + return f.f(_2()).map(x -> P.p(_1(), x)); + } + + public final Either> traverseEither(final F> f) { + return f.f(_2()).right().map(x -> P.p(_1(), x)); + } + /** * Applies a stream of comonadic functions to this product, returning a stream of values. * @@ -219,11 +239,7 @@ public B _2() { * @return A function that splits a given product between the two given functions and combines their output. */ public static F, P2> split_(final F f, final F g) { - return new F, P2>() { - public P2 f(final P2 p) { - return p.split(f, g); - } - }; + return p -> p.split(f, g); } /** @@ -233,11 +249,7 @@ public P2 f(final P2 p) { * @return The given function, promoted to map the first element of products. */ public static F, P2> map1_(final F f) { - return new F, P2>() { - public P2 f(final P2 p) { - return p.map1(f); - } - }; + return p -> p.map1(f); } /** @@ -247,11 +259,7 @@ public P2 f(final P2 p) { * @return The given function, promoted to map the second element of products. */ public static F, P2> map2_(final F f) { - return new F, P2>() { - public P2 f(final P2 p) { - return p.map2(f); - } - }; + return p -> p.map2(f); } /** @@ -283,11 +291,7 @@ public static P2 map(final F f, final P2 p) { * @return A curried form of {@link #swap()}. */ public static F, P2> swap_() { - return new F, P2>() { - public P2 f(final P2 p) { - return p.swap(); - } - }; + return p -> p.swap(); } /** @@ -296,11 +300,7 @@ public P2 f(final P2 p) { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return new F, A>() { - public A f(final P2 p) { - return p._1(); - } - }; + return p -> p._1(); } /** @@ -309,11 +309,7 @@ public A f(final P2 p) { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return new F, B>() { - public B f(final P2 p) { - return p._2(); - } - }; + return p -> p._2(); } /** @@ -323,11 +319,7 @@ public B f(final P2 p) { * @return The function, transformed to operate on on a product-2 */ public static F, C> tuple(final F> f) { - return new F, C>() { - public C f(final P2 p) { - return f.f(p._1()).f(p._2()); - } - }; + return p -> f.f(p._1()).f(p._2()); } /** @@ -347,11 +339,7 @@ public static F, C> tuple(final F2 f) { * @return The function, transformed to an uncurried function of arity-2. */ public static F2 untuple(final F, C> f) { - return new F2() { - public C f(final A a, final B b) { - return f.f(P.p(a, b)); - } - }; + return (a, b) -> f.f(P.p(a, b)); } @Override diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 95c19e6b..5f958c4d 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -11,6 +11,7 @@ import static fj.Unit.unit; import static fj.data.Array.mkArray; +import static fj.data.List.list; import static fj.data.List.single; import static fj.data.List.cons_; import static fj.data.Option.some; @@ -275,6 +276,30 @@ public Either sequence(final Either e) { return bind(Function.>constant(e)); } + /** + * Traverse with function that produces List (non-determinism). + * + * @param f the function to traverse with + * @return An either after traversing through this projection. + */ + public List> traverseList(final F> f) { + return isLeft() ? + f.f(value()).map(x -> Either.left(x)) : + list(Either.right(e.right().value())); + } + + /** + * Anonymous bind through this projection. + * + * @param f the function to traverse with + * @return An either after traversing through this projection. + */ + public IO> traverseIO(final F> f) { + return isRight() ? + IOFunctions.map(f.f(value()), x -> Either.left(x)) : + IOFunctions.unit(Either.right(e.right().value())); + } + /** * Returns None if this projection has no value or if the given predicate * p does not hold for the value, otherwise, returns a right in Some. @@ -286,7 +311,7 @@ public Either sequence(final Either e) { public Option> filter(final F f) { return isLeft() ? f.f(value()) ? - Option.>some(new Left(value())) : + Option.>some(new Left<>(value())) : Option.>none() : Option.>none(); } @@ -298,11 +323,7 @@ public Option> filter(final F f) { * @return The result of function application within either. */ public Either apply(final Either, B> e) { - return e.left().bind(new F, Either>() { - public Either f(final F f) { - return map(f); - } - }); + return e.left().bind(f -> map(f)); } /** @@ -380,6 +401,18 @@ public Stream toStream() { public Collection toCollection() { return toList().toCollection(); } + + public Option> traverseOption(F> f) { + return isLeft() ? + f.f(value()).map(x -> Either.left(x)) : + Option.some(Either.right(e.right().value())); + } + + public Stream> traverseStream(F> f) { + return isLeft() ? + f.f(value()).map(c -> Either.left(c)) : + Stream.single(Either.right(e.right().value())); + } } /** @@ -485,7 +518,7 @@ public void foreachDoEffect(final Effect1 f) { * @return A new either value after mapping. */ public Either map(final F f) { - return isRight() ? new Right(f.f(value())) : new Left(e.left().value()); + return isRight() ? new Right<>(f.f(value())) : new Left<>(e.left().value()); } /** @@ -495,7 +528,7 @@ public Either map(final F f) { * @return A new either value after binding. */ public Either bind(final F> f) { - return isRight() ? f.f(value()) : new Left(e.left().value()); + return isRight() ? f.f(value()) : new Left<>(e.left().value()); } @@ -508,6 +541,41 @@ public Either bind(final F> f) { public Either sequence(final Either e) { return bind(Function.>constant(e)); } + /** + * Traverse with function that produces List (non-determinism). + * + * @param f the function to traverse with + * @return An either after traversing through this projection. + */ + public List> traverseList(final F> f) { + return isRight() ? + f.f(value()).map(x -> Either.right(x)) : + list(Either.left(e.left().value())); + } + + /** + * Traverse with a function that has IO effect + * + * @param f the function to traverse with + * @return An either after traversing through this projection. + */ + public IO> traverseIO(final F> f) { + return isRight() ? + IOFunctions.map(f.f(value()), x -> Either.right(x)) : + IOFunctions.lazy(u -> Either.left(e.left().value())); + } + + public P1> traverseP1(final F> f) { + return isRight() ? + f.f(value()).map(x -> Either.right(x)) : + P.p(Either.left(e.left().value())); + } + + public Option> traverseOption(final F> f) { + return isRight() ? + f.f(value()).map(x -> Either.right(x)) : + Option.some(Either.left(e.left().value())); + } /** * Returns None if this projection has no value or if the given predicate @@ -532,11 +600,7 @@ public Option> filter(final F f) { * @return The result of function application within either. */ public Either apply(final Either> e) { - return e.right().bind(new F, Either>() { - public Either f(final F f) { - return map(f); - } - }); + return e.right().bind(f -> map(f)); } /** @@ -614,6 +678,13 @@ public Stream toStream() { public Collection toCollection() { return toList().toCollection(); } + + public Stream> traverseStream(F> f) { + return isRight() ? + f.f(value()).map(x -> Either.right(x)) : + Stream.>single(Either.left(e.left().value())); + + } } /** @@ -632,11 +703,7 @@ public static Either left(final A a) { * @return A function that constructs a left value of either. */ public static F> left_() { - return new F>() { - public Either f(final A a) { - return left(a); - } - }; + return a -> left(a); } /** @@ -645,11 +712,7 @@ public Either f(final A a) { * @return A function that constructs a right value of either. */ public static F> right_() { - return new F>() { - public Either f(final B b) { - return right(b); - } - }; + return b -> right(b); } /** @@ -666,30 +729,14 @@ public static Either right(final B b) { * @return A function that maps another function across an either's left projection. */ public static F, F, Either>> leftMap_() { - return new F, F, Either>>() { - public F, Either> f(final F axf) { - return new F, Either>() { - public Either f(final Either e) { - return e.left().map(axf); - } - }; - } - }; + return axf -> e -> e.left().map(axf); } /** * @return A function that maps another function across an either's right projection. */ public static F, F, Either>> rightMap_() { - return new F, F, Either>>() { - public F, Either> f(final F axf) { - return new F, Either>() { - public Either f(final Either e) { - return e.right().map(axf); - } - }; - } - }; + return axf -> e -> e.right().map(axf); } /** @@ -723,11 +770,7 @@ public static Either joinRight(final Either> e) { public static Either, X> sequenceLeft(final List> a) { return a.isEmpty() ? Either., X>left(List.nil()) : - a.head().left().bind(new F, X>>() { - public Either, X> f(final A aa) { - return sequenceLeft(a.tail()).left().map(cons_(aa)); - } - }); + a.head().left().bind(aa -> sequenceLeft(a.tail()).left().map(cons_(aa))); } /** @@ -739,13 +782,83 @@ public Either, X> f(final A aa) { public static Either> sequenceRight(final List> a) { return a.isEmpty() ? Either.>right(List.nil()) : - a.head().right().bind(new F>>() { - public Either> f(final B bb) { - return sequenceRight(a.tail()).right().map(cons_(bb)); - } - }); + a.head().right().bind(bb -> sequenceRight(a.tail()).right().map(cons_(bb))); + } + + /** + * Traversable instance of RightProjection of Either for List. + * + * @return traversed value + */ + public List> traverseListRight(final F> f) { + return right().traverseList(f); + } + + /** + * Traversable instance of LeftProjection of Either for List. + * + * @return traversed value + */ + public List> traverseListLeft(final F> f) { + return left().traverseList(f); + } + + /** + * Traversable instance of RightProjection of Either for IO. + * + * @return traversed value + */ + public IO> traverseIORight(final F> f) { + return right().traverseIO(f); + } + + /** + * Traversable instance of LeftProjection of Either for IO. + * + * @return traversed value + */ + public IO> traverseIOLeft(final F> f) { + return left().traverseIO(f); } + /** + * Traversable instance of RightProjection of Either for Option. + * + * @return traversed value + */ + public Option> traverseOptionRight(final F> f) { + return right().traverseOption(f); + } + + /** + * Traversable instance of LeftProjection of Either for Option. + * + * @return traversed value + */ + public Option> traverseOptionLeft(final F> f) { + return left().traverseOption(f); + } + + /** + * Traversable instance of RightProjection of Either for Stream. + * + * @return traversed value + */ + public Stream> traverseStreamRight(final F> f) { + return right().traverseStream(f); + } + + /** + * Traversable instance of LeftProjection of Either for Stream. + * + * @return traversed value + */ + public Stream> traverseStreamLeft(final F> f) { + return left().traverseStream(f); + } + + + /** * Takes an Either to its contained value within left or right. * @@ -775,15 +888,7 @@ public static Either iif(final boolean c, final P1 right, final * @return All the left values in the given list. */ public static List lefts(final List> es) { - return es.foldRight(new F, F, List>>() { - public F, List> f(final Either e) { - return new F, List>() { - public List f(final List as) { - return e.isLeft() ? as.cons(e.left().value()) : as; - } - }; - } - }, List.nil()); + return es.foldRight(e -> as -> e.isLeft() ? as.cons(e.left().value()) : as, List.nil()); } /** @@ -793,15 +898,7 @@ public List f(final List as) { * @return All the right values in the given list. */ public static List rights(final List> es) { - return es.foldRight(new F, F, List>>() { - public F, List> f(final Either e) { - return new F, List>() { - public List f(final List bs) { - return e.isRight() ? bs.cons(e.right().value()) : bs; - } - }; - } - }, List.nil()); + return es.foldRight(e -> bs -> e.isRight() ? bs.cons(e.right().value()) : bs, List.nil()); } public String toString() { diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 7755b8fe..e25f8024 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -349,16 +349,6 @@ public static IO> sequence(Stream> stream) { } - /** - * Map each element of a structure to an action, evaluate these actions from left to right - * and collect the results. - */ - public static IO> traverse(List list, F> f) { - F2>, IO>> f2 = (a, acc) -> - bind(acc, (bs) -> map(f.f(a), b -> bs.append(List.list(b)))); - return list.foldRight(f2, IOFunctions.unit(List.nil())); - } - public static IO join(IO> io1) { return bind(io1, io2 -> io2); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 014124b8..b7d8020d 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -562,7 +562,54 @@ public final List sequence(final List bs) { return bind(c); } - /** + /** + * Traverses through the List with the given function + * + * @param f The function that produces Option value + * @return none if applying f returns none to any element of the list or f mapped list in some . + */ + public Option> traverseOption(final F> f) { + return foldRight( + (a, obs) -> f.f(a).bind(o -> obs.map(os -> os.cons(o))), + Option.some(List.nil()) + ); + } + + /** + * Traverse through the List with given function. + * + * @param f The function that produces Either value. + * @return error in left or f mapped list in right. + */ + public Either> traverseEither(final F> f) { + return foldRight( + (a, acc) -> f.f(a).right().bind(e -> acc.right().map(es -> es.cons(e))), + Either.>right(List.nil()) + ); + } + + public Stream> traverseStream(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(s -> acc.map(ss -> ss.cons(s))), + Stream.>nil() + ); + } + + public P1> traverseP1(final F> f){ + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), + P.p(List.nil()) + ); + } + + public IO> traverseIO(F> f) { + return this.foldRight( + (a, acc) -> IOFunctions.bind(acc, (bs) -> IOFunctions.map(f.f(a), b -> bs.cons(b))), + IOFunctions.unit(List.nil()) + ); + } + + /** * Performs function application within a list (applicative functor pattern). * * @param lf The list of functions to apply. @@ -1058,7 +1105,7 @@ public final F> mapM(final F> f) { * @return A possible list of values after binding through the Option monad. */ public final Option> mapMOption(final F> f) { - return foldRight((a, bs) -> f.f(a).bind(b -> bs.map(bbs -> bbs.cons(b))), Option.>some(List.nil())); + return traverseOption(f); } /** @@ -1828,7 +1875,7 @@ private void copy() { */ @Override public int hashCode() { - return Hash.listHash( Hash.anyHash() ).hash( this ); + return Hash.listHash(Hash.anyHash()).hash(this); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index a6889bd3..4d0bfbe3 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -8,6 +8,7 @@ import static fj.Unit.unit; import static fj.Bottom.error; +import static fj.data.List.list; import java.util.Iterator; @@ -746,7 +747,7 @@ public Validation, C> accumulate(Validation v2, F2 public Validation, D> accumulate(Validation v2, Validation v3, F3 f) { - List list = fails(List.list(this, v2, v3)); + List list = fails(list(this, v2, v3)); if (!list.isEmpty()) { return Validation.fail(list); } else { @@ -755,7 +756,7 @@ public Validation, D> accumulate(Validation v2, Validati } public Validation, E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { - List list = fails(List.list(this, v2, v3, v4)); + List list = fails(list(this, v2, v3, v4)); if (!list.isEmpty()) { return Validation.fail(list); } else { @@ -764,7 +765,7 @@ public Validation, D> accumulate(Validation v2, Validati } public Validation, $F> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, F5 f) { - List list = fails(List.list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return Validation.fail(list); } else { @@ -774,7 +775,7 @@ public Validation, D> accumulate(Validation v2, Validati public Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { - List list = fails(List.list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return Validation.fail(list); } else { @@ -783,7 +784,7 @@ public Validation, D> accumulate(Validation v2, Validati } public Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { - List list = fails(List.list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return Validation.fail(list); } else { @@ -792,7 +793,7 @@ public Validation, D> accumulate(Validation v2, Validati } public Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { - List list = fails(List.list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return Validation.fail(list); } else { @@ -815,6 +816,35 @@ public static Validation, List> sequence(List return list.foldRight(f2, Validation.success(List.nil())); } + public List> traverseList(F> f){ + return isSuccess() ? + f.f(success()).map(Validation::success) : + list(fail(e.left().value())); + } + + public Stream> traverseStream(F> f){ + return isSuccess() ? + f.f(success()).map(Validation::success) : + Stream.stream(fail(e.left().value())); + } + + public Option> traverseOption(F> f){ + return isSuccess() ? + f.f(success()).map(Validation::success) : + Option.some(fail(e.left().value())); + } + + public IO> traverseIO(F> f){ + return isSuccess() ? + IOFunctions.map(f.f(success()), Validation::success) : + IOFunctions.unit(fail(e.left().value())); + } + + public P1> traverseP1(F> f){ + return isSuccess() ? + f.f(success()).map(Validation::success) : + P.p(fail(e.left().value())); + } public static List fails(List> list) { @@ -944,10 +974,6 @@ public Validation sequence(final Validation v) { } - - - - /** * Returns None if this is a success or if the given predicate p does not hold for the * failing value, otherwise, returns a fail in Some. diff --git a/core/src/test/java/fj/data/List_Traverse_Tests.java b/core/src/test/java/fj/data/List_Traverse_Tests.java new file mode 100644 index 00000000..3d964f45 --- /dev/null +++ b/core/src/test/java/fj/data/List_Traverse_Tests.java @@ -0,0 +1,46 @@ +package fj.data; + +import fj.F; +import org.junit.Assert; +import org.junit.Test; + +import static fj.data.List.list; +import static fj.data.Option.some; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Created by amar on 28/12/14. + */ +public class List_Traverse_Tests { + + @Test + public void shouldTraverseListWithGivenFunction(){ + List strings = list("some1", "some2", "some3", "not_some", " "); + F> f = s -> { + if(s.startsWith("some")) + return some(s); + else + return Option.none(); + }; + + Option> optStr = strings.traverseOption(f); + Assert.assertEquals("optStr should be none", Option.none(), optStr); + } + + @Test + public void shouldTraverseListWithGivenFunction2(){ + List strings = list("some1", "some2", "some3"); + F> f = s -> { + if(s.startsWith("some")) + return some(s); + else + return Option.none(); + }; + + Option> optStr = strings.traverseOption(f); + Assert.assertEquals("optStr should be some", optStr.isSome(), true); + assertThat(optStr.some(), is(List.list("some1", "some2", "some3"))); + } + +} From 164e0b764ed8cf6c2811a5482d7d2ca3bb041687 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Thu, 15 Jan 2015 16:31:23 -0800 Subject: [PATCH 237/811] Rename TreeMap.setAll() to TreeMap.union(), and make it left-biased instead of right-biased. --- core/src/main/java/fj/data/TreeMap.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 881cd29b..2f6f5722 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -305,17 +305,17 @@ public TreeMap map(final F f) { return new TreeMap(tree.map(TreeMap.>ord(o), g)); } - /** - * Extend this TreeMap to include all mapping from another TreeMap. Where a - * mapping exists in both this TreeMap and the other one, the value from the - * other one will replace the value in this one. - * - * @param other - * @return - */ - public Object setAll(TreeMap other) { - TreeMap result = this; - for(P2 p : other) { + /** + * The expression t1.union(t2) takes the left-biased union of t1 + * and t2. It prefers t1 when duplicate keys are encountered. + * + * @param t2 The other tree we wish to combine with this one + * @return The combined TreeMap + */ + public TreeMap union(TreeMap t2) { + // TODO This could be implemented more efficiently using "hedge union" + TreeMap result = t2; + for(P2 p : this) { result = result.set(p._1(), p._2()); } return result; From 8133493414f17878265cdd8cc5d326d3289b410d Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Mon, 26 Jan 2015 12:04:55 -0800 Subject: [PATCH 238/811] Add a union() method that takes a list of pairs in addition to the one that takes a TreeMap. --- core/src/main/java/fj/data/TreeMap.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 2f6f5722..0b3cbc84 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -321,4 +321,21 @@ public TreeMap union(TreeMap t2) { return result; } + /** + * The expression t1.union(t2) takes the left-biased union of t1 + * and t2. It prefers t1 when duplicate keys are encountered. + * + * @param t2 The other list/set of pairs we wish to combine with this one + * @return The combined TreeMap + */ + public TreeMap union(Iterable> t2) { + TreeMap result = this; + for(P2 p : t2) { + if(!this.contains(p._1())) { + result = result.set(p._1(), p._2()); + } + } + return result; + } + } From 36ddb945a93fe55c21bc06007596e95c5e028615 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Mon, 26 Jan 2015 17:19:13 -0800 Subject: [PATCH 239/811] Eclipse/OSGI plugin support Compiles all projects except "tests" as an OSGI compatible jar file, and changes the "eclipse" target to generate a MANIFEST.MF and a "plugin" project to use in eclipse. --- .gitignore | 3 +++ build.gradle | 58 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 28b13f3f..51f4271b 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,7 @@ build .classpath .project .DS_Store +MANIFEST.MF +*/bin/** + diff --git a/build.gradle b/build.gradle index ef8501dc..69fd4bf5 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,8 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { + defaultTasks "build" + ext { isSnapshot = true fjBaseVersion = "4.3" @@ -45,34 +47,38 @@ allprojects { version = fjVersion group = "org.functionaljava" + } subprojects { - defaultTasks "build" + buildscript { + repositories { + mavenCentral() + } - buildscript { - repositories { - mavenCentral() - } + dependencies { + classpath 'me.tatarka:gradle-retrolambda:2.5.0' + } + } - dependencies { - classpath 'me.tatarka:gradle-retrolambda:2.5.0' - } - } + apply from: "$rootDir/lib.gradle" + apply plugin: "java" + apply plugin: "eclipse" - repositories { - mavenCentral() + repositories { + mavenCentral() maven { url sonatypeRepositoryUrl } - } +} + +configure(subprojects.findAll {it.name != 'tests'}) { - apply from: "$rootDir/lib.gradle" apply plugin: "maven" - apply plugin: "java" apply plugin: "signing" + apply plugin: "osgi" sourceCompatibility = "1.8" @@ -95,12 +101,34 @@ subprojects { jar { version project.fjVersion manifest { - attributes 'Signature-Version': project.fjVersion + name = 'Functional Java' + instruction 'Signature-Version', project.fjVersion + instruction 'Bundle-ActivationPolicy', 'lazy' + instruction 'Bundle-Vendor', 'functionaljava.org' + if(project.name != "core") { + instruction 'Require-Bundle', 'org.functionaljava;bundle-version="'+project.fjBaseVersion+'"' + } } } + eclipse { + project { + natures 'org.eclipse.pde.PluginNature' + buildCommand 'org.eclipse.pde.ManifestBuilder' + buildCommand 'org.eclipse.pde.SchemaBuilder' + } + } + + // Output MANIFEST.MF statically so eclipse can see it for plugin development + task eclipsePluginManifest(dependsOn: jar) << { + file("META-INF").mkdirs() + jar.manifest.writeTo(file("META-INF/MANIFEST.MF")) + } + + eclipseProject.dependsOn eclipsePluginManifest } + task wrapper(type: Wrapper) { gradleVersion = '2.0' } From 738201e8de1774e568497bca948b2fec082c6d8d Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Mon, 26 Jan 2015 17:20:46 -0800 Subject: [PATCH 240/811] Remove checked-in MANIFEST.MF, now this is generated by gradle. --- META-INF/MANIFEST.MF | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 META-INF/MANIFEST.MF diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF deleted file mode 100644 index 24770b25..00000000 --- a/META-INF/MANIFEST.MF +++ /dev/null @@ -1,21 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Functional Java -Bundle-SymbolicName: org.functionaljava -Bundle-Version: 4.3.0.qualifier -Export-Package: fj, - fj.control, - fj.control.db, - fj.control.parallel, - fj.data, - fj.data.fingertrees, - fj.data.hlist, - fj.data.vector, - fj.demo, - fj.demo.concurrent, - fj.demo.euler, - fj.demo.test, - fj.function, - fj.parser -Bundle-ActivationPolicy: lazy -Bundle-Vendor: functionaljava.org From 62b202f694ed0590ac378b776789c7519d80b693 Mon Sep 17 00:00:00 2001 From: Greg Row Date: Tue, 27 Jan 2015 02:38:21 +0100 Subject: [PATCH 241/811] fix performance and StackOverflowError issue in TreeMap.update() --- core/src/main/java/fj/data/TreeMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 0b3cbc84..ca3dbff7 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -216,7 +216,7 @@ public F> get() { */ public P2> update(final K k, final F f) { final P2>>> up = - tree.update(p(k, Option.none()), P2., Option>map2_(Option.map().f(f))); + tree.update(p(k, Option.none()), compose(P2.tuple(P.p2()), P2., Option>map2_(Option.map().f(f)))); return P.p(up._1(), new TreeMap(up._2())); } From 462338c3ba0b8b01091a5a685ca87a37a04c8bd9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 28 Jan 2015 19:56:46 +1000 Subject: [PATCH 242/811] Better integration with the basic java types --- core/src/main/java/fj/data/Java.java | 13 +++++++-- core/src/main/java/fj/data/List.java | 13 +++++++++ core/src/main/java/fj/data/Stream.java | 10 +++++++ core/src/test/java/fj/data/ListTest.java | 11 +++++++- java8/src/main/java/fj/data/Java8.java | 34 ++++++++++++++++++++---- 5 files changed, 73 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 45da97b1..ba25c73a 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1445,13 +1445,22 @@ public static F, List> ArrayList_List() { /** * A function that converts Java lists to lists. + * @deprecated As of 4.3, use {@link #JavaList_List} * * @return A function that converts Java lists to lists. */ public static F, List> JUList_List() { - return as -> Collection_List(as); + return as -> JavaList_List(as); + } + + public static F, List> JavaList_List() { + return as -> JavaList_List(as); } - + + public static List JavaList_List(java.util.List list) { + return List.list(list); + } + // BEGIN BitSet -> /** diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index b7d8020d..fc993523 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1331,6 +1331,10 @@ public final A minimum(final Ord o) { return foldLeft1(o.min); } + public final java.util.List toJavaList() { + return new java.util.LinkedList(toCollection()); + } + /** * Projects an immutable collection of this list. * @@ -1412,6 +1416,15 @@ public static List list(final A... as) { return Array.array(as).toList(); } + + public static List list(final Iterable i) { + return iterableList(i); + } + + public static List list(final Iterator it) { + return iterableList(() -> it); + } + /** * Returns an empty list. * diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 3ef65941..7abbf765 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -714,6 +714,16 @@ public static Stream stream(final A... as) { : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0)); } + + public static Stream stream(Iterable it) { + return iterableStream(it); + } + + public static Stream stream(Iterator it) { + return iteratorStream(it); + } + + /** * Returns a stream that is either infinite or bounded up to the maximum value of the given iterator starting at the * given value and stepping at increments of 1. diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 27b0b71b..cfb049bf 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -1,8 +1,9 @@ package fj.data; -import org.junit.Assert; import org.junit.Test; +import java.util.Arrays; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -30,4 +31,12 @@ public void objectMethods() { } + @Test + public void integration() { + java.util.List ul = Arrays.asList(1, 2, 3); + List dl = List.list(ul); + assertTrue(ul.equals(dl.toJavaList())); + + } + } diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index c22cd149..0bb3792c 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -5,6 +5,7 @@ import fj.function.Try1; import fj.function.Try2; +import java.util.Iterator; import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; @@ -95,6 +96,10 @@ static public F, BiFunction (a, b) -> Try.f(t).f(a, b); } + public static java.util.stream.Stream List_JavaStream(List list) { + return Iterable_JavaStream(list); + } + static public Option Optional_Option(final Optional o) { return Java8.Optional_Option().f(o); } @@ -122,13 +127,32 @@ public static F Consumer_F(Consumer c) { }; } - static public java.util.stream.Stream Stream_JStream(fj.data.Stream s) { - Spliterator sit = Spliterators.spliteratorUnknownSize(s.iterator(), 0); - return StreamSupport.stream(sit, false); + static public java.util.stream.Stream Stream_JavaStream(fj.data.Stream s) { + return Iterable_JavaStream(s); + } + + static public java.util.stream.Stream Iterable_JavaStream(Iterable it) { + return StreamSupport.stream(it.spliterator(), false); + } + + static public java.util.stream.Stream Iterator_JavaStream(Iterator it) { + return Iterable_JavaStream(() -> it); + } + + static public F, java.util.stream.Stream> Stream_JavaStream() { + return s -> Stream_JavaStream(s); + } + + static public Stream JavaStream_Stream(java.util.stream.Stream s) { + return s.collect(Collectors.toStream()); + } + + static public List JavaStream_List(java.util.stream.Stream s) { + return s.collect(Collectors.toList()); } - static public F, java.util.stream.Stream> Stream_JStream() { - return s -> Stream_JStream(s); + static public Array JavaStream_Array(java.util.stream.Stream s) { + return s.collect(Collectors.toArray()); } } From 625d0600ae64984bf5118cbbec8fe7f85c64836f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 29 Jan 2015 00:09:53 +1000 Subject: [PATCH 243/811] Documented 4.3 changes thus far. Also separated 2.19-2.21 changes --- etc/release-notes/release-notes-2.19.adoc | 11 +++++++++++ etc/release-notes/release-notes-2.20.adoc | 17 +++++++++++++++++ etc/release-notes/release-notes-2.21.adoc | 6 ++++++ etc/release-notes/release-notes-4.3.adoc | 23 +++++++++++++++++++++-- 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 etc/release-notes/release-notes-2.19.adoc create mode 100644 etc/release-notes/release-notes-2.20.adoc create mode 100644 etc/release-notes/release-notes-2.21.adoc diff --git a/etc/release-notes/release-notes-2.19.adoc b/etc/release-notes/release-notes-2.19.adoc new file mode 100644 index 00000000..7dacbacd --- /dev/null +++ b/etc/release-notes/release-notes-2.19.adoc @@ -0,0 +1,11 @@ += Release 2.19 + +Released: March 2009 + +* Comonadic operations on Stream, Tree and others +* Database monad (java.sql.Connection as a functor) +* Natural Number data type +* The Constant Arrow ($) +* Immutable Tree Map +* A parallel quick-sort using Functional Java actors + diff --git a/etc/release-notes/release-notes-2.20.adoc b/etc/release-notes/release-notes-2.20.adoc new file mode 100644 index 00000000..f3dba40a --- /dev/null +++ b/etc/release-notes/release-notes-2.20.adoc @@ -0,0 +1,17 @@ += Release 2.20 + +Released: July 2009 + +The highlight of this release is a parallel module built on top of +actors for doing some very clever and high-level parallel programming. +e.g. An implementation of the parallel map/reduce algorithm +(parFoldMap) and APIs for making use of actors easier for you, the user. + +Other new bits includes: + +* A heap of bug fixes, particularly on Stream (and therefore, many of +its dependencies) +* LazyString -- a lazy sequence of characters +* Function Wrappers +* Improvements to the Tree and Zipper implementations +* Other tidbits and additional APIs diff --git a/etc/release-notes/release-notes-2.21.adoc b/etc/release-notes/release-notes-2.21.adoc new file mode 100644 index 00000000..f44b144e --- /dev/null +++ b/etc/release-notes/release-notes-2.21.adoc @@ -0,0 +1,6 @@ += Release 2.21 + +Released: Feb, 2010 + +* Bug fixes +* Immutable 2-3 finger tree diff --git a/etc/release-notes/release-notes-4.3.adoc b/etc/release-notes/release-notes-4.3.adoc index 75e5bca0..4e59ce0f 100644 --- a/etc/release-notes/release-notes-4.3.adoc +++ b/etc/release-notes/release-notes-4.3.adoc @@ -5,8 +5,27 @@ Released: Unreleased == Enhancements -TODO +* Added toInt and fromInt to fj.Ordering (#71) +* Added Java 8 collectors (#69) +* Made Seq.empty() and List.nil() return singleton instances (#70) +* Made anonymous classes using lamdas (#67) +* Improved show for list, tree, set, treemap, stream, array, V arity 2 to 8, HList (#77) +* Added TreeMap.splitLookup (#4) +* Add union to TreeMap (#83) +* Added List.isSingle (#84) +* Added Option traverse family of methods (#85) +* Added equals, hashCode and toString to classes P's, Array, Either, List, Option, Seq, Set, Stream, Tree, TreeMap, Validation (#75, 86) +* Added release notes as asciidoc (#`2) +* Added F0 interface (#93) +* Added wrapper functions for function arity 1 and 2 (#94) +* Enhanced implementation of equals for standard classes (#95) +* Added traverse method family to P1, P2, Either, List, Validation (#80) +* Enhanced integration with basic Java types (#99) == Fixes -TODO +* Fixed TreeMap.split (#4, #79) +* Fixed Option.fromNull javadoc (#73) +* Fixed Try javadoc (#91) + + From 9304052eece77c9fbc48d7d75a1c96f37bd66bc7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 29 Jan 2015 00:11:11 +1000 Subject: [PATCH 244/811] Removed aggregated release notes --- etc/release-notes.md | 174 ------------------------------------------- 1 file changed, 174 deletions(-) delete mode 100644 etc/release-notes.md diff --git a/etc/release-notes.md b/etc/release-notes.md deleted file mode 100644 index 21db503a..00000000 --- a/etc/release-notes.md +++ /dev/null @@ -1,174 +0,0 @@ - -Release Notes -============= - -4.3 -=== -Target date: To be decided - -* Enhancements - * To be decided -* Fixes - * To be decided - -4.2 -=== -Released: 20 December, 2014 - -* Enhancements - * Added Java 8 examples - * Added new website - * Added Option.none_() - * Gradle 2.2.1 support with wrapper - * Added to Strings: isNullOrEmpty, isNullOrBlank and isNotNullOrBlank - * Added Try with arity 0-8 for lambdas that throw exceptions - * Added Effect with arity 0-8 for lambdas with a void return - * Added TryEffect with arity 0-8 for lambdas with a void return that throw an Exception. - * Conversion from Java 8 types to Functional Java types and vice-versa - * Added monadic IO methods - * Support instantiation of IO with lambdas - * Added first class cons_ for List - * Added partial application of first parameter for F 1-8 - * Added SafeIO that encodes IOExceptions into Validations - * Added simple RNG - * Added Reader, Writer and State - * Deprecated $._ - * Added Array.scan family of methods - * Support instantiating P1 values using lambdas to P.lazy - * Added toString for Validation, P arities 1 to 8, Either - * Added vending machine demo - * Added Option.toValidation - * Added map and contramap for F and F2. - * Added partial application for F1. - * Added filter and uncurried foldLeft and foldRight to FingerTree. - * Added foldLeft, foldRight and map to Seq. - * Accumulate Validation errors in a List. - * Convert from fj.data.Stream to java.util.Stream and vice versa. - * Added groupBy on List. -* Fixes - * Various Javadoc issues - * Large inserts into TreeMap - * Javadoc support for Java 8 - * Null parameter NullPointerException for Show.anyShow - * Exception propagation in test data generators - * Product memoisation for arities 1 to 8 - * ClassCastException in class fj.data.Java - * Fixed performance of Set.member. - -4.1 -=== -Released: 30 May, 2014 - -* Support Java 7 by removing default methods. Methods on class C with default methods moved to static methods on new class ${C}Functions. - -4.0 -=== -Released: 30 May, 2014 - -* Merged changes from 3.2 -* Minimal changes to support Java 8. -* Changed abstract classes to interfaces with default methods (P1, F1 to F8). - -3.2 -=== -Released: 30 May, 2014 - -* Added methods to HashMap: toList, toStream, toOption, toArray, map, mapKeys, foreach, convert to/from java.util.Map. -* Convert from java.util.List to List. -* Fixed findChild method in TreeZipper to handle empty stream. -* Fixed stack overflow when sorting and zipping. -* Fixed stack overflow in Stream's bind method. -* Small Javadoc fixes. - -3.1 -=== -Released: May 2012 - -Administrivia: - -* Sources have been moved to GitHub: https://github.com/functionaljava/functionaljava -* Built has been converted to SBT - -New features: - -* List.mapMOption - list traversal in the Option monad. -* List.allEqual - Returns whether or not all elements in the list are equal. -* Added a monoid for Double. -* Tree.bottomUp - Grows a tree from another tree by folding it from the bottom up. -* Strings.isNotNullOrEmpty - does what it says. -* Ord.hashOrd - an order instance that uses hashCode() for the order. -* Ord.hashEqualsOrd - same as above but also uses .equals() -* Set.set - A vararg Set factory method. -* Added first-class functions for Set intersect, union, and minus. -* First-class LazyString.toString. -* Added hashCode() and equals() to Option. -* Iteratees and an IO monad. -* Trampoline - a general solution for tail-call elimination in Java. -* List.equals(), List.hashCode(), and List.toString(). - -Bug fixes: - -* Stream.inits should always be nonempty. -* Stream was not compiling in Eclipse. -* Stream.length is now tail-recursive. -* TreeZipper.delete was flipping lefts and rights. -* Fixed naturalOrd Javadoc. - -3.0 -=== -Released: Jun 2010 - -A crucial change has been made to the F interfaces, which are now abstract classes and containing useful methods. This means some other methods (fj.Function) are redundant and will be removed in a release soon (perhaps with a @Deprecated first). - -There are other minor additions and bug fixes. - -2.23 -==== -Released: TODO - -Changes: TODO - -2.22 -==== -Released: March 2010 - -* Bug fixes -* Documentation fixes -* Built against JDK 1.5 (not 1.6) - -2.21 -==== -Released Feb, 2010 - -* Bug fixes -* Immutable 2-3 finger tree - -2.20 -=== -Released: July 2009 - -The highlight of this release is a parallel module built on top of -actors for doing some very clever and high-level parallel programming. -e.g. An implementation of the parallel map/reduce algorithm -(parFoldMap) and APIs for making use of actors easier for you, the user. - -Other new bits includes: - -* A heap of bug fixes, particularly on Stream (and therefore, many of -its dependencies) -* LazyString -- a lazy sequence of characters -* Function Wrappers -* Improvements to the Tree and Zipper implementations -* Other tidbits and additional APIs - -2.19 -=== -Released March 2009 - -* Comonadic operations on Stream, Tree and others -* Database monad (java.sql.Connection as a functor) -* Natural Number data type -* The Constant Arrow ($) -* Immutable Tree Map -* A parallel quick-sort using Functional Java actors - From d0a1f10fcd8ea812d47318735bd4f2c68ee3e403 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 29 Jan 2015 00:47:20 +1000 Subject: [PATCH 245/811] Added contributors from github commit log --- etc/CONTRIBUTORS | 74 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/etc/CONTRIBUTORS b/etc/CONTRIBUTORS index 4c4085b1..ef8b2ed4 100644 --- a/etc/CONTRIBUTORS +++ b/etc/CONTRIBUTORS @@ -1,6 +1,7 @@ Tony Morris Workingmouse Pty. Ltd. tony@functionaljava.org +tmorris@tmorris.net http://tmorris.net/ -----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1.4.6 (GNU/Linux) @@ -36,6 +37,7 @@ gAAKCRCaemCth7qvrcbtAJ9j3C6lKNRB3uKcrfze66jAVQh0qACaAysOK82TcQ/2 Runar Bjarnason runar@functionaljava.org +runarorama@gmail.com -----BEGIN PGP PUBLIC KEY BLOCK----- Version: PGP Key Server 0.9.6 @@ -117,16 +119,18 @@ Workingmouse Pty. Ltd. brad@functionaljava.org http://bradclow.blogspot.com/ - Ricky Clarkson ricky@functionaljava.org +ricky.clarkson@gmail.com http://rickyclarkson.blogspot.com/ Nick Partridge nick@functionaljava.org Jason Zaugg +retronym jason@functionaljava.org +jzaugg@gmail.com Dylan Just dylan@techtangents.com @@ -134,3 +138,71 @@ dylan@techtangents.com Sam Reid reids@colorado.edu +Mark Perry +maperry78@yahoo.com.au + +Dobes Vandermeer +dobesv@gmail.com + +daneko +3a3k.web+github@gmail.com + +amarpotghan +amarpotghan@gmail.com + +Alexey Mz +zackflame@gmail.com + +Paul Horn +knutwalker@gmail.com + +Martin Seeler +mseeler@avantgarde-labs.de + +rxxg +robbiexgibson@yahoo.com + +Piotr Bzdyl +piotr@bzdyl.net + +Steven Ruppert +blendmaster@gmail.com + +xuwei-k +6b656e6a69@gmail.com + +Andrea Richiardi +a.richiardi.work@gmail.com + +Martin Grotzke +martin.grotzke@googlemail.com + +Dan Rosen +dr@stealthy.(none) + +Grégoire Neuville +gregoire.neuville@gmail.com + +Tom Crockett +pelotom@gmail.com + +Pawel Krupinski +pawel.krupinski@youdevise.com +pawel.krupinski@gmail.com + +Marc Siegel +marc.siegel@timgroup.com + +Gary Pamparà +gpampara@gmail.com + +kenji yoshida +6b656e6a69@gmail.com + +etorreborre +etorreborre@yahoo.com + +Gabor Liptak +gliptak@gmail.com + + From 097b298a37956b9ccd0e45834938f1cf5d5eb9bd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 31 Jan 2015 21:19:29 +1000 Subject: [PATCH 246/811] Reviewed examples shown on the website --- demo/src/main/java/fj/demo/Array_exists.java | 16 ++--- demo/src/main/java/fj/demo/Array_filter.java | 12 ++-- .../src/main/java/fj/demo/Array_foldLeft.java | 19 +++--- demo/src/main/java/fj/demo/Array_forall.java | 16 ++--- demo/src/main/java/fj/demo/Array_map.java | 1 - demo/src/main/java/fj/demo/List_map.java | 1 - demo/src/main/java/fj/demo/Option_bind.java | 58 ++++++++++--------- demo/src/main/java/fj/demo/Option_filter.java | 35 ++++++----- demo/src/main/java/fj/demo/Option_map.java | 24 ++++---- 9 files changed, 86 insertions(+), 96 deletions(-) diff --git a/demo/src/main/java/fj/demo/Array_exists.java b/demo/src/main/java/fj/demo/Array_exists.java index 0089b475..54641239 100644 --- a/demo/src/main/java/fj/demo/Array_exists.java +++ b/demo/src/main/java/fj/demo/Array_exists.java @@ -1,20 +1,14 @@ package fj.demo; -import fj.F; import fj.data.Array; import static fj.data.Array.array; import static fj.data.List.fromString; import static fj.function.Characters.isLowerCase; public final class Array_exists { - public static void main(final String[] args) { - final Array a = array("Hello", "There", "what", "DAY", "iS", "iT"); - final boolean b = a.exists(new F() { - public Boolean f(final String s) { - return fromString(s).forall(isLowerCase); - } - }); - final boolean b2 = a.exists(s -> fromString(s).forall(isLowerCase)); - System.out.println(b); // true ("what" provides the only example; try removing it) - } + public static void main(final String[] args) { + final Array a = array("Hello", "There", "what", "DAY", "iS", "iT"); + final boolean b = a.exists(s -> fromString(s).forall(isLowerCase)); + System.out.println(b); // true ("what" is the only value that qualifies; try removing it) + } } diff --git a/demo/src/main/java/fj/demo/Array_filter.java b/demo/src/main/java/fj/demo/Array_filter.java index 9b5a9330..cad6d393 100644 --- a/demo/src/main/java/fj/demo/Array_filter.java +++ b/demo/src/main/java/fj/demo/Array_filter.java @@ -7,10 +7,10 @@ import static fj.function.Integers.even; public final class Array_filter { - public static void main(final String[] args) { - final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); - final Array b = a.filter(even); - final Array c = a.filter(i -> i % 2 == 0); - arrayShow(intShow).println(b); // {44,22,90,98,1078,6,64,6,42} - } + public static void main(final String[] args) { + final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); + final Array b = a.filter(even); + final Array c = a.filter(i -> i % 2 == 0); + arrayShow(intShow).println(b); // {44,22,90,98,1078,6,64,6,42} + } } diff --git a/demo/src/main/java/fj/demo/Array_foldLeft.java b/demo/src/main/java/fj/demo/Array_foldLeft.java index 63d90bb0..9acb86be 100644 --- a/demo/src/main/java/fj/demo/Array_foldLeft.java +++ b/demo/src/main/java/fj/demo/Array_foldLeft.java @@ -6,15 +6,14 @@ import static fj.function.Integers.add; public final class Array_foldLeft { - public static void main(final String[] args) { - final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); - final int b = a.foldLeft(add, 0); + public static void main(final String[] args) { + final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); + final int b = a.foldLeft(add, 0); - // WARNING: In JDK 8, update 20 and 25 (current version) the following code triggers an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. - // final int c = a.foldLeft(i -> (j -> i + j), 0); - F> add2 = i -> (j -> i + j); - final int c = a.foldLeft(add2, 0); - - System.out.println(b); // 1774 - } + // WARNING: In JDK 8, update 20 and 25 (current version) the following code triggers an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. + // final int c = a.foldLeft(i -> (j -> i + j), 0); + F> add2 = i -> (j -> i + j); + final int c = a.foldLeft(add2, 0); + System.out.println(b); // 1774 + } } diff --git a/demo/src/main/java/fj/demo/Array_forall.java b/demo/src/main/java/fj/demo/Array_forall.java index c9888823..49e971d7 100644 --- a/demo/src/main/java/fj/demo/Array_forall.java +++ b/demo/src/main/java/fj/demo/Array_forall.java @@ -1,20 +1,14 @@ package fj.demo; -import fj.F; import fj.data.Array; import static fj.data.Array.array; import static fj.data.List.fromString; import static fj.function.Characters.isLowerCase; public final class Array_forall { - public static void main(final String[] args) { - final Array a = array("hello", "There", "what", "day", "is", "it"); - final boolean b = a.forall(new F() { - public Boolean f(final String s) { - return fromString(s).forall(isLowerCase); - } - }); - final boolean b2 = a.forall(s -> fromString(s).forall(isLowerCase)); - System.out.println(b); // false ("There" is a counter-example; try removing it) - } + public static void main(final String[] args) { + final Array a = array("hello", "There", "what", "day", "is", "it"); + final boolean b = a.forall(s -> fromString(s).forall(isLowerCase)); + System.out.println(b); // false ("There" is a counter-example; try removing it) + } } diff --git a/demo/src/main/java/fj/demo/Array_map.java b/demo/src/main/java/fj/demo/Array_map.java index cc638c5c..072610cf 100644 --- a/demo/src/main/java/fj/demo/Array_map.java +++ b/demo/src/main/java/fj/demo/Array_map.java @@ -1,7 +1,6 @@ package fj.demo; import fj.data.Array; - import static fj.data.Array.array; import static fj.function.Integers.add; import static fj.Show.arrayShow; diff --git a/demo/src/main/java/fj/demo/List_map.java b/demo/src/main/java/fj/demo/List_map.java index 83f89ead..55216810 100644 --- a/demo/src/main/java/fj/demo/List_map.java +++ b/demo/src/main/java/fj/demo/List_map.java @@ -1,7 +1,6 @@ package fj.demo; import fj.data.List; - import static fj.data.List.list; import static fj.function.Integers.add; import static fj.Show.intShow; diff --git a/demo/src/main/java/fj/demo/Option_bind.java b/demo/src/main/java/fj/demo/Option_bind.java index 4a478a22..96ecf153 100644 --- a/demo/src/main/java/fj/demo/Option_bind.java +++ b/demo/src/main/java/fj/demo/Option_bind.java @@ -2,38 +2,40 @@ import fj.F; import fj.data.Option; -import static fj.data.Option.none; -import static fj.data.Option.some; import static fj.Show.intShow; import static fj.Show.optionShow; +import static fj.data.Option.none; +import static fj.data.Option.some; public final class Option_bind { - public static void main(final String[] args) { - final Option o1 = some(7); - final Option o2 = some(8); - final Option o3 = none(); - final Option p1 = o1.bind(new F>() { - public Option f(final Integer i) { - return i % 2 == 0 ? some(i * 3) : Option.none(); - } - }); - final Option p2 = o2.bind(new F>() { - public Option f(final Integer i) { - return i % 2 == 0 ? some(i * 3) : Option.none(); - } - }); - final Option p3 = o3.bind(new F>() { - public Option f(final Integer i) { - return i % 2 == 0 ? some(i * 3) : Option.none(); - } - }); + public static void main(final String[] args) { + final Option o1 = some(7); + final Option o2 = some(8); + final Option o3 = none(); + + F> f = i -> i % 2 == 0 ? some(i * 3) : none(); + final Option o4 = o1.bind(f); + final Option o5 = o2.bind(f); + final Option o6 = o3.bind(f); - final Option p4 = o1.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); - final Option p5 = o2.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); - final Option p6 = o3.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p1 = o1.bind(new F>() { + public Option f(final Integer i) { + return i % 2 == 0 ? some(i * 3) : Option.none(); + } + }); + final Option p2 = o2.bind(new F>() { + public Option f(final Integer i) { + return i % 2 == 0 ? some(i * 3) : Option.none(); + } + }); + final Option p3 = o3.bind(new F>() { + public Option f(final Integer i) { + return i % 2 == 0 ? some(i * 3) : Option.none(); + } + }); - optionShow(intShow).println(p1); // None - optionShow(intShow).println(p2); // Some(24) - optionShow(intShow).println(p3); // None - } + optionShow(intShow).println(o4); // None + optionShow(intShow).println(o5); // Some(24) + optionShow(intShow).println(o6); // None + } } diff --git a/demo/src/main/java/fj/demo/Option_filter.java b/demo/src/main/java/fj/demo/Option_filter.java index ee7fa1ca..b572d315 100644 --- a/demo/src/main/java/fj/demo/Option_filter.java +++ b/demo/src/main/java/fj/demo/Option_filter.java @@ -1,27 +1,30 @@ package fj.demo; +import fj.F; import fj.data.Option; +import static fj.Show.intShow; +import static fj.Show.optionShow; import static fj.data.Option.none; import static fj.data.Option.some; import static fj.function.Integers.even; -import static fj.Show.intShow; -import static fj.Show.optionShow; public final class Option_filter { - public static void main(final String[] args) { - final Option o1 = some(7); - final Option o2 = none(); - final Option o3 = some(8); - final Option p1 = o1.filter(even); - final Option p2 = o2.filter(even); - final Option p3 = o3.filter(even); + public static void main(final String[] args) { + final Option o1 = some(7); + final Option o2 = none(); + final Option o3 = some(8); + + final Option o4 = o1.filter(even); + final Option o5 = o2.filter(even); + final Option o6 = o3.filter(even); - final Option p4 = o1.filter(i -> i % 2 == 0); - final Option p5 = o1.filter(i -> i % 2 == 0); - final Option p6 = o1.filter(i -> i % 2 == 0); + F f = i -> i % 2 == 0; + final Option o7 = o1.filter(f); + final Option o8 = o1.filter(f); + final Option o9 = o1.filter(i -> i % 2 == 0); - optionShow(intShow).println(p1); // None - optionShow(intShow).println(p2); // None - optionShow(intShow).println(p3); // Some(8) - } + optionShow(intShow).println(o4); // None + optionShow(intShow).println(o5); // None + optionShow(intShow).println(o6); // Some(8) + } } diff --git a/demo/src/main/java/fj/demo/Option_map.java b/demo/src/main/java/fj/demo/Option_map.java index 5f947b04..fa637385 100644 --- a/demo/src/main/java/fj/demo/Option_map.java +++ b/demo/src/main/java/fj/demo/Option_map.java @@ -1,23 +1,23 @@ package fj.demo; import fj.data.Option; +import static fj.Show.intShow; +import static fj.Show.optionShow; import static fj.data.Option.none; import static fj.data.Option.some; import static fj.function.Integers.add; -import static fj.Show.intShow; -import static fj.Show.optionShow; public final class Option_map { - public static void main(final String[] args) { - final Option o1 = some(7); - final Option o2 = none(); - final Option p1 = o1.map(add.f(42)); - final Option p2 = o2.map(add.f(42)); + public static void main(final String[] args) { + final Option o1 = some(7); + final Option o2 = none(); + final Option p1 = o1.map(add.f(42)); + final Option p2 = o2.map(add.f(42)); - final Option p3 = o1.map(i -> i + 42); - final Option p4 = o2.map(i -> i + 42); + final Option p3 = o1.map(i -> i + 42); + final Option p4 = o2.map(i -> i + 42); - optionShow(intShow).println(p1); // Some(49) - optionShow(intShow).println(p2); // None - } + optionShow(intShow).println(p1); // Some(49) + optionShow(intShow).println(p2); // None + } } From 7991c2f9cf00488844ab48385696a133dbb0a7b1 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Fri, 30 Jan 2015 17:00:05 +0530 Subject: [PATCH 247/811] adding predicate combinators --- core/src/main/java/fj/function/Booleans.java | 114 ++++++++++++++++--- 1 file changed, 96 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/fj/function/Booleans.java b/core/src/main/java/fj/function/Booleans.java index 8b509cad..56ad03dd 100644 --- a/core/src/main/java/fj/function/Booleans.java +++ b/core/src/main/java/fj/function/Booleans.java @@ -1,11 +1,11 @@ package fj.function; -import fj.F; -import fj.F2; -import fj.F3; + import static fj.Function.*; +import fj.F; import fj.Monoid; +import fj.Semigroup; import fj.data.List; import fj.data.Stream; @@ -42,20 +42,12 @@ private Booleans() { /** * Logical negation. */ - public static final F not = new F() { - public Boolean f(final Boolean p) { - return !p; - } - }; + public static final F not = p -> !p; /** * Curried form of logical "only if" (material implication). */ - public static final F> implies = curry(new F2() { - public Boolean f(final Boolean p, final Boolean q) { - return !p || q; - } - }); + public static final F> implies = curry((p, q) -> !p || q); /** * Curried form of logical "if" (reverse material implication). @@ -92,6 +84,56 @@ public static boolean and(final List l) { return Monoid.conjunctionMonoid.sumLeft(l); } + /** + * maps function on given predicate function + * @param p predicate to be mapped over + * @param f function + * @return predicate function + */ + public static F contramap(F f, F p){ + return compose(p, f); + } + + /** + * checks if given predicate does not hold for given function + * @param p predicate to be mapped over + * @param f function + * @return predicate function + */ + public static F isnot(F f, F p){ + return compose(not, contramap(f, p)); + } + + /** + * composes given predicates using conjunction + * @param p1 first predicate + * @param p2 second predicate + * @return composed predicate function + */ + public static F and(F p1, F p2){ + return Semigroup.functionSemigroup(conjunctionSemigroup).sum(p1, p2); + } + + /** + * composes given predicates using exclusive disjunction + * @param p1 first predicate + * @param p2 second predicate + * @return composed predicate function + */ + public static F xor(F p1, F p2){ + return Semigroup.functionSemigroup(exclusiveDisjunctionSemiGroup).sum(p1, p2); + } + + /** + * returns composes given predicates using disjunction + * @param p1 first predicate + * @param p2 second predicate + * @return composed predicate function + */ + public static F or(F p1, F p2){ + return Semigroup.functionSemigroup(disjunctionSemigroup).sum(p1, p2); + } + /** * Returns true if all the elements of the given stream are true. * @@ -102,6 +144,46 @@ public static boolean and(final Stream l) { return Monoid.conjunctionMonoid.sumLeft(l); } + /** + * Returns a composed predicate of given Stream of predicates + * + * @param l A stream of predicate functions + * @return composed predicate function + */ + public static F andAll(final Stream> l) { + return Monoid.functionMonoid(Monoid.conjunctionMonoid).sumLeft(l); + } + + /** + * Returns a composed predicate of given List of predicates + * + * @param l A list of predicate functions + * @return composed predicate function + */ + public static F andAll(final List> l) { + return Monoid.functionMonoid(Monoid.conjunctionMonoid).sumLeft(l); + } + + /** + * Returns a composed predicate of given List of predicates + * + * @param l A list of predicate functions + * @return composed predicate function + */ + public static F orAll(final List> l) { + return Monoid.functionMonoid(Monoid.disjunctionMonoid).sumLeft(l); + } + + /** + * Returns a composed predicate of given Stream of predicates + * + * @param l A stream of predicate functions + * @return composed predicate function + */ + public static F orAll(final Stream> l) { + return Monoid.functionMonoid(Monoid.disjunctionMonoid).sumLeft(l); + } + /** * Returns true if any element of the given list is true. * @@ -139,10 +221,6 @@ public static F not(final F p) { * @return A function that returns its second argument if the first argument is true, otherwise the third argument. */ public static F>> cond() { - return curry(new F3() { - public A f(final Boolean p, final A a1, final A a2) { - return p ? a1 : a2; - } - }); + return curry((p, a1, a2) -> p ? a1 : a2); } } From 75bec132b88e073d62e60f826f9354e5bfb1fcf5 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Wed, 4 Feb 2015 11:33:29 +0530 Subject: [PATCH 248/811] changing @javadoc --- core/src/main/java/fj/function/Booleans.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/fj/function/Booleans.java b/core/src/main/java/fj/function/Booleans.java index 56ad03dd..b691f476 100644 --- a/core/src/main/java/fj/function/Booleans.java +++ b/core/src/main/java/fj/function/Booleans.java @@ -85,7 +85,7 @@ public static boolean and(final List l) { } /** - * maps function on given predicate function + * maps given function to the predicate function * @param p predicate to be mapped over * @param f function * @return predicate function @@ -95,7 +95,7 @@ public static F contramap(F f, F p){ } /** - * checks if given predicate does not hold for given function + * returns inverse of contramap * @param p predicate to be mapped over * @param f function * @return predicate function @@ -105,7 +105,7 @@ public static F isnot(F f, F p){ } /** - * composes given predicates using conjunction + * composes the given predicate using conjunction * @param p1 first predicate * @param p2 second predicate * @return composed predicate function @@ -115,7 +115,7 @@ public static F and(F p1, F p2){ } /** - * composes given predicates using exclusive disjunction + * composes the given predicate using exclusive disjunction * @param p1 first predicate * @param p2 second predicate * @return composed predicate function @@ -125,10 +125,10 @@ public static F xor(F p1, F p2){ } /** - * returns composes given predicates using disjunction + * returns composed predicate using disjunction * @param p1 first predicate * @param p2 second predicate - * @return composed predicate function + * @return composed predicate */ public static F or(F p1, F p2){ return Semigroup.functionSemigroup(disjunctionSemigroup).sum(p1, p2); @@ -145,10 +145,10 @@ public static boolean and(final Stream l) { } /** - * Returns a composed predicate of given Stream of predicates + * Returns composed predicate * - * @param l A stream of predicate functions - * @return composed predicate function + * @param l A stream of predicates + * @return composed predicate */ public static F andAll(final Stream> l) { return Monoid.functionMonoid(Monoid.conjunctionMonoid).sumLeft(l); From 0cf8f9d2178fc4062fc7e5ccc9f3b4f301379f46 Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sat, 7 Feb 2015 12:04:31 +0530 Subject: [PATCH 249/811] fixing test for andAll --- core/src/test/java/fj/data/BooleansTest.java | 81 ++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 core/src/test/java/fj/data/BooleansTest.java diff --git a/core/src/test/java/fj/data/BooleansTest.java b/core/src/test/java/fj/data/BooleansTest.java new file mode 100644 index 00000000..c2a799e7 --- /dev/null +++ b/core/src/test/java/fj/data/BooleansTest.java @@ -0,0 +1,81 @@ +package fj.data; + +import fj.F; +import fj.function.Booleans; +import fj.test.Property; +import org.junit.Assert; +import org.junit.Test; + +import static fj.P1.curry; +import static fj.data.List.list; +import static fj.function.Booleans.isnot; +import static org.hamcrest.core.Is.is; + +/** + * Created by amar on 28/01/15. + */ +public class BooleansTest { + + @Test + public void testAnd(){ + F f1 = a -> a.startsWith("fj"); + F f2 = a -> a.contains("data"); + + F f3 = Booleans.and(f1, f2); + + Assert.assertTrue(f3.f("fj.data")); + Assert.assertTrue(f3.f("fj.data.Function")); + + } + + @Test + public void testOr(){ + F f1 = a -> a.startsWith("fj"); + F f2 = a -> a.startsWith("someOtherPackage"); + + F f3 = Booleans.or(f1, f2); + + Assert.assertTrue(f3.f("fj.data")); + Assert.assertTrue(f3.f("someOtherPackage.fj.data")); + Assert.assertFalse(f3.f("something.fj.data.Function")); + + } + + @Test + public void testComap(){ + F f1 = a -> a.length() > 3; + F f2 = a -> a.toString(); + + F f3 = Booleans.contramap(f2, f1); + + Assert.assertTrue(f3.f(1000)); + Assert.assertFalse(f3.f(100)); + + } + + @SuppressWarnings("unchecked") + @Test + public void testAndAll(){ + F f1 = a -> a.endsWith("fj"); + F f2 = a -> a.startsWith("someOtherPackage"); + F f3 = a -> a.length() < 20; + + F f4 = Booleans.andAll(Stream.>stream(f1, f2, f3)); + + Assert.assertTrue(f4.f("someOtherPackage.fj")); + Assert.assertFalse(f4.f("otther")); + Assert.assertFalse(f4.f("someOtherPackage.fj.data.something.really.big")); + + } + + @SuppressWarnings("unchecked") + @Test + public void testIsNot(){ + F f1 = a -> a == 4; + List result = list("some", "come", "done!").filter(isnot(String::length, f1)); + + Assert.assertThat(result.length(), is(1)); + Assert.assertEquals(result, list("done!")); + + } +} From 68253583b1a1df337256fd54e9db1be334cb555b Mon Sep 17 00:00:00 2001 From: amarpotghan Date: Sun, 8 Feb 2015 20:36:10 +0530 Subject: [PATCH 250/811] adding `is` alias for `contramap` --- core/src/main/java/fj/function/Booleans.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/src/main/java/fj/function/Booleans.java b/core/src/main/java/fj/function/Booleans.java index b691f476..6211e870 100644 --- a/core/src/main/java/fj/function/Booleans.java +++ b/core/src/main/java/fj/function/Booleans.java @@ -94,6 +94,16 @@ public static F contramap(F f, F p){ return compose(p, f); } + /** + * alias for contramap + * @param p predicate to be mapped over + * @param f function + * @return predicate function + */ + public static F is(F f, F p){ + return contramap(f, p); + } + /** * returns inverse of contramap * @param p predicate to be mapped over From bb1cb0151af308d5b84f4a042425cb0433a00d5e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 9 Feb 2015 21:46:43 +1000 Subject: [PATCH 251/811] Updated future 4.3 release notes and contributors --- etc/CONTRIBUTORS | 4 +++- etc/release-notes/release-notes-4.3.adoc | 21 +++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/etc/CONTRIBUTORS b/etc/CONTRIBUTORS index ef8b2ed4..c4dc5934 100644 --- a/etc/CONTRIBUTORS +++ b/etc/CONTRIBUTORS @@ -147,7 +147,7 @@ dobesv@gmail.com daneko 3a3k.web+github@gmail.com -amarpotghan +Amar Potghan amarpotghan@gmail.com Alexey Mz @@ -205,4 +205,6 @@ etorreborre@yahoo.com Gabor Liptak gliptak@gmail.com +Greg Row +gregrow@users.noreply.github.com diff --git a/etc/release-notes/release-notes-4.3.adoc b/etc/release-notes/release-notes-4.3.adoc index 4e59ce0f..13bae6ed 100644 --- a/etc/release-notes/release-notes-4.3.adoc +++ b/etc/release-notes/release-notes-4.3.adoc @@ -14,18 +14,35 @@ Released: Unreleased * Add union to TreeMap (#83) * Added List.isSingle (#84) * Added Option traverse family of methods (#85) -* Added equals, hashCode and toString to classes P's, Array, Either, List, Option, Seq, Set, Stream, Tree, TreeMap, Validation (#75, 86) -* Added release notes as asciidoc (#`2) +* Added equals, hashCode and toString to classes P's, Array, Either, List, Option, Seq, Set, Stream, Tree, TreeMap, Validation (#75, #86) +* Added release notes as asciidoc (#92) * Added F0 interface (#93) * Added wrapper functions for function arity 1 and 2 (#94) * Enhanced implementation of equals for standard classes (#95) * Added traverse method family to P1, P2, Either, List, Validation (#80) * Enhanced integration with basic Java types (#99) +* Made artifact OSGI compatible, suitable as Eclipse plugin (#72) +* Added predicate combinators (#98) == Fixes * Fixed TreeMap.split (#4, #79) * Fixed Option.fromNull javadoc (#73) * Fixed Try javadoc (#91) +* Fixed stack overflow in TreeMap.update (#97) + +== Documentation + +* Added contributors from commit log. + +== Contributors + +* Mark Perry +* Amar Potghan +* Dobes Vandermeer +* Paul Horn +* Alexey Mz +* daneko +* Greg Row From b59c3d8e564abb489be4f0973adcb87586d2e924 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 9 Feb 2015 22:03:20 +1000 Subject: [PATCH 252/811] Documented breaking change in 4.3 release notes --- etc/release-notes/release-notes-4.3.adoc | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/etc/release-notes/release-notes-4.3.adoc b/etc/release-notes/release-notes-4.3.adoc index 13bae6ed..5779277d 100644 --- a/etc/release-notes/release-notes-4.3.adoc +++ b/etc/release-notes/release-notes-4.3.adoc @@ -1,7 +1,7 @@ = Release 4.3 -Released: Unreleased +Released: Some future date == Enhancements @@ -17,7 +17,7 @@ Released: Unreleased * Added equals, hashCode and toString to classes P's, Array, Either, List, Option, Seq, Set, Stream, Tree, TreeMap, Validation (#75, #86) * Added release notes as asciidoc (#92) * Added F0 interface (#93) -* Added wrapper functions for function arity 1 and 2 (#94) +* Added wrapper functions for function interfaces arity 1 and 2 (#94) * Enhanced implementation of equals for standard classes (#95) * Added traverse method family to P1, P2, Either, List, Validation (#80) * Enhanced integration with basic Java types (#99) @@ -31,6 +31,24 @@ Released: Unreleased * Fixed Try javadoc (#91) * Fixed stack overflow in TreeMap.update (#97) +== Breaking Changes + +* #93 added the F0 interface which P1 implements. This could break code where the _1 method for a new P1 called the method 'f' outside P1's scope. Making P1 implement F0 means that P1 now has an 'f' method which hides the visibility of the previously visible outer 'f'. You can fix this by using P.lazy, as per the example below. + +[source,java] +---- +// old code +return fromString(s.some()).append(new P1>() { + public Stream _1() { + return f(reader); // call outer f, 4.3 code change breaks this + } +}); + +// new code +return fromString(s.some()).append(P.lazy(u -> f(reader))); // outer f now visible +---- + + == Documentation * Added contributors from commit log. From a0d4ec5f15a000720d0617a574cfe28e55ef1f32 Mon Sep 17 00:00:00 2001 From: Paul Horn Date: Wed, 11 Feb 2015 12:58:39 +0100 Subject: [PATCH 253/811] Fix race condition in P1.memo() The race was when two thread encountered the uninitialized state, `a == null`. One thread gets suspended before entering the `synchronized` block, while the other runs though it. The latter thread sets `v` to something not null. Then the first thread resumes, enters the `synchronized` block and checks if `(v == null || v.get() == null)` which is now false, and thus returns the still uninitialized `a`. Fixes #105 --- core/src/main/java/fj/P1.java | 7 +++++-- core/src/test/java/fj/P1Test.java | 31 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 core/src/test/java/fj/P1Test.java diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 711b1436..84fedd91 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -223,9 +223,12 @@ public A _1() { A a = v != null ? v.get() : null; if (a == null) synchronized (latch) { - if (v == null || v.get() == null) + if (v == null || v.get() == null) { a = self._1(); - v = new SoftReference(a); + v = new SoftReference(a); + } else { + a = v.get(); + } } return a; } diff --git a/core/src/test/java/fj/P1Test.java b/core/src/test/java/fj/P1Test.java new file mode 100644 index 00000000..2a161777 --- /dev/null +++ b/core/src/test/java/fj/P1Test.java @@ -0,0 +1,31 @@ +package fj; + +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +public final class P1Test { + + @Test + public void bug105() throws Exception { + final P1 p1 = P.p("Foo").memo(); + final AtomicInteger nullCounter = new AtomicInteger(); + ExecutorService executorService = Executors.newCachedThreadPool(); + + for (int i = 0; i < 10000; i++) { + executorService.submit(() -> { + if (p1._1() == null) { + nullCounter.incrementAndGet(); + } + }); + } + + executorService.shutdown(); + executorService.awaitTermination(10, TimeUnit.DAYS); + + org.junit.Assert.assertEquals("Race condition in P1.memo()", 0, nullCounter.get()); + } +} From e99218072518f9943568c9363780826614b0e7b1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 14 Feb 2015 14:24:14 +1000 Subject: [PATCH 254/811] Updated version to 4.3, small update to release notes --- build.gradle | 2 +- etc/release-notes/release-notes-4.3.adoc | 3 ++- gradle.properties | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 69fd4bf5..4480766b 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.3" snapshotAppendix = "-SNAPSHOT" diff --git a/etc/release-notes/release-notes-4.3.adoc b/etc/release-notes/release-notes-4.3.adoc index 5779277d..094eb08a 100644 --- a/etc/release-notes/release-notes-4.3.adoc +++ b/etc/release-notes/release-notes-4.3.adoc @@ -1,7 +1,7 @@ = Release 4.3 -Released: Some future date +Released: 14 February 2015 == Enhancements @@ -30,6 +30,7 @@ Released: Some future date * Fixed Option.fromNull javadoc (#73) * Fixed Try javadoc (#91) * Fixed stack overflow in TreeMap.update (#97) +* Fixed concurrency issue with P1.memo (#105) == Breaking Changes diff --git a/gradle.properties b/gradle.properties index d4552a30..07c2b60c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false +signingEnabled = true From 6f74280a68a56346fde91ccf5d9bd16ae34bc88e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 14 Feb 2015 15:38:58 +1000 Subject: [PATCH 255/811] Increased version to 4.4-SNAPSHOT --- build.gradle | 6 +++--- gradle.properties | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 4480766b..c3f5144a 100644 --- a/build.gradle +++ b/build.gradle @@ -17,12 +17,12 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.3" + isSnapshot = true + fjBaseVersion = "4.4" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.2" + fjConsumeVersion = "4.3" signModule = false diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From c66943afc92e2a7fa642ec4358df38c3e120d7b1 Mon Sep 17 00:00:00 2001 From: daneko <3a3k.web+github@gmail.com> Date: Tue, 17 Feb 2015 00:49:45 +0900 Subject: [PATCH 256/811] fix LazyString#toString for android --- core/src/main/java/fj/data/LazyString.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index 5ce04e36..d95ae8ed 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -108,7 +108,7 @@ public CharSequence subSequence(final int start, final int end) { * @return The String representation of this lazy string. */ public String toString() { - return new StringBuilder(this).toString(); + return new StringBuilder(length() + 16).append(this).toString(); } /** From 5b7c6bcf8e48c7cea53d92561c43178776b25ef7 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Fri, 20 Feb 2015 11:25:25 -0800 Subject: [PATCH 257/811] Preserve ordering in TreeMap.toMutableMap() --- core/src/main/java/fj/Ord.java | 11 +++++++++++ core/src/main/java/fj/data/TreeMap.java | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 81ad92a8..36ac45f4 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -12,6 +12,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Comparator; import static fj.Function.curry; @@ -503,4 +504,14 @@ public static Ord hashEqualsOrd() { }); } + class OrdComparator implements Comparator { + @Override + public int compare(A o1, A o2) { + return Ord.this.compare(o1, o2).toInt(); + } + } + + public Comparator toComparator() { + return new OrdComparator(); + } } diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 0b3cbc84..ed43a16a 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -2,6 +2,7 @@ import fj.*; +import java.util.Comparator; import java.util.Iterator; import java.util.Map; @@ -172,7 +173,9 @@ public Iterator> iterator() { * @return A new mutable map isomorphic to this tree map. */ public Map toMutableMap() { - final Map m = new java.util.TreeMap(); + final F>> fakePair = k -> P.p(k, Option.none()); + final Comparator comparator = tree.ord().comap(fakePair).toComparator(); + final Map m = new java.util.TreeMap(comparator); for (final P2 e : this) { m.put(e._1(), e._2()); } From 7dd5bd8bfff7d8e3ba123b35873834f71b6a60c7 Mon Sep 17 00:00:00 2001 From: Dobes Vandermeer Date: Fri, 20 Feb 2015 11:33:22 -0800 Subject: [PATCH 258/811] Add a test case to verify that toMutableMap() works with keys that don't implement Comparable (i.e. a List) --- core/src/test/java/fj/data/TreeMapTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 0f8651b7..e89f4a26 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -1,13 +1,17 @@ package fj.data; +import java.util.Map; + import fj.Equal; import fj.Ord; import fj.P3; import fj.Show; import fj.P; + import org.junit.Test; import static fj.data.Option.some; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** @@ -74,4 +78,12 @@ public void splitLookup() { assertTrue(eq.eq(p3, P.p(leftMap, some(Integer.toString(pivot)), rightMap))); } + @Test + public void toMutableMap() { + int max = 5; + List> l = List.range(1, max + 1).map(n -> List.single(n)); + TreeMap, String> m2 = TreeMap.treeMap(Ord.listOrd(Ord.intOrd), l.zip(l.map(i -> i.toString()))); + Map, String> mm = m2.toMutableMap(); + assertEquals(m2.keys().reverse(), List.iterableList(mm.keySet())); + } } From f5e9f6a6a90ef3fa0b2ec6e74ce9f928117580e9 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 21 Mar 2015 14:30:00 +0900 Subject: [PATCH 259/811] travis --- .travis.yml | 11 +++++++++++ README.adoc | 4 +++- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..1d62c9c3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: java + +sudo: false + +jdk: + - oraclejdk8 + +script: + - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME + - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME + - ./gradlew build --stacktrace --info diff --git a/README.adoc b/README.adoc index d256f5e8..7c42ad86 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,7 @@ = Functional Java +image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] + image::http://www.functionaljava.org/img/logo-600x144.png[] Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. @@ -98,4 +100,4 @@ A more complete description of the features mentioned above are: == License -link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause license) available at https://en.wikipedia.org/wiki/BSD_licenses[]. \ No newline at end of file +link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause license) available at https://en.wikipedia.org/wiki/BSD_licenses[]. From 35f87adb9d3b9d9c792d23d8c67e2d8c99ac0243 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 21 Mar 2015 14:59:31 +0900 Subject: [PATCH 260/811] fix some exhausted tests --- tests/src/test/scala/fj/data/CheckArray.scala | 16 ++++++++++------ tests/src/test/scala/fj/data/CheckIteratee.scala | 9 ++++----- tests/src/test/scala/fj/data/CheckList.scala | 8 +++++--- tests/src/test/scala/fj/data/CheckStream.scala | 8 +++++--- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/src/test/scala/fj/data/CheckArray.scala b/tests/src/test/scala/fj/data/CheckArray.scala index a1c8a446..f8cce111 100755 --- a/tests/src/test/scala/fj/data/CheckArray.scala +++ b/tests/src/test/scala/fj/data/CheckArray.scala @@ -107,9 +107,11 @@ object CheckArray extends Properties("Array") { a.reverse.reverse, a)) - property("reverse") = forAll((a: Array[String], n: Int) => - (n >= 0 && n < a.length) ==> - (a.reverse.get(n) == a.get(a.length - 1 - n))) + property("reverse") = forAll((a: Array[String], x: Byte) => + (a.length > 0) ==> { + val n = math.abs(x) % a.length + (a.reverse.get(n) == a.get(a.length - 1 - n)) + }) property("appendLeftIdentity") = forAll((a: Array[String]) => arrayEqual(stringEqual).eq(a.append(empty[String]), a)) @@ -123,9 +125,11 @@ object CheckArray extends Properties("Array") { property("appendLength") = forAll((a: Array[String], b: Array[String]) => a.append(b).length == a.length + b.length) - property("array") = forAll((a: scala.Array[String], n: Int) => - (n >= 0 && n < a.length) ==> - (array[String](a: _*).length == a.length && array[String](a: _*).get(n) == a(n))) + property("array") = forAll((a: scala.Array[String], x: Byte) => + (a.length > 0) ==> { + val n = math.abs(x) % a.length + array[String](a: _*).length == a.length && array[String](a: _*).get(n) == a(n) + }) property("join") = forAll((a: Array[Array[String]]) => arrayEqual(stringEqual).eq( diff --git a/tests/src/test/scala/fj/data/CheckIteratee.scala b/tests/src/test/scala/fj/data/CheckIteratee.scala index 76213a5d..d47c95f8 100644 --- a/tests/src/test/scala/fj/data/CheckIteratee.scala +++ b/tests/src/test/scala/fj/data/CheckIteratee.scala @@ -27,11 +27,10 @@ object CheckIteratee extends Properties("Iteratee") { property("head") = forAll((a: List[Int]) => enumerate(a, IterV.head[Int]).run == a.toOption) - property("drop") = forAll((a: List[String], n: Int) => { - (n >= 0 && n <= a.length) ==> { - val actual = enumerate(a, IterV.drop(n).bind(Function.constant(IterV.list[String]))).run.reverse - listEqual(stringEqual).eq(actual, a.drop(n)) - } + property("drop") = forAll((a: List[String], x: Byte) => (a.length > 0) ==> { + val n = math.abs(x) % a.length + val actual = enumerate(a, IterV.drop(n).bind(Function.constant(IterV.list[String]))).run.reverse + listEqual(stringEqual).eq(actual, a.drop(n)) }) property("list") = forAll((a: List[String]) => diff --git a/tests/src/test/scala/fj/data/CheckList.scala b/tests/src/test/scala/fj/data/CheckList.scala index 1f41e5ec..f00bae1a 100644 --- a/tests/src/test/scala/fj/data/CheckList.scala +++ b/tests/src/test/scala/fj/data/CheckList.scala @@ -118,9 +118,11 @@ object CheckList extends Properties("List") { (a append b).reverse, b.reverse.append(a.reverse))) - property("index") = forAll((a: List[String], n: Int) => - (n > 0 && n < a.length) ==> - (a.index(n) == a.tail.index(n - 1))) + property("index") = forAll((a: List[String], x: Byte) => + (a.length > 0) ==> { + val n = math.abs(x) % a.length + 1 + (n < a.length) ==> (a.index(n) == a.tail.index(n - 1)) + }) property("snoc") = forAll((a: List[String], s: String) => listEqual(stringEqual).eq( diff --git a/tests/src/test/scala/fj/data/CheckStream.scala b/tests/src/test/scala/fj/data/CheckStream.scala index 26ac6d31..8d97600d 100644 --- a/tests/src/test/scala/fj/data/CheckStream.scala +++ b/tests/src/test/scala/fj/data/CheckStream.scala @@ -128,9 +128,11 @@ object CheckStream extends Properties("Stream") { (a append b).reverse, b.reverse.append(a.reverse))) - property("index") = forAll((a: Stream[String], n: Int) => - (n > 0 && n < a.length) ==> - (a.index(n) == a.tail._1.index(n - 1))) + property("index") = forAll((a: Stream[String], x: Byte) => + (a.length > 0) ==> { + val n = math.abs(x) % a.length + 1 + (n < a.length) ==> (a.index(n) == a.tail._1.index(n - 1)) + }) property("forall") = forAll((a: Stream[Int]) => a.forall((x: Int) => ((x % 2 == 0): java.lang.Boolean)) == From 245ea694d9e15089b10b117a70a34235dee2de9e Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 21 Mar 2015 17:08:12 +0900 Subject: [PATCH 261/811] maxSize = 20 --- tests/src/test/scala/fj/Tests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/src/test/scala/fj/Tests.scala b/tests/src/test/scala/fj/Tests.scala index 5c54cd2b..d0ddb983 100644 --- a/tests/src/test/scala/fj/Tests.scala +++ b/tests/src/test/scala/fj/Tests.scala @@ -29,7 +29,7 @@ object Tests { def run(tests: List[(String, Prop)]) = tests foreach { case (name, p) => { - val c = check(new Test.Parameters.Default { }, p) + val c = check(new Test.Parameters.Default { override val maxSize = 20 }, p) c.status match { case Test.Passed => println("Passed " + name) case Test.Proved(_) => println("Proved " + name) From c71f0d4c6b845d236e2207df900edef966d6799f Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sat, 28 Feb 2015 04:35:38 +0900 Subject: [PATCH 262/811] avoid overflow ``` scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25). Type in expressions to have them evaluated. Type :help for more information. scala> fj.test.Rand.standard.choose(Int.MinValue, Int.MaxValue) java.lang.IllegalArgumentException: bound must be positive at java.util.Random.nextInt(Random.java:388) at fj.test.Rand$4$1$1.f(Rand.java:135) at fj.test.Rand$4$1$1.f(Rand.java:131) at fj.test.Rand.choose(Rand.java:45) ``` --- core/src/main/java/fj/test/Rand.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/test/Rand.java b/core/src/main/java/fj/test/Rand.java index 68c91062..57e90a0e 100644 --- a/core/src/main/java/fj/test/Rand.java +++ b/core/src/main/java/fj/test/Rand.java @@ -130,9 +130,14 @@ public F> f(final Option seed) { public F f(final Integer from) { return new F() { public Integer f(final Integer to) { - final int f = min(from, to); - final int t = max(from, to); - return f + seed.map(fr).orSome(new Random()).nextInt(t - f + 1); + if(from == to){ + return from; + }else{ + final int f = min(from, to); + final int t = max(from, to); + final int x = Math.abs(t - f); + return f + seed.map(fr).orSome(new Random()).nextInt(x == Integer.MIN_VALUE ? Integer.MAX_VALUE : x); + } } }; } From 297df92b0d76a452dc63732e4585aee3dfa95a05 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Mar 2015 14:13:12 +0900 Subject: [PATCH 263/811] remove unused settings --- tests/build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/build.gradle b/tests/build.gradle index d9a4e0bd..4725f21c 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -5,8 +5,6 @@ ext { scalaVersion = "2.10.3" scalacheckScalaVersion = "2.10" scalacheckVersion = "1.10.1" - scalatestScalaVersion= "2.10" - scalatestVersion = "1.9.2" } tasks.withType(ScalaCompile) { From 8d3d5bfafe184448652d29fd07f51c3bed0d35cf Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Mar 2015 15:14:32 +0900 Subject: [PATCH 264/811] update README. latest version is 4.3 --- README.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.adoc b/README.adoc index 7c42ad86..556947da 100644 --- a/README.adoc +++ b/README.adoc @@ -30,10 +30,10 @@ The Functional Java artifact is published to Maven Central using the group `org. * the core library (`functionaljava`) * Java 8 specific support (`functionaljava-java8`) -The latest version is `4.2`. This can be added to your Gradle project by adding the dependencies: +The latest version is `4.3`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.2" -compile "org.functionaljava:functionaljava-java8:4.2" +compile "org.functionaljava:functionaljava:4.3" +compile "org.functionaljava:functionaljava-java8:4.3" ---- and in Maven: @@ -41,12 +41,12 @@ and in Maven: org.functionaljava functionaljava - 4.2 + 4.3 org.functionaljava functionaljava-java8 - 4.2 + 4.3 ---- From c77c06586c05363e357a83e3df6e3dbf2de01223 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 22 Mar 2015 20:30:57 +1000 Subject: [PATCH 265/811] #118: Update to gradle 2.3 --- gradle/wrapper/gradle-wrapper.properties | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 212683d8..f96025de 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,5 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -#distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip From 627d9dfa6725bcb301361477fcbc50c6efe77f61 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 22 Mar 2015 22:08:43 +1000 Subject: [PATCH 266/811] #119: Added gradle uptodate plugin --- build.gradle | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index c3f5144a..853d2ea3 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,24 @@ defaultTasks 'build' ext { } +buildscript { + ext { + uptodateVersion = "1.3.1" + retrolambdaVersion = "2.5.0" + } + + repositories { + mavenLocal() + jcenter() + mavenCentral() + } + + dependencies { + classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" + classpath "me.tatarka:gradle-retrolambda:$retrolambdaVersion" + } +} + if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { @@ -52,21 +70,14 @@ allprojects { subprojects { - buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath 'me.tatarka:gradle-retrolambda:2.5.0' - } - } - apply from: "$rootDir/lib.gradle" apply plugin: "java" apply plugin: "eclipse" + apply plugin: "com.ofg.uptodate" repositories { + mavenLocal() + jcenter() mavenCentral() maven { url sonatypeRepositoryUrl From c953b078bd27c88cf1782d0de236418d8ba85279 Mon Sep 17 00:00:00 2001 From: xuwei-k <6b656e6a69@gmail.com> Date: Sun, 22 Mar 2015 14:31:16 +0900 Subject: [PATCH 267/811] update scala and scalacheck version --- tests/build.gradle | 16 ++++++++-------- tests/src/test/scala/fj/Tests.scala | 5 ----- .../fj/control/parallel/ArbitraryStrategy.scala | 5 ++--- .../src/test/scala/fj/data/ArbitraryOption.scala | 4 ++-- tests/src/test/scala/fj/data/ArbitraryTree.scala | 8 ++++++-- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/tests/build.gradle b/tests/build.gradle index 4725f21c..24902acb 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -2,21 +2,21 @@ apply plugin: 'scala' ext { - scalaVersion = "2.10.3" - scalacheckScalaVersion = "2.10" - scalacheckVersion = "1.10.1" + scalaVersion = "2.11.6" + scalacheckScalaVersion = "2.11" + scalacheckVersion = "1.12.2" } tasks.withType(ScalaCompile) { - scalaCompileOptions.useAnt = false + scalaCompileOptions.useAnt = false } dependencies { - compile project(":core") - compile "org.scala-lang:scala-library:$scalaVersion" + compile project(":core") + compile "org.scala-lang:scala-library:$scalaVersion" - testCompile "org.scala-lang:scala-library:$scalaVersion" - testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" + testCompile "org.scala-lang:scala-library:$scalaVersion" + testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" testCompile dependencyJunit } diff --git a/tests/src/test/scala/fj/Tests.scala b/tests/src/test/scala/fj/Tests.scala index d0ddb983..2110fa6c 100644 --- a/tests/src/test/scala/fj/Tests.scala +++ b/tests/src/test/scala/fj/Tests.scala @@ -23,7 +23,6 @@ object Tests { } import org.scalacheck.Prop - import org.scalacheck.ConsoleReporter._ import org.scalacheck.Test import org.scalacheck.Test.check @@ -35,10 +34,6 @@ object Tests { case Test.Proved(_) => println("Proved " + name) case f @ Test.Failed(_, _) => sys.error(name + ": " + f) case Test.Exhausted => println("Exhausted " + name) - case f @ Test.GenException(e) => { - e.printStackTrace - sys.error(name + ": " + f) - } case f @ Test.PropException(_, e, _) => { e.printStackTrace sys.error(name + ": " + f) diff --git a/tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala b/tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala index 4ff0dd8d..a3e49011 100644 --- a/tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala +++ b/tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala @@ -2,9 +2,8 @@ package fj package control package parallel -import control._ import org.scalacheck.Arbitrary -import org.scalacheck.Gen.value +import org.scalacheck.Gen.const import Strategy.executorStrategy import java.util.concurrent.Executors.newFixedThreadPool import java.util.concurrent._ @@ -20,5 +19,5 @@ object ArbitraryStrategy { }) implicit def arbitraryStrategy[A]: Arbitrary[Strategy[A]] = - Arbitrary(value(executorStrategy[A](executor))) + Arbitrary(const(executorStrategy[A](executor))) } diff --git a/tests/src/test/scala/fj/data/ArbitraryOption.scala b/tests/src/test/scala/fj/data/ArbitraryOption.scala index 43bb08fc..d92a70f5 100644 --- a/tests/src/test/scala/fj/data/ArbitraryOption.scala +++ b/tests/src/test/scala/fj/data/ArbitraryOption.scala @@ -3,10 +3,10 @@ package data import org.scalacheck.Arbitrary import org.scalacheck.Arbitrary.arbitrary -import org.scalacheck.Gen.{value, sized, resize} +import org.scalacheck.Gen.{const, sized, resize} import Option.{none, some} object ArbitraryOption { implicit def arbitraryOption[A](implicit a: Arbitrary[A]): Arbitrary[Option[A]] = - Arbitrary(sized(n => if(n == 0) value(none[A]) else resize(n - 1, arbitrary[A]).map(some(_)))) + Arbitrary(sized(n => if(n == 0) const(none[A]) else resize(n - 1, arbitrary[A]).map(some(_)))) } diff --git a/tests/src/test/scala/fj/data/ArbitraryTree.scala b/tests/src/test/scala/fj/data/ArbitraryTree.scala index e8169f0c..1138e9d4 100644 --- a/tests/src/test/scala/fj/data/ArbitraryTree.scala +++ b/tests/src/test/scala/fj/data/ArbitraryTree.scala @@ -8,13 +8,17 @@ import org.scalacheck.Gen import ArbitraryStream.arbitraryStream import ArbitraryList.{listOf} import Tree.{node, leaf} -import math.{round, sqrt} object ArbitraryTree { implicit def arbitraryTree[A](implicit a: Arbitrary[A]): Arbitrary[Tree[A]] = { def tree(implicit a:Arbitrary[A], n:Int, g:Gen[A]) : Gen[Tree[A]] = n match { case 0 => g.map(leaf(_)) - case n => choose(0, 10).flatMap((i) => lzy(g.map2(resize(i, listOf(tree(a, n/5, g)).map((x:fj.data.List[Tree[A]]) => P.p(x.toStream)))) (node(_, _)))) + case n => choose(0, 10).flatMap(i => + lzy(Gen.zip( + g, + resize(i, listOf(tree(a, n/5, g)).map((x:fj.data.List[Tree[A]]) => P.p(x.toStream))) + ).map(t => node(t._1, t._2))) + ) } Arbitrary(sized(tree(a, _, arbitrary[A]))) } From 949e0c3e5e055d7a2fa12a0df4e8d3fa89980956 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 31 Mar 2015 23:47:00 +0200 Subject: [PATCH 268/811] Add bimap to Either --- core/src/main/java/fj/data/Either.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 5f958c4d..739b6f01 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -78,6 +78,19 @@ public final X either(final F left, final F right) { right.f(right().value()); } + /** + * Map the given functions across the appropriate side. + * + * @param left The function to map if this is left. + * @param right The function to map if this is right. + * @return A new either value after mapping with the appropriate function applied. + */ + public final Either bimap(final F left, final F right) { + return isLeft() ? + left(left.f(left().value())) : + right(right.f(right().value())); + } + @Override public boolean equals(Object other) { From 91dc69007ccdb245a62ea4c9fec0b66d297ed3f1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 11 Apr 2015 14:22:07 +0200 Subject: [PATCH 269/811] Equal.equals0: helper method to implements Object.equals. Fix #122 --- core/src/main/java/fj/Equal.java | 29 ++++++++++++++++++++++ core/src/main/java/fj/P1.java | 3 +-- core/src/main/java/fj/P2.java | 2 +- core/src/main/java/fj/P3.java | 3 ++- core/src/main/java/fj/P4.java | 3 ++- core/src/main/java/fj/P5.java | 3 ++- core/src/main/java/fj/P6.java | 3 ++- core/src/main/java/fj/P7.java | 3 ++- core/src/main/java/fj/P8.java | 3 ++- core/src/main/java/fj/data/Array.java | 2 +- core/src/main/java/fj/data/Either.java | 2 +- core/src/main/java/fj/data/List.java | 7 +----- core/src/main/java/fj/data/Option.java | 2 +- core/src/main/java/fj/data/Seq.java | 2 +- core/src/main/java/fj/data/Set.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/Tree.java | 2 +- core/src/main/java/fj/data/TreeMap.java | 2 +- core/src/main/java/fj/data/Validation.java | 2 +- core/src/test/java/fj/P1Test.java | 20 +++++++++++++++ 20 files changed, 73 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index cd719e8c..f778bb69 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -1,6 +1,7 @@ package fj; import static fj.Function.curry; +import static fj.Unit.unit; import fj.data.*; import fj.data.hlist.HList; @@ -549,5 +550,33 @@ public static Option shallowEqualsO(Object o1, Object o2) { return Option.some(false); } } + + /** + * Helper method to implement {@link Object#equals(Object)} correctly. DO NOT USE it for any other purpose. + * + * @param clazz the class in which the {@link Object#equals(Object)} is implemented + * @param self a reference to 'this' + * @param other the other object of the comparison + * @param equal an equal instance for the type of self (that use {@link #anyEqual()} if generic type). + * @return true if self and other are equal + */ + @SuppressWarnings("unchecked") + public static boolean equals0(final java.lang.Class clazz, final A self, final Object other, final Equal equal) { + return self == other ? true : clazz.isInstance(other) ? equal.eq(self, (A) other) : false; + } + + /** + * Helper method to implement {@link Object#equals(Object)} correctly. DO NOT USE it for any other purpose. + * + * @param clazz the class in which the {@link Object#equals(Object)} is implemented + * @param self a reference to 'this' + * @param other the other object of the comparison + * @param equal a lazy equal instance for the type (that use {@link #anyEqual()} if generic type).. + * @return true if self and other are equal + */ + @SuppressWarnings("unchecked") + public static boolean equals0(final java.lang.Class clazz, final A self, final Object other, final F> equal) { + return self == other ? true : clazz.isInstance(other) ? equal.f(unit()).eq(self, (A) other) : false; + } } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 84fedd91..5e62d594 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -254,10 +254,9 @@ public String toString() { return Show.p1Show(Show.anyShow()).showS(this); } - @SuppressWarnings("unchecked") @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other))); + return Equal.equals0(P1.class, this, other, u -> Equal.p1Equal(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index cab07c3e..bdcc4f9d 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -26,7 +26,7 @@ public abstract class P2 { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual()).eq(this, (P2) other))); + return Equal.equals0(P2.class, this, other, u -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index e2c7aa26..2308bd40 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -192,7 +192,8 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P3) other))); + return Equal.equals0(P3.class, this, other, + u -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 267e4d86..b74a3d0b 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -265,7 +265,8 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P4) other))); + return Equal.equals0(P4.class, this, other, + u -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index b5f62f4b..43ee7f34 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -344,7 +344,8 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P5) other))); + return Equal.equals0(P5.class, this, other, + u -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 40802b0b..72512b2e 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -435,7 +435,8 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P6) other))); + return Equal.equals0(P6.class, this, other, + u -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index cdff75ce..2dc1a29a 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -529,7 +529,8 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P7) other))); + return Equal.equals0(P7.class, this, other, + u -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index ffd9081a..e94a0359 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -635,7 +635,8 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P8) other))); + return Equal.equals0(P8.class, this, other, + u -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index ea9c2026..a7276cc1 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -682,7 +682,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object o) { - return Equal.shallowEqualsO(this, o).orSome(P.lazy(u -> Equal.arrayEqual(Equal.anyEqual()).eq(this, (Array) o))); + return Equal.equals0(Array.class, this, o, u -> Equal.arrayEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 739b6f01..57e74a76 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -94,7 +94,7 @@ public final Either bimap(final F left, final F right) @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Either) other))); + return Equal.equals0(Either.class, this, other, u -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fc993523..38bfdebc 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1870,14 +1870,9 @@ private void copy() { * @param obj the other object to check for equality against. * @return true if this list is equal to the provided argument */ - //Suppress the warning for cast to List because the type is checked in the previous line. - @SuppressWarnings({ "unchecked" }) @Override public boolean equals( final Object obj ) { - //Casting to List here does not cause a runtime exception even if the type arguments don't match. - //The cast is done to avoid the compiler warning "raw use of parameterized class 'List'" - - return Equal.shallowEqualsO(this, obj).orSome(P.lazy(u -> Equal.listEqual(Equal.anyEqual()).eq(this, (List) obj))); + return Equal.equals0(List.class, this, obj, u -> Equal.listEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 90a88b9d..82b7f409 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -626,7 +626,7 @@ public final boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.optionEqual(Equal.anyEqual()).eq(this, (Option) other))); + return Equal.equals0(Option.class, this, other, u -> Equal.optionEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index d696e497..2608c3fe 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -48,7 +48,7 @@ public static Seq empty() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.seqEqual(Equal.anyEqual()).eq(this, (Seq) other))); + return Equal.equals0(Seq.class, this, other, u -> Equal.seqEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 7bb868aa..075f154d 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -142,7 +142,7 @@ public static Set empty(final Ord ord) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.setEqual(Equal.anyEqual()).eq(this, (Set) other))); + return Equal.equals0(Set.class, this, other, u -> Equal.setEqual(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 7abbf765..232f9f9a 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1247,7 +1247,7 @@ public final boolean forall(final F f) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other))); + return Equal.equals0(Stream.class, this, other, u -> Equal.streamEqual(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index f0e19602..488f4da4 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -261,7 +261,7 @@ private Stream drawTree(final Show s) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.treeEqual(Equal.anyEqual()).eq(this, (Tree) other))); + return Equal.equals0(Tree.class, this, other, u -> Equal.treeEqual(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 08596ebb..317c749a 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -38,7 +38,7 @@ public static TreeMap empty(final Ord keyOrd) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (TreeMap) other))); + return Equal.equals0(TreeMap.class, this, other, u -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 4d0bfbe3..cfbb2354 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -252,7 +252,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Validation) other))); + return Equal.equals0(Validation.class, this, other, u -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/test/java/fj/P1Test.java b/core/src/test/java/fj/P1Test.java index 2a161777..16309aae 100644 --- a/core/src/test/java/fj/P1Test.java +++ b/core/src/test/java/fj/P1Test.java @@ -28,4 +28,24 @@ public void bug105() throws Exception { org.junit.Assert.assertEquals("Race condition in P1.memo()", 0, nullCounter.get()); } + + @Test + public void bug122() throws Exception { + final P1 p1a = new P1() { + + @Override + public Integer _1() { + return 1; + } + }; + final P1 p1b = new P1() { + + @Override + public Integer _1() { + return 1; + } + }; + + org.junit.Assert.assertTrue(p1a + " and " + p1b + " should be equal by Object.equals", p1a.equals(p1b)); + } } From a48ef2fa277b60ec59e2492dbfc87ab7f0e1be53 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 11 Apr 2015 15:41:04 +0200 Subject: [PATCH 270/811] deprecate Equals.shallowEqualsO due to #122 --- core/src/main/java/fj/Equal.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index cd719e8c..a6a9668f 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -536,7 +536,9 @@ public static Equal> writerEqual(Equal eq1, Equal eq2) /** * @return Returns none if no equality can be determined by checking the nullity and reference values, else the equality + * @deprecated see issue #122. */ + @Deprecated public static Option shallowEqualsO(Object o1, Object o2) { if (o1 == null && o2 == null) { return Option.some(true); @@ -544,6 +546,7 @@ public static Option shallowEqualsO(Object o1, Object o2) { return Option.some(true); } else if (o1 != null && o2 != null) { java.lang.Class c = o1.getClass(); + // WARNING: this may return some(false) for two instance of same type (and thus comparable) but of different class (typicaly anonymous class instance). return c.isInstance(o2) ? Option.none() : Option.some(false); } else { return Option.some(false); From 09438537864875b708ef948ad8566b3566baee64 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 11 Apr 2015 21:12:44 +0200 Subject: [PATCH 271/811] better Equal.equals0 - use F0 instead of F1 - use boolean operator instead of ternary conditional operator --- core/src/main/java/fj/Equal.java | 7 +++---- core/src/main/java/fj/P1.java | 2 +- core/src/main/java/fj/P2.java | 2 +- core/src/main/java/fj/P3.java | 2 +- core/src/main/java/fj/P4.java | 2 +- core/src/main/java/fj/P5.java | 2 +- core/src/main/java/fj/P6.java | 2 +- core/src/main/java/fj/P7.java | 2 +- core/src/main/java/fj/P8.java | 2 +- core/src/main/java/fj/data/Array.java | 2 +- core/src/main/java/fj/data/Either.java | 2 +- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/Option.java | 2 +- core/src/main/java/fj/data/Seq.java | 2 +- core/src/main/java/fj/data/Set.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/Tree.java | 2 +- core/src/main/java/fj/data/TreeMap.java | 2 +- core/src/main/java/fj/data/Validation.java | 2 +- 19 files changed, 21 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index f778bb69..f09f8fc9 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -1,7 +1,6 @@ package fj; import static fj.Function.curry; -import static fj.Unit.unit; import fj.data.*; import fj.data.hlist.HList; @@ -562,7 +561,7 @@ public static Option shallowEqualsO(Object o1, Object o2) { */ @SuppressWarnings("unchecked") public static boolean equals0(final java.lang.Class clazz, final A self, final Object other, final Equal equal) { - return self == other ? true : clazz.isInstance(other) ? equal.eq(self, (A) other) : false; + return self == other || clazz.isInstance(other) && equal.eq(self, (A) other); } /** @@ -575,8 +574,8 @@ public static boolean equals0(final java.lang.Class clazz, final * @return true if self and other are equal */ @SuppressWarnings("unchecked") - public static boolean equals0(final java.lang.Class clazz, final A self, final Object other, final F> equal) { - return self == other ? true : clazz.isInstance(other) ? equal.f(unit()).eq(self, (A) other) : false; + public static boolean equals0(final java.lang.Class clazz, final A self, final Object other, final F0> equal) { + return self == other || clazz.isInstance(other) && equal.f().eq(self, (A) other); } } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 5e62d594..5ae82a97 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -256,7 +256,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.equals0(P1.class, this, other, u -> Equal.p1Equal(Equal.anyEqual())); + return Equal.equals0(P1.class, this, other, () -> Equal.p1Equal(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index bdcc4f9d..a6fa05f7 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -26,7 +26,7 @@ public abstract class P2 { @Override public boolean equals(Object other) { - return Equal.equals0(P2.class, this, other, u -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(P2.class, this, other, () -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 2308bd40..58d1898a 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -193,7 +193,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P3.class, this, other, - u -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index b74a3d0b..082ceec8 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -266,7 +266,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P4.class, this, other, - u -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 43ee7f34..21b7523b 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -345,7 +345,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P5.class, this, other, - u -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 72512b2e..a6ed6c8f 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -436,7 +436,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P6.class, this, other, - u -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 2dc1a29a..76900fc4 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -530,7 +530,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P7.class, this, other, - u -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index e94a0359..d9e9f42c 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -636,7 +636,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P8.class, this, other, - u -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index a7276cc1..3575728b 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -682,7 +682,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object o) { - return Equal.equals0(Array.class, this, o, u -> Equal.arrayEqual(Equal.anyEqual())); + return Equal.equals0(Array.class, this, o, () -> Equal.arrayEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 57e74a76..92efe645 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -94,7 +94,7 @@ public final Either bimap(final F left, final F right) @Override public boolean equals(Object other) { - return Equal.equals0(Either.class, this, other, u -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(Either.class, this, other, () -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 38bfdebc..0ffd6021 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1872,7 +1872,7 @@ private void copy() { */ @Override public boolean equals( final Object obj ) { - return Equal.equals0(List.class, this, obj, u -> Equal.listEqual(Equal.anyEqual())); + return Equal.equals0(List.class, this, obj, () -> Equal.listEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 82b7f409..cab0c2d0 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -626,7 +626,7 @@ public final boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.equals0(Option.class, this, other, u -> Equal.optionEqual(Equal.anyEqual())); + return Equal.equals0(Option.class, this, other, () -> Equal.optionEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 2608c3fe..0935a7fd 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -48,7 +48,7 @@ public static Seq empty() { @Override public boolean equals(Object other) { - return Equal.equals0(Seq.class, this, other, u -> Equal.seqEqual(Equal.anyEqual())); + return Equal.equals0(Seq.class, this, other, () -> Equal.seqEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 075f154d..ad437a11 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -142,7 +142,7 @@ public static Set empty(final Ord ord) { @Override public boolean equals(Object other) { - return Equal.equals0(Set.class, this, other, u -> Equal.setEqual(Equal.anyEqual())); + return Equal.equals0(Set.class, this, other, () -> Equal.setEqual(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 232f9f9a..01563b5a 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1247,7 +1247,7 @@ public final boolean forall(final F f) { @Override public boolean equals(Object other) { - return Equal.equals0(Stream.class, this, other, u -> Equal.streamEqual(Equal.anyEqual())); + return Equal.equals0(Stream.class, this, other, () -> Equal.streamEqual(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 488f4da4..c5422408 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -261,7 +261,7 @@ private Stream drawTree(final Show s) { @Override public boolean equals(Object other) { - return Equal.equals0(Tree.class, this, other, u -> Equal.treeEqual(Equal.anyEqual())); + return Equal.equals0(Tree.class, this, other, () -> Equal.treeEqual(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 317c749a..4bede107 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -38,7 +38,7 @@ public static TreeMap empty(final Ord keyOrd) { @Override public boolean equals(Object other) { - return Equal.equals0(TreeMap.class, this, other, u -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(TreeMap.class, this, other, () -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index cfbb2354..978d9bdb 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -252,7 +252,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.equals0(Validation.class, this, other, u -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(Validation.class, this, other, () -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override From 35b55ff6ab655cfd8e84dd6e02155aafbacca556 Mon Sep 17 00:00:00 2001 From: Runar Bjarnason Date: Fri, 17 Apr 2015 18:41:17 -0400 Subject: [PATCH 272/811] Added monoid composition --- .gitignore | 3 +-- core/src/main/java/fj/Monoid.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 51f4271b..6988acc1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,4 @@ build .DS_Store MANIFEST.MF */bin/** - - +*~ diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index cff6a556..71750f00 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -1,7 +1,6 @@ package fj; import static fj.Function.curry; -import static fj.Function.compose; import static fj.Function.flip; import fj.data.Array; import fj.data.List; @@ -20,7 +19,7 @@ *
    *
  • Left Identity; forall x. sum(zero(), x) == x
  • *
  • Right Identity; forall x. sum(x, zero()) == x
  • - *
  • Associativity; forall x. forall y. forall z. sum(sum(x, y), z) == sum(x, sum(y, z))
  • + *
  • Associativity; forall x y z. sum(sum(x, y), z) == sum(x, sum(y, z))
  • *
* * @version %build.number% @@ -34,6 +33,14 @@ private Monoid(final F> sum, final A zero) { this.zero = zero; } + /** + * Composes this monoid with another. + */ + public Monoid>compose(Monoid m) { + return monoid((P2 x) -> (P2 y) -> + P.p(sum(x._1(), y._1()), m.sum(x._2(), y._2())), P.p(zero, m.zero)); + } + /** * Returns a semigroup projection of this monoid. * @@ -176,7 +183,7 @@ public A join(final Iterable
as, final A a) { final Stream s = iterableStream(as); return s.isEmpty() ? zero : - s.foldLeft1(compose(sum, flip(sum).f(a))); + s.foldLeft1(Function.compose(sum, flip(sum).f(a))); } /** From 642f59beb67f750358694cbc0a545a2220cf513a Mon Sep 17 00:00:00 2001 From: Paul Horn Date: Tue, 21 Apr 2015 10:07:52 +0200 Subject: [PATCH 273/811] List.init now uses the head of the sublists Fixes #128 --- core/src/main/java/fj/data/List.java | 2 +- tests/src/test/scala/fj/data/CheckList.scala | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fc993523..2136eb3a 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1152,7 +1152,7 @@ public final List init() { List ys = this; final Buffer a = empty(); while(ys.isNotEmpty() && ys.tail().isNotEmpty()) { - a.snoc(head()); + a.snoc(ys.head()); ys = ys.tail(); } return a.toList(); diff --git a/tests/src/test/scala/fj/data/CheckList.scala b/tests/src/test/scala/fj/data/CheckList.scala index f00bae1a..3692fa9c 100644 --- a/tests/src/test/scala/fj/data/CheckList.scala +++ b/tests/src/test/scala/fj/data/CheckList.scala @@ -174,6 +174,9 @@ object CheckList extends Properties("List") { property("nub") = forAll((a: List[String], b: List[String]) => listEqual(stringEqual).eq(a append b nub, a.nub.append(b.nub).nub)) + property("init") = forAll((a: List[String], b: String) => + listEqual(stringEqual).eq(a.snoc(b).init(), a)) + property("join") = forAll((a: List[List[String]]) => listEqual(stringEqual).eq( a.foldRight((a: List[String], b: List[String]) => a.append(b), nil[String]), From e6cb9e831733a867e03854dab37c76298193de1f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 31 Mar 2015 23:22:05 +0200 Subject: [PATCH 274/811] Optics (adapted from Scala Monocle library) --- core/src/main/java/fj/data/optic/Fold.java | 118 ++++ core/src/main/java/fj/data/optic/Getter.java | 106 +++ core/src/main/java/fj/data/optic/Iso.java | 459 +++++++++++++ core/src/main/java/fj/data/optic/Lens.java | 395 +++++++++++ .../src/main/java/fj/data/optic/Optional.java | 366 +++++++++++ core/src/main/java/fj/data/optic/PIso.java | 597 +++++++++++++++++ core/src/main/java/fj/data/optic/PLens.java | 502 ++++++++++++++ .../main/java/fj/data/optic/POptional.java | 481 ++++++++++++++ core/src/main/java/fj/data/optic/PPrism.java | 438 ++++++++++++ core/src/main/java/fj/data/optic/PSetter.java | 103 +++ .../main/java/fj/data/optic/PTraversal.java | 622 ++++++++++++++++++ core/src/main/java/fj/data/optic/Prism.java | 275 ++++++++ core/src/main/java/fj/data/optic/Setter.java | 71 ++ .../main/java/fj/data/optic/Traversal.java | 474 +++++++++++++ 14 files changed, 5007 insertions(+) create mode 100644 core/src/main/java/fj/data/optic/Fold.java create mode 100644 core/src/main/java/fj/data/optic/Getter.java create mode 100644 core/src/main/java/fj/data/optic/Iso.java create mode 100644 core/src/main/java/fj/data/optic/Lens.java create mode 100644 core/src/main/java/fj/data/optic/Optional.java create mode 100644 core/src/main/java/fj/data/optic/PIso.java create mode 100644 core/src/main/java/fj/data/optic/PLens.java create mode 100644 core/src/main/java/fj/data/optic/POptional.java create mode 100644 core/src/main/java/fj/data/optic/PPrism.java create mode 100644 core/src/main/java/fj/data/optic/PSetter.java create mode 100644 core/src/main/java/fj/data/optic/PTraversal.java create mode 100644 core/src/main/java/fj/data/optic/Prism.java create mode 100644 core/src/main/java/fj/data/optic/Setter.java create mode 100644 core/src/main/java/fj/data/optic/Traversal.java diff --git a/core/src/main/java/fj/data/optic/Fold.java b/core/src/main/java/fj/data/optic/Fold.java new file mode 100644 index 00000000..7f177a5b --- /dev/null +++ b/core/src/main/java/fj/data/optic/Fold.java @@ -0,0 +1,118 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.data.Either; +import fj.data.List; +import fj.data.Option; + +/** + * A {@link Fold} can be seen as a {@link Getter} with many targets or a weaker {@link PTraversal} which cannot modify its + * target. + * + * {@link Fold} is on the top of the Optic hierarchy which means that {@link Getter}, {@link PTraversal}, {@link POptional}, + * {@link PLens}, {@link PPrism} and {@link PIso} are valid {@link Fold} + * + * @param the source of a {@link Fold} + * @param the target of a {@link Fold} + */ +public abstract class Fold { + + /** + * map each target to a {@link Monoid} and combine the results underlying representation of {@link Fold}, all {@link Fold} + * methods are defined in terms of foldMap + */ + public abstract F foldMap(Monoid m, F f); + + /** combine all targets using a target's {@link Monoid} */ + public final F fold(final Monoid m) { + return foldMap(m, Function.identity()); + } + + /** + * get all the targets of a {@link Fold} TODO: Shall it return a Stream as there might be an infinite number of targets? + */ + public final List getAll(final S s) { + return foldMap(Monoid.listMonoid(), List::single).f(s); + } + + /** find the first target of a {@link Fold} matching the predicate */ + public final F> find(final F p) { + return foldMap(Monoid.optionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none()); + } + + /** get the first target of a {@link Fold} */ + public final Option headOption(final S s) { + return find(__ -> true).f(s); + } + + /** check if at least one target satisfies the predicate */ + public final F exist(final F p) { + return foldMap(Monoid.disjunctionMonoid, p); + } + + /** check if all targets satisfy the predicate */ + public final F all(final F p) { + return foldMap(Monoid.conjunctionMonoid, p); + } + + /** join two {@link Fold} with the same target */ + public final Fold, A> sum(final Fold other) { + return new Fold, A>() { + @Override + public F, B> foldMap(final Monoid m, final F f) { + return s -> s.either(Fold.this.foldMap(m, f), other.foldMap(m, f)); + } + }; + } + + /**********************************************************/ + /** Compose methods between a {@link Fold} and another Optics */ + /**********************************************************/ + + /** compose a {@link Fold} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return new Fold() { + @Override + public F foldMap(final Monoid m, final F f) { + return Fold.this. foldMap(m, other. foldMap(m, f)); + } + }; + } + + /** compose a {@link Fold} with a {@link Getter} */ + public final Fold composeGetter(final Getter other) { + return composeFold(other.asFold()); + } + + /** compose a {@link Fold} with a {@link POptional} */ + public final Fold composeOptional(final POptional other) { + return composeFold(other.asFold()); + } + + /** compose a {@link Fold} with a {@link PPrism} */ + public final Fold composePrism(final PPrism other) { + return composeFold(other.asFold()); + } + + /** compose a {@link Fold} with a {@link PLens} */ + public final Fold composeLens(final PLens other) { + return composeFold(other.asFold()); + } + + /** compose a {@link Fold} with a {@link PIso} */ + public final Fold composeIso(final PIso other) { + return composeFold(other.asFold()); + } + + public static final Fold, A> codiagonal() { + return new Fold, A>() { + @Override + public F, B> foldMap(final Monoid m, final F f) { + return e -> e.either(f, f); + } + }; + } + +} diff --git a/core/src/main/java/fj/data/optic/Getter.java b/core/src/main/java/fj/data/optic/Getter.java new file mode 100644 index 00000000..89fd0bc9 --- /dev/null +++ b/core/src/main/java/fj/data/optic/Getter.java @@ -0,0 +1,106 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P; +import fj.P2; +import fj.data.Either; + +/** + * A {@link Getter} can be seen as a glorified get method between a type S and a type A. + * + * A {@link Getter} is also a valid {@link Fold} + * + * @param the source of a {@link Getter} + * @param the target of a {@link Getter} + */ +public abstract class Getter { + + Getter() { + super(); + } + + /** get the target of a {@link Getter} */ + public abstract A get(S s); + + /** join two {@link Getter} with the same target */ + public final Getter, A> sum(final Getter other) { + return getter(e -> e.either(this::get, other::get)); + } + + /** pair two disjoint {@link Getter} */ + public final Getter, P2> product(final Getter other) { + return getter(p2 -> P.p(this.get(p2._1()), other.get(p2._2()))); + } + + public final Getter, P2> first() { + return getter(p -> P.p(this.get(p._1()), p._2())); + } + + public final Getter, P2> second() { + return getter(p -> P.p(p._1(), this.get(p._2()))); + } + + /*************************************************************/ + /** Compose methods between a {@link Getter} and another Optics */ + /*************************************************************/ + + /** compose a {@link Getter} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return asFold().composeFold(other); + } + + /** compose a {@link Getter} with a {@link Getter} */ + public final Getter composeGetter(final Getter other) { + return getter(s -> other.get(get(s))); + } + + /** compose a {@link Getter} with a {@link POptional} */ + public final Fold composeOptional(final POptional other) { + return asFold().composeOptional(other); + } + + /** compose a {@link Getter} with a {@link PPrism} */ + public final Fold composePrism(final PPrism other) { + return asFold().composePrism(other); + } + + /** compose a {@link Getter} with a {@link PLens} */ + public final Getter composeLens(final PLens other) { + return composeGetter(other.asGetter()); + } + + /** compose a {@link Getter} with a {@link PIso} */ + public final Getter composeIso(final PIso other) { + return composeGetter(other.asGetter()); + } + + /******************************************************************/ + /** Transformation methods to view a {@link Getter} as another Optics */ + /******************************************************************/ + + /** view a {@link Getter} with a {@link Fold} */ + public final Fold asFold() { + return new Fold() { + @Override + public F foldMap(final Monoid m, final F f) { + return s -> f.f(get(s)); + } + }; + } + + public static final Getter, A> codiagonal() { + return getter(e -> e.either(Function.identity(), Function.identity())); + } + + public static final Getter getter(final F get) { + return new Getter() { + + @Override + public A get(final S s) { + return get.f(s); + } + }; + } +} diff --git a/core/src/main/java/fj/data/optic/Iso.java b/core/src/main/java/fj/data/optic/Iso.java new file mode 100644 index 00000000..bbfbe8e1 --- /dev/null +++ b/core/src/main/java/fj/data/optic/Iso.java @@ -0,0 +1,459 @@ +package fj.data.optic; + +import fj.F; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.P2; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** {@link PIso} when S = T and A = B */ +public abstract class Iso extends PIso { + + private Iso() { + super(); + } + + @Override + public abstract Iso reverse(); + + /** pair two disjoint {@link Iso} */ + public Iso, P2> product(final Iso other) { + return iso( + ss1 -> P.p(get(ss1._1()), other.get(ss1._2())), + bb1 -> P.p(reverseGet(bb1._1()), other.reverseGet(bb1._2()))); + } + + @Override + public Iso, P2> first() { + return iso( + sc -> P.p(get(sc._1()), sc._2()), + bc -> P.p(reverseGet(bc._1()), bc._2())); + } + + @Override + public Iso, P2> second() { + return iso( + cs -> P.p(cs._1(), get(cs._2())), + cb -> P.p(cb._1(), reverseGet(cb._2()))); + } + + /**********************************************************/ + /** Compose methods between an {@link Iso} and another Optics */ + /**********************************************************/ + + /** compose an {@link Iso} with a {@link Setter} */ + public final Setter composeSetter(final Setter other) { + return asSetter().composeSetter(other); + } + + /** compose an {@link Iso} with a {@link Traversal} */ + public final Traversal composeTraversal(final Traversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose an {@link Iso} with a {@link Optional} */ + public final Optional composeOptional(final Optional other) { + return asOptional().composeOptional(other); + } + + /** compose an {@link Iso} with a {@link Prism} */ + public final Prism composePrism(final Prism other) { + return asPrism().composePrism(other); + } + + /** compose an {@link Iso} with a {@link Lens} */ + public final Lens composeLens(final Lens other) { + return asLens().composeLens(other); + } + + /** compose an {@link Iso} with an {@link Iso} */ + public final Iso composeIso(final Iso other) { + final Iso self = this; + return new Iso() { + + @Override + public C get(final S s) { + return other.get(self.get(s)); + } + + @Override + public S reverseGet(final C c) { + return self.reverseGet(other.reverseGet(c)); + } + + @Override + public Iso reverse() { + final Iso composeSelf = this; + return new Iso() { + + @Override + public S get(final C c) { + return self.reverseGet(other.reverseGet(c)); + } + + @Override + public C reverseGet(final S s) { + return other.get(self.get(s)); + } + + @Override + public Iso reverse() { + return composeSelf; + } + }; + } + + }; + } + + /****************************************************************/ + /** Transformation methods to view an {@link Iso} as another Optics */ + /****************************************************************/ + + /** view an {@link Iso} as a {@link Setter} */ + @Override + public final Setter asSetter() { + final Iso self = this; + return new Setter() { + @Override + public F modify(final F f) { + return self.modify(f); + } + + @Override + public F set(final A a) { + return self.set(a); + } + }; + } + + /** view an {@link Iso} as a {@link Traversal} */ + @Override + public final Traversal asTraversal() { + final Iso self = this; + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> f.f(self.get(s)); + } + + }; + } + + /** view an {@link Iso} as a {@link Optional} */ + @Override + public final Optional asOptional() { + final Iso self = this; + return new Optional() { + @Override + public Either getOrModify(final S s) { + return Either.right(self.get(s)); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F set(final A b) { + return self.set(b); + } + + @Override + public Option getOption(final S s) { + return Option.some(self.get(s)); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + }; + } + + /** view an {@link Iso} as a {@link Prism} */ + @Override + public final Prism asPrism() { + final Iso self = this; + return new Prism() { + @Override + public Either getOrModify(final S s) { + return Either.right(self.get(s)); + } + + @Override + public S reverseGet(final A b) { + return self.reverseGet(b); + } + + @Override + public Option getOption(final S s) { + return Option.some(self.get(s)); + } + }; + } + + /** view an {@link Iso} as a {@link Lens} */ + @Override + public final Lens asLens() { + final Iso self = this; + return new Lens() { + @Override + public A get(final S s) { + return self.get(s); + } + + @Override + public F set(final A b) { + return self.set(b); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + }; + } + + /** create an {@link Iso} using a pair of functions: one to get the target and one to get the source. */ + public static Iso iso(final F get, final F reverseGet) { + return new Iso() { + + @Override + public A get(final S s) { + return get.f(s); + } + + @Override + public S reverseGet(final A a) { + return reverseGet.f(a); + } + + @Override + public Iso reverse() { + final Iso self = this; + return new Iso() { + @Override + public S get(final A a) { + return reverseGet.f(a); + } + + @Override + public A reverseGet(final S s) { + return get.f(s); + } + + @Override + public Iso reverse() { + return self; + } + + }; + } + }; + } + + /** + * create an {@link Iso} between any type and itself. id is the zero element of optics composition, for all optics o of type O + * (e.g. Lens, Iso, Prism, ...): + * + *
+   *  o composeIso Iso.id == o
+   *  Iso.id composeO o == o
+   * 
+ * + * (replace composeO by composeLens, composeIso, composePrism, ...) + */ + public static Iso id() { + return new Iso() { + + @Override + public S get(final S s) { + return s; + } + + @Override + public S reverseGet(final S s) { + return s; + } + + @Override + public Iso reverse() { + return this; + } + + }; + } + +} diff --git a/core/src/main/java/fj/data/optic/Lens.java b/core/src/main/java/fj/data/optic/Lens.java new file mode 100644 index 00000000..e89edb60 --- /dev/null +++ b/core/src/main/java/fj/data/optic/Lens.java @@ -0,0 +1,395 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P1; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * {@link PLens} with a monomorphic set function + */ +public abstract class Lens extends PLens { + + Lens() { + super(); + } + + /** join two {@link Lens} with the same target */ + public final Lens, A> sum(final Lens other) { + return lens( + e -> e.either(this::get, other::get), + b -> e -> e.bimap(Lens.this.set(b), other.set(b))); + } + + /**********************************************************/ + /** Compose methods between a {@link Lens} and another Optics */ + /**********************************************************/ + + /** + * compose a {@link Lens} with a {@link Setter} + */ + public final Setter composeSetter(final Setter other) { + return asSetter().composeSetter(other); + } + + /** + * compose a {@link Lens} with a {@link Traversal} + */ + public final Traversal composeTraversal(final Traversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link Lens} with an {@link Optional} */ + public final Optional composeOptional(final Optional other) { + return asOptional().composeOptional(other); + } + + /** compose a {@link Lens} with a {@link Prism} */ + public final Optional composePrism(final Prism other) { + return asOptional().composeOptional(other.asOptional()); + } + + /** compose a {@link Lens} with a {@link Lens} */ + public final Lens composeLens(final Lens other) { + final Lens self = this; + return new Lens() { + @Override + public C get(final S s) { + return other.get(self.get(s)); + } + + @Override + public F set(final C d) { + return self.modify(other.set(d)); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(other.modifyFunctionF(f)); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(other.modifyEitherF(f)); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(other.modifyIOF(f)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(other.modifyTrampolineF(f)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(other.modifyPromiseF(f)); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(other.modifyListF(f)); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(other.modifyOptionF(f)); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(other.modifyStreamF(f)); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(other.modifyP1F(f)); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(other.modifyValidationF(f)); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(other.modifyV2F(f)); + } + + @Override + public F modify(final F f) { + return self.modify(other.modify(f)); + } + }; + } + + /** compose a {@link Lens} with an {@link Iso} */ + public final Lens composeIso(final Iso other) { + return composeLens(other.asLens()); + } + + /****************************************************************/ + /** Transformation methods to view a {@link Lens} as another Optics */ + /****************************************************************/ + + /** view a {@link Lens} as a {@link Setter} */ + @Override + public Setter asSetter() { + return new Setter() { + @Override + public F modify(final F f) { + return Lens.this.modify(f); + } + + @Override + public F set(final A b) { + return Lens.this.set(b); + } + }; + } + + /** view a {@link Lens} as a {@link Traversal} */ + @Override + public final Traversal asTraversal() { + final Lens self = this; + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> f.f(get(s)); + } + + }; + } + + /** view a {@link Lens} as an {@link Optional} */ + @Override + public final Optional asOptional() { + final Lens self = this; + return new Optional() { + @Override + public Either getOrModify(final S s) { + return Either.right(self.get(s)); + } + + @Override + public F set(final A b) { + return self.set(b); + } + + @Override + public Option
getOption(final S s) { + return Option.some(self.get(s)); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + }; + } + + public static final Lens id() { + return Iso. id().asLens(); + } + + /** + * create a {@link Lens} using a pair of functions: one to get the target, one to set the target. + */ + public static Lens lens(final F get, final F> set) { + return new Lens() { + + @Override + public A get(final S s) { + return get.f(s); + } + + @Override + public F set(final A b) { + return set.f(b); + } + + @Override + public F> modifyFunctionF(final F> f) { + return s -> Function.compose(b -> set.f(b).f(s), f.f(get(s))); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> f.f(get.f(s)).right().map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> IOFunctions.map(f.f(get.f(s)), a -> set.f(a).f(s)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> f.f(get.f(s)).fmap(a -> set.f(a).f(s)); + } + + @Override + public F> modifyListF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F modify(final F f) { + return s -> set(f.f(get.f(s))).f(s); + } + }; + } +} \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java new file mode 100644 index 00000000..02da3cd4 --- /dev/null +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -0,0 +1,366 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.P2; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** {@link POptional} restricted to monomorphic update */ +public abstract class Optional extends POptional { + + Optional() { + super(); + } + + /** join two {@link Optional} with the same target */ + public final Optional, A> sum(final Optional other) { + return optional( + e -> e.either(s -> getOrModify(s).left().map(Either.left_()), s1 -> other.getOrModify(s1).left().map(Either.right_())), + b -> e -> e.bimap(set(b), other.set(b))); + } + + @Override + public final Optional, P2> first() { + return optional( + sc -> getOrModify(sc._1()).bimap(t -> P.p(t, sc._2()), a -> P.p(a, sc._2())), + bc -> s_ -> P.p(set(bc._1()).f(s_._1()), bc._2())); + } + + @Override + public final Optional, P2> second() { + return optional( + cs -> getOrModify(cs._2()).bimap(t -> P.p(cs._1(), t), a -> P.p(cs._1(), a)), + cb -> _s -> P.p(cb._1(), set(cb._2()).f(_s._2()))); + } + + /**************************************************************/ + /** Compose methods between a {@link Optional} and another Optics */ + /**************************************************************/ + + /** compose a {@link Optional} with a {@link Setter} */ + public final Setter composeSetter(final Setter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link Optional} with a {@link Traversal} */ + public final Traversal composeTraversal(final Traversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link Optional} with a {@link Optional} */ + public final Optional composeOptional(final Optional other) { + final Optional self = this; + return new Optional() { + + @Override + public Either getOrModify(final S s) { + return self.getOrModify(s).right() + .bind(a -> other.getOrModify(a).bimap(b -> Optional.this.set(b).f(s), Function.identity())); + } + + @Override + public F set(final C d) { + return self.modify(other.set(d)); + } + + @Override + public Option getOption(final S s) { + return self.getOption(s).bind(other::getOption); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(other.modifyFunctionF(f)); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(other.modifyEitherF(f)); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(other.modifyIOF(f)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(other.modifyTrampolineF(f)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(other.modifyPromiseF(f)); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(other.modifyListF(f)); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(other.modifyOptionF(f)); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(other.modifyStreamF(f)); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(other.modifyP1F(f)); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(other.modifyValidationF(f)); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(other.modifyV2F(f)); + } + + @Override + public F modify(final F f) { + return self.modify(other.modify(f)); + } + }; + } + + /** compose a {@link Optional} with a {@link Prism} */ + public final Optional composePrism(final Prism other) { + return composeOptional(other.asOptional()); + } + + /** compose a {@link Optional} with a {@link Lens} */ + public final Optional composeLens(final Lens other) { + return composeOptional(other.asOptional()); + } + + /** compose a {@link Optional} with an {@link Iso} */ + public final Optional composeIso(final Iso other) { + return composeOptional(other.asOptional()); + } + + /********************************************************************/ + /** Transformation methods to view a {@link Optional} as another Optics */ + /********************************************************************/ + + /** view a {@link Optional} as a {@link Setter} */ + @Override + public final Setter asSetter() { + return new Setter() { + @Override + public F modify(final F f) { + return Optional.this.modify(f); + } + + @Override + public F set(final A b) { + return Optional.this.set(b); + } + }; + } + + /** view a {@link Optional} as a {@link Traversal} */ + @Override + public final Traversal asTraversal() { + final Optional self = this; + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> self.getOption(s).map(f).orSome(monoid.zero()); + } + }; + } + + public static Optional id() { + return Iso. id().asOptional(); + } + + /** create a {@link Optional} using the canonical functions: getOrModify and set */ + public static final Optional optional(final F> getOrModify, final F> set) { + return new Optional() { + @Override + public Either getOrModify(final S s) { + return getOrModify.f(s); + } + + @Override + public F set(final A b) { + return set.f(b); + } + + @Override + public Option getOption(final S s) { + return getOrModify.f(s).right().toOption(); + } + + @Override + public F> modifyFunctionF(final F> f) { + return s -> getOrModify(s).either( + Function.constant(), + a -> Function.compose(b -> set(b).f(s), f.f(a)) + ); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> getOrModify(s).either( + Either.right_(), + t -> f.f(t).right().map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> getOrModify(s).either( + IOFunctions::unit, + t -> IOFunctions. map(f.f(t), b -> set(b).f(s)) + ); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> getOrModify(s).either( + Trampoline.pure(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> getOrModify(s).either( + t -> Promise.promise(Strategy.idStrategy(), P.p(t)), + t -> f.f(t).fmap(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyListF(final F> f) { + return s -> getOrModify(s).either( + List::single, + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> getOrModify(s).either( + Option.some_(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> getOrModify(s).either( + Stream.single(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> getOrModify(s).either( + P.p1(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> getOrModify(s).either( + t -> Validation. success(t), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> getOrModify(s).either( + t -> V2.p(P.p(t, t)), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F modify(final F f) { + return s -> getOrModify.f(s).either(Function.identity(), a -> set.f(f.f(a)).f(s)); + } + }; + } + +} diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java new file mode 100644 index 00000000..46716bb1 --- /dev/null +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -0,0 +1,597 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.P2; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * A {@link PIso} defines an isomorphism between types S, A and B, T: + * + *
+ *              get                           reverse.get
+ *     -------------------->             -------------------->
+ *   S                       A         T                       B
+ *     <--------------------             <--------------------
+ *       reverse.reverseGet                   reverseGet
+ * 
+ * + * In addition, if f and g forms an isomorphism between `A` and `B`, i.e. if `f . g = id` and `g . f = id`, then a {@link PIso} + * defines an isomorphism between `S` and `T`: + * + *
+ *     S           T                                   S           T
+ *     |           ↑                                   ↑           |
+ *     |           |                                   |           |
+ * get |           | reverseGet     reverse.reverseGet |           | reverse.get
+ *     |           |                                   |           |
+ *     ↓     f     |                                   |     g     ↓
+ *     A --------> B                                   A <-------- B
+ * 
+ * + * A {@link PIso} is also a valid {@link Getter}, {@link Fold}, {@link PLens}, {@link PPrism}, {@link POptional}, + * {@link PTraversal} and {@link PSetter} + * + * @param the source of a {@link PIso} + * @param the modified source of a {@link PIso} + * @param
the target of a {@link PIso} + * @param the modified target of a {@link PIso} + */ +public abstract class PIso { + + PIso() { + super(); + } + + /** get the target of a {@link PIso} */ + public abstract A get(S s); + + /** get the modified source of a {@link PIso} */ + public abstract T reverseGet(B b); + + /** reverse a {@link PIso}: the source becomes the target and the target becomes the source */ + public abstract PIso reverse(); + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyFunctionF(final F> f) { + return s -> Function.compose(this::reverseGet, f.f(get(s))); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyEitherF(final F> f) { + return s -> f.f(get(s)).right().map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyIOF(final F> f) { + return s -> IOFunctions.map(f.f(get(s)), this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyTrampolineF(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyPromiseF(final F> f) { + return s -> f.f(get(s)).fmap(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyListF(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyOptionF(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyStreamF(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyP1F(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyValidationF(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with an Applicative function */ + public final F> modifyV2F(final F> f) { + return s -> f.f(get(s)).map(this::reverseGet); + } + + /** modify polymorphically the target of a {@link PIso} with a function */ + public final F modify(final F f) { + return s -> reverseGet(f.f(get(s))); + } + + /** set polymorphically the target of a {@link PIso} with a value */ + public final F set(final B b) { + return __ -> reverseGet(b); + } + + /** pair two disjoint {@link PIso} */ + public PIso, P2, P2, P2> product(final PIso other) { + return pIso( + ss1 -> P.p(get(ss1._1()), other.get(ss1._2())), + bb1 -> P.p(reverseGet(bb1._1()), other.reverseGet(bb1._2()))); + } + + public PIso, P2, P2, P2> first() { + return pIso( + sc -> P.p(get(sc._1()), sc._2()), + bc -> P.p(reverseGet(bc._1()), bc._2())); + } + + public PIso, P2, P2, P2> second() { + return pIso( + cs -> P.p(cs._1(), get(cs._2())), + cb -> P.p(cb._1(), reverseGet(cb._2()))); + } + + /**********************************************************/ + /** Compose methods between a {@link PIso} and another Optics */ + /**********************************************************/ + + /** compose a {@link PIso} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return asFold().composeFold(other); + } + + /** compose a {@link PIso} with a {@link Getter} */ + public final Getter composeGetter(final Getter other) { + return asGetter().composeGetter(other); + } + + /** compose a {@link PIso} with a {@link PSetter} */ + public final PSetter composeSetter(final PSetter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link PIso} with a {@link PTraversal} */ + public final PTraversal composeTraversal(final PTraversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link PIso} with a {@link POptional} */ + public final POptional composeOptional(final POptional other) { + return asOptional().composeOptional(other); + } + + /** compose a {@link PIso} with a {@link PPrism} */ + public final PPrism composePrism(final PPrism other) { + return asPrism().composePrism(other); + } + + /** compose a {@link PIso} with a {@link PLens} */ + public final PLens composeLens(final PLens other) { + return asLens().composeLens(other); + } + + /** compose a {@link PIso} with a {@link PIso} */ + public final PIso composeIso(final PIso other) { + final PIso self = this; + return new PIso() { + @Override + public C get(final S s) { + return other.get(self.get(s)); + } + + @Override + public T reverseGet(final D d) { + return self.reverseGet(other.reverseGet(d)); + } + + @Override + public PIso reverse() { + final PIso composeSelf = this; + return new PIso() { + @Override + public T get(final D d) { + return self.reverseGet(other.reverseGet(d)); + } + + @Override + public C reverseGet(final S s) { + return other.get(self.get(s)); + } + + @Override + public PIso reverse() { + return composeSelf; + } + }; + } + }; + } + + /****************************************************************/ + /** Transformation methods to view a {@link PIso} as another Optics */ + /****************************************************************/ + + /** view a {@link PIso} as a {@link Fold} */ + public final Fold asFold() { + return new Fold() { + @Override + public F foldMap(final Monoid m, final F f) { + return s -> f.f(PIso.this.get(s)); + } + }; + } + + /** view a {@link PIso} as a {@link Getter} */ + public final Getter asGetter() { + return new Getter() { + @Override + public A get(final S s) { + return PIso.this.get(s); + } + }; + } + + /** view a {@link PIso} as a {@link Setter} */ + public PSetter asSetter() { + return new PSetter() { + @Override + public F modify(final F f) { + return PIso.this.modify(f); + } + + @Override + public F set(final B b) { + return PIso.this.set(b); + } + }; + } + + /** view a {@link PIso} as a {@link PTraversal} */ + public PTraversal asTraversal() { + final PIso self = this; + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> f.f(self.get(s)); + } + + }; + } + + /** view a {@link PIso} as a {@link POptional} */ + public POptional asOptional() { + final PIso self = this; + return new POptional() { + @Override + public Either getOrModify(final S s) { + return Either.right(self.get(s)); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F set(final B b) { + return self.set(b); + } + + @Override + public Option getOption(final S s) { + return Option.some(self.get(s)); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + }; + } + + /** view a {@link PIso} as a {@link PPrism} */ + public PPrism asPrism() { + final PIso self = this; + return new PPrism() { + @Override + public Either getOrModify(final S s) { + return Either.right(self.get(s)); + } + + @Override + public T reverseGet(final B b) { + return self.reverseGet(b); + } + + @Override + public Option getOption(final S s) { + return Option.some(self.get(s)); + } + }; + } + + /** view a {@link PIso} as a {@link PLens} */ + public PLens asLens() { + final PIso self = this; + return new PLens() { + @Override + public A get(final S s) { + return self.get(s); + } + + @Override + public F set(final B b) { + return self.set(b); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + }; + } + + /** create a {@link PIso} using a pair of functions: one to get the target and one to get the source. */ + public static final PIso pIso(final F get, final F reverseGet) { + return new PIso() { + + @Override + public A get(final S s) { + return get.f(s); + } + + @Override + public T reverseGet(final B b) { + return reverseGet.f(b); + } + + @Override + public PIso reverse() { + final PIso self = this; + return new PIso() { + @Override + public T get(final B b) { + return reverseGet.f(b); + } + + @Override + public A reverseGet(final S s) { + return get.f(s); + } + + @Override + public PIso reverse() { + return self; + } + }; + } + + }; + } + + /** + * create a {@link PIso} between any type and itself. id is the zero element of optics composition, for all optics o of type O + * (e.g. Lens, Iso, Prism, ...): + * + *
+   *  o composeIso Iso.id == o
+   *  Iso.id composeO o == o
+   * 
+ * + * (replace composeO by composeLens, composeIso, composePrism, ...) + */ + public static PIso pId() { + return new PIso() { + + @Override + public S get(final S s) { + return s; + } + + @Override + public T reverseGet(final T t) { + return t; + } + + @Override + public PIso reverse() { + final PIso self = this; + return new PIso() { + @Override + public T get(final T t) { + return t; + } + + @Override + public S reverseGet(final S s) { + return s; + } + + @Override + public PIso reverse() { + return self; + } + }; + } + }; + } + +} diff --git a/core/src/main/java/fj/data/optic/PLens.java b/core/src/main/java/fj/data/optic/PLens.java new file mode 100644 index 00000000..31d3bc4d --- /dev/null +++ b/core/src/main/java/fj/data/optic/PLens.java @@ -0,0 +1,502 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P1; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * A {@link PLens} can be seen as a pair of functions: - `get: S => A` i.e. from an `S`, we can extract an `A` - `set: (B, S) => + * T` i.e. if we replace an `A` by a `B` in an `S`, we obtain a `T` + * + * A {@link PLens} could also be defined as a weaker {@link PIso} where set requires an additional parameter than reverseGet. + * + * {@link PLens} stands for Polymorphic Lens as it set and modify methods change a type `A` to `B` and `S` to `T`. {@link Lens} + * is a {@link PLens} restricted to monomoprhic updates. + * + * A {@link PLens} is also a valid {@link Getter}, {@link Fold}, {@link POptional}, {@link PTraversal} and {@link PSetter} + * + * Typically a {@link PLens} or {@link Lens} can be defined between a Product (e.g. case class, tuple, HList) and one of it is + * component. + * + * @param the source of a {@link PLens} + * @param the modified source of a {@link PLens} + * @param
the target of a {@link PLens} + * @param the modified target of a {@link PLens} + */ +public abstract class PLens { + + PLens() { + super(); + } + + /** get the target of a {@link PLens} */ + public abstract A get(S s); + + /** set polymorphically the target of a {@link PLens} using a function */ + public abstract F set(B b); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyFunctionF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyEitherF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyIOF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyTrampolineF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyPromiseF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyListF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyOptionF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyStreamF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyP1F(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyValidationF(F> f); + + /** + * modify polymorphically the target of a {@link PLens} with an Applicative function + */ + public abstract F> modifyV2F(F> f); + + /** modify polymorphically the target of a {@link PLens} using a function */ + public abstract F modify(final F f); + + /** join two {@link PLens} with the same target */ + public final PLens, Either, A, B> sum(final PLens other) { + return pLens( + e -> e.either(this::get, other::get), + b -> e -> e.bimap(PLens.this.set(b), other.set(b))); + } + + /***********************************************************/ + /** Compose methods between a {@link PLens} and another Optics */ + /***********************************************************/ + + /** compose a {@link PLens} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return asFold().composeFold(other); + } + + /** compose a {@link PLens} with a {@link Getter} */ + public final Getter composeGetter(final Getter other) { + return asGetter().composeGetter(other); + } + + /** + * compose a {@link PLens} with a {@link PSetter} + */ + public final PSetter composeSetter(final PSetter other) { + return asSetter().composeSetter(other); + } + + /** + * compose a {@link PLens} with a {@link PTraversal} + */ + public final PTraversal composeTraversal(final PTraversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link PLens} with an {@link POptional} */ + public final POptional composeOptional(final POptional other) { + return asOptional().composeOptional(other); + } + + /** compose a {@link PLens} with a {@link PPrism} */ + public final POptional composePrism(final PPrism other) { + return asOptional().composeOptional(other.asOptional()); + } + + /** compose a {@link PLens} with a {@link PLens} */ + public final PLens composeLens(final PLens other) { + final PLens self = this; + return new PLens() { + @Override + public C get(final S s) { + return other.get(self.get(s)); + } + + @Override + public F set(final D d) { + return self.modify(other.set(d)); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(other.modifyFunctionF(f)); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(other.modifyEitherF(f)); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(other.modifyIOF(f)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(other.modifyTrampolineF(f)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(other.modifyPromiseF(f)); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(other.modifyListF(f)); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(other.modifyOptionF(f)); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(other.modifyStreamF(f)); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(other.modifyP1F(f)); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(other.modifyValidationF(f)); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(other.modifyV2F(f)); + } + + @Override + public F modify(final F f) { + return self.modify(other.modify(f)); + } + }; + } + + /** compose a {@link PLens} with an {@link PIso} */ + public final PLens composeIso(final PIso other) { + return composeLens(other.asLens()); + } + + /************************************************************************************************/ + /** Transformation methods to view a {@link PLens} as another Optics */ + /************************************************************************************************/ + + /** view a {@link PLens} as a {@link Fold} */ + public final Fold asFold() { + return new Fold() { + @Override + public F foldMap(final Monoid m, final F f) { + return s -> f.f(get(s)); + } + }; + } + + /** view a {@link PLens} as a {@link Getter} */ + public final Getter asGetter() { + return new Getter() { + @Override + public A get(final S s) { + return PLens.this.get(s); + } + }; + } + + /** view a {@link PLens} as a {@link PSetter} */ + public PSetter asSetter() { + return new PSetter() { + @Override + public F modify(final F f) { + return PLens.this.modify(f); + } + + @Override + public F set(final B b) { + return PLens.this.set(b); + } + }; + } + + /** view a {@link PLens} as a {@link PTraversal} */ + public PTraversal asTraversal() { + final PLens self = this; + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> f.f(get(s)); + } + + }; + } + + /** view a {@link PLens} as an {@link POptional} */ + public POptional asOptional() { + final PLens self = this; + return new POptional() { + @Override + public Either getOrModify(final S s) { + return Either.right(self.get(s)); + } + + @Override + public F set(final B b) { + return self.set(b); + } + + @Override + public Option getOption(final S s) { + return Option.some(self.get(s)); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + }; + } + + public static final PLens pId() { + return PIso. pId().asLens(); + } + + /** + * create a {@link PLens} using a pair of functions: one to get the target, one to set the target. + */ + public static PLens pLens(final F get, final F> set) { + return new PLens() { + + @Override + public A get(final S s) { + return get.f(s); + } + + @Override + public F set(final B b) { + return set.f(b); + } + + @Override + public F> modifyFunctionF(final F> f) { + return s -> Function.compose(b -> set.f(b).f(s), f.f(get(s))); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> f.f(get.f(s)).right().map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> IOFunctions.map(f.f(get.f(s)), a -> set.f(a).f(s)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> f.f(get.f(s)).fmap(a -> set.f(a).f(s)); + } + + @Override + public F> modifyListF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); + } + + @Override + public F modify(final F f) { + return s -> set(f.f(get.f(s))).f(s); + } + }; + } +} \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java new file mode 100644 index 00000000..1ba31459 --- /dev/null +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -0,0 +1,481 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.P2; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * A {@link POptional} can be seen as a pair of functions: - `getOrModify: S => T \/ A` - `set : (B, S) => T` + * + * A {@link POptional} could also be defined as a weaker {@link PLens} and weaker {@link PPrism} + * + * {@link POptional} stands for Polymorphic Optional as it set and modify methods change a type `A` to `B` and `S` to `T`. + * {@link Optional} is a {@link POptional} restricted to monomoprhic updates: {{{ type Optional[S, A] = POptional[S, S, A, A] + * }}} + * + * @param the source of a {@link POptional} + * @param the modified source of a {@link POptional} + * @param the target of a {@link POptional} + * @param the modified target of a {@link POptional} + */ +public abstract class POptional { + + POptional() { + super(); + } + + /** get the target of a {@link POptional} or modify the source in case there is no target */ + public abstract Either getOrModify(S s); + + /** get the modified source of a {@link POptional} */ + public abstract F set(final B b); + + /** get the target of a {@link POptional} or nothing if there is no target */ + public abstract Option getOption(final S s); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyFunctionF(final F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyEitherF(final F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyIOF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyTrampolineF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyPromiseF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyListF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyOptionF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyStreamF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyP1F(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyValidationF(F> f); + + /** + * modify polymorphically the target of a {@link POptional} with an Applicative function + */ + public abstract F> modifyV2F(F> f); + + /** modify polymorphically the target of a {@link POptional} with a function */ + public abstract F modify(final F f); + + /** + * modify polymorphically the target of a {@link POptional} with a function. return empty if the {@link POptional} is not + * matching + */ + public final F> modifyOption(final F f) { + return s -> getOption(s).map(__ -> modify(f).f(s)); + } + + /** set polymorphically the target of a {@link POptional} with a value. return empty if the {@link POptional} is not matching */ + public final F> setOption(final B b) { + return modifyOption(__ -> b); + } + + /** check if a {@link POptional} has a target */ + public final boolean isMatching(final S s) { + return getOption(s).isSome(); + + } + + /** join two {@link POptional} with the same target */ + public final POptional, Either, A, B> sum(final POptional other) { + return pOptional( + e -> e.either(s -> getOrModify(s).left().map(Either.left_()), s1 -> other.getOrModify(s1).left().map(Either.right_())), + b -> e -> e.bimap(set(b), other.set(b))); + } + + public POptional, P2, P2, P2> first() { + return pOptional( + sc -> getOrModify(sc._1()).bimap(t -> P.p(t, sc._2()), a -> P.p(a, sc._2())), + bc -> s_ -> P.p(set(bc._1()).f(s_._1()), bc._2())); + } + + public POptional, P2, P2, P2> second() { + return pOptional( + cs -> getOrModify(cs._2()).bimap(t -> P.p(cs._1(), t), a -> P.p(cs._1(), a)), + cb -> _s -> P.p(cb._1(), set(cb._2()).f(_s._2()))); + } + + /***************************************************************/ + /** Compose methods between a {@link POptional} and another Optics */ + /***************************************************************/ + + /** compose a {@link POptional} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return asFold().composeFold(other); + } + + /** compose a {@link POptional} with a {@link Getter} */ + public final Fold composeGetter(final Getter other) { + return asFold().composeGetter(other); + } + + /** compose a {@link POptional} with a {@link PSetter} */ + public final PSetter composeSetter(final PSetter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link POptional} with a {@link PTraversal} */ + public final PTraversal composeTraversal(final PTraversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link POptional} with a {@link POptional} */ + public final POptional composeOptional(final POptional other) { + final POptional self = this; + return new POptional() { + + @Override + public Either getOrModify(final S s) { + return self.getOrModify(s).right() + .bind(a -> other.getOrModify(a).bimap(b -> POptional.this.set(b).f(s), Function.identity())); + } + + @Override + public F set(final D d) { + return self.modify(other.set(d)); + } + + @Override + public Option getOption(final S s) { + return self.getOption(s).bind(other::getOption); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(other.modifyFunctionF(f)); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(other.modifyEitherF(f)); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(other.modifyIOF(f)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(other.modifyTrampolineF(f)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(other.modifyPromiseF(f)); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(other.modifyListF(f)); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(other.modifyOptionF(f)); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(other.modifyStreamF(f)); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(other.modifyP1F(f)); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(other.modifyValidationF(f)); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(other.modifyV2F(f)); + } + + @Override + public F modify(final F f) { + return self.modify(other.modify(f)); + } + }; + } + + /** compose a {@link POptional} with a {@link PPrism} */ + public final POptional composePrism(final PPrism other) { + return composeOptional(other.asOptional()); + } + + /** compose a {@link POptional} with a {@link PLens} */ + public final POptional composeLens(final PLens other) { + return composeOptional(other.asOptional()); + } + + /** compose a {@link POptional} with a {@link PIso} */ + public final POptional composeIso(final PIso other) { + return composeOptional(other.asOptional()); + } + + /*********************************************************************/ + /** Transformation methods to view a {@link POptional} as another Optics */ + /*********************************************************************/ + + /** view a {@link POptional} as a {@link Fold} */ + public final Fold asFold() { + return new Fold() { + @Override + public F foldMap(final Monoid m, final F f) { + return s -> POptional.this.getOption(s).map(f).orSome(m.zero()); + } + }; + } + + /** view a {@link POptional} as a {@link PSetter} */ + public PSetter asSetter() { + return new PSetter() { + @Override + public F modify(final F f) { + return POptional.this.modify(f); + } + + @Override + public F set(final B b) { + return POptional.this.set(b); + } + }; + } + + /** view a {@link POptional} as a {@link PTraversal} */ + public PTraversal asTraversal() { + final POptional self = this; + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> self.getOption(s).map(f).orSome(monoid.zero()); + } + }; + } + + public static POptional pId() { + return PIso. pId().asOptional(); + } + + /** create a {@link POptional} using the canonical functions: getOrModify and set */ + public static final POptional pOptional(final F> getOrModify, final F> set) { + return new POptional() { + @Override + public Either getOrModify(final S s) { + return getOrModify.f(s); + } + + @Override + public F set(final B b) { + return set.f(b); + } + + @Override + public Option getOption(final S s) { + return getOrModify.f(s).right().toOption(); + } + + @Override + public F> modifyFunctionF(final F> f) { + return s -> getOrModify(s).either( + Function.constant(), + a -> Function.compose(b -> set(b).f(s), f.f(a)) + ); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> getOrModify(s).either( + Either.right_(), + t -> f.f(t).right().map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> getOrModify(s).either( + IOFunctions::unit, + t -> IOFunctions. map(f.f(t), b -> set(b).f(s)) + ); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> getOrModify(s).either( + Trampoline.pure(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> getOrModify(s).either( + t -> Promise.promise(Strategy.idStrategy(), P.p(t)), + t -> f.f(t).fmap(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyListF(final F> f) { + return s -> getOrModify(s).either( + List::single, + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> getOrModify(s).either( + Option.some_(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> getOrModify(s).either( + Stream.single(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> getOrModify(s).either( + P.p1(), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> getOrModify(s).either( + t -> Validation. success(t), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> getOrModify(s).either( + t -> V2.p(P.p(t, t)), + t -> f.f(t).map(b -> set(b).f(s)) + ); + } + + @Override + public F modify(final F f) { + return s -> getOrModify.f(s).either(Function.identity(), a -> set.f(f.f(a)).f(s)); + } + }; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/PPrism.java b/core/src/main/java/fj/data/optic/PPrism.java new file mode 100644 index 00000000..d00a56f3 --- /dev/null +++ b/core/src/main/java/fj/data/optic/PPrism.java @@ -0,0 +1,438 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * A {@link PPrism} can be seen as a pair of functions: - `getOrModify: S => T \/ A` - `reverseGet : B => T` + * + * A {@link PPrism} could also be defined as a weaker {@link PIso} where get can fail. + * + * Typically a {@link PPrism} or {@link Prism} encodes the relation between a Sum or CoProduct type (e.g. sealed trait) and one + * of it is element. + * + * {@link PPrism} stands for Polymorphic Prism as it set and modify methods change a type `A` to `B` and `S` to `T`. + * {@link Prism} is a {@link PPrism} where the type of target cannot be modified. + * + * A {@link PPrism} is also a valid {@link Fold}, {@link POptional}, {@link PTraversal} and {@link PSetter} + * + * @param the source of a {@link PPrism} + * @param the modified source of a {@link PPrism} + * @param the target of a {@link PPrism} + * @param the modified target of a {@link PPrism} + */ +public abstract class PPrism { + + PPrism() { + super(); + } + + /** get the target of a {@link PPrism} or modify the source in case there is no target */ + + public abstract Either getOrModify(S s); + + /** get the modified source of a {@link PPrism} */ + public abstract T reverseGet(B b); + + /** get the target of a {@link PPrism} or nothing if there is no target */ + public abstract Option getOption(final S s); + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyFunctionF(final F> f) { + return s -> getOrModify(s).either( + Function.constant(), + a -> Function.compose(this::reverseGet, f.f(a)) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyEitherF(final F> f) { + return s -> getOrModify(s).either( + Either.right_(), + t -> f.f(t).right().map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyIOF(final F> f) { + return s -> getOrModify(s).either( + IOFunctions::unit, + t -> IOFunctions.map(f.f(t), this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyTrampolineF(final F> f) { + return s -> getOrModify(s).either( + Trampoline.pure(), + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyPromiseF(final F> f) { + return s -> getOrModify(s).either( + t -> Promise.promise(Strategy.idStrategy(), P.p(t)), + t -> f.f(t).fmap(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyListF(final F> f) { + return s -> getOrModify(s).either( + List::single, + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyOptionF(final F> f) { + return s -> getOrModify(s).either( + Option.some_(), + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyStreamF(final F> f) { + return s -> getOrModify(s).either( + Stream.single(), + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyP1F(final F> f) { + return s -> getOrModify(s).either( + P.p1(), + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyValidationF(final F> f) { + return s -> getOrModify(s).either( + t -> Validation. success(t), + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ + public final F> modifyV2F(final F> f) { + return s -> getOrModify(s).either( + t -> V2.p(P.p(t, t)), + t -> f.f(t).map(this::reverseGet) + ); + } + + /** modify polymorphically the target of a {@link PPrism} with a function */ + public final F modify(final F f) { + return s -> getOrModify(s).either(Function.identity(), a -> reverseGet(f.f(a))); + } + + /** modify polymorphically the target of a {@link PPrism} with a function. return empty if the {@link PPrism} is not matching */ + public final F> modifyOption(final F f) { + return s -> getOption(s).map(a -> reverseGet(f.f(a))); + } + + /** set polymorphically the target of a {@link PPrism} with a value */ + public final F set(final B b) { + return modify(__ -> b); + } + + /** set polymorphically the target of a {@link PPrism} with a value. return empty if the {@link PPrism} is not matching */ + public final F> setOption(final B b) { + return modifyOption(__ -> b); + } + + /** check if a {@link PPrism} has a target */ + public final boolean isMatching(final S s) { + return getOption(s).isSome(); + } + + /** create a {@link Getter} from the modified target to the modified source of a {@link PPrism} */ + public final Getter re() { + return Getter.getter(this::reverseGet); + } + + /************************************************************/ + /** Compose methods between a {@link PPrism} and another Optics */ + /************************************************************/ + + /** compose a {@link PPrism} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return asFold().composeFold(other); + } + + /** compose a {@link PPrism} with a {@link Getter} */ + public final Fold composeGetter(final Getter other) { + return asFold().composeGetter(other); + } + + /** compose a {@link PPrism} with a {@link PSetter} */ + public final PSetter composeSetter(final PSetter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link PPrism} with a {@link PTraversal} */ + public final PTraversal composeTraversal(final PTraversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link PPrism} with a {@link POptional} */ + public final POptional composeOptional(final POptional other) { + return asOptional().composeOptional(other); + } + + /** compose a {@link PPrism} with a {@link PLens} */ + public final POptional composeLens(final PLens other) { + return asOptional().composeOptional(other.asOptional()); + } + + /** compose a {@link PPrism} with a {@link PPrism} */ + public final PPrism composePrism(final PPrism other) { + return new PPrism() { + + @Override + public Either getOrModify(final S s) { + return PPrism.this.getOrModify(s).right() + .bind(a -> other.getOrModify(a).bimap(b -> PPrism.this.set(b).f(s), Function.identity())); + } + + @Override + public T reverseGet(final D d) { + return PPrism.this.reverseGet(other.reverseGet(d)); + } + + @Override + public Option getOption(final S s) { + return PPrism.this.getOption(s).bind(other::getOption); + } + }; + } + + /** compose a {@link PPrism} with a {@link PIso} */ + public final PPrism composeIso(final PIso other) { + return composePrism(other.asPrism()); + } + + /******************************************************************/ + /** Transformation methods to view a {@link PPrism} as another Optics */ + /******************************************************************/ + + /** view a {@link PPrism} as a {@link Fold} */ + public final Fold asFold() { + return new Fold() { + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> getOption(s).map(f).orSome(monoid.zero()); + } + }; + } + + /** view a {@link PPrism} as a {@link Setter} */ + public PSetter asSetter() { + return new PSetter() { + @Override + public F modify(final F f) { + return PPrism.this.modify(f); + } + + @Override + public F set(final B b) { + return PPrism.this.set(b); + } + }; + } + + /** view a {@link PPrism} as a {@link PTraversal} */ + public PTraversal asTraversal() { + final PPrism self = this; + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> getOption(s).map(f).orSome(monoid.zero()); + } + + }; + } + + /** view a {@link PPrism} as a {@link POptional} */ + public POptional asOptional() { + final PPrism self = this; + return new POptional() { + + @Override + public Either getOrModify(final S s) { + return self.getOrModify(s); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F set(final B b) { + return self.set(b); + } + + @Override + public Option getOption(final S s) { + return self.getOption(s); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + + }; + } + + public static PPrism pId() { + return PIso. pId().asPrism(); + } + + /** create a {@link PPrism} using the canonical functions: getOrModify and reverseGet */ + public static PPrism pPrism(final F> getOrModify, final F reverseGet) { + return new PPrism() { + + @Override + public Either getOrModify(final S s) { + return getOrModify.f(s); + } + + @Override + public T reverseGet(final B b) { + return reverseGet.f(b); + } + + @Override + public Option getOption(final S s) { + return getOrModify.f(s).right().toOption(); + } + }; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/PSetter.java b/core/src/main/java/fj/data/optic/PSetter.java new file mode 100644 index 00000000..71443a53 --- /dev/null +++ b/core/src/main/java/fj/data/optic/PSetter.java @@ -0,0 +1,103 @@ +package fj.data.optic; + +import fj.F; +import fj.data.Either; + +/** + * A {@link PSetter} is a generalisation of Functor map: - `map: (A => B) => F[A] => F[B]` - `modify: (A => B) => S => + * T` + * + * {@link PSetter} stands for Polymorphic Setter as it set and modify methods change a type `A` to `B` and `S` to `T`. + * + * {@link PTraversal}, {@link POptional}, {@link PPrism}, {@link PLens} and {@link PIso} are valid {@link PSetter} + * + * @param the source of a {@link PSetter} + * @param the modified source of a {@link PSetter} + * @param the target of a {@link PSetter} + * @param the modified target of a {@link PSetter} + */ +public abstract class PSetter { + + PSetter() { + super(); + } + + /** modify polymorphically the target of a {@link PSetter} with a function */ + public abstract F modify(F f); + + /** set polymorphically the target of a {@link PSetter} with a value */ + public abstract F set(final B b); + + /** join two {@link PSetter} with the same target */ + public final PSetter, Either, A, B> sum(final PSetter other) { + return pSetter(f -> e -> e.bimap(modify(f), other.modify(f))); + } + + /*************************************************************/ + /** Compose methods between a {@link PSetter} and another Optics */ + /*************************************************************/ + + /** compose a {@link PSetter} with a {@link PSetter} */ + public final PSetter composeSetter(final PSetter other) { + final PSetter self = this; + return new PSetter() { + + @Override + public F modify(final F f) { + return self.modify(other.modify(f)); + } + + @Override + public F set(final D d) { + return self.modify(other.set(d)); + } + }; + } + + /** compose a {@link PSetter} with a {@link PTraversal} */ + public final PSetter composeTraversal(final PTraversal other) { + return composeSetter(other.asSetter()); + } + + /** compose a {@link PSetter} with a {@link POptional} */ + public final PSetter composeOptional(final POptional other) { + return composeSetter(other.asSetter()); + } + + /** compose a {@link PSetter} with a {@link PPrism} */ + public final PSetter composePrism(final PPrism other) { + return composeSetter(other.asSetter()); + } + + /** compose a {@link PSetter} with a {@link PLens} */ + public final PSetter composeLens(final PLens other) { + return composeSetter(other.asSetter()); + } + + /** compose a {@link PSetter} with a {@link PIso} */ + public final PSetter composeIso(final PIso other) { + return composeSetter(other.asSetter()); + } + + public static PSetter pId() { + return PIso. pId().asSetter(); + } + + public static final PSetter, Either, S, T> pCodiagonal() { + return pSetter(f -> e -> e.bimap(f, f)); + } + + public static final PSetter pSetter(final F, F> modify) { + return new PSetter() { + @Override + public F modify(final F f) { + return modify.f(f); + } + + @Override + public F set(final B b) { + return modify(__ -> b); + } + }; + } +} diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java new file mode 100644 index 00000000..3ba8660b --- /dev/null +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -0,0 +1,622 @@ +package fj.data.optic; + +import fj.F; +import fj.F2; +import fj.F3; +import fj.F4; +import fj.F5; +import fj.F6; +import fj.Function; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * A {@link PTraversal} can be seen as a {@link POptional} generalised to 0 to n targets where n can be infinite. + * + * {@link PTraversal} stands for Polymorphic Traversal as it set and modify methods change a type `A` to `B` and `S` to `T`. + * {@link Traversal} is a {@link PTraversal} restricted to monomoprhic updates. + * + * @param the source of a {@link PTraversal} + * @param the modified source of a {@link PTraversal} + * @param the target of a {@link PTraversal} + * @param the modified target of a {@link PTraversal} + */ +public abstract class PTraversal { + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyFunctionF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyEitherF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyIOF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyTrampolineF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyPromiseF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyListF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyOptionF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyStreamF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyP1F(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyValidationF(F> f); + + /** + * modify polymorphically the target of a {@link PTraversal} with an Applicative function + */ + public abstract F> modifyV2F(F> f); + + /** map each target to a {@link Monoid} and combine the results */ + public abstract F foldMap(Monoid monoid, F f); + + /** combine all targets using a target's {@link Monoid} */ + public final F fold(final Monoid m) { + return foldMap(m, Function.identity()); + } + + /** get all the targets of a {@link PTraversal} */ + public final List getAll(final S s) { + return foldMap(Monoid.listMonoid(), List::single).f(s); + } + + /** find the first target of a {@link PTraversal} matching the predicate */ + public final F> find(final F p) { + return foldMap(Monoid.optionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none()); + } + + /** get the first target of a {@link PTraversal} */ + public final Option headOption(final S s) { + return find(__ -> true).f(s); + } + + /** check if at least one target satisfies the predicate */ + public final F exist(final F p) { + return foldMap(Monoid.disjunctionMonoid, p); + } + + /** check if all targets satisfy the predicate */ + public final F all(final F p) { + return foldMap(Monoid.conjunctionMonoid, p); + } + + /** modify polymorphically the target of a {@link PTraversal} with a function */ + public final F modify(final F f) { + return s -> this.modifyP1F(a -> P.p(f.f(a))).f(s)._1(); + } + + /** set polymorphically the target of a {@link PTraversal} with a value */ + public final F set(final B b) { + return modify(Function.constant(b)); + } + + /** join two {@link PTraversal} with the same target */ + public final PTraversal, Either, A, B> sum(final PTraversal other) { + final PTraversal self = this; + return new PTraversal, Either, A, B>() { + + @Override + public F, F>> modifyFunctionF(final F> f) { + return ss1 -> ss1.either( + s -> Function.compose(Either.left_(), self.modifyFunctionF(f).f(s)), + s1 -> Function.compose(Either.right_(), other.modifyFunctionF(f).f(s1)) + ); + } + + @Override + public F, Either>> modifyEitherF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyEitherF(f).f(s).right().map(Either.left_()), + s1 -> other.modifyEitherF(f).f(s1).right().map(Either.right_()) + ); + } + + @Override + public F, IO>> modifyIOF(final F> f) { + return ss1 -> ss1.either( + s -> IOFunctions.map(self.modifyIOF(f).f(s), Either.left_()), + s1 -> IOFunctions.map(other.modifyIOF(f).f(s1), Either.right_()) + ); + } + + @Override + public F, Trampoline>> modifyTrampolineF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyTrampolineF(f).f(s).map(Either.left_()), + s1 -> other.modifyTrampolineF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Promise>> modifyPromiseF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyPromiseF(f).f(s).fmap(Either.left_()), + s1 -> other.modifyPromiseF(f).f(s1).fmap(Either.right_()) + ); + } + + @Override + public F, List>> modifyListF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyListF(f).f(s).map(Either.left_()), + s1 -> other.modifyListF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Option>> modifyOptionF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyOptionF(f).f(s).map(Either.left_()), + s1 -> other.modifyOptionF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Stream>> modifyStreamF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyStreamF(f).f(s).map(Either.left_()), + s1 -> other.modifyStreamF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, P1>> modifyP1F(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyP1F(f).f(s).map(Either.left_()), + s1 -> other.modifyP1F(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, V2>> modifyV2F(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyV2F(f).f(s).map(Either.left_()), + s1 -> other.modifyV2F(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Validation>> modifyValidationF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyValidationF(f).f(s).map(Either.left_()), + s1 -> other.modifyValidationF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, M> foldMap(final Monoid monoid, final F f) { + return ss1 -> ss1.either( + self.foldMap(monoid, f), + other.foldMap(monoid, f) + ); + } + + }; + } + + /****************************************************************/ + /** Compose methods between a {@link PTraversal} and another Optics */ + /****************************************************************/ + + /** compose a {@link PTraversal} with a {@link Fold} */ + public final Fold composeFold(final Fold other) { + return asFold().composeFold(other); + } + + // + /** compose a {@link PTraversal} with a {@link Getter} */ + public final Fold composeFold(final Getter other) { + return asFold().composeGetter(other); + } + + /** compose a {@link PTraversal} with a {@link PSetter} */ + public final PSetter composeSetter(final PSetter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link PTraversal} with a {@link PTraversal} */ + public final PTraversal composeTraversal(final PTraversal other) { + final PTraversal self = this; + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(other.modifyFunctionF(f)); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(other.modifyEitherF(f)); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(other.modifyIOF(f)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(other.modifyTrampolineF(f)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(other.modifyPromiseF(f)); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(other.modifyListF(f)); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(other.modifyOptionF(f)); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(other.modifyStreamF(f)); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(other.modifyP1F(f)); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(other.modifyValidationF(f)); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(other.modifyV2F(f)); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return self.foldMap(monoid, other.foldMap(monoid, f)); + } + }; + } + + /** compose a {@link PTraversal} with a {@link POptional} */ + public final PTraversal composeOptional(final POptional other) { + return composeTraversal(other.asTraversal()); + } + + /** compose a {@link PTraversal} with a {@link PPrism} */ + public final PTraversal composePrism(final PPrism other) { + return composeTraversal(other.asTraversal()); + } + + /** compose a {@link PTraversal} with a {@link PLens} */ + public final PTraversal composeLens(final PLens other) { + return composeTraversal(other.asTraversal()); + } + + /** compose a {@link PTraversal} with a {@link PIso} */ + public final PTraversal composeIso(final PIso other) { + return composeTraversal(other.asTraversal()); + } + + /**********************************************************************/ + /** Transformation methods to view a {@link PTraversal} as another Optics */ + /**********************************************************************/ + + /** view a {@link PTraversal} as a {@link Fold} */ + public final Fold asFold() { + return new Fold() { + @Override + public F foldMap(final Monoid monoid, final F f) { + return PTraversal.this.foldMap(monoid, f); + } + }; + } + + /** view a {@link PTraversal} as a {@link PSetter} */ + public PSetter asSetter() { + return PSetter.pSetter(this::modify); + } + + public static PTraversal pId() { + return PIso. pId().asTraversal(); + } + + public static PTraversal, Either, S, T> pCodiagonal() { + return new PTraversal, Either, S, T>() { + + @Override + public F, F>> modifyFunctionF(final F> f) { + return s -> s.bimap(f, f).either( + f1 -> Function.compose(Either.left_(), f1), + f1 -> Function.compose(Either.right_(), f1) + ); + } + + @Override + public F, Either>> modifyEitherF(final F> f) { + return s -> s.bimap(f, f).either( + e -> e.right().map(Either.left_()), + e -> e.right().map(Either.right_()) + ); + } + + @Override + public F, IO>> modifyIOF(final F> f) { + return s -> s.bimap(f, f).either( + io -> IOFunctions.map(io, Either.left_()), + io -> IOFunctions.map(io, Either.right_()) + ); + } + + @Override + public F, Trampoline>> modifyTrampolineF(final F> f) { + return s -> s.bimap(f, f).either( + t -> t.map(Either.left_()), + t -> t.map(Either.right_()) + ); + } + + @Override + public F, Promise>> modifyPromiseF(final F> f) { + return s -> s.bimap(f, f).either( + p -> p.fmap(Either.left_()), + p -> p.fmap(Either.right_()) + ); + } + + @Override + public F, List>> modifyListF(final F> f) { + return s -> s.bimap(f, f).either( + l -> l.map(Either.left_()), + l -> l.map(Either.right_()) + ); + } + + @Override + public F, Option>> modifyOptionF(final F> f) { + return s -> s.bimap(f, f).either( + o -> o.map(Either.left_()), + o -> o.map(Either.right_()) + ); + } + + @Override + public F, Stream>> modifyStreamF(final F> f) { + return s -> s.bimap(f, f).either( + stream -> stream.map(Either.left_()), + stream -> stream.map(Either.right_()) + ); + } + + @Override + public F, P1>> modifyP1F(final F> f) { + return s -> s.bimap(f, f).either( + p1 -> p1.map(Either.left_()), + p1 -> p1.map(Either.right_()) + ); + } + + @Override + public F, V2>> modifyV2F(final F> f) { + return s -> s.bimap(f, f).either( + v2 -> v2.map(Either.left_()), + v2 -> v2.map(Either.right_()) + ); + } + + @Override + public F, Validation>> modifyValidationF(final F> f) { + return s -> s.bimap(f, f).either( + v -> v.map(Either.left_()), + v -> v.map(Either.right_()) + ); + } + + @Override + public F, M> foldMap(final Monoid monoid, final F f) { + return s -> s.either(f, f); + } + }; + } + + public static PTraversal pTraversal(final F get1, final F get2, final F2 set) { + final F> curriedSet = Function.curry(set); + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return s -> Function.apply(Function.compose(curriedSet, f.f(get1.f(s))), f.f(get2.f(s))); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().map(curriedSet)); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> IOFunctions.apply(f.f(get2.f(s)), IOFunctions.map(f.f(get1.f(s)), curriedSet)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).fmap(curriedSet)); + } + + @Override + public F> modifyListF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> monoid.sum(f.f(get1.f(s)), f.f(get2.f(s))); + } + }; + } + + public static PTraversal pTraversal(final F get1, final F get2, final F get3, + final F3 set) { + return fromCurried(pTraversal(get1, get2, (b1, b2) -> b3 -> set.f(b1, b2, b3)), get3); + } + + public static PTraversal pTraversal(final F get1, final F get2, final F get3, + final F get4, + final F4 set) { + return fromCurried(pTraversal(get1, get2, get3, (b1, b2, b3) -> b4 -> set.f(b1, b2, b3, b4)), get4); + } + + public static PTraversal pTraversal(final F get1, final F get2, final F get3, + final F get4, final F get5, + final F5 set) { + return fromCurried(pTraversal(get1, get2, get3, get4, (b1, b2, b3, b4) -> b5 -> set.f(b1, b2, b3, b4, b5)), get5); + } + + public static PTraversal pTraversal(final F get1, final F get2, final F get3, + final F get4, final F get5, final F get6, + final F6 set) { + return fromCurried(pTraversal(get1, get2, get3, get4, get5, (b1, b2, b3, b4, b5) -> b6 -> set.f(b1, b2, b3, b4, b5, b6)), + get6); + } + + private static PTraversal fromCurried(final PTraversal, A, B> curriedTraversal, + final F lastGet) { + return new PTraversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return s -> Function.apply(curriedTraversal.modifyFunctionF(f).f(s), f.f(lastGet.f(s))); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> f.f(lastGet.f(s)).right().apply(curriedTraversal.modifyEitherF(f).f(s)); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> IOFunctions.apply(f.f(lastGet.f(s)), curriedTraversal.modifyIOF(f).f(s)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyTrampolineF(f).f(s)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyPromiseF(f).f(s)); + } + + @Override + public F> modifyListF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyListF(f).f(s)); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyOptionF(f).f(s)); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyStreamF(f).f(s)); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyP1F(f).f(s)); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyV2F(f).f(s)); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyValidationF(f).f(s)); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> monoid.sum(curriedTraversal.foldMap(monoid, f).f(s), f.f(lastGet.f(s))); + } + }; + } +} diff --git a/core/src/main/java/fj/data/optic/Prism.java b/core/src/main/java/fj/data/optic/Prism.java new file mode 100644 index 00000000..04d2cb2c --- /dev/null +++ b/core/src/main/java/fj/data/optic/Prism.java @@ -0,0 +1,275 @@ +package fj.data.optic; + +import fj.F; +import fj.Function; +import fj.Monoid; +import fj.P1; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +/** + * {@link PPrism} restricted to monomorphic update + */ +public abstract class Prism extends PPrism { + + Prism() { + super(); + } + + /***********************************************************/ + /** Compose methods between a {@link Prism} and another Optics */ + /***********************************************************/ + + /** compose a {@link Prism} with a {@link Setter} */ + public final Setter composeSetter(final Setter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link Prism} with a {@link Traversal} */ + public final Traversal composeTraversal(final Traversal other) { + return asTraversal().composeTraversal(other); + } + + /** compose a {@link Prism} with a {@link Optional} */ + public final Optional composeOptional(final Optional other) { + return asOptional().composeOptional(other); + } + + /** compose a {@link Prism} with a {@link Lens} */ + public final Optional composeLens(final Lens other) { + return asOptional().composeOptional(other.asOptional()); + } + + /** compose a {@link Prism} with a {@link Prism} */ + public final Prism composePrism(final Prism other) { + return new Prism() { + + @Override + public Either getOrModify(final S s) { + return Prism.this.getOrModify(s).right() + .bind(a -> other.getOrModify(a).bimap(b -> Prism.this.set(b).f(s), Function.identity())); + } + + @Override + public S reverseGet(final C d) { + return Prism.this.reverseGet(other.reverseGet(d)); + } + + @Override + public Option getOption(final S s) { + return Prism.this.getOption(s).bind(other::getOption); + } + }; + } + + /** compose a {@link Prism} with an {@link Iso} */ + public final Prism composeIso(final Iso other) { + return composePrism(other.asPrism()); + } + + /*****************************************************************/ + /** Transformation methods to view a {@link Prism} as another Optics */ + /*****************************************************************/ + + /** view a {@link Prism} as a {@link Setter} */ + @Override + public final Setter asSetter() { + return new Setter() { + @Override + public F modify(final F f) { + return Prism.this.modify(f); + } + + @Override + public F set(final A b) { + return Prism.this.set(b); + } + }; + } + + /** view a {@link Prism} as a {@link Traversal} */ + @Override + public final Traversal asTraversal() { + final Prism self = this; + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> getOption(s).map(f).orSome(monoid.zero()); + } + + }; + } + + /** view a {@link Prism} as a {@link Optional} */ + @Override + public final Optional asOptional() { + final Prism self = this; + return new Optional() { + + @Override + public Either getOrModify(final S s) { + return self.getOrModify(s); + } + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(f); + } + + @Override + public F set(final A b) { + return self.set(b); + } + + @Override + public Option getOption(final S s) { + return self.getOption(s); + } + + @Override + public F modify(final F f) { + return self.modify(f); + } + + }; + } + + public static Prism id() { + return Iso. id().asPrism(); + } + + /** create a {@link Prism} using the canonical functions: getOrModify and reverseGet */ + public static Prism prism(final F> getOrModify, final F reverseGet) { + return new Prism() { + + @Override + public Either getOrModify(final S s) { + return getOrModify.f(s); + } + + @Override + public S reverseGet(final A b) { + return reverseGet.f(b); + } + + @Override + public Option getOption(final S s) { + return getOrModify.f(s).right().toOption(); + } + }; + } + +} \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/Setter.java b/core/src/main/java/fj/data/optic/Setter.java new file mode 100644 index 00000000..184ee289 --- /dev/null +++ b/core/src/main/java/fj/data/optic/Setter.java @@ -0,0 +1,71 @@ +package fj.data.optic; + +import fj.F; +import fj.data.Either; + +/** {@link PSetter} with a monomorphic modify function */ +public abstract class Setter extends PSetter { + + Setter() { + super(); + } + + /** join two {@link Setter} with the same target */ + public final Setter, A> sum(final Setter other) { + return setter(f -> e -> e.bimap(modify(f), other.modify(f))); + } + + /************************************************************/ + /** Compose methods between a {@link Setter} and another Optics */ + /************************************************************/ + + /** compose a {@link Setter} with a {@link Setter} */ + public final Setter composeSetter(final Setter other) { + final Setter self = this; + return new Setter() { + + @Override + public F modify(final F f) { + return self.modify(other.modify(f)); + } + + @Override + public F set(final C c) { + return self.modify(other.set(c)); + } + }; + } + + /** compose a {@link Setter} with a {@link Traversal} */ + public final Setter composeTraversal(final Traversal other) { + return composeSetter(other.asSetter()); + } + + /** compose a {@link Setter} with an {@link Iso} */ + public final Setter composeIso(final Iso other) { + return composeSetter(other.asSetter()); + } + + public static Setter id() { + return Iso. id().asSetter(); + } + + public static final Setter, S> codiagonal() { + return setter(f -> e -> e.bimap(f, f)); + } + + /** alias for {@link PSetter} constructor with a monomorphic modify function */ + public static final Setter setter(final F, F> modify) { + return new Setter() { + @Override + public F modify(final F f) { + return modify.f(f); + } + + @Override + public F set(final A a) { + return modify(__ -> a); + } + }; + } +} diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java new file mode 100644 index 00000000..00870b3d --- /dev/null +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -0,0 +1,474 @@ +package fj.data.optic; + +import fj.F; +import fj.F2; +import fj.F3; +import fj.F4; +import fj.F5; +import fj.F6; +import fj.Function; +import fj.Monoid; +import fj.P1; +import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.data.Either; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Option; +import fj.data.Stream; +import fj.data.Validation; +import fj.data.vector.V2; + +public abstract class Traversal extends PTraversal { + + /** join two {@link Traversal} with the same target */ + public final Traversal, A> sum(final Traversal other) { + final Traversal self = this; + return new Traversal, A>() { + + @Override + public F, F>> modifyFunctionF(final F> f) { + return ss1 -> ss1.either( + s -> Function.compose(Either.left_(), self.modifyFunctionF(f).f(s)), + s1 -> Function.compose(Either.right_(), other.modifyFunctionF(f).f(s1)) + ); + } + + @Override + public F, Either>> modifyEitherF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyEitherF(f).f(s).right().map(Either.left_()), + s1 -> other.modifyEitherF(f).f(s1).right().map(Either.right_()) + ); + } + + @Override + public F, IO>> modifyIOF(final F> f) { + return ss1 -> ss1.either( + s -> IOFunctions.map(self.modifyIOF(f).f(s), Either.left_()), + s1 -> IOFunctions.map(other.modifyIOF(f).f(s1), Either.right_()) + ); + } + + @Override + public F, Trampoline>> modifyTrampolineF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyTrampolineF(f).f(s).map(Either.left_()), + s1 -> other.modifyTrampolineF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Promise>> modifyPromiseF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyPromiseF(f).f(s).fmap(Either.left_()), + s1 -> other.modifyPromiseF(f).f(s1).fmap(Either.right_()) + ); + } + + @Override + public F, List>> modifyListF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyListF(f).f(s).map(Either.left_()), + s1 -> other.modifyListF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Option>> modifyOptionF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyOptionF(f).f(s).map(Either.left_()), + s1 -> other.modifyOptionF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Stream>> modifyStreamF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyStreamF(f).f(s).map(Either.left_()), + s1 -> other.modifyStreamF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, P1>> modifyP1F(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyP1F(f).f(s).map(Either.left_()), + s1 -> other.modifyP1F(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, V2>> modifyV2F(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyV2F(f).f(s).map(Either.left_()), + s1 -> other.modifyV2F(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, Validation>> modifyValidationF(final F> f) { + return ss1 -> ss1.either( + s -> self.modifyValidationF(f).f(s).map(Either.left_()), + s1 -> other.modifyValidationF(f).f(s1).map(Either.right_()) + ); + } + + @Override + public F, M> foldMap(final Monoid monoid, final F f) { + return ss1 -> ss1.either( + self.foldMap(monoid, f), + other.foldMap(monoid, f) + ); + } + + }; + } + + /***************************************************************/ + /** Compose methods between a {@link Traversal} and another Optics */ + /***************************************************************/ + + /** compose a {@link Traversal} with a {@link Setter} */ + public final Setter composeSetter(final Setter other) { + return asSetter().composeSetter(other); + } + + /** compose a {@link Traversal} with a {@link Traversal} */ + public final Traversal composeTraversal(final Traversal other) { + final Traversal self = this; + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return self.modifyFunctionF(other.modifyFunctionF(f)); + } + + @Override + public F> modifyEitherF(final F> f) { + return self.modifyEitherF(other.modifyEitherF(f)); + } + + @Override + public F> modifyIOF(final F> f) { + return self.modifyIOF(other.modifyIOF(f)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return self.modifyTrampolineF(other.modifyTrampolineF(f)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return self.modifyPromiseF(other.modifyPromiseF(f)); + } + + @Override + public F> modifyListF(final F> f) { + return self.modifyListF(other.modifyListF(f)); + } + + @Override + public F> modifyOptionF(final F> f) { + return self.modifyOptionF(other.modifyOptionF(f)); + } + + @Override + public F> modifyStreamF(final F> f) { + return self.modifyStreamF(other.modifyStreamF(f)); + } + + @Override + public F> modifyP1F(final F> f) { + return self.modifyP1F(other.modifyP1F(f)); + } + + @Override + public F> modifyValidationF(final F> f) { + return self.modifyValidationF(other.modifyValidationF(f)); + } + + @Override + public F> modifyV2F(final F> f) { + return self.modifyV2F(other.modifyV2F(f)); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return self.foldMap(monoid, other.foldMap(monoid, f)); + } + }; + } + + /*********************************************************************/ + /** Transformation methods to view a {@link Traversal} as another Optics */ + /*********************************************************************/ + + /** view a {@link Traversal} as a {@link Setter} */ + @Override + public final Setter asSetter() { + return Setter.setter(this::modify); + } + + public static Traversal id() { + return Iso. id().asTraversal(); + } + + public static Traversal, S> codiagonal() { + return new Traversal, S>() { + + @Override + public F, F>> modifyFunctionF(final F> f) { + return s -> s.bimap(f, f).either( + f1 -> Function.compose(Either.left_(), f1), + f1 -> Function.compose(Either.right_(), f1) + ); + } + + @Override + public F, Either>> modifyEitherF(final F> f) { + return s -> s.bimap(f, f).either( + e -> e.right().map(Either.left_()), + e -> e.right().map(Either.right_()) + ); + } + + @Override + public F, IO>> modifyIOF(final F> f) { + return s -> s.bimap(f, f).either( + io -> IOFunctions.map(io, Either.left_()), + io -> IOFunctions.map(io, Either.right_()) + ); + } + + @Override + public F, Trampoline>> modifyTrampolineF(final F> f) { + return s -> s.bimap(f, f).either( + t -> t.map(Either.left_()), + t -> t.map(Either.right_()) + ); + } + + @Override + public F, Promise>> modifyPromiseF(final F> f) { + return s -> s.bimap(f, f).either( + p -> p.fmap(Either.left_()), + p -> p.fmap(Either.right_()) + ); + } + + @Override + public F, List>> modifyListF(final F> f) { + return s -> s.bimap(f, f).either( + l -> l.map(Either.left_()), + l -> l.map(Either.right_()) + ); + } + + @Override + public F, Option>> modifyOptionF(final F> f) { + return s -> s.bimap(f, f).either( + o -> o.map(Either.left_()), + o -> o.map(Either.right_()) + ); + } + + @Override + public F, Stream>> modifyStreamF(final F> f) { + return s -> s.bimap(f, f).either( + stream -> stream.map(Either.left_()), + stream -> stream.map(Either.right_()) + ); + } + + @Override + public F, P1>> modifyP1F(final F> f) { + return s -> s.bimap(f, f).either( + p1 -> p1.map(Either.left_()), + p1 -> p1.map(Either.right_()) + ); + } + + @Override + public F, V2>> modifyV2F(final F> f) { + return s -> s.bimap(f, f).either( + v2 -> v2.map(Either.left_()), + v2 -> v2.map(Either.right_()) + ); + } + + @Override + public F, Validation>> modifyValidationF(final F> f) { + return s -> s.bimap(f, f).either( + v -> v.map(Either.left_()), + v -> v.map(Either.right_()) + ); + } + + @Override + public F, M> foldMap(final Monoid monoid, final F f) { + return s -> s.either(f, f); + } + }; + } + + public static Traversal traversal(final F get1, final F get2, final F2 set) { + final F> curriedSet = Function.curry(set); + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return s -> Function.apply(Function.compose(curriedSet, f.f(get1.f(s))), f.f(get2.f(s))); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().map(curriedSet)); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> IOFunctions.apply(f.f(get2.f(s)), IOFunctions.map(f.f(get1.f(s)), curriedSet)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).fmap(curriedSet)); + } + + @Override + public F> modifyListF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> monoid.sum(f.f(get1.f(s)), f.f(get2.f(s))); + } + }; + } + + public static Traversal traversal(final F get1, final F get2, final F get3, + final F3 set) { + return fromCurried(PTraversal.pTraversal(get1, get2, (b1, b2) -> b3 -> set.f(b1, b2, b3)), get3); + } + + public static Traversal traversal(final F get1, final F get2, final F get3, + final F get4, + final F4 set) { + return fromCurried(PTraversal.pTraversal(get1, get2, get3, (b1, b2, b3) -> b4 -> set.f(b1, b2, b3, b4)), get4); + } + + public static Traversal traversal(final F get1, final F get2, final F get3, + final F get4, final F get5, + final F5 set) { + return fromCurried(PTraversal.pTraversal(get1, get2, get3, get4, (b1, b2, b3, b4) -> b5 -> set.f(b1, b2, b3, b4, b5)), get5); + } + + public static Traversal traversal(final F get1, final F get2, final F get3, + final F get4, final F get5, final F get6, + final F6 set) { + return fromCurried( + PTraversal.pTraversal(get1, get2, get3, get4, get5, (b1, b2, b3, b4, b5) -> b6 -> set.f(b1, b2, b3, b4, b5, b6)), + get6); + } + + private static Traversal fromCurried(final PTraversal, A, A> curriedTraversal, + final F lastGet) { + return new Traversal() { + + @Override + public F> modifyFunctionF(final F> f) { + return s -> Function.apply(curriedTraversal.modifyFunctionF(f).f(s), f.f(lastGet.f(s))); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> f.f(lastGet.f(s)).right().apply(curriedTraversal.modifyEitherF(f).f(s)); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> IOFunctions.apply(f.f(lastGet.f(s)), curriedTraversal.modifyIOF(f).f(s)); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyTrampolineF(f).f(s)); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyPromiseF(f).f(s)); + } + + @Override + public F> modifyListF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyListF(f).f(s)); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyOptionF(f).f(s)); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyStreamF(f).f(s)); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyP1F(f).f(s)); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyV2F(f).f(s)); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyValidationF(f).f(s)); + } + + @Override + public F foldMap(final Monoid monoid, final F f) { + return s -> monoid.sum(curriedTraversal.foldMap(monoid, f).f(s), f.f(lastGet.f(s))); + } + }; + } + +} From 9358d13f39e0b0281013507fca79388d06ef474b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 8 May 2015 22:17:16 +0200 Subject: [PATCH 275/811] Fixed setter signature of fixed arrity PTraversal constructors (Setter functions should return modified source) --- .../main/java/fj/data/optic/PTraversal.java | 45 +++---- .../main/java/fj/data/optic/Traversal.java | 113 ++++-------------- 2 files changed, 48 insertions(+), 110 deletions(-) diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index 3ba8660b..b40468cd 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -1,11 +1,11 @@ package fj.data.optic; import fj.F; -import fj.F2; import fj.F3; import fj.F4; import fj.F5; import fj.F6; +import fj.F7; import fj.Function; import fj.Monoid; import fj.P; @@ -464,63 +464,63 @@ public F, M> foldMap(final Monoid monoid, final F f) { }; } - public static PTraversal pTraversal(final F get1, final F get2, final F2 set) { - final F> curriedSet = Function.curry(set); + public static PTraversal pTraversal(final F get1, final F get2, + final F3 set) { return new PTraversal() { @Override public F> modifyFunctionF(final F> f) { - return s -> Function.apply(Function.compose(curriedSet, f.f(get1.f(s))), f.f(get2.f(s))); + return s -> Function.apply(Function.compose(b1 -> b2 -> set.f(b1, b2, s), f.f(get1.f(s))), f.f(get2.f(s))); } @Override public F> modifyEitherF(final F> f) { - return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().map(curriedSet)); + return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyIOF(final F> f) { - return s -> IOFunctions.apply(f.f(get2.f(s)), IOFunctions.map(f.f(get1.f(s)), curriedSet)); + return s -> IOFunctions.apply(f.f(get2.f(s)), IOFunctions.map(f.f(get1.f(s)), b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyTrampolineF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyPromiseF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).fmap(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).fmap(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyListF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyOptionF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyStreamF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyP1F(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyV2F(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyValidationF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); } @Override @@ -531,26 +531,27 @@ public F foldMap(final Monoid monoid, final F f) { } public static PTraversal pTraversal(final F get1, final F get2, final F get3, - final F3 set) { - return fromCurried(pTraversal(get1, get2, (b1, b2) -> b3 -> set.f(b1, b2, b3)), get3); + final F4 set) { + return fromCurried(pTraversal(get1, get2, (b1, b2, s) -> (b3 -> set.f(b1, b2, b3, s))), get3); } public static PTraversal pTraversal(final F get1, final F get2, final F get3, final F get4, - final F4 set) { - return fromCurried(pTraversal(get1, get2, get3, (b1, b2, b3) -> b4 -> set.f(b1, b2, b3, b4)), get4); + final F5 set) { + return fromCurried(pTraversal(get1, get2, get3, (b1, b2, b3, s) -> b4 -> set.f(b1, b2, b3, b4, s)), get4); } public static PTraversal pTraversal(final F get1, final F get2, final F get3, final F get4, final F get5, - final F5 set) { - return fromCurried(pTraversal(get1, get2, get3, get4, (b1, b2, b3, b4) -> b5 -> set.f(b1, b2, b3, b4, b5)), get5); + final F6 set) { + return fromCurried(pTraversal(get1, get2, get3, get4, (b1, b2, b3, b4, s) -> b5 -> set.f(b1, b2, b3, b4, b5, s)), get5); } public static PTraversal pTraversal(final F get1, final F get2, final F get3, final F get4, final F get5, final F get6, - final F6 set) { - return fromCurried(pTraversal(get1, get2, get3, get4, get5, (b1, b2, b3, b4, b5) -> b6 -> set.f(b1, b2, b3, b4, b5, b6)), + final F7 set) { + return fromCurried( + pTraversal(get1, get2, get3, get4, get5, (b1, b2, b3, b4, b5, s) -> b6 -> set.f(b1, b2, b3, b4, b5, b6, s)), get6); } diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java index 00870b3d..e3529d1e 100644 --- a/core/src/main/java/fj/data/optic/Traversal.java +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -314,161 +314,98 @@ public F, M> foldMap(final Monoid monoid, final F f) { }; } - public static Traversal traversal(final F get1, final F get2, final F2 set) { - final F> curriedSet = Function.curry(set); + public static Traversal fromPtraversal(final PTraversal pTraversal) { return new Traversal() { @Override public F> modifyFunctionF(final F> f) { - return s -> Function.apply(Function.compose(curriedSet, f.f(get1.f(s))), f.f(get2.f(s))); + return pTraversal.modifyFunctionF(f); } @Override public F> modifyEitherF(final F> f) { - return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().map(curriedSet)); + return pTraversal.modifyEitherF(f); } @Override public F> modifyIOF(final F> f) { - return s -> IOFunctions.apply(f.f(get2.f(s)), IOFunctions.map(f.f(get1.f(s)), curriedSet)); + return pTraversal.modifyIOF(f); } @Override public F> modifyTrampolineF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return pTraversal.modifyTrampolineF(f); } @Override public F> modifyPromiseF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).fmap(curriedSet)); + return pTraversal.modifyPromiseF(f); } @Override public F> modifyListF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return pTraversal.modifyListF(f); } @Override public F> modifyOptionF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return pTraversal.modifyOptionF(f); } @Override public F> modifyStreamF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return pTraversal.modifyStreamF(f); } @Override public F> modifyP1F(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + return pTraversal.modifyP1F(f); } @Override - public F> modifyV2F(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + public F> modifyValidationF(final F> f) { + return pTraversal.modifyValidationF(f); } @Override - public F> modifyValidationF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(curriedSet)); + public F> modifyV2F(final F> f) { + return pTraversal.modifyV2F(f); } @Override public F foldMap(final Monoid monoid, final F f) { - return s -> monoid.sum(f.f(get1.f(s)), f.f(get2.f(s))); + return pTraversal.foldMap(monoid, f); } }; } + public static Traversal traversal(final F get1, final F get2, final F2 set) { + return fromPtraversal(PTraversal.pTraversal(get1, get2, (a1, a2, s) -> set.f(a1, a2))); + } + public static Traversal traversal(final F get1, final F get2, final F get3, final F3 set) { - return fromCurried(PTraversal.pTraversal(get1, get2, (b1, b2) -> b3 -> set.f(b1, b2, b3)), get3); + return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, (a1, a2, a3, s) -> set.f(a1, a2, a3))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F get4, final F4 set) { - return fromCurried(PTraversal.pTraversal(get1, get2, get3, (b1, b2, b3) -> b4 -> set.f(b1, b2, b3, b4)), get4); + return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, get4, (a1, a2, a3, a4, s) -> set.f(a1, a2, a3, a4))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F get4, final F get5, final F5 set) { - return fromCurried(PTraversal.pTraversal(get1, get2, get3, get4, (b1, b2, b3, b4) -> b5 -> set.f(b1, b2, b3, b4, b5)), get5); + return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, get4, get5, + (a1, a2, a3, a4, a5, s) -> set.f(a1, a2, a3, a4, a5))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F get4, final F get5, final F get6, final F6 set) { - return fromCurried( - PTraversal.pTraversal(get1, get2, get3, get4, get5, (b1, b2, b3, b4, b5) -> b6 -> set.f(b1, b2, b3, b4, b5, b6)), - get6); - } - - private static Traversal fromCurried(final PTraversal, A, A> curriedTraversal, - final F lastGet) { - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return s -> Function.apply(curriedTraversal.modifyFunctionF(f).f(s), f.f(lastGet.f(s))); - } - - @Override - public F> modifyEitherF(final F> f) { - return s -> f.f(lastGet.f(s)).right().apply(curriedTraversal.modifyEitherF(f).f(s)); - } - - @Override - public F> modifyIOF(final F> f) { - return s -> IOFunctions.apply(f.f(lastGet.f(s)), curriedTraversal.modifyIOF(f).f(s)); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyTrampolineF(f).f(s)); - } - - @Override - public F> modifyPromiseF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyPromiseF(f).f(s)); - } - - @Override - public F> modifyListF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyListF(f).f(s)); - } - - @Override - public F> modifyOptionF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyOptionF(f).f(s)); - } - - @Override - public F> modifyStreamF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyStreamF(f).f(s)); - } - - @Override - public F> modifyP1F(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyP1F(f).f(s)); - } - - @Override - public F> modifyV2F(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyV2F(f).f(s)); - } - - @Override - public F> modifyValidationF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyValidationF(f).f(s)); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return s -> monoid.sum(curriedTraversal.foldMap(monoid, f).f(s), f.f(lastGet.f(s))); - } - }; + return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, get4, get5, get6, + (a1, a2, a3, a4, a5, a6, s) -> set.f(a1, a2, a3, a4, a5, a6))); } } From a26613feafe219beacaadcbf7e083d0e792661b4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 9 May 2015 19:35:36 +0200 Subject: [PATCH 276/811] Remove code duplication in monomorphic optics by delegating all methods to the corresponding polymorphic optic --- core/src/main/java/fj/data/optic/Iso.java | 392 ++--------------- core/src/main/java/fj/data/optic/Lens.java | 399 ++++-------------- .../src/main/java/fj/data/optic/Optional.java | 378 ++++------------- core/src/main/java/fj/data/optic/Prism.java | 239 ++--------- core/src/main/java/fj/data/optic/Setter.java | 54 +-- .../main/java/fj/data/optic/Traversal.java | 390 +++-------------- 6 files changed, 334 insertions(+), 1518 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Iso.java b/core/src/main/java/fj/data/optic/Iso.java index bbfbe8e1..71ca7359 100644 --- a/core/src/main/java/fj/data/optic/Iso.java +++ b/core/src/main/java/fj/data/optic/Iso.java @@ -1,49 +1,45 @@ package fj.data.optic; import fj.F; -import fj.Monoid; -import fj.P; -import fj.P1; import fj.P2; -import fj.control.Trampoline; -import fj.control.parallel.Promise; -import fj.data.Either; -import fj.data.IO; -import fj.data.List; -import fj.data.Option; -import fj.data.Stream; -import fj.data.Validation; -import fj.data.vector.V2; /** {@link PIso} when S = T and A = B */ -public abstract class Iso extends PIso { +public final class Iso extends PIso { - private Iso() { - super(); + final PIso pIso; + + public Iso(final PIso pIso) { + this.pIso = pIso; } @Override - public abstract Iso reverse(); + public A get(final S s) { + return pIso.get(s); + } + + @Override + public S reverseGet(final A a) { + return pIso.reverseGet(a); + } + + @Override + public Iso reverse() { + return new Iso<>(pIso.reverse()); + } /** pair two disjoint {@link Iso} */ public Iso, P2> product(final Iso other) { - return iso( - ss1 -> P.p(get(ss1._1()), other.get(ss1._2())), - bb1 -> P.p(reverseGet(bb1._1()), other.reverseGet(bb1._2()))); + return new Iso<>(pIso.product(other.pIso)); } @Override public Iso, P2> first() { - return iso( - sc -> P.p(get(sc._1()), sc._2()), - bc -> P.p(reverseGet(bc._1()), bc._2())); + return new Iso<>(pIso.first()); } @Override public Iso, P2> second() { - return iso( - cs -> P.p(cs._1(), get(cs._2())), - cb -> P.p(cb._1(), reverseGet(cb._2()))); + return new Iso<>(pIso.second()); } /**********************************************************/ @@ -52,22 +48,22 @@ public Iso, P2> second() { /** compose an {@link Iso} with a {@link Setter} */ public final Setter composeSetter(final Setter other) { - return asSetter().composeSetter(other); + return new Setter<>(pIso.composeSetter(other.pSetter)); } /** compose an {@link Iso} with a {@link Traversal} */ public final Traversal composeTraversal(final Traversal other) { - return asTraversal().composeTraversal(other); + return new Traversal<>(pIso.composeTraversal(other.pTraversal)); } /** compose an {@link Iso} with a {@link Optional} */ public final Optional composeOptional(final Optional other) { - return asOptional().composeOptional(other); + return new Optional<>(pIso.composeOptional(other.pOptional)); } /** compose an {@link Iso} with a {@link Prism} */ public final Prism composePrism(final Prism other) { - return asPrism().composePrism(other); + return new Prism<>(pIso.composePrism(other.pPrism)); } /** compose an {@link Iso} with a {@link Lens} */ @@ -77,42 +73,7 @@ public final Lens composeLens(final Lens other) { /** compose an {@link Iso} with an {@link Iso} */ public final Iso composeIso(final Iso other) { - final Iso self = this; - return new Iso() { - - @Override - public C get(final S s) { - return other.get(self.get(s)); - } - - @Override - public S reverseGet(final C c) { - return self.reverseGet(other.reverseGet(c)); - } - - @Override - public Iso reverse() { - final Iso composeSelf = this; - return new Iso() { - - @Override - public S get(final C c) { - return self.reverseGet(other.reverseGet(c)); - } - - @Override - public C reverseGet(final S s) { - return other.get(self.get(s)); - } - - @Override - public Iso reverse() { - return composeSelf; - } - }; - } - - }; + return new Iso<>(pIso.composeIso(other.pIso)); } /****************************************************************/ @@ -122,306 +83,36 @@ public Iso reverse() { /** view an {@link Iso} as a {@link Setter} */ @Override public final Setter asSetter() { - final Iso self = this; - return new Setter() { - @Override - public F modify(final F f) { - return self.modify(f); - } - - @Override - public F set(final A a) { - return self.set(a); - } - }; + return new Setter<>(pIso.asSetter()); } /** view an {@link Iso} as a {@link Traversal} */ @Override public final Traversal asTraversal() { - final Iso self = this; - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return s -> f.f(self.get(s)); - } - - }; + return new Traversal<>(pIso.asTraversal()); } /** view an {@link Iso} as a {@link Optional} */ @Override public final Optional asOptional() { - final Iso self = this; - return new Optional() { - @Override - public Either getOrModify(final S s) { - return Either.right(self.get(s)); - } - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F set(final A b) { - return self.set(b); - } - - @Override - public Option getOption(final S s) { - return Option.some(self.get(s)); - } - - @Override - public F modify(final F f) { - return self.modify(f); - } - }; + return new Optional<>(pIso.asOptional()); } /** view an {@link Iso} as a {@link Prism} */ @Override public final Prism asPrism() { - final Iso self = this; - return new Prism() { - @Override - public Either getOrModify(final S s) { - return Either.right(self.get(s)); - } - - @Override - public S reverseGet(final A b) { - return self.reverseGet(b); - } - - @Override - public Option getOption(final S s) { - return Option.some(self.get(s)); - } - }; + return new Prism<>(pIso.asPrism()); } /** view an {@link Iso} as a {@link Lens} */ @Override public final Lens asLens() { - final Iso self = this; - return new Lens() { - @Override - public A get(final S s) { - return self.get(s); - } - - @Override - public F set(final A b) { - return self.set(b); - } - - @Override - public F modify(final F f) { - return self.modify(f); - } - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - }; + return new Lens<>(pIso.asLens()); } /** create an {@link Iso} using a pair of functions: one to get the target and one to get the source. */ public static Iso iso(final F get, final F reverseGet) { - return new Iso() { - - @Override - public A get(final S s) { - return get.f(s); - } - - @Override - public S reverseGet(final A a) { - return reverseGet.f(a); - } - - @Override - public Iso reverse() { - final Iso self = this; - return new Iso() { - @Override - public S get(final A a) { - return reverseGet.f(a); - } - - @Override - public A reverseGet(final S s) { - return get.f(s); - } - - @Override - public Iso reverse() { - return self; - } - - }; - } - }; + return new Iso<>(PIso.pIso(get, reverseGet)); } /** @@ -436,24 +127,7 @@ public Iso reverse() { * (replace composeO by composeLens, composeIso, composePrism, ...) */ public static Iso id() { - return new Iso() { - - @Override - public S get(final S s) { - return s; - } - - @Override - public S reverseGet(final S s) { - return s; - } - - @Override - public Iso reverse() { - return this; - } - - }; + return new Iso<>(PIso.pId()); } } diff --git a/core/src/main/java/fj/data/optic/Lens.java b/core/src/main/java/fj/data/optic/Lens.java index e89edb60..bb65952b 100644 --- a/core/src/main/java/fj/data/optic/Lens.java +++ b/core/src/main/java/fj/data/optic/Lens.java @@ -1,14 +1,11 @@ package fj.data.optic; import fj.F; -import fj.Function; -import fj.Monoid; import fj.P1; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.data.Either; import fj.data.IO; -import fj.data.IOFunctions; import fj.data.List; import fj.data.Option; import fj.data.Stream; @@ -18,17 +15,87 @@ /** * {@link PLens} with a monomorphic set function */ -public abstract class Lens extends PLens { +public final class Lens extends PLens { - Lens() { - super(); + final PLens pLens; + + public Lens(final PLens pLens) { + this.pLens = pLens; + } + + @Override + public A get(final S s) { + return pLens.get(s); + } + + @Override + public F set(final A a) { + return pLens.set(a); + } + + @Override + public F> modifyFunctionF(final F> f) { + return pLens.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return pLens.modifyEitherF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return pLens.modifyIOF(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return pLens.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return pLens.modifyPromiseF(f); + } + + @Override + public F> modifyListF(final F> f) { + return pLens.modifyListF(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return pLens.modifyOptionF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return pLens.modifyStreamF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return pLens.modifyP1F(f); + } + + @Override + public F> modifyValidationF(final F> f) { + return pLens.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return pLens.modifyV2F(f); + } + + @Override + public F modify(final F f) { + return pLens.modify(f); } /** join two {@link Lens} with the same target */ public final Lens, A> sum(final Lens other) { - return lens( - e -> e.either(this::get, other::get), - b -> e -> e.bimap(Lens.this.set(b), other.set(b))); + return new Lens<>(pLens.sum(other.pLens)); } /**********************************************************/ @@ -39,105 +106,34 @@ public final Lens, A> sum(final Lens other) { * compose a {@link Lens} with a {@link Setter} */ public final Setter composeSetter(final Setter other) { - return asSetter().composeSetter(other); + return new Setter<>(pLens.composeSetter(other.pSetter)); } /** * compose a {@link Lens} with a {@link Traversal} */ public final Traversal composeTraversal(final Traversal other) { - return asTraversal().composeTraversal(other); + return new Traversal<>(pLens.composeTraversal(other.pTraversal)); } /** compose a {@link Lens} with an {@link Optional} */ public final Optional composeOptional(final Optional other) { - return asOptional().composeOptional(other); + return new Optional<>(pLens.composeOptional(other.pOptional)); } /** compose a {@link Lens} with a {@link Prism} */ public final Optional composePrism(final Prism other) { - return asOptional().composeOptional(other.asOptional()); + return new Optional<>(pLens.composePrism(other.pPrism)); } /** compose a {@link Lens} with a {@link Lens} */ public final Lens composeLens(final Lens other) { - final Lens self = this; - return new Lens() { - @Override - public C get(final S s) { - return other.get(self.get(s)); - } - - @Override - public F set(final C d) { - return self.modify(other.set(d)); - } - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(other.modifyFunctionF(f)); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(other.modifyEitherF(f)); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(other.modifyIOF(f)); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(other.modifyTrampolineF(f)); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(other.modifyPromiseF(f)); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(other.modifyListF(f)); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(other.modifyOptionF(f)); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(other.modifyStreamF(f)); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(other.modifyP1F(f)); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(other.modifyValidationF(f)); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(other.modifyV2F(f)); - } - - @Override - public F modify(final F f) { - return self.modify(other.modify(f)); - } - }; + return new Lens<>(pLens.composeLens(other.pLens)); } /** compose a {@link Lens} with an {@link Iso} */ public final Lens composeIso(final Iso other) { - return composeLens(other.asLens()); + return new Lens<>(pLens.composeIso(other.pIso)); } /****************************************************************/ @@ -147,249 +143,30 @@ public final Lens composeIso(final Iso other) { /** view a {@link Lens} as a {@link Setter} */ @Override public Setter asSetter() { - return new Setter() { - @Override - public F modify(final F f) { - return Lens.this.modify(f); - } - - @Override - public F set(final A b) { - return Lens.this.set(b); - } - }; + return new Setter<>(pLens.asSetter()); } /** view a {@link Lens} as a {@link Traversal} */ @Override public final Traversal asTraversal() { - final Lens self = this; - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return s -> f.f(get(s)); - } - - }; + return new Traversal<>(pLens.asTraversal()); } /** view a {@link Lens} as an {@link Optional} */ @Override public final Optional asOptional() { - final Lens self = this; - return new Optional() { - @Override - public Either getOrModify(final S s) { - return Either.right(self.get(s)); - } - - @Override - public F set(final A b) { - return self.set(b); - } - - @Override - public Option getOption(final S s) { - return Option.some(self.get(s)); - } - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F modify(final F f) { - return self.modify(f); - } - }; + return new Optional<>(pLens.asOptional()); } public static final Lens id() { - return Iso. id().asLens(); + return new Lens<>(PLens.pId()); } /** * create a {@link Lens} using a pair of functions: one to get the target, one to set the target. */ public static Lens lens(final F get, final F> set) { - return new Lens() { - - @Override - public A get(final S s) { - return get.f(s); - } - - @Override - public F set(final A b) { - return set.f(b); - } - - @Override - public F> modifyFunctionF(final F> f) { - return s -> Function.compose(b -> set.f(b).f(s), f.f(get(s))); - } - - @Override - public F> modifyEitherF(final F> f) { - return s -> f.f(get.f(s)).right().map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyIOF(final F> f) { - return s -> IOFunctions.map(f.f(get.f(s)), a -> set.f(a).f(s)); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyPromiseF(final F> f) { - return s -> f.f(get.f(s)).fmap(a -> set.f(a).f(s)); - } - - @Override - public F> modifyListF(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyOptionF(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyStreamF(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyP1F(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyValidationF(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F> modifyV2F(final F> f) { - return s -> f.f(get.f(s)).map(a -> set.f(a).f(s)); - } - - @Override - public F modify(final F f) { - return s -> set(f.f(get.f(s))).f(s); - } - }; + return new Lens<>(PLens.pLens(get, set)); } + } \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index 02da3cd4..a699a063 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -1,17 +1,12 @@ package fj.data.optic; import fj.F; -import fj.Function; -import fj.Monoid; -import fj.P; import fj.P1; import fj.P2; import fj.control.Trampoline; import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; import fj.data.Either; import fj.data.IO; -import fj.data.IOFunctions; import fj.data.List; import fj.data.Option; import fj.data.Stream; @@ -19,31 +14,102 @@ import fj.data.vector.V2; /** {@link POptional} restricted to monomorphic update */ -public abstract class Optional extends POptional { +public final class Optional extends POptional { - Optional() { - super(); + final POptional pOptional; + + public Optional(final POptional pOptional) { + this.pOptional = pOptional; + } + + @Override + public F set(final A a) { + return pOptional.set(a); + } + + @Override + public F> modifyValidationF(final F> f) { + return pOptional.modifyValidationF(f); + } + + @Override + public F> modifyV2F(final F> f) { + return pOptional.modifyV2F(f); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return pOptional.modifyTrampolineF(f); + } + + @Override + public F> modifyStreamF(final F> f) { + return pOptional.modifyStreamF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return pOptional.modifyPromiseF(f); + } + + @Override + public F> modifyP1F(final F> f) { + return pOptional.modifyP1F(f); + } + + @Override + public F> modifyOptionF(final F> f) { + return pOptional.modifyOptionF(f); + } + + @Override + public F> modifyListF(final F> f) { + return pOptional.modifyListF(f); + } + + @Override + public F> modifyIOF(final F> f) { + return pOptional.modifyIOF(f); + } + + @Override + public F> modifyFunctionF(final F> f) { + return pOptional.modifyFunctionF(f); + } + + @Override + public F> modifyEitherF(final F> f) { + return pOptional.modifyEitherF(f); + } + + @Override + public F modify(final F f) { + return pOptional.modify(f); + } + + @Override + public Either getOrModify(final S s) { + return pOptional.getOrModify(s); + } + + @Override + public Option getOption(final S s) { + return pOptional.getOption(s); } /** join two {@link Optional} with the same target */ public final Optional, A> sum(final Optional other) { - return optional( - e -> e.either(s -> getOrModify(s).left().map(Either.left_()), s1 -> other.getOrModify(s1).left().map(Either.right_())), - b -> e -> e.bimap(set(b), other.set(b))); + return new Optional<>(pOptional.sum(other.pOptional)); } @Override public final Optional, P2> first() { - return optional( - sc -> getOrModify(sc._1()).bimap(t -> P.p(t, sc._2()), a -> P.p(a, sc._2())), - bc -> s_ -> P.p(set(bc._1()).f(s_._1()), bc._2())); + return new Optional<>(pOptional.first()); } @Override public final Optional, P2> second() { - return optional( - cs -> getOrModify(cs._2()).bimap(t -> P.p(cs._1(), t), a -> P.p(cs._1(), a)), - cb -> _s -> P.p(cb._1(), set(cb._2()).f(_s._2()))); + return new Optional<>(pOptional.second()); } /**************************************************************/ @@ -52,110 +118,32 @@ public final Optional, P2> second() { /** compose a {@link Optional} with a {@link Setter} */ public final Setter composeSetter(final Setter other) { - return asSetter().composeSetter(other); + return new Setter<>(pOptional.composeSetter(other.pSetter)); } /** compose a {@link Optional} with a {@link Traversal} */ public final Traversal composeTraversal(final Traversal other) { - return asTraversal().composeTraversal(other); + return new Traversal<>(pOptional.composeTraversal(other.pTraversal)); } /** compose a {@link Optional} with a {@link Optional} */ public final Optional composeOptional(final Optional other) { - final Optional self = this; - return new Optional() { - - @Override - public Either getOrModify(final S s) { - return self.getOrModify(s).right() - .bind(a -> other.getOrModify(a).bimap(b -> Optional.this.set(b).f(s), Function.identity())); - } - - @Override - public F set(final C d) { - return self.modify(other.set(d)); - } - - @Override - public Option getOption(final S s) { - return self.getOption(s).bind(other::getOption); - } - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(other.modifyFunctionF(f)); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(other.modifyEitherF(f)); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(other.modifyIOF(f)); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(other.modifyTrampolineF(f)); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(other.modifyPromiseF(f)); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(other.modifyListF(f)); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(other.modifyOptionF(f)); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(other.modifyStreamF(f)); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(other.modifyP1F(f)); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(other.modifyValidationF(f)); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(other.modifyV2F(f)); - } - - @Override - public F modify(final F f) { - return self.modify(other.modify(f)); - } - }; + return new Optional<>(pOptional.composeOptional(other.pOptional)); } /** compose a {@link Optional} with a {@link Prism} */ public final Optional composePrism(final Prism other) { - return composeOptional(other.asOptional()); + return new Optional<>(pOptional.composePrism(other.pPrism)); } /** compose a {@link Optional} with a {@link Lens} */ public final Optional composeLens(final Lens other) { - return composeOptional(other.asOptional()); + return new Optional<>(pOptional.composeLens(other.pLens)); } /** compose a {@link Optional} with an {@link Iso} */ public final Optional composeIso(final Iso other) { - return composeOptional(other.asOptional()); + return new Optional<>(pOptional.composeIso(other.pIso)); } /********************************************************************/ @@ -165,202 +153,22 @@ public final Optional composeIso(final Iso other) { /** view a {@link Optional} as a {@link Setter} */ @Override public final Setter asSetter() { - return new Setter() { - @Override - public F modify(final F f) { - return Optional.this.modify(f); - } - - @Override - public F set(final A b) { - return Optional.this.set(b); - } - }; + return new Setter<>(pOptional.asSetter()); } /** view a {@link Optional} as a {@link Traversal} */ @Override public final Traversal asTraversal() { - final Optional self = this; - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return s -> self.getOption(s).map(f).orSome(monoid.zero()); - } - }; + return new Traversal<>(pOptional.asTraversal()); } public static Optional id() { - return Iso. id().asOptional(); + return new Optional<>(POptional.pId()); } /** create a {@link Optional} using the canonical functions: getOrModify and set */ public static final Optional optional(final F> getOrModify, final F> set) { - return new Optional() { - @Override - public Either getOrModify(final S s) { - return getOrModify.f(s); - } - - @Override - public F set(final A b) { - return set.f(b); - } - - @Override - public Option getOption(final S s) { - return getOrModify.f(s).right().toOption(); - } - - @Override - public F> modifyFunctionF(final F> f) { - return s -> getOrModify(s).either( - Function.constant(), - a -> Function.compose(b -> set(b).f(s), f.f(a)) - ); - } - - @Override - public F> modifyEitherF(final F> f) { - return s -> getOrModify(s).either( - Either.right_(), - t -> f.f(t).right().map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyIOF(final F> f) { - return s -> getOrModify(s).either( - IOFunctions::unit, - t -> IOFunctions. map(f.f(t), b -> set(b).f(s)) - ); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return s -> getOrModify(s).either( - Trampoline.pure(), - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyPromiseF(final F> f) { - return s -> getOrModify(s).either( - t -> Promise.promise(Strategy.idStrategy(), P.p(t)), - t -> f.f(t).fmap(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyListF(final F> f) { - return s -> getOrModify(s).either( - List::single, - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyOptionF(final F> f) { - return s -> getOrModify(s).either( - Option.some_(), - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyStreamF(final F> f) { - return s -> getOrModify(s).either( - Stream.single(), - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyP1F(final F> f) { - return s -> getOrModify(s).either( - P.p1(), - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyValidationF(final F> f) { - return s -> getOrModify(s).either( - t -> Validation. success(t), - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F> modifyV2F(final F> f) { - return s -> getOrModify(s).either( - t -> V2.p(P.p(t, t)), - t -> f.f(t).map(b -> set(b).f(s)) - ); - } - - @Override - public F modify(final F f) { - return s -> getOrModify.f(s).either(Function.identity(), a -> set.f(f.f(a)).f(s)); - } - }; + return new Optional<>(POptional.pOptional(getOrModify, set)); } } diff --git a/core/src/main/java/fj/data/optic/Prism.java b/core/src/main/java/fj/data/optic/Prism.java index 04d2cb2c..82204c51 100644 --- a/core/src/main/java/fj/data/optic/Prism.java +++ b/core/src/main/java/fj/data/optic/Prism.java @@ -1,26 +1,33 @@ package fj.data.optic; import fj.F; -import fj.Function; -import fj.Monoid; -import fj.P1; -import fj.control.Trampoline; -import fj.control.parallel.Promise; import fj.data.Either; -import fj.data.IO; -import fj.data.List; import fj.data.Option; -import fj.data.Stream; -import fj.data.Validation; -import fj.data.vector.V2; /** * {@link PPrism} restricted to monomorphic update */ -public abstract class Prism extends PPrism { +public final class Prism extends PPrism { - Prism() { - super(); + final PPrism pPrism; + + public Prism(final PPrism pPrism) { + this.pPrism = pPrism; + } + + @Override + public Either getOrModify(final S s) { + return pPrism.getOrModify(s); + } + + @Override + public S reverseGet(final A a) { + return pPrism.reverseGet(a); + } + + @Override + public Option getOption(final S s) { + return pPrism.getOption(s); } /***********************************************************/ @@ -29,49 +36,32 @@ public abstract class Prism extends PPrism { /** compose a {@link Prism} with a {@link Setter} */ public final Setter composeSetter(final Setter other) { - return asSetter().composeSetter(other); + return new Setter<>(pPrism.composeSetter(other.pSetter)); } /** compose a {@link Prism} with a {@link Traversal} */ public final Traversal composeTraversal(final Traversal other) { - return asTraversal().composeTraversal(other); + return new Traversal<>(pPrism.composeTraversal(other.pTraversal)); } /** compose a {@link Prism} with a {@link Optional} */ public final Optional composeOptional(final Optional other) { - return asOptional().composeOptional(other); + return new Optional<>(pPrism.composeOptional(other.pOptional)); } /** compose a {@link Prism} with a {@link Lens} */ public final Optional composeLens(final Lens other) { - return asOptional().composeOptional(other.asOptional()); + return new Optional<>(pPrism.composeLens(other.pLens)); } /** compose a {@link Prism} with a {@link Prism} */ public final Prism composePrism(final Prism other) { - return new Prism() { - - @Override - public Either getOrModify(final S s) { - return Prism.this.getOrModify(s).right() - .bind(a -> other.getOrModify(a).bimap(b -> Prism.this.set(b).f(s), Function.identity())); - } - - @Override - public S reverseGet(final C d) { - return Prism.this.reverseGet(other.reverseGet(d)); - } - - @Override - public Option getOption(final S s) { - return Prism.this.getOption(s).bind(other::getOption); - } - }; + return new Prism<>(pPrism.composePrism(other.pPrism)); } /** compose a {@link Prism} with an {@link Iso} */ public final Prism composeIso(final Iso other) { - return composePrism(other.asPrism()); + return new Prism<>(pPrism.composeIso(other.pIso)); } /*****************************************************************/ @@ -81,195 +71,28 @@ public final Prism composeIso(final Iso other) { /** view a {@link Prism} as a {@link Setter} */ @Override public final Setter asSetter() { - return new Setter() { - @Override - public F modify(final F f) { - return Prism.this.modify(f); - } - - @Override - public F set(final A b) { - return Prism.this.set(b); - } - }; + return new Setter<>(pPrism.asSetter()); } /** view a {@link Prism} as a {@link Traversal} */ @Override public final Traversal asTraversal() { - final Prism self = this; - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return s -> getOption(s).map(f).orSome(monoid.zero()); - } - - }; + return new Traversal<>(pPrism.asTraversal()); } /** view a {@link Prism} as a {@link Optional} */ @Override public final Optional asOptional() { - final Prism self = this; - return new Optional() { - - @Override - public Either getOrModify(final S s) { - return self.getOrModify(s); - } - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(f); - } - - @Override - public F set(final A b) { - return self.set(b); - } - - @Override - public Option getOption(final S s) { - return self.getOption(s); - } - - @Override - public F modify(final F f) { - return self.modify(f); - } - - }; + return new Optional<>(pPrism.asOptional()); } public static Prism id() { - return Iso. id().asPrism(); + return new Prism<>(PPrism.pId()); } /** create a {@link Prism} using the canonical functions: getOrModify and reverseGet */ public static Prism prism(final F> getOrModify, final F reverseGet) { - return new Prism() { - - @Override - public Either getOrModify(final S s) { - return getOrModify.f(s); - } - - @Override - public S reverseGet(final A b) { - return reverseGet.f(b); - } - - @Override - public Option getOption(final S s) { - return getOrModify.f(s).right().toOption(); - } - }; + return new Prism<>(PPrism.pPrism(getOrModify, reverseGet)); } } \ No newline at end of file diff --git a/core/src/main/java/fj/data/optic/Setter.java b/core/src/main/java/fj/data/optic/Setter.java index 184ee289..40fc8473 100644 --- a/core/src/main/java/fj/data/optic/Setter.java +++ b/core/src/main/java/fj/data/optic/Setter.java @@ -4,15 +4,27 @@ import fj.data.Either; /** {@link PSetter} with a monomorphic modify function */ -public abstract class Setter extends PSetter { +public final class Setter extends PSetter { - Setter() { - super(); + final PSetter pSetter; + + public Setter(final PSetter pSetter) { + this.pSetter = pSetter; + } + + @Override + public F modify(final F f) { + return pSetter.modify(f); + } + + @Override + public F set(final A b) { + return pSetter.set(b); } /** join two {@link Setter} with the same target */ public final Setter, A> sum(final Setter other) { - return setter(f -> e -> e.bimap(modify(f), other.modify(f))); + return new Setter<>(pSetter.sum(other.pSetter)); } /************************************************************/ @@ -21,51 +33,29 @@ public final Setter, A> sum(final Setter other) { /** compose a {@link Setter} with a {@link Setter} */ public final Setter composeSetter(final Setter other) { - final Setter self = this; - return new Setter() { - - @Override - public F modify(final F f) { - return self.modify(other.modify(f)); - } - - @Override - public F set(final C c) { - return self.modify(other.set(c)); - } - }; + return new Setter<>(pSetter.composeSetter(other.pSetter)); } /** compose a {@link Setter} with a {@link Traversal} */ public final Setter composeTraversal(final Traversal other) { - return composeSetter(other.asSetter()); + return new Setter<>(pSetter.composeTraversal(other.pTraversal)); } /** compose a {@link Setter} with an {@link Iso} */ public final Setter composeIso(final Iso other) { - return composeSetter(other.asSetter()); + return new Setter<>(pSetter.composeIso(other.pIso)); } public static Setter id() { - return Iso. id().asSetter(); + return new Setter<>(PSetter.pId()); } public static final Setter, S> codiagonal() { - return setter(f -> e -> e.bimap(f, f)); + return new Setter<>(PSetter.pCodiagonal()); } /** alias for {@link PSetter} constructor with a monomorphic modify function */ public static final Setter setter(final F, F> modify) { - return new Setter() { - @Override - public F modify(final F f) { - return modify.f(f); - } - - @Override - public F set(final A a) { - return modify(__ -> a); - } - }; + return new Setter<>(PSetter.pSetter(modify)); } } diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java index e3529d1e..03503cf4 100644 --- a/core/src/main/java/fj/data/optic/Traversal.java +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -6,124 +6,89 @@ import fj.F4; import fj.F5; import fj.F6; -import fj.Function; import fj.Monoid; import fj.P1; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.data.Either; import fj.data.IO; -import fj.data.IOFunctions; import fj.data.List; import fj.data.Option; import fj.data.Stream; import fj.data.Validation; import fj.data.vector.V2; -public abstract class Traversal extends PTraversal { +public final class Traversal extends PTraversal { - /** join two {@link Traversal} with the same target */ - public final Traversal, A> sum(final Traversal other) { - final Traversal self = this; - return new Traversal, A>() { + final PTraversal pTraversal; - @Override - public F, F>> modifyFunctionF(final F> f) { - return ss1 -> ss1.either( - s -> Function.compose(Either.left_(), self.modifyFunctionF(f).f(s)), - s1 -> Function.compose(Either.right_(), other.modifyFunctionF(f).f(s1)) - ); - } + public Traversal(final PTraversal pTraversal) { + this.pTraversal = pTraversal; + } - @Override - public F, Either>> modifyEitherF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyEitherF(f).f(s).right().map(Either.left_()), - s1 -> other.modifyEitherF(f).f(s1).right().map(Either.right_()) - ); - } + @Override + public F> modifyFunctionF(final F> f) { + return pTraversal.modifyFunctionF(f); + } - @Override - public F, IO>> modifyIOF(final F> f) { - return ss1 -> ss1.either( - s -> IOFunctions.map(self.modifyIOF(f).f(s), Either.left_()), - s1 -> IOFunctions.map(other.modifyIOF(f).f(s1), Either.right_()) - ); - } + @Override + public F> modifyEitherF(final F> f) { + return pTraversal.modifyEitherF(f); + } - @Override - public F, Trampoline>> modifyTrampolineF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyTrampolineF(f).f(s).map(Either.left_()), - s1 -> other.modifyTrampolineF(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyIOF(final F> f) { + return pTraversal.modifyIOF(f); + } - @Override - public F, Promise>> modifyPromiseF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyPromiseF(f).f(s).fmap(Either.left_()), - s1 -> other.modifyPromiseF(f).f(s1).fmap(Either.right_()) - ); - } + @Override + public F> modifyTrampolineF(final F> f) { + return pTraversal.modifyTrampolineF(f); + } + + @Override + public F> modifyPromiseF(final F> f) { + return pTraversal.modifyPromiseF(f); + } - @Override - public F, List>> modifyListF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyListF(f).f(s).map(Either.left_()), - s1 -> other.modifyListF(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyListF(final F> f) { + return pTraversal.modifyListF(f); + } - @Override - public F, Option>> modifyOptionF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyOptionF(f).f(s).map(Either.left_()), - s1 -> other.modifyOptionF(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyOptionF(final F> f) { + return pTraversal.modifyOptionF(f); + } - @Override - public F, Stream>> modifyStreamF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyStreamF(f).f(s).map(Either.left_()), - s1 -> other.modifyStreamF(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyStreamF(final F> f) { + return pTraversal.modifyStreamF(f); + } - @Override - public F, P1>> modifyP1F(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyP1F(f).f(s).map(Either.left_()), - s1 -> other.modifyP1F(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyP1F(final F> f) { + return pTraversal.modifyP1F(f); + } - @Override - public F, V2>> modifyV2F(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyV2F(f).f(s).map(Either.left_()), - s1 -> other.modifyV2F(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyValidationF(final F> f) { + return pTraversal.modifyValidationF(f); + } - @Override - public F, Validation>> modifyValidationF(final F> f) { - return ss1 -> ss1.either( - s -> self.modifyValidationF(f).f(s).map(Either.left_()), - s1 -> other.modifyValidationF(f).f(s1).map(Either.right_()) - ); - } + @Override + public F> modifyV2F(final F> f) { + return pTraversal.modifyV2F(f); + } - @Override - public F, M> foldMap(final Monoid monoid, final F f) { - return ss1 -> ss1.either( - self.foldMap(monoid, f), - other.foldMap(monoid, f) - ); - } + @Override + public F foldMap(final Monoid monoid, final F f) { + return pTraversal.foldMap(monoid, f); + } - }; + /** join two {@link Traversal} with the same target */ + public final Traversal, A> sum(final Traversal other) { + return new Traversal<>(pTraversal.sum(other.pTraversal)); } /***************************************************************/ @@ -132,74 +97,12 @@ public F, M> foldMap(final Monoid monoid, final F f) /** compose a {@link Traversal} with a {@link Setter} */ public final Setter composeSetter(final Setter other) { - return asSetter().composeSetter(other); + return new Setter<>(pTraversal.composeSetter(other.pSetter)); } /** compose a {@link Traversal} with a {@link Traversal} */ public final Traversal composeTraversal(final Traversal other) { - final Traversal self = this; - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return self.modifyFunctionF(other.modifyFunctionF(f)); - } - - @Override - public F> modifyEitherF(final F> f) { - return self.modifyEitherF(other.modifyEitherF(f)); - } - - @Override - public F> modifyIOF(final F> f) { - return self.modifyIOF(other.modifyIOF(f)); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return self.modifyTrampolineF(other.modifyTrampolineF(f)); - } - - @Override - public F> modifyPromiseF(final F> f) { - return self.modifyPromiseF(other.modifyPromiseF(f)); - } - - @Override - public F> modifyListF(final F> f) { - return self.modifyListF(other.modifyListF(f)); - } - - @Override - public F> modifyOptionF(final F> f) { - return self.modifyOptionF(other.modifyOptionF(f)); - } - - @Override - public F> modifyStreamF(final F> f) { - return self.modifyStreamF(other.modifyStreamF(f)); - } - - @Override - public F> modifyP1F(final F> f) { - return self.modifyP1F(other.modifyP1F(f)); - } - - @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(other.modifyValidationF(f)); - } - - @Override - public F> modifyV2F(final F> f) { - return self.modifyV2F(other.modifyV2F(f)); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return self.foldMap(monoid, other.foldMap(monoid, f)); - } - }; + return new Traversal<>(pTraversal.composeTraversal(other.pTraversal)); } /*********************************************************************/ @@ -209,202 +112,43 @@ public F foldMap(final Monoid monoid, final F f) { /** view a {@link Traversal} as a {@link Setter} */ @Override public final Setter asSetter() { - return Setter.setter(this::modify); + return new Setter<>(pTraversal.asSetter()); } public static Traversal id() { - return Iso. id().asTraversal(); + return new Traversal<>(PTraversal.pId()); } public static Traversal, S> codiagonal() { - return new Traversal, S>() { - - @Override - public F, F>> modifyFunctionF(final F> f) { - return s -> s.bimap(f, f).either( - f1 -> Function.compose(Either.left_(), f1), - f1 -> Function.compose(Either.right_(), f1) - ); - } - - @Override - public F, Either>> modifyEitherF(final F> f) { - return s -> s.bimap(f, f).either( - e -> e.right().map(Either.left_()), - e -> e.right().map(Either.right_()) - ); - } - - @Override - public F, IO>> modifyIOF(final F> f) { - return s -> s.bimap(f, f).either( - io -> IOFunctions.map(io, Either.left_()), - io -> IOFunctions.map(io, Either.right_()) - ); - } - - @Override - public F, Trampoline>> modifyTrampolineF(final F> f) { - return s -> s.bimap(f, f).either( - t -> t.map(Either.left_()), - t -> t.map(Either.right_()) - ); - } - - @Override - public F, Promise>> modifyPromiseF(final F> f) { - return s -> s.bimap(f, f).either( - p -> p.fmap(Either.left_()), - p -> p.fmap(Either.right_()) - ); - } - - @Override - public F, List>> modifyListF(final F> f) { - return s -> s.bimap(f, f).either( - l -> l.map(Either.left_()), - l -> l.map(Either.right_()) - ); - } - - @Override - public F, Option>> modifyOptionF(final F> f) { - return s -> s.bimap(f, f).either( - o -> o.map(Either.left_()), - o -> o.map(Either.right_()) - ); - } - - @Override - public F, Stream>> modifyStreamF(final F> f) { - return s -> s.bimap(f, f).either( - stream -> stream.map(Either.left_()), - stream -> stream.map(Either.right_()) - ); - } - - @Override - public F, P1>> modifyP1F(final F> f) { - return s -> s.bimap(f, f).either( - p1 -> p1.map(Either.left_()), - p1 -> p1.map(Either.right_()) - ); - } - - @Override - public F, V2>> modifyV2F(final F> f) { - return s -> s.bimap(f, f).either( - v2 -> v2.map(Either.left_()), - v2 -> v2.map(Either.right_()) - ); - } - - @Override - public F, Validation>> modifyValidationF(final F> f) { - return s -> s.bimap(f, f).either( - v -> v.map(Either.left_()), - v -> v.map(Either.right_()) - ); - } - - @Override - public F, M> foldMap(final Monoid monoid, final F f) { - return s -> s.either(f, f); - } - }; - } - - public static Traversal fromPtraversal(final PTraversal pTraversal) { - return new Traversal() { - - @Override - public F> modifyFunctionF(final F> f) { - return pTraversal.modifyFunctionF(f); - } - - @Override - public F> modifyEitherF(final F> f) { - return pTraversal.modifyEitherF(f); - } - - @Override - public F> modifyIOF(final F> f) { - return pTraversal.modifyIOF(f); - } - - @Override - public F> modifyTrampolineF(final F> f) { - return pTraversal.modifyTrampolineF(f); - } - - @Override - public F> modifyPromiseF(final F> f) { - return pTraversal.modifyPromiseF(f); - } - - @Override - public F> modifyListF(final F> f) { - return pTraversal.modifyListF(f); - } - - @Override - public F> modifyOptionF(final F> f) { - return pTraversal.modifyOptionF(f); - } - - @Override - public F> modifyStreamF(final F> f) { - return pTraversal.modifyStreamF(f); - } - - @Override - public F> modifyP1F(final F> f) { - return pTraversal.modifyP1F(f); - } - - @Override - public F> modifyValidationF(final F> f) { - return pTraversal.modifyValidationF(f); - } - - @Override - public F> modifyV2F(final F> f) { - return pTraversal.modifyV2F(f); - } - - @Override - public F foldMap(final Monoid monoid, final F f) { - return pTraversal.foldMap(monoid, f); - } - }; + return new Traversal<>(PTraversal.pCodiagonal()); } public static Traversal traversal(final F get1, final F get2, final F2 set) { - return fromPtraversal(PTraversal.pTraversal(get1, get2, (a1, a2, s) -> set.f(a1, a2))); + return new Traversal<>(PTraversal.pTraversal(get1, get2, (a1, a2, s) -> set.f(a1, a2))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F3 set) { - return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, (a1, a2, a3, s) -> set.f(a1, a2, a3))); + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, (a1, a2, a3, s) -> set.f(a1, a2, a3))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F get4, final F4 set) { - return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, get4, (a1, a2, a3, a4, s) -> set.f(a1, a2, a3, a4))); + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, (a1, a2, a3, a4, s) -> set.f(a1, a2, a3, a4))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F get4, final F get5, final F5 set) { - return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, get4, get5, + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, (a1, a2, a3, a4, a5, s) -> set.f(a1, a2, a3, a4, a5))); } public static Traversal traversal(final F get1, final F get2, final F get3, final F get4, final F get5, final F get6, final F6 set) { - return fromPtraversal(PTraversal.pTraversal(get1, get2, get3, get4, get5, get6, + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, get6, (a1, a2, a3, a4, a5, a6, s) -> set.f(a1, a2, a3, a4, a5, a6))); } From 84642e0de34276b76005e493003ca58e5d909771 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 10 May 2015 09:12:26 +0200 Subject: [PATCH 277/811] Added identity on Fold and Getter --- core/src/main/java/fj/data/optic/Fold.java | 4 ++++ core/src/main/java/fj/data/optic/Getter.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/core/src/main/java/fj/data/optic/Fold.java b/core/src/main/java/fj/data/optic/Fold.java index 7f177a5b..8a8d417f 100644 --- a/core/src/main/java/fj/data/optic/Fold.java +++ b/core/src/main/java/fj/data/optic/Fold.java @@ -106,6 +106,10 @@ public final Fold composeIso(final PIso other) { return composeFold(other.asFold()); } + public static Fold id() { + return PIso. pId().asFold(); + } + public static final Fold, A> codiagonal() { return new Fold, A>() { @Override diff --git a/core/src/main/java/fj/data/optic/Getter.java b/core/src/main/java/fj/data/optic/Getter.java index 89fd0bc9..b5c60d50 100644 --- a/core/src/main/java/fj/data/optic/Getter.java +++ b/core/src/main/java/fj/data/optic/Getter.java @@ -90,6 +90,10 @@ public F foldMap(final Monoid m, final F f) { }; } + public static Getter id() { + return PIso. pId().asGetter(); + } + public static final Getter, A> codiagonal() { return getter(e -> e.either(Function.identity(), Function.identity())); } From 6650342bd66780a311c58816e093d4a9f86cc9e5 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 10 May 2015 23:19:52 +0200 Subject: [PATCH 278/811] Help type inference for some old versions of jdk8. --- .../main/java/fj/data/optic/PTraversal.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index b40468cd..60fd1393 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -475,52 +475,53 @@ public F> modifyFunctionF(final F> f) { @Override public F> modifyEitherF(final F> f) { - return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).right().apply(f.f(get1.f(s)).right().> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyIOF(final F> f) { - return s -> IOFunctions.apply(f.f(get2.f(s)), IOFunctions.map(f.f(get1.f(s)), b1 -> b2 -> set.f(b1, b2, s))); + return s -> IOFunctions.apply(f.f(get2.f(s)), + IOFunctions.> map(f.f(get1.f(s)), b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyTrampolineF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyPromiseF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).fmap(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> fmap(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyListF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyOptionF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyStreamF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyP1F(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyV2F(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override public F> modifyValidationF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).map(b1 -> b2 -> set.f(b1, b2, s))); + return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override From 6bdd384099db12d8bee76b4162923567a63f5064 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 14 May 2015 15:41:13 +0200 Subject: [PATCH 279/811] Added optics laws in tests and configured tests module for publishing as it might be useful as a test dependency --- build.gradle | 4 +- tests/build.gradle | 12 ++++- .../{test => main}/scala/fj/ArbitraryP.scala | 0 .../control/parallel/ArbitraryParModule.scala | 0 .../control/parallel/ArbitraryStrategy.scala | 0 .../scala/fj/data/ArbitraryArray.scala | 0 .../scala/fj/data/ArbitraryHashMap.scala | 0 .../scala/fj/data/ArbitraryHashSet.scala | 0 .../scala/fj/data/ArbitraryList.scala | 0 .../scala/fj/data/ArbitraryOption.scala | 0 .../scala/fj/data/ArbitrarySet.scala | 0 .../scala/fj/data/ArbitraryStream.scala | 0 .../scala/fj/data/ArbitraryTree.scala | 0 .../scala/fj/data/ArbitraryTreeMap.scala | 0 .../main/scala/fj/data/optic/IsoLaws.scala | 32 +++++++++++++ .../main/scala/fj/data/optic/LensLaws.scala | 36 ++++++++++++++ .../scala/fj/data/optic/OptionalLaws.scala | 47 +++++++++++++++++++ .../main/scala/fj/data/optic/PrismLaws.scala | 44 +++++++++++++++++ .../main/scala/fj/data/optic/SetterLaws.scala | 25 ++++++++++ .../scala/fj/data/optic/TraversalLaws.scala | 42 +++++++++++++++++ .../src/{test => main}/scala/fj/package.scala | 0 21 files changed, 238 insertions(+), 4 deletions(-) rename tests/src/{test => main}/scala/fj/ArbitraryP.scala (100%) rename tests/src/{test => main}/scala/fj/control/parallel/ArbitraryParModule.scala (100%) rename tests/src/{test => main}/scala/fj/control/parallel/ArbitraryStrategy.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryArray.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryHashMap.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryHashSet.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryList.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryOption.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitrarySet.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryStream.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryTree.scala (100%) rename tests/src/{test => main}/scala/fj/data/ArbitraryTreeMap.scala (100%) create mode 100644 tests/src/main/scala/fj/data/optic/IsoLaws.scala create mode 100644 tests/src/main/scala/fj/data/optic/LensLaws.scala create mode 100644 tests/src/main/scala/fj/data/optic/OptionalLaws.scala create mode 100644 tests/src/main/scala/fj/data/optic/PrismLaws.scala create mode 100644 tests/src/main/scala/fj/data/optic/SetterLaws.scala create mode 100644 tests/src/main/scala/fj/data/optic/TraversalLaws.scala rename tests/src/{test => main}/scala/fj/package.scala (100%) diff --git a/build.gradle b/build.gradle index 853d2ea3..86020a73 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ subprojects { } } -configure(subprojects.findAll {it.name != 'tests'}) { +configure(subprojects) { apply plugin: "maven" apply plugin: "signing" @@ -146,4 +146,4 @@ task wrapper(type: Wrapper) { task env << { println System.getenv() -} \ No newline at end of file +} diff --git a/tests/build.gradle b/tests/build.gradle index 24902acb..e8c4c67b 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -1,10 +1,13 @@ +archivesBaseName = "${project.projectName}-${project.name}" + apply plugin: 'scala' ext { scalaVersion = "2.11.6" scalacheckScalaVersion = "2.11" scalacheckVersion = "1.12.2" + signModule = true } tasks.withType(ScalaCompile) { @@ -14,11 +17,16 @@ tasks.withType(ScalaCompile) { dependencies { compile project(":core") compile "org.scala-lang:scala-library:$scalaVersion" + compile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - testCompile "org.scala-lang:scala-library:$scalaVersion" - testCompile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" testCompile dependencyJunit } sourceCompatibility = "1.7" +performSigning(signingEnabled, signModule) +configureUpload(signingEnabled, signModule) + +uploadArchives.enabled = true + + diff --git a/tests/src/test/scala/fj/ArbitraryP.scala b/tests/src/main/scala/fj/ArbitraryP.scala similarity index 100% rename from tests/src/test/scala/fj/ArbitraryP.scala rename to tests/src/main/scala/fj/ArbitraryP.scala diff --git a/tests/src/test/scala/fj/control/parallel/ArbitraryParModule.scala b/tests/src/main/scala/fj/control/parallel/ArbitraryParModule.scala similarity index 100% rename from tests/src/test/scala/fj/control/parallel/ArbitraryParModule.scala rename to tests/src/main/scala/fj/control/parallel/ArbitraryParModule.scala diff --git a/tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala b/tests/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala similarity index 100% rename from tests/src/test/scala/fj/control/parallel/ArbitraryStrategy.scala rename to tests/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryArray.scala b/tests/src/main/scala/fj/data/ArbitraryArray.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryArray.scala rename to tests/src/main/scala/fj/data/ArbitraryArray.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryHashMap.scala b/tests/src/main/scala/fj/data/ArbitraryHashMap.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryHashMap.scala rename to tests/src/main/scala/fj/data/ArbitraryHashMap.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryHashSet.scala b/tests/src/main/scala/fj/data/ArbitraryHashSet.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryHashSet.scala rename to tests/src/main/scala/fj/data/ArbitraryHashSet.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryList.scala b/tests/src/main/scala/fj/data/ArbitraryList.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryList.scala rename to tests/src/main/scala/fj/data/ArbitraryList.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryOption.scala b/tests/src/main/scala/fj/data/ArbitraryOption.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryOption.scala rename to tests/src/main/scala/fj/data/ArbitraryOption.scala diff --git a/tests/src/test/scala/fj/data/ArbitrarySet.scala b/tests/src/main/scala/fj/data/ArbitrarySet.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitrarySet.scala rename to tests/src/main/scala/fj/data/ArbitrarySet.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryStream.scala b/tests/src/main/scala/fj/data/ArbitraryStream.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryStream.scala rename to tests/src/main/scala/fj/data/ArbitraryStream.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryTree.scala b/tests/src/main/scala/fj/data/ArbitraryTree.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryTree.scala rename to tests/src/main/scala/fj/data/ArbitraryTree.scala diff --git a/tests/src/test/scala/fj/data/ArbitraryTreeMap.scala b/tests/src/main/scala/fj/data/ArbitraryTreeMap.scala similarity index 100% rename from tests/src/test/scala/fj/data/ArbitraryTreeMap.scala rename to tests/src/main/scala/fj/data/ArbitraryTreeMap.scala diff --git a/tests/src/main/scala/fj/data/optic/IsoLaws.scala b/tests/src/main/scala/fj/data/optic/IsoLaws.scala new file mode 100644 index 00000000..a562bd75 --- /dev/null +++ b/tests/src/main/scala/fj/data/optic/IsoLaws.scala @@ -0,0 +1,32 @@ +package fj +package data.optic + +import org.scalacheck.Prop._ +import org.scalacheck.{ Arbitrary, Properties } +import P.p1 +import Function.identity + +object IsoLaws { + + def apply[S: Arbitrary, A: Arbitrary](iso: PIso[S, S, A, A])(implicit sEqual: Equal[S], aEqual: Equal[A]) = new Properties("Iso") { + + property("get and reverseGet forms an Isomorphism") = forAll { (s: S, a: A) => + sEqual.eq(iso.reverseGet(iso.get(s)), s) + aEqual.eq(iso.get(iso.reverseGet(a)), a) + } + + property("set is a weaker version of reverseGet") = forAll { (s: S, a: A) => + sEqual.eq(iso.set(a).f(s), iso.reverseGet(a)) + } + + property("modifyF with Id does not do anything") = forAll { s: S => + sEqual.eq(iso.modifyP1F(p1()).f(s)._1(), s) + } + + property("modify with id does not do anything") = forAll { s: S => + sEqual.eq(iso.modify(identity()).f(s), s) + } + + } + +} diff --git a/tests/src/main/scala/fj/data/optic/LensLaws.scala b/tests/src/main/scala/fj/data/optic/LensLaws.scala new file mode 100644 index 00000000..a1da1789 --- /dev/null +++ b/tests/src/main/scala/fj/data/optic/LensLaws.scala @@ -0,0 +1,36 @@ +package fj +package data.optic + +import org.scalacheck.Prop._ +import org.scalacheck.{ Arbitrary, Properties } +import P.p1 +import Function.identity + +object LensLaws { + + def apply[S: Arbitrary, A: Arbitrary](lens: PLens[S, S, A, A])(implicit sEqual: Equal[S], aEqual: Equal[A]) = new Properties("Lens") { + + property("setting what you get does not do anything") = forAll { s: S => + sEqual.eq(lens.set(lens.get(s)).f(s), s) + } + + property("you get what you set") = forAll { (s: S, a: A) => + aEqual.eq(lens.get(lens.set(a).f(s)), a) + } + + /** calling set twice is the same as calling set once */ + property("set is idempotent") = forAll { (s: S, a: A) => + sEqual.eq(lens.set(a).f(lens.set(a).f(s)), lens.set(a).f(s)) + } + + property("modifyF with Id does not do anything") = forAll { s: S => + sEqual.eq(lens.modifyP1F(p1()).f(s)._1(), s) + } + + property("modify with id does not do anything") = forAll { s: S => + sEqual.eq(lens.modify(identity()).f(s), s) + } + + } + +} diff --git a/tests/src/main/scala/fj/data/optic/OptionalLaws.scala b/tests/src/main/scala/fj/data/optic/OptionalLaws.scala new file mode 100644 index 00000000..094df990 --- /dev/null +++ b/tests/src/main/scala/fj/data/optic/OptionalLaws.scala @@ -0,0 +1,47 @@ +package fj +package data.optic + +import org.scalacheck.Prop._ +import org.scalacheck.{ Arbitrary, Properties } +import P.p1 +import Function.{identity, constant} +import Equal.optionEqual + +object OptionalLaws { + + def apply[S: Arbitrary, A: Arbitrary](optional: POptional[S, S, A, A])(implicit sEqual: Equal[S], aEqual: Equal[A]) = new Properties("Optional") { + + property("setting what you get does not do anything") = forAll { s: S => + sEqual.eq(optional.getOrModify(s).either(identity(), {a:A => optional.set(a).f(s)}), s) + } + + property("you get what you set") = forAll { (s: S, a: A) => + optionEqual(aEqual).eq(optional.getOption(optional.set(a).f(s)), optional.getOption(s).map(constant(a))) + } + + /** calling set twice is the same as calling set once */ + property("set is idempotent") = forAll { (s: S, a: A) => + sEqual.eq(optional.set(a).f(optional.set(a).f(s)), optional.set(a).f(s)) + } + + /** modifyF does not change the number of targets */ + property("modifyF with Id does not do anything") = forAll { s: S => + sEqual.eq(optional.modifyP1F(p1()).f(s)._1(), s) + } + + /** modify does not change the number of targets */ + property("modify with id does not do anything") = forAll { s: S => + sEqual.eq(optional.modify(identity()).f(s), s) + } + + property("setOption only succeeds when the Optional is matching") = forAll { (s: S, a: A) => + optionEqual(sEqual).eq(optional.setOption(a).f(s), optional.getOption(s).map(Function.constant(optional.set(a).f(s)))) + } + + property("modifyOption with id is isomorphomic to isMatching") = forAll { s: S => + optionEqual(sEqual).eq(optional.modifyOption(identity()).f(s), optional.getOption(s).map(constant(s))) + } + + } + +} diff --git a/tests/src/main/scala/fj/data/optic/PrismLaws.scala b/tests/src/main/scala/fj/data/optic/PrismLaws.scala new file mode 100644 index 00000000..075825cb --- /dev/null +++ b/tests/src/main/scala/fj/data/optic/PrismLaws.scala @@ -0,0 +1,44 @@ +package fj +package data +package optic + +import org.scalacheck.Prop._ +import org.scalacheck.{ Arbitrary, Properties } +import P.p1 +import Function.{identity, constant} +import Equal.optionEqual +import Option.some + +object PrismLaws { + + def apply[S: Arbitrary, A: Arbitrary](prism: PPrism[S, S, A, A])(implicit sEqual: Equal[S], aEqual: Equal[A]) = new Properties("Prism") { + + property("reverseGet produces a value") = forAll { a: A => + optionEqual(aEqual).eq(prism.getOption(prism.reverseGet(a)), some(a)) + } + + property("if a Prism match you can always go back to the source") = forAll { s: S => + sEqual.eq(prism.getOrModify(s).either(identity(), {a:A => prism.reverseGet(a)}), s) + } + + /** modifyF does not change the number of targets */ + property("modifyF with Id does not do anything") = forAll { s: S => + sEqual.eq(prism.modifyP1F(p1()).f(s)._1(), s) + } + + /** modify does not change the number of targets */ + property("modify with id does not do anything") = forAll { s: S => + sEqual.eq(prism.modify(identity()).f(s), s) + } + + property("setOption only succeeds when the prism is matching") = forAll { (s: S, a: A) => + optionEqual(sEqual).eq(prism.setOption(a).f(s), prism.getOption(s).map(constant(prism.set(a).f(s)))) + } + + property("modifyOption with id is isomorphomic to isMatching") = forAll { s: S => + optionEqual(sEqual).eq(prism.modifyOption(identity()).f(s), prism.getOption(s).map(constant(s))) + } + + } + +} diff --git a/tests/src/main/scala/fj/data/optic/SetterLaws.scala b/tests/src/main/scala/fj/data/optic/SetterLaws.scala new file mode 100644 index 00000000..764698ef --- /dev/null +++ b/tests/src/main/scala/fj/data/optic/SetterLaws.scala @@ -0,0 +1,25 @@ +package fj +package data +package optic + +import org.scalacheck.Prop._ +import org.scalacheck.{ Arbitrary, Properties } +import Function.identity + +object SetterLaws { + + def apply[S: Arbitrary, A: Arbitrary](setter: PSetter[S, S, A, A])(implicit sEqual: Equal[S]) = new Properties("Setter") { + + /** calling set twice is the same as calling set once */ + property("set is idempotent") = forAll { (s: S, a: A) => + sEqual.eq(setter.set(a).f(setter.set(a).f(s)), setter.set(a).f(s)) + } + + /** modify does not change the number of targets */ + property("modify preserves the structure") = forAll { s: S => + sEqual.eq(setter.modify(identity()).f(s), s) + } + + } + +} \ No newline at end of file diff --git a/tests/src/main/scala/fj/data/optic/TraversalLaws.scala b/tests/src/main/scala/fj/data/optic/TraversalLaws.scala new file mode 100644 index 00000000..2172db2c --- /dev/null +++ b/tests/src/main/scala/fj/data/optic/TraversalLaws.scala @@ -0,0 +1,42 @@ +package fj +package data +package optic + +import org.scalacheck.Prop._ +import org.scalacheck.{ Arbitrary, Properties } +import P.p1 +import Function.{identity, constant} +import Equal.{optionEqual, listEqual} +import Option.some + +object TraversalLaws { + + def apply[S: Arbitrary, A: Arbitrary](traversal: PTraversal[S, S, A, A])(implicit sEqual: Equal[S], aEqual: Equal[A]) = new Properties("Traversal") { + + /** set does not change the number of targets */ + property("you get what you set") = forAll { (s: S, a: A) => + listEqual(aEqual).eq(traversal.getAll(traversal.set(a).f(s)), traversal.getAll(s).map(constant(a))) + } + + /** calling set twice is the same as calling set once */ + property("set is idempotent") = forAll { (s: S, a: A) => + sEqual.eq(traversal.set(a).f(traversal.set(a).f(s)), traversal.set(a).f(s)) + } + + /** modifyF does not change the number of targets */ + property("modifyF preserves the structure") = forAll { s: S => + sEqual.eq(traversal.modifyP1F(p1()).f(s)._1(), s) + } + + /** modify does not change the number of targets */ + property("modify preserves the structure") = forAll { s: S => + sEqual.eq(traversal.modify(identity()).f(s), s) + } + + property("headMaybe returns the first element of getAll (if getAll is finite)") = forAll { s: S => + optionEqual(aEqual).eq(traversal.headOption(s), traversal.getAll(s).toOption()) + } + + } + +} diff --git a/tests/src/test/scala/fj/package.scala b/tests/src/main/scala/fj/package.scala similarity index 100% rename from tests/src/test/scala/fj/package.scala rename to tests/src/main/scala/fj/package.scala From 1bb00f18fb5cc73318a959eab61d4c742228e06b Mon Sep 17 00:00:00 2001 From: JB Giraudeau Date: Tue, 19 May 2015 20:59:31 +0200 Subject: [PATCH 280/811] Fixed #133 Effect.f(Effect0) now does not ignore its argument --- core/src/main/java/fj/Effect.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 884e7399..f7df707b 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -22,7 +22,10 @@ public class Effect { private Effect() {} public static P1 f(Effect0 e) { - return P.lazy(u -> unit()); + return P.lazy(() -> { + e.f(); + return unit(); + }); } /** From 35cdd652518ceccf1adbe6bb0ca9f9a631f1690e Mon Sep 17 00:00:00 2001 From: JB Giraudeau Date: Tue, 19 May 2015 21:29:20 +0200 Subject: [PATCH 281/811] Fixed #135: make Effect.comap static --- core/src/main/java/fj/Effect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index f7df707b..ef4cd547 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -95,7 +95,7 @@ public static F5 f(Effect5 z * @param f The function to map over the effect. * @return An effect after a contra-variant map. */ - public final Effect1 comap(Effect1 e1, final F f) { + public static final Effect1 comap(Effect1 e1, final F f) { return b -> e1.f(f.f(b)); } From 7a34deca69bf22483b579dc5ca04080978bf18b4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 19 May 2015 23:45:25 +0200 Subject: [PATCH 282/811] Replace P1 by F0 in method arguments of various API whenever it safe to do so without breaking source compatibility. This should improve overall support for java8 lambda syntax. --- core/src/main/java/fj/Effect.java | 2 +- core/src/main/java/fj/F1Functions.java | 4 +- core/src/main/java/fj/P.java | 242 ++++-------------- core/src/main/java/fj/P1.java | 12 +- core/src/main/java/fj/P2.java | 2 +- core/src/main/java/fj/P3.java | 2 +- core/src/main/java/fj/P4.java | 2 +- core/src/main/java/fj/P5.java | 2 +- core/src/main/java/fj/P6.java | 2 +- core/src/main/java/fj/P7.java | 2 +- core/src/main/java/fj/P8.java | 2 +- core/src/main/java/fj/Try.java | 2 +- core/src/main/java/fj/TryEffect.java | 2 +- core/src/main/java/fj/control/Trampoline.java | 8 +- .../java/fj/control/parallel/Callables.java | 9 +- .../java/fj/control/parallel/Promise.java | 2 +- .../java/fj/control/parallel/Strategy.java | 4 +- core/src/main/java/fj/data/Array.java | 11 +- core/src/main/java/fj/data/Either.java | 24 +- core/src/main/java/fj/data/IOFunctions.java | 14 +- core/src/main/java/fj/data/Iteratee.java | 147 +++-------- core/src/main/java/fj/data/Java.java | 2 +- core/src/main/java/fj/data/List.java | 16 +- core/src/main/java/fj/data/Option.java | 31 ++- core/src/main/java/fj/data/Seq.java | 2 +- core/src/main/java/fj/data/Set.java | 2 +- core/src/main/java/fj/data/Stream.java | 37 +-- core/src/main/java/fj/data/Tree.java | 2 +- core/src/main/java/fj/data/TreeMap.java | 2 +- core/src/main/java/fj/data/Validation.java | 10 +- core/src/main/java/fj/data/vector/V.java | 37 +-- core/src/main/java/fj/function/Visitor.java | 10 +- core/src/main/java/fj/parser/Parser.java | 66 ++--- core/src/main/java/fj/test/Bool.java | 3 +- core/src/main/java/fj/test/Property.java | 22 +- core/src/main/java/fj/test/Result.java | 6 +- core/src/main/java/fj/test/Shrink.java | 8 +- .../java/fj/test/reflect/CheckParams.java | 4 +- java8/src/main/java/fj/data/Java8.java | 35 +-- 39 files changed, 272 insertions(+), 520 deletions(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 884e7399..fbeaea6f 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -22,7 +22,7 @@ public class Effect { private Effect() {} public static P1 f(Effect0 e) { - return P.lazy(u -> unit()); + return P.lazy(() -> unit()); } /** diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index dc3b4378..6f0f4a07 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -128,7 +128,7 @@ static public F>, F>> on(final F f) { * @return This function promoted to return its result in a product-1. */ static public F> lazy(final F f) { - return a -> P.lazy(u -> f.f(a)); + return a -> P.lazy(() -> f.f(a)); } /** @@ -138,7 +138,7 @@ static public F> lazy(final F f) { * @return The function partially applied to the given argument to return a lazy value. */ static public P1 f(final F f, final A a) { - return P.lazy(u -> f.f(a)); + return P.lazy(() -> f.f(a)); } /** diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index d0e99bb4..789f1d34 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -44,192 +44,192 @@ public static P1 lazy(final P1 pa) { return pa; } - public static P2 lazy(final P1 pa, final P1 pb) { + public static P2 lazy(final F0 pa, final F0 pb) { return new P2() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } }; } - public static P3 lazy(final P1 pa, final P1 pb, final P1 pc) { + public static P3 lazy(final F0 pa, final F0 pb, final F0 pc) { return new P3() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } @Override public C _3() { - return pc._1(); + return pc.f(); } }; } - public static P4 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd) { + public static P4 lazy(final F0 pa, final F0 pb, final F0 pc, final F0 pd) { return new P4() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } @Override public C _3() { - return pc._1(); + return pc.f(); } @Override public D _4() { - return pd._1(); + return pd.f(); } }; } - public static P5 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe) { + public static P5 lazy(final F0 pa, final F0 pb, final F0 pc, final F0 pd, F0 pe) { return new P5() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } @Override public C _3() { - return pc._1(); + return pc.f(); } @Override public D _4() { - return pd._1(); + return pd.f(); } @Override public E _5() { - return pe._1(); + return pe.f(); } }; } - public static P6 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe, P1 pf) { + public static P6 lazy(final F0 pa, final F0 pb, final F0 pc, final F0 pd, F0 pe, F0 pf) { return new P6() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } @Override public C _3() { - return pc._1(); + return pc.f(); } @Override public D _4() { - return pd._1(); + return pd.f(); } @Override public E _5() { - return pe._1(); + return pe.f(); } @Override public F _6() { - return pf._1(); + return pf.f(); } }; } - public static P7 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe, P1 pf, P1 pg) { + public static P7 lazy(final F0 pa, final F0 pb, final F0 pc, final F0 pd, F0 pe, F0 pf, F0 pg) { return new P7() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } @Override public C _3() { - return pc._1(); + return pc.f(); } @Override public D _4() { - return pd._1(); + return pd.f(); } @Override public E _5() { - return pe._1(); + return pe.f(); } @Override public F _6() { - return pf._1(); + return pf.f(); } @Override public G _7() { - return pg._1(); + return pg.f(); } }; } - public static P8 lazy(final P1 pa, final P1 pb, final P1 pc, final P1 pd, P1 pe, P1 pf, P1 pg, P1 ph) { + public static P8 lazy(final F0 pa, final F0 pb, final F0 pc, final F0 pd, F0 pe, F0 pf, F0 pg, F0 ph) { return new P8() { @Override public A _1() { - return pa._1(); + return pa.f(); } @Override public B _2() { - return pb._1(); + return pb.f(); } @Override public C _3() { - return pc._1(); + return pc.f(); } @Override public D _4() { - return pd._1(); + return pd.f(); } @Override public E _5() { - return pe._1(); + return pe.f(); } @Override public F _6() { - return pf._1(); + return pf.f(); } @Override public G _7() { - return pg._1(); + return pg.f(); } @Override public H _8() { - return ph._1(); + return ph.f(); } }; } @@ -240,15 +240,7 @@ public H _8() { * @return A function that puts an element in a product-2. */ public static F>> p2() { - return new F>>() { - public F> f(final A a) { - return new F>() { - public P2 f(final B b) { - return p(a, b); - } - }; - } - }; + return a -> b -> p(a, b); } /** @@ -271,24 +263,12 @@ public B _2() { } /** - * A function that puts an element in a product-3. + * A function that puts elements in a product-3. * - * @return A function that puts an element in a product-3. + * @return A function that puts elements in a product-3. */ public static F>>> p3() { - return new F>>>() { - public F>> f(final A a) { - return new F>>() { - public F> f(final B b) { - return new F>() { - public P3 f(final C c) { - return p(a, b, c); - } - }; - } - }; - } - }; + return a -> b -> c -> p(a, b, c); } /** @@ -321,23 +301,7 @@ public C _3() { * @return A function that puts an element in a product-4. */ public static F>>>> p4() { - return new F>>>>() { - public F>>> f(final A a) { - return new F>>>() { - public F>> f(final B b) { - return new F>>() { - public F> f(final C c) { - return new F>() { - public P4 f(final D d) { - return p(a, b, c, d); - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> p(a, b, c, d); } /** @@ -375,27 +339,7 @@ public D _4() { * @return A function that puts an element in a product-5. */ public static F>>>>> p5() { - return new F>>>>>() { - public F>>>> f(final A a) { - return new F>>>>() { - public F>>> f(final B b) { - return new F>>>() { - public F>> f(final C c) { - return new F>>() { - public F> f(final D d) { - return new F>() { - public P5 f(final E e) { - return p(a, b, c, d, e); - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> p(a, b, c, d, e); } /** @@ -438,31 +382,7 @@ public E _5() { * @return A function that puts an element in a product-6. */ public static F>>>>>> p6() { - return new F>>>>>>() { - public F>>>>> f(final A a) { - return new F>>>>>() { - public F>>>> f(final B b) { - return new F>>>>() { - public F>>> f(final C c) { - return new F>>>() { - public F>> f(final D d) { - return new F>>() { - public F> f(final E e) { - return new F>() { - public P6 f(final F$ f) { - return p(a, b, c, d, e, f); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f -> p(a, b, c, d, e, f); } /** @@ -510,35 +430,7 @@ public E _5() { * @return A function that puts an element in a product-7. */ public static F>>>>>>> p7() { - return new F>>>>>>>() { - public F>>>>>> f(final A a) { - return new F>>>>>>() { - public F>>>>> f(final B b) { - return new F>>>>>() { - public F>>>> f(final C c) { - return new F>>>>() { - public F>>> f(final D d) { - return new F>>>() { - public F>> f(final E e) { - return new F>>() { - public F> f(final F$ f) { - return new F>() { - public P7 f(final G g) { - return p(a, b, c, d, e, f, g); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f -> g -> p(a, b, c, d, e, f, g); } /** @@ -591,39 +483,7 @@ public G _7() { * @return A function that puts an element in a product-8. */ public static F>>>>>>>> p8() { - return new F>>>>>>>>() { - public F>>>>>>> f(final A a) { - return new F>>>>>>>() { - public F>>>>>> f(final B b) { - return new F>>>>>>() { - public F>>>>> f(final C c) { - return new F>>>>>() { - public F>>>> f(final D d) { - return new F>>>>() { - public F>>> f(final E e) { - return new F>>>() { - public F>> f(final F$ f) { - return new F>>() { - public F> f(final G g) { - return new F>() { - public P8 f(final H h) { - return p(a, b, c, d, e, f, g, h); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; + return a -> b -> c -> d -> e -> f -> g -> h -> p(a, b, c, d, e, f, g, h); } /** diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 84fedd91..aa4ddccb 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -14,7 +14,7 @@ public abstract class P1 implements F0 { @Override - public A f() { + public final A f() { return _1(); } @@ -52,7 +52,7 @@ public static F, P1> fmap(final F f) { */ public P1 bind(final F> f) { P1 self = this; - return P.lazy(u -> f.f(self._1())._1()); + return P.lazy(() -> f.f(self._1())._1()); } /** @@ -62,7 +62,7 @@ public P1 bind(final F> f) { * @return A function whose result is wrapped in a P1. */ public static F> curry(final F f) { - return a -> P.lazy(u -> f.f(a)); + return a -> P.lazy(() -> f.f(a)); } /** @@ -143,7 +143,7 @@ public static P1> sequence(final Stream> as) { * @return A single P1 for the given array. */ public static P1> sequence(final Array> as) { - return P.lazy(u -> as.map(P1.__1())); + return P.lazy(() -> as.map(P1.__1())); } /** @@ -204,7 +204,7 @@ public Stream> traverseStream(final F> f){ */ public P1 map(final F f) { final P1 self = this; - return P.lazy(u -> f.f(self._1())); + return P.lazy(() -> f.f(self._1())); } /** @@ -257,7 +257,7 @@ public String toString() { @SuppressWarnings("unchecked") @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p1Equal(Equal.anyEqual()).eq(this, (P1) other)); } @Override diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index cab07c3e..f748d07d 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -26,7 +26,7 @@ public abstract class P2 { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual()).eq(this, (P2) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual()).eq(this, (P2) other)); } @Override diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index e2c7aa26..bd5ab1f3 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -192,7 +192,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P3) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P3) other)); } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 267e4d86..6b2079c4 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -265,7 +265,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P4) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P4) other)); } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index b5f62f4b..15701d36 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -344,7 +344,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P5) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P5) other)); } @Override diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 40802b0b..9c21a8d8 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -435,7 +435,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P6) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P6) other)); } @Override diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index cdff75ce..6204d9ea 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -529,7 +529,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P7) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P7) other)); } @Override diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index ffd9081a..660a4b03 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -635,7 +635,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P8) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual()).eq(this, (P8) other)); } @Override diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index d8cb2034..ed454b5a 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -22,7 +22,7 @@ public class Try { * @return A Validation with an Exception on the failure side and its result on the success side. */ static public P1> f(final Try0 t) { - return P.lazy(u -> { + return P.lazy(() -> { try { return success(t.f()); } catch (Exception e) { diff --git a/core/src/main/java/fj/TryEffect.java b/core/src/main/java/fj/TryEffect.java index 7db7ee11..22889338 100644 --- a/core/src/main/java/fj/TryEffect.java +++ b/core/src/main/java/fj/TryEffect.java @@ -15,7 +15,7 @@ public class TryEffect { private TryEffect(){} public static P1> f(TryEffect0 t) { - return P.lazy(u -> { + return P.lazy(() -> { try { t.f(); return Validation.success(Unit.unit()); diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index c245e021..f609fb0f 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -46,7 +46,7 @@ public R fold(final F, R> n, // The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the // continuations. public Trampoline bind(final F> f) { - return codense(sub, o -> suspend(P.lazy(u -> cont.f(o).bind(f)))); + return codense(sub, o -> suspend(P.lazy(() -> cont.f(o).bind(f)))); } // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result @@ -61,7 +61,7 @@ public Either>, A> resume() { F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); return ot.fold(f, g); }); - }, o -> P.lazy(u -> cont.f(o)))); + }, o -> P.lazy(() -> cont.f(o)))); } } @@ -259,7 +259,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.>lazy(u -> ta.zipWith(tb, f)))))); + return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.>lazy(() -> ta.zipWith(tb, f)))))); } for (final B y : eb.right()) { return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); @@ -267,7 +267,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) } for (final A x : ea.right()) { for (final B y : eb.right()) { - return suspend(P.lazy(u -> pure(f.f(x, y)))); + return suspend(P.lazy(() -> pure(f.f(x, y)))); } for (final P1> y : eb.left()) { return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index 658908cc..3b4fbbee 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -1,6 +1,7 @@ package fj.control.parallel; import fj.F; +import fj.F0; import fj.F2; import fj.Function; import static fj.Function.curry; @@ -221,10 +222,10 @@ public static F, P1>> either() { * @param e Either an exception or a value to wrap in a Callable * @return A Callable equivalent to the given Either value. */ - public static Callable fromEither(final P1> e) { + public static Callable fromEither(final F0> e) { return new Callable() { public A call() throws Exception { - final Either e1 = e._1(); + final Either e1 = e.f(); if (e1.isLeft()) throw e1.left().value(); else @@ -248,10 +249,10 @@ public static F>, Callable> fromEither() { * @param o An optional value to turn into a Callable. * @return A Callable that yields some value or throws an exception in the case of no value. */ - public static Callable fromOption(final P1> o) { + public static Callable fromOption(final F0> o) { return new Callable() { public A call() throws Exception { - final Option o1 = o._1(); + final Option o1 = o.f(); if (o1.isSome()) return o1.some(); else diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index d74e6522..ac768b59 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -348,7 +348,7 @@ public static F, Promise> foldRightS(final Strategy s, return new F, Promise>() { public Promise f(final Stream as) { return as.isEmpty() ? promise(s, P.p(b)) : liftM2(f).f(promise(s, P.p(as.head()))).f( - Promise.>join(s, P.lazy(u -> f(as.tail()._1()).fmap(P.p1())))); + Promise.>join(s, P.lazy(() -> f(as.tail()._1()).fmap(P.p1())))); } }; } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index 3582545d..ad6e3923 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -322,7 +322,7 @@ public static F, P1> obtain() { * @return A product-1 that waits for the given future to obtain a value. */ public static P1 obtain(final Future t) { - return P.lazy(u -> { + return P.lazy(() -> { try { return t.get(); } catch (InterruptedException e) { @@ -453,7 +453,7 @@ public Strategy errorStrategy(final Effect1 e) { * @return A strategy that captures any runtime errors with a side-effect. */ public static Strategy errorStrategy(final Strategy s, final Effect1 e) { - return s.comap(a -> P.lazy(u -> { + return s.comap(a -> P.lazy(() -> { try { return a._1(); } catch (Throwable t) { diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index ea9c2026..2d11cfac 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -1,6 +1,7 @@ package fj.data; import fj.F; +import fj.F0; import fj.F2; import fj.P; import fj.P1; @@ -10,7 +11,6 @@ import fj.Hash; import fj.Unit; import fj.function.Effect1; - import static fj.Function.*; import static fj.P.p; import static fj.P.p2; @@ -18,7 +18,6 @@ import static fj.data.List.iterableList; import static fj.data.Option.none; import static fj.data.Option.some; - import static java.lang.Math.min; import static java.lang.System.arraycopy; @@ -145,8 +144,8 @@ public Option toOption() { * @return An either projection of this array. */ @SuppressWarnings("unchecked") - public Either toEither(final P1 x) { - return a.length == 0 ? Either.left(x._1()) : Either.right((A) a[0]); + public Either toEither(final F0 x) { + return a.length == 0 ? Either. left(x.f()) : Either. right((A) a[0]); } /** @@ -682,7 +681,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object o) { - return Equal.shallowEqualsO(this, o).orSome(P.lazy(u -> Equal.arrayEqual(Equal.anyEqual()).eq(this, (Array) o))); + return Equal.shallowEqualsO(this, o).orSome(() -> Equal.arrayEqual(Equal.anyEqual()).eq(this, (Array) o)); } /** @@ -926,7 +925,7 @@ public Option toOption() { * @param x The value to return in left if this array is empty. * @return An either projection of this array. */ - public Either toEither(final P1 x) { + public Either toEither(final F0 x) { return a.toEither(x); } diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 739b6f01..ce945711 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -94,7 +94,7 @@ public final Either bimap(final F left, final F right) @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Either) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Either) other)); } @Override @@ -177,12 +177,12 @@ public Either either() { * @param err The error message to fail with. * @return The value of this projection */ - public A valueE(final P1 err) { + public A valueE(final F0 err) { if (e.isLeft()) //noinspection CastToConcreteClass return ((Left) e).a; else - throw error(err._1()); + throw error(err.f()); } /** @@ -210,8 +210,8 @@ public A value() { * @param a The value to return if this projection has no value. * @return The value of this projection or the given argument. */ - public A orValue(final P1 a) { - return isLeft() ? value() : a._1(); + public A orValue(final F0 a) { + return isLeft() ? value() : a.f(); } /** @@ -462,12 +462,12 @@ public Either either() { * @param err The error message to fail with. * @return The value of this projection */ - public B valueE(final P1 err) { + public B valueE(final F0 err) { if (e.isRight()) //noinspection CastToConcreteClass return ((Right) e).b; else - throw error(err._1()); + throw error(err.f()); } /** @@ -485,8 +485,8 @@ public B value() { * @param b The value to return if this projection has no value. * @return The value of this projection or the given argument. */ - public B orValue(final P1 b) { - return isRight() ? value() : b._1(); + public B orValue(final F0 b) { + return isRight() ? value() : b.f(); } /** @@ -575,7 +575,7 @@ public List> traverseList(final F> f) { public IO> traverseIO(final F> f) { return isRight() ? IOFunctions.map(f.f(value()), x -> Either.right(x)) : - IOFunctions.lazy(u -> Either.left(e.left().value())); + IOFunctions.lazy(() -> Either.left(e.left().value())); } public P1> traverseP1(final F> f) { @@ -890,8 +890,8 @@ public static A reduce(final Either e) { * @param left The left value to use if the condition does not satisfy. * @return A constructed either based on the given condition. */ - public static Either iif(final boolean c, final P1 right, final P1 left) { - return c ? new Right(right._1()) : new Left(left._1()); + public static Either iif(final boolean c, final F0 right, final F0 left) { + return c ? new Right(right.f()) : new Left(left.f()); } /** diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index e25f8024..a5445d48 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -39,8 +39,8 @@ public static P1> p(IO io) { return Try.f(toTry(io)); } - public static IO io(P1 p) { - return () -> p._1(); + public static IO io(F0 p) { + return p::f; } public static IO io(Try0 t) { @@ -150,8 +150,8 @@ public A run() throws IOException { }; } - public static final IO lazy(final P1 p) { - return () -> p._1(); + public static final IO lazy(final F0 p) { + return io(p); } public static final IO lazy(final F f) { @@ -162,8 +162,8 @@ public static final SafeIO lazySafe(final F f) { return () -> f.f(Unit.unit()); } - public static final SafeIO lazySafe(final P1 f) { - return () -> f._1(); + public static final SafeIO lazySafe(final F0 f) { + return f::f; } /** @@ -344,7 +344,7 @@ public static IO> sequence(List> list) { public static IO> sequence(Stream> stream) { F2>, IO, IO>> f2 = (ioList, io) -> - IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, P.lazy(u -> xs)))); + IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, P.lazy(() -> xs)))); return stream.foldLeft(f2, IOFunctions.unit(Stream.nil())); } diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index 7b5961cd..9eaeb95e 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -1,6 +1,7 @@ package fj.data; import fj.F; +import fj.F0; import fj.F1Functions; import fj.Function; import fj.P; @@ -18,14 +19,14 @@ public static abstract class Input { Input() {} // sealed - public abstract Z apply(final P1 empty, final P1> el, final P1 eof); + public abstract Z apply(final F0 empty, final F0> el, final F0 eof); /** Input that has no values available */ public static final Input empty() { return new Input() { @Override - public Z apply(final P1 empty, final P1> el, final P1 eof) { - return empty._1(); + public Z apply(final F0 empty, final F0> el, final F0 eof) { + return empty.f(); } }; } @@ -34,8 +35,8 @@ public Z apply(final P1 empty, final P1> el, final P1 eof) { public static final Input eof() { return new Input() { @Override - public Z apply(final P1 empty, final P1> el, final P1 eof) { - return eof._1(); + public Z apply(final F0 empty, final F0> el, final F0 eof) { + return eof.f(); } }; } @@ -44,8 +45,8 @@ public Z apply(final P1 empty, final P1> el, final P1 eof) { public static final Input el(final E element) { return new Input() { @Override - public Z apply(final P1 empty, final P1> el, final P1 eof) { - return el._1().f(element); + public Z apply(final F0 empty, final F0> el, final F0 eof) { + return el.f().f(element); } }; } @@ -127,27 +128,12 @@ public static final IterV length() { @Override public F, IterV> f(final Integer acc) { - final P1> empty = - new P1>() { - @Override - public IterV _1() { - return cont(step.f(acc)); - } - }; - final P1>> el = - new P1>>() { - @Override - public F> _1() { - return P.p(cont(step.f(acc + 1))).constant(); - } - }; - final P1> eof = - new P1>() { - @Override - public IterV _1() { - return done(acc, Input.eof()); - } - }; + final F0> empty = () -> cont(step.f(acc)); + + final F0>> el = () -> P.p(cont(step.f(acc + 1))).constant(); + + final F0> eof = () -> done(acc, Input.eof()); + return s -> s.apply(empty, el, eof); } }; @@ -160,27 +146,11 @@ public static final IterV drop(final int n) { new F, IterV>() { final F, IterV> step = this; - final P1> empty = - new P1>() { - @Override - public IterV _1() { - return cont(step); - } - }; - final P1>> el = - new P1>>() { - @Override - public F> _1() { - return P.p(IterV.drop(n - 1)).constant(); - } - }; - final P1> eof = - new P1>() { - @Override - public IterV _1() { - return done(Unit.unit(), Input.eof()); - } - }; + final F0> empty = () -> cont(step); + + final F0>> el = () -> P.p(IterV.drop(n - 1)).constant(); + + final F0> eof = () -> done(Unit.unit(), Input.eof()); @Override public IterV f(final Input s) { @@ -198,27 +168,11 @@ public static final IterV> head() { new F, IterV>>() { final F, IterV>> step = this; - final P1>> empty = - new P1>>() { - @Override - public IterV> _1() { - return cont(step); - } - }; - final P1>>> el = - new P1>>>() { - @Override - public F>> _1() { - return e -> done(Option.some(e), Input.empty()); - } - }; - final P1>> eof = - new P1>>() { - @Override - public IterV> _1() { - return done(Option.none(), Input.eof()); - } - }; + final F0>> empty = () -> cont(step); + + final F0>>> el = () -> e -> done(Option.some(e), Input.empty()); + + final F0>> eof = () -> done(Option.none(), Input.eof()); @Override public IterV> f(final Input s) { @@ -234,27 +188,11 @@ public static final IterV> peek() { new F, IterV>>() { final F, IterV>> step = this; - final P1>> empty = - new P1>>() { - @Override - public IterV> _1() { - return cont(step); - } - }; - final P1>>> el = - new P1>>>() { - @Override - public F>> _1() { - return e -> done(Option.some(e), Input.el(e)); - } - }; - final P1>> eof = - new P1>>() { - @Override - public IterV> _1() { - return done(Option.none(), Input.eof()); - } - }; + final F0>> empty = () -> cont(step); + + final F0>>> el = () -> e -> done(Option.some(e), Input.el(e)); + + final F0>> eof = () -> done(Option.none(), Input.eof()); @Override public IterV> f(final Input s) { @@ -273,27 +211,12 @@ public static final IterV> list() { @Override public F, IterV>> f(final List acc) { - final P1>> empty = - new P1>>() { - @Override - public IterV> _1() { - return cont(step.f(acc)); - } - }; - final P1>>> el = - new P1>>>() { - @Override - public F>> _1() { - return e -> cont(step.f(acc.cons(e))); - } - }; - final P1>> eof = - new P1>>() { - @Override - public IterV> _1() { - return done(acc, Input.eof()); - } - }; + final F0>> empty = () -> cont(step.f(acc)); + + final F0>>> el = () -> e -> cont(step.f(acc.cons(e))); + + final F0>> eof = () -> done(acc, Input.eof()); + return s -> s.apply(empty, el, eof); } }; diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index ba25c73a..14ba97d6 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1738,7 +1738,7 @@ public static F, Callable> P1_Callable() { // BEGIN Future -> public static F, P1>> Future_P1() { - return a -> P.lazy(u -> { + return a -> P.lazy(() -> { Either r; try { r = Either.right(a.get()); diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fc993523..bec3ae0c 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1,6 +1,7 @@ package fj.data; import static fj.Bottom.error; +import fj.F0; import fj.F2Functions; import fj.Equal; import fj.F; @@ -28,7 +29,6 @@ import static fj.function.Booleans.not; import static fj.Ordering.GT; import static fj.Ord.intOrd; - import fj.Ordering; import fj.control.Trampoline; import fj.function.Effect1; @@ -118,8 +118,8 @@ public final B list(final B nil, final F, B>> cons) { * @param a The argument to return if this list is empty. * @return The head of this list if there is one or the given argument if this list is empty. */ - public final A orHead(final P1 a) { - return isEmpty() ? a._1() : head(); + public final A orHead(final F0 a) { + return isEmpty() ? a.f() : head(); } /** @@ -128,8 +128,8 @@ public final A orHead(final P1 a) { * @param as The argument to return if this list is empty. * @return The tail of this list if there is one or the given argument if this list is empty. */ - public final List orTail(final P1> as) { - return isEmpty() ? as._1() : tail(); + public final List orTail(final F0> as) { + return isEmpty() ? as.f() : tail(); } /** @@ -149,8 +149,8 @@ public final Option toOption() { * @param x The value to return in left if this list is empty. * @return An either projection of this list. */ - public final Either toEither(final P1 x) { - return isEmpty() ? Either.left(x._1()) : Either.right(head()); + public final Either toEither(final F0 x) { + return isEmpty() ? Either.left(x.f()) : Either.right(head()); } /** @@ -1877,7 +1877,7 @@ private void copy() { //Casting to List here does not cause a runtime exception even if the type arguments don't match. //The cast is done to avoid the compiler warning "raw use of parameterized class 'List'" - return Equal.shallowEqualsO(this, obj).orSome(P.lazy(u -> Equal.listEqual(Equal.anyEqual()).eq(this, (List) obj))); + return Equal.shallowEqualsO(this, obj).orSome(() -> Equal.listEqual(Equal.anyEqual()).eq(this, (List) obj)); } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 90a88b9d..59737808 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -1,8 +1,8 @@ package fj.data; import static fj.Bottom.error; - import fj.F; +import fj.F0; import fj.F2; import fj.P; import fj.P1; @@ -19,7 +19,6 @@ import fj.Equal; import fj.Ord; import fj.Hash; - import static fj.Function.*; import static fj.P.p; import static fj.Unit.unit; @@ -130,8 +129,8 @@ public final B option(final B b, final F f) { * @param f The function to apply to the value of this optional value. * @return A reduction on this optional value. */ - public final B option(final P1 b, final F f) { - return isSome() ? f.f(some()) : b._1(); + public final B option(final F0 b, final F f) { + return isSome() ? f.f(some()) : b.f(); } /** @@ -149,8 +148,8 @@ public final int length() { * @param a The argument to return if this optiona value has no value. * @return The value of this optional value or the given argument. */ - public final A orSome(final P1 a) { - return isSome() ? some() : a._1(); + public final A orSome(final F0 a) { + return isSome() ? some() : a.f(); } /** @@ -169,11 +168,11 @@ public final A orSome(final A a) { * @param message The message to fail with if this optional value has no value. * @return The value of this optional value if there there is one. */ - public final A valueE(final P1 message) { + public final A valueE(final F0 message) { if(isSome()) return some(); else - throw error(message._1()); + throw error(message.f()); } /** @@ -421,7 +420,7 @@ public Either> traverseEither(F> f) { } public IO> traverseIO(F> f) { - return map(a -> IOFunctions.map(f.f(a), b -> some(b))).orSome(IOFunctions.lazy(u -> none())); + return map(a -> IOFunctions.map(f.f(a), b -> some(b))).orSome(IOFunctions.lazy(() -> none())); } public List> traverseList(F> f) { @@ -482,8 +481,8 @@ public B f(final A a) { * @param o The optional value to return if this optional value has no value. * @return This optional value if there is one, otherwise, returns the argument optional value. */ - public final Option orElse(final P1> o) { - return isSome() ? this : o._1(); + public final Option orElse(final F0> o) { + return isSome() ? this : o.f(); } /** @@ -503,8 +502,8 @@ public final Option orElse(final Option o) { * @param x The value to return in left if this optional value has no value. * @return An either projection of this optional value. */ - public final Either toEither(final P1 x) { - return isSome() ? Either.right(some()) : Either.left(x._1()); + public final Either toEither(final F0 x) { + return isSome() ? Either.right(some()) : Either.left(x.f()); } /** @@ -626,7 +625,7 @@ public final boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.optionEqual(Equal.anyEqual()).eq(this, (Option) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.optionEqual(Equal.anyEqual()).eq(this, (Option) other)); } /** @@ -751,8 +750,8 @@ public static Option iif(final F f, final A a) { * @return An optional value that has a value of the given argument if the given boolean is true, otherwise, returns * no value. */ - public static Option iif(final boolean p, final P1 a) { - return p ? some(a._1()) : Option.none(); + public static Option iif(final boolean p, final F0 a) { + return p ? some(a.f()) : Option.none(); } /** diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index d696e497..cf6a92bf 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -48,7 +48,7 @@ public static Seq empty() { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.seqEqual(Equal.anyEqual()).eq(this, (Seq) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.seqEqual(Equal.anyEqual()).eq(this, (Seq) other)); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 7bb868aa..61e07095 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -142,7 +142,7 @@ public static Set empty(final Ord ord) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.setEqual(Equal.anyEqual()).eq(this, (Set) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.setEqual(Equal.anyEqual()).eq(this, (Set) other)); } @Override diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 7abbf765..b0c76005 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1,6 +1,7 @@ package fj.data; import fj.Equal; +import fj.F0; import fj.Hash; import fj.Show; import fj.F; @@ -207,8 +208,8 @@ public final A foldLeft1(final F> f) { * @param a The argument to return if this stream is empty. * @return The head of this stream if there is one or the given argument if this stream is empty. */ - public final A orHead(final P1 a) { - return isEmpty() ? a._1() : head(); + public final A orHead(final F0 a) { + return isEmpty() ? a.f() : head(); } /** @@ -325,8 +326,8 @@ public Stream _1() { * @param as The stream to append to this one. * @return A new stream that has appended the given stream. */ - public final Stream append(final P1> as) { - return isEmpty() ? as._1() : cons(head(), new P1>() { + public final Stream append(final F0> as) { + return isEmpty() ? as.f() : cons(head(), new P1>() { public Stream _1() { return tail()._1().append(as); } @@ -900,8 +901,8 @@ public final Stream> zipIndex() { * @param x The value to return in left if this stream is empty. * @return An either projection of this stream. */ - public final Either toEither(final P1 x) { - return isEmpty() ? Either.left(x._1()) : Either.right(head()); + public final Either toEither(final F0 x) { + return isEmpty() ? Either.left(x.f()) : Either.right(head()); } /** @@ -1029,12 +1030,8 @@ public final Stream snoc(final A a) { * @param a The element to append. * @return A new stream with the given element at the end. */ - public final Stream snoc(final P1 a) { - return append(new P1>() { - public Stream _1() { - return single(a._1()); - } - }); + public final Stream snoc(final F0 a) { + return append(() -> single(a.f())); } /** @@ -1247,7 +1244,7 @@ public final boolean forall(final F f) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.streamEqual(Equal.anyEqual()).eq(this, (Stream) other)); } @Override @@ -1323,11 +1320,7 @@ public Stream> _1() { return nil(); } }); - return isEmpty() ? nil : nil.append(new P1>>() { - public Stream> _1() { - return tail()._1().inits().map(Stream.cons_().f(head())); - } - }); + return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.cons_().f(head()))); } /** @@ -1624,7 +1617,7 @@ public static Stream iterableStream(final Iterable i) { public static Stream iteratorStream(final Iterator i) { if (i.hasNext()) { final A a = i.next(); - return cons(a, P.lazy(u -> iteratorStream(i))); + return cons(a, P.lazy(() -> iteratorStream(i))); } else return nil(); } @@ -1653,11 +1646,7 @@ public static Stream cycle(final Stream as) { if (as.isEmpty()) throw error("cycle on empty list"); else - return as.append(new P1>() { - public Stream _1() { - return cycle(as); - } - }); + return as.append(() -> cycle(as)); } /** diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index f0e19602..3b81df25 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -261,7 +261,7 @@ private Stream drawTree(final Show s) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.treeEqual(Equal.anyEqual()).eq(this, (Tree) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.treeEqual(Equal.anyEqual()).eq(this, (Tree) other)); } @Override diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 08596ebb..c033fa33 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -38,7 +38,7 @@ public static TreeMap empty(final Ord keyOrd) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (TreeMap) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (TreeMap) other)); } @Override diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 4d0bfbe3..43e5bd97 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -103,7 +103,7 @@ public Either toEither() { * @param err The error message to fail with. * @return The success value. */ - public T successE(final P1 err) { + public T successE(final F0 err) { return e.right().valueE(err); } @@ -123,7 +123,7 @@ public T successE(final String err) { * @param t The value to return if this is failure. * @return The success value or the given value. */ - public T orSuccess(final P1 t) { + public T orSuccess(final F0 t) { return e.right().orValue(t); } @@ -252,7 +252,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.shallowEqualsO(this, other).orSome(P.lazy(u -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Validation) other))); + return Equal.shallowEqualsO(this, other).orSome(() -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual()).eq(this, (Validation) other)); } @Override @@ -880,7 +880,7 @@ public Validation validation() { * @param err The error message to fail with. * @return The failing value. */ - public E failE(final P1 err) { + public E failE(final F0 err) { return v.toEither().left().valueE(err); } @@ -900,7 +900,7 @@ public E failE(final String err) { * @param e The value to return if this is success. * @return The failing value or the given value. */ - public E orFail(final P1 e) { + public E orFail(final F0 e) { return v.toEither().left().orValue(e); } diff --git a/core/src/main/java/fj/data/vector/V.java b/core/src/main/java/fj/data/vector/V.java index 4f551be2..80e1c0f9 100644 --- a/core/src/main/java/fj/data/vector/V.java +++ b/core/src/main/java/fj/data/vector/V.java @@ -1,5 +1,6 @@ package fj.data.vector; +import fj.F0; import fj.F2; import fj.F3; import fj.F4; @@ -34,14 +35,14 @@ public static V2 v(final A a1, final A a2) { * @param a2 An element to put in a vector. * @return The vector-2. */ - public static V2 v(final P1 a1, final P1 a2) { + public static V2 v(final F0 a1, final F0 a2) { return V2.p(new P2() { public A _1() { - return a1._1(); + return a1.f(); } public A _2() { - return a2._1(); + return a2.f(); } }); } @@ -52,11 +53,7 @@ public A _2() { * @return A function that puts elements in a vector-2. */ public static F2> v2() { - return new F2>() { - public V2 f(final A a, final A a1) { - return v(a, a1); - } - }; + return (a, a1) -> v(a, a1); } /** @@ -79,7 +76,7 @@ public static V3 v(final A a1, final A a2, final A a3) { * @param a3 An element to put in a vector. * @return The vector-3. */ - public static V3 v(final P1 a1, final P1 a2, final P1 a3) { + public static V3 v(final P1 a1, final F0 a2, final F0 a3) { return V3.cons(a1, v(a2, a3)); } @@ -89,11 +86,7 @@ public static V3 v(final P1 a1, final P1 a2, final P1 a3) { * @return A function that puts elements in a vector-3. */ public static F3> v3() { - return new F3>() { - public V3 f(final A a, final A a1, final A a2) { - return v(a, a1, a2); - } - }; + return (a, a1, a2) -> v(a, a1, a2); } /** @@ -118,7 +111,7 @@ public static V4 v(final A a1, final A a2, final A a3, final A a4) { * @param a4 An element to put in a vector. * @return The vector-4. */ - public static V4 v(final P1 a1, final P1 a2, final P1 a3, final P1 a4) { + public static V4 v(final P1 a1, final P1 a2, final F0 a3, final F0 a4) { return V4.cons(a1, v(a2, a3, a4)); } @@ -128,11 +121,7 @@ public static V4 v(final P1 a1, final P1 a2, final P1 a3, final * @return A function that puts elements in a vector-4. */ public static F4> v4() { - return new F4>() { - public V4 f(final A a, final A a1, final A a2, final A a3) { - return v(a, a1, a2, a3); - } - }; + return (a, a1, a2, a3) -> v(a, a1, a2, a3); } @@ -160,7 +149,7 @@ public static V5 v(final A a1, final A a2, final A a3, final A a4, final * @param a5 An element to put in a vector. * @return The vector-5. */ - public static V5 v(final P1 a1, final P1 a2, final P1 a3, final P1 a4, final P1 a5) { + public static V5 v(final P1 a1, final P1 a2, final P1 a3, final F0 a4, final F0 a5) { return V5.cons(a1, v(a2, a3, a4, a5)); } @@ -170,11 +159,7 @@ public static V5 v(final P1 a1, final P1 a2, final P1 a3, final * @return A function that puts elements in a vector-5. */ public static F5> v5() { - return new F5>() { - public V5 f(final A a, final A a1, final A a2, final A a3, final A a4) { - return v(a, a1, a2, a3, a4); - } - }; + return (a, a1, a2, a3, a4) -> v(a, a1, a2, a3, a4); } } diff --git a/core/src/main/java/fj/function/Visitor.java b/core/src/main/java/fj/function/Visitor.java index fdece88e..211c4e16 100644 --- a/core/src/main/java/fj/function/Visitor.java +++ b/core/src/main/java/fj/function/Visitor.java @@ -2,6 +2,7 @@ import fj.Equal; import fj.F; +import fj.F0; import fj.F2; import fj.Function; import fj.Monoid; @@ -9,7 +10,6 @@ import fj.P2; import fj.data.List; import fj.data.Option; - import static fj.Function.compose; import static fj.Function.curry; import static fj.data.List.lookup; @@ -31,7 +31,7 @@ private Visitor() { * @param def The default value if no value is found in the list. * @return The first value available in the given list of optional values. If none is found return the given default value. */ - public static X findFirst(final List> values, final P1 def) { + public static X findFirst(final List> values, final F0 def) { return Monoid.firstOptionMonoid().sumLeft(values).orSome(def); } @@ -42,7 +42,7 @@ public static X findFirst(final List> values, final P1 def) { * @param def The default value if no value is found in the list. * @return The first non-null value in the given list of optional values. If none is found return the given default value. */ - public static X nullablefindFirst(final List values, final P1 def) { + public static X nullablefindFirst(final List values, final F0 def) { return findFirst(values.map(Option.fromNull()), def); } @@ -56,7 +56,7 @@ public static X nullablefindFirst(final List values, final P1 def) { * @return The first value found in the list of visitors after application of the given value, otherwise returns the * given default. */ - public static B visitor(final List>> visitors, final P1 def, final A value) { + public static B visitor(final List>> visitors, final F0 def, final A value) { return findFirst(visitors.map(Function.>apply(value)), def); } @@ -70,7 +70,7 @@ public static B visitor(final List>> visitors, final P1 * @return The first value found in the list of visitors after application of the given value, otherwise returns the * given default. */ - public static B nullableVisitor(final List> visitors, final P1 def, final A value) { + public static B nullableVisitor(final List> visitors, final F0 def, final A value) { return visitor(visitors.map(new F, F>>() { public F> f(final F k) { return compose(Option.fromNull(), k); diff --git a/core/src/main/java/fj/parser/Parser.java b/core/src/main/java/fj/parser/Parser.java index b974b73b..e5ce04c9 100644 --- a/core/src/main/java/fj/parser/Parser.java +++ b/core/src/main/java/fj/parser/Parser.java @@ -219,8 +219,8 @@ public Parser apply(final Parser, E> p) { * @param alt The parser to try if this parser fails. * @return A parser that tries this parser and if it fails, then tries the given parser. */ - public Parser or(final P1> alt) { - return parser(i -> parse(i).f().sequence(alt._1().parse(i))); + public Parser or(final F0> alt) { + return parser(i -> parse(i).f().sequence(alt.f().parse(i))); } /** @@ -241,8 +241,8 @@ public Parser or(final Parser alt) { * @param s The semigroup to append error messages if both parsers fail. * @return A parser that tries this parser and if it fails, then tries the given parser. */ - public Parser or(final P1> alt, final Semigroup s) { - return parser(i -> parse(i).f().bind(e -> alt._1().parse(i).f().map(s.sum(e)))); + public Parser or(final F0> alt, final Semigroup s) { + return parser(i -> parse(i).f().bind(e -> alt.f().parse(i).f().map(s.sum(e)))); } /** @@ -263,10 +263,10 @@ public Parser or(final Parser alt, final Semigroup s) { * @param e The error message to fail with if this parser succeeds. * @return A parser that negates this parser. */ - public Parser not(final P1 e) { + public Parser not(final F0 e) { return parser(i -> parse(i).isFail() ? Validation.>success(result(i, unit())) : - Validation.>fail(e._1())); + Validation.>fail(e.f())); } /** @@ -285,7 +285,7 @@ public Parser not(final E e) { * @return A parser that repeats application of this parser zero or many times. */ public Parser, E> repeat() { - return repeat1().or(P.lazy(u -> value(Stream.nil()))); + return repeat1().or(() -> value(Stream.nil())); } /** @@ -363,9 +363,9 @@ private StreamParser() { * @param e The error to fail with if no element is available. * @return A parser that produces an element from the stream if it is available and fails otherwise. */ - public static Parser, I, E> element(final P1 e) { + public static Parser, I, E> element(final F0 e) { return parser(is -> is.isEmpty() ? - Validation., I>>fail(e._1()) : + Validation., I>>fail(e.f()) : Validation., I>>success(result(is.tail()._1(), is.head()))); } @@ -387,7 +387,7 @@ public static Parser, I, E> element(final E e) { * @param f The predicate that the element should satisfy. * @return A parser that produces an element from the stream that satisfies the given predicate, or fails. */ - public static Parser, I, E> satisfy(final P1 missing, final F sat, + public static Parser, I, E> satisfy(final F0 missing, final F sat, final F f) { return StreamParser.element(missing).bind(x -> f.f(x) ? Parser., I, E>value(x) : @@ -421,7 +421,7 @@ private CharsParser() { * @param e The error to fail with if a character is unavailable. * @return A parser that produces a character if one is available or fails with the given error. */ - public static Parser, Character, E> character(final P1 e) { + public static Parser, Character, E> character(final F0 e) { return StreamParser.element(e); } @@ -443,7 +443,7 @@ public static Parser, Character, E> character(final E e) { * @param c The character to produce in the parser. * @return A parser that produces the given character or fails otherwise. */ - public static Parser, Character, E> character(final P1 missing, final F sat, + public static Parser, Character, E> character(final F0 missing, final F sat, final char c) { return StreamParser.satisfy(missing, sat, x -> x == c); } @@ -468,7 +468,7 @@ public static Parser, Character, E> character(final E miss * @param n The number of characters to produce in the parse result. * @return A parser that produces the given number of characters, or fails with the given error. */ - public static Parser, Stream, E> characters(final P1 missing, final int n) { + public static Parser, Stream, E> characters(final F0 missing, final int n) { return n <= 0 ? Parser., Stream, E>value(Stream.nil()) : character(missing).bind(characters(missing, n - 1), Stream.cons_()); @@ -493,7 +493,7 @@ public static Parser, Stream, E> characters(fin * @param cs The stream of characters to produce. * @return A parser that produces the given stream of characters or fails otherwise. */ - public static Parser, Stream, E> characters(final P1 missing, + public static Parser, Stream, E> characters(final F0 missing, final F sat, final Stream cs) { return cs.isEmpty() ? @@ -523,7 +523,7 @@ public static Parser, Stream, E> characters(fin * @param s The string to produce. * @return A parser that produces the given string or fails otherwise. */ - public static Parser, String, E> string(final P1 missing, final F sat, + public static Parser, String, E> string(final F0 missing, final F sat, final String s) { return characters(missing, sat, List.fromString(s).toStream()).map(cs -> List.asString(cs.toList())); } @@ -548,7 +548,7 @@ public static Parser, String, E> string(final E missing, f * @param sat The error if the produced character is not a digit. * @return A parser that produces a digit (0 to 9). */ - public static Parser, Digit, E> digit(final P1 missing, final F sat) { + public static Parser, Digit, E> digit(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isDigit(c)).map(c1 -> Digit.fromChar(c1).some()); } @@ -571,7 +571,7 @@ public static Parser, Digit, E> digit(final E missing, fin * @return A parser that produces a lower-case character. * @see Character#isLowerCase(char) */ - public static Parser, Character, E> lower(final P1 missing, final F sat) { + public static Parser, Character, E> lower(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isLowerCase(c)); } @@ -595,7 +595,7 @@ public static Parser, Character, E> lower(final E missing, * @return A parser that produces a upper-case character. * @see Character#isUpperCase(char) */ - public static Parser, Character, E> upper(final P1 missing, final F sat) { + public static Parser, Character, E> upper(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isUpperCase(c)); } @@ -619,7 +619,7 @@ public static Parser, Character, E> upper(final E missing, * @return A parser that produces a defined character. * @see Character#isDefined(char) */ - public static Parser, Character, E> defined(final P1 missing, final F sat) { + public static Parser, Character, E> defined(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isDefined(c)); } @@ -643,7 +643,7 @@ public static Parser, Character, E> defined(final E missin * @return A parser that produces a high-surrogate character. * @see Character#isHighSurrogate(char) */ - public static Parser, Character, E> highSurrogate(final P1 missing, + public static Parser, Character, E> highSurrogate(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isHighSurrogate(c)); } @@ -669,7 +669,7 @@ public static Parser, Character, E> highSurrogate(final E * @return A parser that produces an identifier-ignorable character. * @see Character#isIdentifierIgnorable(char) */ - public static Parser, Character, E> identifierIgnorable(final P1 missing, + public static Parser, Character, E> identifierIgnorable(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isIdentifierIgnorable(c)); } @@ -695,7 +695,7 @@ public static Parser, Character, E> identifierIgnorable(fi * @return A parser that produces an ISO control character. * @see Character#isISOControl(char) */ - public static Parser, Character, E> isoControl(final P1 missing, + public static Parser, Character, E> isoControl(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isISOControl(c)); } @@ -720,7 +720,7 @@ public static Parser, Character, E> isoControl(final E mis * @return A parser that produces a Java identifier part character. * @see Character#isJavaIdentifierPart(char) */ - public static Parser, Character, E> javaIdentifierPart(final P1 missing, + public static Parser, Character, E> javaIdentifierPart(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierPart(c)); } @@ -746,7 +746,7 @@ public static Parser, Character, E> javaIdentifierPart(fin * @return A parser that produces a Java identifier start character. * @see Character#isJavaIdentifierStart(char) */ - public static Parser, Character, E> javaIdentifierStart(final P1 missing, + public static Parser, Character, E> javaIdentifierStart(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierStart(c)); } @@ -772,7 +772,7 @@ public static Parser, Character, E> javaIdentifierStart(fi * @return A parser that produces an alpha character. * @see Character#isLetter(char) */ - public static Parser, Character, E> alpha(final P1 missing, final F sat) { + public static Parser, Character, E> alpha(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isLetter(c)); } @@ -796,7 +796,7 @@ public static Parser, Character, E> alpha(final E missing, * @return A parser that produces an alpha-numeric character. * @see Character#isLetterOrDigit(char) */ - public static Parser, Character, E> alphaNum(final P1 missing, final F sat) { + public static Parser, Character, E> alphaNum(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isLetterOrDigit(c)); } @@ -820,7 +820,7 @@ public static Parser, Character, E> alphaNum(final E missi * @return A parser that produces a low-surrogate character. * @see Character#isLowSurrogate(char) */ - public static Parser, Character, E> lowSurrogate(final P1 missing, + public static Parser, Character, E> lowSurrogate(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isLowSurrogate(c)); } @@ -845,7 +845,7 @@ public static Parser, Character, E> lowSurrogate(final E m * @return A parser that produces a mirrored character. * @see Character#isMirrored(char) */ - public static Parser, Character, E> mirrored(final P1 missing, final F sat) { + public static Parser, Character, E> mirrored(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isMirrored(c)); } @@ -869,7 +869,7 @@ public static Parser, Character, E> mirrored(final E missi * @return A parser that produces a space character. * @see Character#isSpace(char) */ - public static Parser, Character, E> space(final P1 missing, final F sat) { + public static Parser, Character, E> space(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isSpaceChar(c)); } @@ -893,7 +893,7 @@ public static Parser, Character, E> space(final E missing, * @return A parser that produces a title-case character. * @see Character#isTitleCase(char) */ - public static Parser, Character, E> titleCase(final P1 missing, + public static Parser, Character, E> titleCase(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isTitleCase(c)); } @@ -918,7 +918,7 @@ public static Parser, Character, E> titleCase(final E miss * @return A parser that produces a unicode identifier part character. * @see Character#isUnicodeIdentifierPart(char) */ - public static Parser, Character, E> unicodeIdentiferPart(final P1 missing, + public static Parser, Character, E> unicodeIdentiferPart(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isUnicodeIdentifierPart(c)); } @@ -944,7 +944,7 @@ public static Parser, Character, E> unicodeIdentiferPart(f * @return A parser that produces a unicode identifier start character. * @see Character#isUnicodeIdentifierStart(char) */ - public static Parser, Character, E> unicodeIdentiferStart(final P1 missing, + public static Parser, Character, E> unicodeIdentiferStart(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isUnicodeIdentifierStart(c)); } @@ -970,7 +970,7 @@ public static Parser, Character, E> unicodeIdentiferStart( * @return A parser that produces a white-space character. * @see Character#isWhitespace(char) */ - public static Parser, Character, E> whitespace(final P1 missing, + public static Parser, Character, E> whitespace(final F0 missing, final F sat) { return StreamParser.satisfy(missing, sat, c -> Character.isWhitespace(c)); } diff --git a/core/src/main/java/fj/test/Bool.java b/core/src/main/java/fj/test/Bool.java index 3c70a00f..aff8b295 100644 --- a/core/src/main/java/fj/test/Bool.java +++ b/core/src/main/java/fj/test/Bool.java @@ -1,5 +1,6 @@ package fj.test; +import fj.F0; import fj.P1; import static fj.test.Property.prop; @@ -43,7 +44,7 @@ public boolean isNot() { * @param p The property to return if this value is true. * @return a property that produces a result only if this value is true. */ - public Property implies(final P1 p) { + public Property implies(final F0 p) { return Property.implies(b, p); } diff --git a/core/src/main/java/fj/test/Property.java b/core/src/main/java/fj/test/Property.java index 6e54ebab..04b9d93c 100644 --- a/core/src/main/java/fj/test/Property.java +++ b/core/src/main/java/fj/test/Property.java @@ -128,7 +128,7 @@ public Result f(final Result res2) { * @param r The random generator to use for checking. * @param minSuccessful The minimum number of successful tests before a result is reached. * @param maxDiscarded The maximum number of tests discarded because they did not satisfy - * pre-conditions (i.e. {@link #implies(boolean, P1)}). + * pre-conditions (i.e. {@link #implies(boolean, F0)}). * @param minSize The minimum size to use for checking. * @param maxSize The maximum size to use for checking. * @return A result after checking this property. @@ -189,7 +189,7 @@ else if (x.isFalsified()) { * * @param minSuccessful The minimum number of successful tests before a result is reached. * @param maxDiscarded The maximum number of tests discarded because they did not satisfy - * pre-conditions (i.e. {@link #implies(boolean, P1)}). + * pre-conditions (i.e. {@link #implies(boolean, F0)}). * @param minSize The minimum size to use for checking. * @param maxSize The maximum size to use for checking. * @return A result after checking this property. @@ -276,7 +276,7 @@ public CheckResult minSuccessful(final Rand r, final int minSuccessful) { * successful checks, the given maximum discarded tests, minimum size of 0, maximum size of 100. * * @param maxDiscarded The maximum number of tests discarded because they did not satisfy - * pre-conditions (i.e. {@link #implies(boolean, P1)}). + * pre-conditions (i.e. {@link #implies(boolean, F0)}). * @return A result after checking this property. */ public CheckResult maxDiscarded(final int maxDiscarded) { @@ -289,7 +289,7 @@ public CheckResult maxDiscarded(final int maxDiscarded) { * * @param r The random generator. * @param maxDiscarded The maximum number of tests discarded because they did not satisfy - * pre-conditions (i.e. {@link #implies(boolean, P1)}). + * pre-conditions (i.e. {@link #implies(boolean, F0)}). * @return A result after checking this property. */ public CheckResult maxDiscarded(final Rand r, final int maxDiscarded) { @@ -350,8 +350,8 @@ public CheckResult maxSize(final Rand r, final int maxSize) { * @param p The property to return if the condition satisfies. * @return A property that produces a result only if the given condition satisfies. */ - public static Property implies(final boolean b, final P1 p) { - return b ? p._1() : new Property(new F>() { + public static Property implies(final boolean b, final F0 p) { + return b ? p.f() : new Property(new F>() { public F f(final Integer i) { return new F() { public Result f(final Rand r) { @@ -457,11 +457,7 @@ public P2 f(final Result result) { public Boolean f(final Option> o) { return failed(o); } - }).orSome(new P1>>() { - public Option> _1() { - return results.head(); - } - }); + }).orSome(() -> results.head()); } public boolean failed(final Option> o) { @@ -1640,9 +1636,9 @@ public Property f(final H h) { * @return A property that has a result of exception, if the evaluation of the given property * throws an exception; otherwise, the given property is returned. */ - public static Property exception(final P1 p) { + public static Property exception(final F0 p) { try { - return p._1(); + return p.f(); } catch (final Throwable t) { return new Property(new F>() { public F f(final Integer i) { diff --git a/core/src/main/java/fj/test/Result.java b/core/src/main/java/fj/test/Result.java index f70e5095..40a388d6 100644 --- a/core/src/main/java/fj/test/Result.java +++ b/core/src/main/java/fj/test/Result.java @@ -157,11 +157,7 @@ public Option toOption() { * @return The result that may be {@link #noResult() noResult()}. */ public static Result noResult(final Option r) { - return r.orSome(new P1() { - public Result _1() { - return noResult(); - } - }); + return r.orSome(() -> noResult()); } /** diff --git a/core/src/main/java/fj/test/Shrink.java b/core/src/main/java/fj/test/Shrink.java index c51da04e..687c6549 100644 --- a/core/src/main/java/fj/test/Shrink.java +++ b/core/src/main/java/fj/test/Shrink.java @@ -138,9 +138,9 @@ public static Shrink empty() { if (i == 0L) return nil(); else { - final Stream is = cons(0L, P.lazy(u -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1))); + final Stream is = cons(0L, P.lazy(() -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1))); - return i < 0L ? cons(-i, P.lazy(u -> is)) : is; + return i < 0L ? cons(-i, P.lazy(() -> is)) : is; } }); @@ -231,10 +231,10 @@ else if (as.tail().isEmpty()) final F, Boolean> isNotEmpty = isNotEmpty_(); return cons( as1, - P.lazy(u -> + P.lazy(() -> { final List as2 = as.drop(n1); - return cons(as2, P.lazy(u1 -> removeChunks(n1, as1) + return cons(as2, P.lazy(() -> removeChunks(n1, as1) .filter(isNotEmpty) .map(aas1 -> aas1.append(as2)) .interleave(removeChunks(n2, as2) diff --git a/core/src/main/java/fj/test/reflect/CheckParams.java b/core/src/main/java/fj/test/reflect/CheckParams.java index e144ba44..725a7504 100644 --- a/core/src/main/java/fj/test/reflect/CheckParams.java +++ b/core/src/main/java/fj/test/reflect/CheckParams.java @@ -29,10 +29,10 @@ /** * The maximum number of tests discarded because they did not satisfy pre-conditions - * (i.e. {@link Property#implies(boolean, P1)}). + * (i.e. {@link Property#implies(boolean, F0)}). * * @return The maximum number of tests discarded because they did not satisfy pre-conditions - * (i.e. {@link Property#implies(boolean, P1)}). + * (i.e. {@link Property#implies(boolean, F0)}). */ int maxDiscarded() default 500; diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 0bb3792c..03e310d2 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -1,20 +1,23 @@ package fj.data; -import fj.*; -import fj.function.Try0; -import fj.function.Try1; -import fj.function.Try2; - import java.util.Iterator; import java.util.Optional; -import java.util.Spliterator; -import java.util.Spliterators; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.StreamSupport; +import fj.F; +import fj.F2; +import fj.P; +import fj.P1; +import fj.Try; +import fj.Unit; +import fj.function.Try0; +import fj.function.Try1; +import fj.function.Try2; + /** * Created by mperry on 3/06/2014. */ @@ -29,7 +32,7 @@ public static P1 Supplier_P1(final Supplier s) { } public static F, P1> Supplier_P1() { - return s -> P.lazy(u -> s.get()); + return s -> P.lazy(() -> s.get()); } public static Supplier P1_Supplier(final P1 p) { @@ -96,7 +99,7 @@ static public F, BiFunction (a, b) -> Try.f(t).f(a, b); } - public static java.util.stream.Stream List_JavaStream(List list) { + public static java.util.stream.Stream List_JavaStream(final List list) { return Iterable_JavaStream(list); } @@ -120,22 +123,22 @@ static public F, F> Consumer_F() { return c -> Consumer_F(c); } - public static F Consumer_F(Consumer c) { + public static F Consumer_F(final Consumer c) { return a -> { c.accept(a); return Unit.unit(); }; } - static public java.util.stream.Stream Stream_JavaStream(fj.data.Stream s) { + static public java.util.stream.Stream Stream_JavaStream(final fj.data.Stream s) { return Iterable_JavaStream(s); } - static public java.util.stream.Stream Iterable_JavaStream(Iterable it) { + static public java.util.stream.Stream Iterable_JavaStream(final Iterable it) { return StreamSupport.stream(it.spliterator(), false); } - static public java.util.stream.Stream Iterator_JavaStream(Iterator it) { + static public java.util.stream.Stream Iterator_JavaStream(final Iterator it) { return Iterable_JavaStream(() -> it); } @@ -143,15 +146,15 @@ static public F, java.util.stream.Stream> Stream_JavaSt return s -> Stream_JavaStream(s); } - static public Stream JavaStream_Stream(java.util.stream.Stream s) { + static public Stream JavaStream_Stream(final java.util.stream.Stream s) { return s.collect(Collectors.toStream()); } - static public List JavaStream_List(java.util.stream.Stream s) { + static public List JavaStream_List(final java.util.stream.Stream s) { return s.collect(Collectors.toList()); } - static public Array JavaStream_Array(java.util.stream.Stream s) { + static public Array JavaStream_Array(final java.util.stream.Stream s) { return s.collect(Collectors.toArray()); } From 334753ad57533e535d512fdb0bcaee363196f4f0 Mon Sep 17 00:00:00 2001 From: Zheka Kozlov Date: Wed, 20 May 2015 15:05:01 +0600 Subject: [PATCH 283/811] inheritance() returned infinite list --- core/src/main/java/fj/Class.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index 50c7c5a7..6eac6e39 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -30,18 +30,18 @@ private Class(final java.lang.Class c) { public List> inheritance() { return unfold( (java.lang.Class c2) -> { - if (c == null) + if (c2 == null) return none(); else { final P2, java.lang.Class> p = new P2, java.lang.Class>() { public java.lang.Class _1() { - return c; + return c2; } @SuppressWarnings({"unchecked"}) public java.lang.Class _2() { - return c.getSuperclass(); + return c2.getSuperclass(); } }; return some(p); From 85f7ce959e577bcf98938521fd55d76062b4ef94 Mon Sep 17 00:00:00 2001 From: Zheka Kozlov Date: Wed, 20 May 2015 16:51:47 +0600 Subject: [PATCH 284/811] Stream.toString() returns a nonreadable message. showS() should be used instead, which returns a String. --- core/src/main/java/fj/test/CheckResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/test/CheckResult.java b/core/src/main/java/fj/test/CheckResult.java index b5b90685..fe3ca92a 100644 --- a/core/src/main/java/fj/test/CheckResult.java +++ b/core/src/main/java/fj/test/CheckResult.java @@ -286,7 +286,7 @@ else if (r.isPropException()) { public static Show summaryEx(final Show> sa) { return showS(new F() { public String f(final CheckResult r) { - final String s = summary(sa).show(r).toString(); + final String s = summary(sa).showS(r); if (r.isProven() || r.isPassed() || r.isExhausted()) return s; else if (r.isFalsified() || r.isPropException() || r.isGenException()) From a2e9b5c21ad2b4635dcaed7077aa1aad1746074b Mon Sep 17 00:00:00 2001 From: orionll Date: Fri, 22 May 2015 01:25:03 +0600 Subject: [PATCH 285/811] Added missing functionality for FingerTree and Seq. Seq implements Iterable. --- core/src/main/java/fj/data/Seq.java | 84 ++++++++++- .../main/java/fj/data/fingertrees/Deep.java | 130 +++++++++++------- .../main/java/fj/data/fingertrees/Digit.java | 30 +++- .../main/java/fj/data/fingertrees/Empty.java | 19 ++- .../java/fj/data/fingertrees/FingerTree.java | 56 ++++++++ .../main/java/fj/data/fingertrees/Four.java | 47 +++++++ .../main/java/fj/data/fingertrees/Node.java | 5 + .../main/java/fj/data/fingertrees/Node2.java | 26 +++- .../main/java/fj/data/fingertrees/Node3.java | 36 ++++- .../main/java/fj/data/fingertrees/One.java | 14 ++ .../main/java/fj/data/fingertrees/Single.java | 18 ++- .../main/java/fj/data/fingertrees/Three.java | 37 +++++ .../main/java/fj/data/fingertrees/Two.java | 28 ++++ 13 files changed, 460 insertions(+), 70 deletions(-) diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index d696e497..b4553753 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -10,11 +10,15 @@ import fj.data.fingertrees.MakeTree; import fj.data.fingertrees.Measured; +import java.util.AbstractList; +import java.util.Iterator; +import java.util.NoSuchElementException; + /** * Provides an immutable finite sequence, implemented as a finger tree. This structure gives O(1) access to * the head and tail, as well as O(log n) random access and concatenation of sequences. */ -public final class Seq { +public final class Seq implements Iterable { private static final Measured ELEM_MEASURED = measured(intAdditionMonoid, Function.constant(1)); private static final MakeTree MK_TREE = FingerTree.mkTree(ELEM_MEASURED); private static final Seq EMPTY = new Seq(MK_TREE.empty()); @@ -89,10 +93,79 @@ public Seq snoc(final A a) { return new Seq(ftree.snoc(a)); } + /** + * The first element of this sequence. This is an O(1) operation. + * + * @return The first element if this sequence is nonempty, otherwise throws an error. + */ + public A head() { return ftree.head(); } + + /** + * The last element of this sequence. This is an O(1) operation. + * + * @return The last element if this sequence is nonempty, otherwise throws an error. + */ + public A last() { return ftree.last(); } + + /** + * The sequence without the first element. This is an O(1) operation. + * + * @return The sequence without the first element if this sequence is nonempty, otherwise throws an error. + */ + public Seq tail() { + return (length() == 1) ? empty() : new Seq<>(ftree.tail()); + } + + /** + * The sequence without the last element. This is an O(1) operation. + * + * @return The sequence without the last element if this sequence is nonempty, otherwise throws an error. + */ + public Seq init() { + return (length() == 1) ? empty() : new Seq<>(ftree.init()); + } + public Stream toStream() { return ftree.foldLeft((b, a) -> b.cons(a), Stream.nil()).reverse(); } + public final java.util.List toJavaList() { + return new AbstractList() { + @Override public A get(int i) { return index(i); } + @Override public Iterator iterator() { return Seq.this.iterator(); } + @Override public int size() { return length(); } + }; + } + + /** + * Returns an iterator for this seq. This method exists to permit the use in a for-each loop. + * + * @return A iterator for this seq. + */ + public final Iterator iterator() { + return new Iterator() { + private FingerTree ftree = Seq.this.ftree; + + public boolean hasNext() { + return !ftree.isEmpty(); + } + + public A next() { + if (ftree.isEmpty()) + throw new NoSuchElementException(); + else { + final A a = ftree.head(); + ftree = ftree.tail(); + return a; + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + @Override public String toString() { return Show.seqShow(Show.anyShow()).showS(this); @@ -126,15 +199,20 @@ public int length() { return ftree.measure(); } + public P2, Seq> split(final int i) { + final P2, FingerTree> lr = ftree.split(index -> index > i); + return P.p(new Seq<>(lr._1()), new Seq<>(lr._2())); + } + /** - * Returns the element at the given index. + * Returns the element at the given index. This is an O(log(n)) operation. * * @param i The index of the element to return. * @return The element at the given index, or throws an error if the index is out of bounds. */ public A index(final int i) { if (i < 0 || i >= length()) - throw error("Index " + i + "out of bounds."); + throw error("Index " + i + " is out of bounds."); return ftree.lookup(Function.identity(), i)._2(); } diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index f53a7e28..aa5e87cd 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -1,8 +1,7 @@ package fj.data.fingertrees; -import fj.F; -import fj.Function; -import fj.P2; +import fj.*; +import fj.data.Option; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; @@ -97,54 +96,60 @@ public V measure() { final Measured m = measured(); final V measure = m.sum(m.measure(a), v); final MakeTree mk = mkTree(m); - return prefix.match(new F, FingerTree>() { - public FingerTree f(final One one) { - return new Deep(m, measure, mk.two(a, one.value()), middle, suffix); - } - }, new F, FingerTree>() { - public FingerTree f(final Two two) { - return new Deep(m, measure, mk.three(a, two.values()._1(), two.values()._2()), middle, suffix); - } - }, new F, FingerTree>() { - public FingerTree f(final Three three) { - return new Deep(m, measure, mk.four(a, three.values()._1(), three.values()._2(), - three.values()._3()), middle, suffix); - } - }, new F, FingerTree>() { - public FingerTree f(final Four four) { - return new Deep(m, measure, mk.two(a, four.values()._1()), - middle.cons(mk.node3(four.values()._2(), four.values()._3(), four.values()._4())), - suffix); - } - }); + + return prefix.match( + one -> new Deep<>(m, measure, mk.two(a, one.value()), middle, suffix), + two -> new Deep<>(m, measure, mk.three(a, two.values()._1(), two.values()._2()), middle, suffix), + three -> new Deep<>(m, measure, mk.four(a, three.values()._1(), three.values()._2(), three.values()._3()), middle, suffix), + four -> new Deep<>(m, measure, mk.two(a, four.values()._1()), middle.cons(mk.node3(four.values()._2(), four.values()._3(), four.values()._4())), suffix)); } public FingerTree snoc(final A a) { final Measured m = measured(); final V measure = m.sum(m.measure(a), v); final MakeTree mk = mkTree(m); - return suffix.match(new F, FingerTree>() { - public FingerTree f(final One one) { - return new Deep(m, measure, prefix, middle, mk.two(one.value(), a)); - } - }, new F, FingerTree>() { - public FingerTree f(final Two two) { - return new Deep(m, measure, prefix, middle, mk.three(two.values()._1(), two.values()._2(), a)); - } - }, new F, FingerTree>() { - public FingerTree f(final Three three) { - return new Deep(m, measure, prefix, middle, mk.four(three.values()._1(), three.values()._2(), - three.values()._3(), a)); - } - }, new F, FingerTree>() { - public FingerTree f(final Four four) { - return new Deep(m, measure, prefix, - middle.snoc(mk.node3(four.values()._1(), four.values()._2(), four.values()._3())), - mk.two(four.values()._4(), a)); - } - }); + + return suffix.match( + one -> new Deep<>(m, measure, prefix, middle, mk.two(one.value(), a)), + two -> new Deep<>(m, measure, prefix, middle, mk.three(two.values()._1(), two.values()._2(), a)), + three -> new Deep<>(m, measure, prefix, middle, mk.four(three.values()._1(), three.values()._2(), three.values()._3(), a)), + four -> new Deep<>(m, measure, prefix, middle.snoc(mk.node3(four.values()._1(), four.values()._2(), four.values()._3())), mk.two(four.values()._4(), a))); + } + + @Override public A head() { + return prefix.match( + One::value, + two -> two.values()._1(), + three -> three.values()._1(), + four -> four.values()._1()); } + @Override public A last() { + return suffix.match( + One::value, + two -> two.values()._2(), + three -> three.values()._3(), + four -> four.values()._4()); + } + + private static final FingerTree deepL(final Measured measured, final Option> lOpt, final FingerTree> m, final Digit r) { + return lOpt.option( + P.lazy(() -> m.isEmpty() ? r.toTree() : mkTree(measured).deep(m.head().toDigit(), m.tail(), r)), + (F, FingerTree>) l -> mkTree(measured).deep(l, m, r) + ); + } + + private static final FingerTree deepR(final Measured measured, final Option> rOpt, final FingerTree> m, final Digit l) { + return rOpt.option( + P.lazy(() -> m.isEmpty() ? l.toTree() : mkTree(measured).deep(l, m.init(), m.last().toDigit())), + (F, FingerTree>) r -> mkTree(measured).deep(l, m, r) + ); + } + + @Override public FingerTree tail() { return deepL(measured(), prefix.tail(), middle, suffix); } + + @Override public FingerTree init() { return deepR(measured(), suffix.init(), middle, prefix); } + @Override public FingerTree append(final FingerTree t) { final Measured m = measured(); return t.match(Function., FingerTree>constant(t), new F, FingerTree>() { @@ -159,19 +164,38 @@ public FingerTree f(final Deep deep) { }); } - @SuppressWarnings({"ReturnOfNull", "IfStatementWithIdenticalBranches"}) + @Override P3, A, FingerTree> split1(final F predicate, final V acc) { + final Measured m = measured(); + final V accL = m.sum(acc, prefix.measure()); + if (predicate.f(accL)) { + final P3>, A, Option>> lxr = prefix.split1(predicate, accL); + return P.p(lxr._1().option(new Empty<>(m), Digit::toTree), lxr._2(), deepL(m, lxr._3(), middle, suffix)); + } else { + final V accM = m.sum(accL, middle.measure()); + if (predicate.f(accM)) { + final P3>, Node, FingerTree>> mlXsMr = middle.split1(predicate, accL); + final P3>, A, Option>> lxr = mlXsMr._2().split1(predicate, m.sum(accL, mlXsMr._1().measure())); + return P.p(deepR(m, lxr._1(), mlXsMr._1(), prefix), lxr._2(), deepL(m, lxr._3(), mlXsMr._3(), suffix)); + } else { + final P3>, A, Option>> lxr = suffix.split1(predicate, accM); + return P.p(deepR(m, lxr._1(), middle, prefix), lxr._2(), lxr._3().option(new Empty<>(m), Digit::toTree)); + } + } + } + @Override public P2 lookup(final F o, final int i) { final int spr = o.f(prefix.measure()); - final int spm = o.f(middle.measure()); - if (i < spr) - return null; // TODO - //return prefix.lookup(o, i); - if (i < spm) { - return null; // TODO - /* final P2> p = middle.lookup(o, i - spr); - return p._2().lookup(o, p._1()); */ + if (i < spr) { + return prefix.lookup(o, i); + } else { + final int spm = spr + o.f(middle.measure()); + if (i < spm) { + final P2> p = middle.lookup(o, i - spr); + return p._2().lookup(o, p._1()); + } else { + return suffix.lookup(o, i - spm); + } } - return null; // TODO suffix.lookup(i - spm); } private static FingerTree> addDigits0(final Measured m, final FingerTree> m1, diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index 09e92d62..cf0f1a36 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -1,11 +1,11 @@ package fj.data.fingertrees; -import fj.F; -import fj.F2; -import fj.Function; +import fj.*; +import fj.data.Option; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; + import static fj.data.fingertrees.FingerTree.mkTree; /** @@ -134,6 +134,8 @@ public abstract B match(final F, B> one, final F, B> two this.m = m; } + final Measured measured() { return m; } + /** * Returns the sum of the measurements of this digit according to the monoid. * @@ -173,4 +175,26 @@ public FingerTree f(final Four four) { } }); } + + Option> tail() { + return match( + one -> Option.> none(), + two -> Option.> some(mkTree(m).one(two.values()._2())), + three -> Option.> some(mkTree(m).two(three.values()._2(), three.values()._3())), + four -> Option.> some(mkTree(m).three(four.values()._2(), four.values()._3(), four.values()._4())) + ); + } + + Option> init() { + return match( + one -> Option.> none(), + two -> Option.> some(mkTree(m).one(two.values()._1())), + three -> Option.> some(mkTree(m).two(three.values()._1(), three.values()._2())), + four -> Option.> some(mkTree(m).three(four.values()._1(), four.values()._2(), four.values()._3())) + ); + } + + abstract P3>, A, Option>> split1(final F predicate, final V acc); + + public abstract P2 lookup(final F o, final int i); } diff --git a/core/src/main/java/fj/data/fingertrees/Empty.java b/core/src/main/java/fj/data/fingertrees/Empty.java index cb5fe863..5d034192 100644 --- a/core/src/main/java/fj/data/fingertrees/Empty.java +++ b/core/src/main/java/fj/data/fingertrees/Empty.java @@ -1,7 +1,10 @@ package fj.data.fingertrees; import fj.F; +import fj.P; import fj.P2; +import fj.P3; + import static fj.Bottom.error; /** @@ -20,13 +23,19 @@ public final class Empty extends FingerTree { return cons(a); } + @Override public A head() { throw error("Selection of head in empty tree"); } + + @Override public A last() { throw error("Selection of last in empty tree"); } + + @Override public FingerTree tail() { throw error("Selection of tail in empty tree"); } + + @Override public FingerTree init() { throw error("Selection of init in empty tree"); } + @Override public FingerTree append(final FingerTree t) { return t; } - @Override public P2 lookup(final F o, final int i) { - throw error("Lookup of empty tree."); - } + @Override public P2 lookup(final F o, final int i) { throw error("Lookup of empty tree."); } @Override public B foldRight(final F> aff, final B z) { return z; @@ -65,5 +74,7 @@ public V measure() { return empty.f(this); } - + @Override P3, A, FingerTree> split1(final F predicate, final V acc) { + throw error("Splitting an empty tree"); + } } diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index 8fb2f158..a7449fb1 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -1,6 +1,7 @@ package fj.data.fingertrees; import fj.*; +import fj.data.Option; import fj.data.Seq; /** @@ -150,6 +151,34 @@ public static MakeTree mkTree(final Measured m) { */ public abstract FingerTree snoc(final A a); + /** + * The first element of this tree. This is an O(1) operation. + * + * @return The first element if this tree is nonempty, otherwise throws an error. + */ + public abstract A head(); + + /** + * The last element of this tree. This is an O(1) operation. + * + * @return The last element if this tree is nonempty, otherwise throws an error. + */ + public abstract A last(); + + /** + * The tree without the first element. This is an O(1) operation. + * + * @return The tree without the first element if this tree is nonempty, otherwise throws an error. + */ + public abstract FingerTree tail(); + + /** + * The tree without the last element. This is an O(1) operation. + * + * @return The tree without the last element if this tree is nonempty, otherwise throws an error. + */ + public abstract FingerTree init(); + /** * Appends one finger tree to another. * @@ -158,5 +187,32 @@ public static MakeTree mkTree(final Measured m) { */ public abstract FingerTree append(final FingerTree t); + /** + * Splits this tree into a pair of subtrees at the point where the given predicate, based on the measure, + * changes from false to true. This is a O(log(n)) operation. + * + * @return Pair: the subtree containing elements before the point where pred first holds and the subtree + * containing element at and after the point where pred first holds. Empty if pred never holds. + */ + public final P2, FingerTree> split(final F predicate) { + if (!isEmpty() && predicate.f(measure())) { + final P3, A, FingerTree> lxr = split1(predicate); + return P.p(lxr._1(), lxr._3().cons(lxr._2())); + } else { + return P.p(this, mkTree(m).empty()); + } + } + + /** + * Like split, but returns the element where pred first holds separately. + * + * Throws an error if the tree is empty. + */ + public final P3, A, FingerTree> split1(final F predicate) { + return split1(predicate, measured().zero()); + } + + abstract P3, A, FingerTree> split1(final F predicate, final V acc); + public abstract P2 lookup(final F o, final int i); } diff --git a/core/src/main/java/fj/data/fingertrees/Four.java b/core/src/main/java/fj/data/fingertrees/Four.java index f3242c00..1cdf8355 100644 --- a/core/src/main/java/fj/data/fingertrees/Four.java +++ b/core/src/main/java/fj/data/fingertrees/Four.java @@ -1,8 +1,16 @@ package fj.data.fingertrees; +import fj.P; +import fj.P2; +import fj.P3; +import fj.data.Option; import fj.data.vector.V4; import fj.F; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.fingertrees.FingerTree.mkTree; + /** * A four-element prefix or suffix of a finger tree. */ @@ -36,4 +44,43 @@ public B foldLeft(final F> bff, final B z) { public V4 values() { return as; } + + @Override P3>, A, Option>> split1(final F predicate, final V acc) { + final Measured m = measured(); + final MakeTree mk = mkTree(m); + final F measure = m.measure(); + final V acc1 = m.sum(acc, measure.f(as._1())); + if (predicate.f(acc1)) { + return P.p(none(), as._1(), some(mk.three(as._2(), as._3(), as._4()))); + } else { + final V acc2 = m.sum(acc1, measure.f(as._2())); + if (predicate.f(acc2)) { + return P.p(some(mk.one(as._1())), as._2(), some(mk.two(as._3(), as._4()))); + } else if (predicate.f(m.sum(acc2, measure.f(as._3())))) { + return P.p(some(mk.two(as._1(), as._2())), as._3(), some(mk.one(as._4()))); + } else { + return P.p(some(mk.three(as._1(), as._2(), as._3())), as._4(), none()); + } + } + } + + @Override public P2 lookup(final F o, final int i) { + final F m = measured().measure(); + final int s1 = o.f(m.f(as._1())); + if (i < s1) { + return P.p(i, as._1()); + } else { + final int s2 = s1 + o.f(m.f(as._2())); + if (i < s2) { + return P.p(i - s1, as._2()); + } else { + final int s3 = s2 + o.f(m.f(as._3())); + if (i < s3) { + return P.p(i - s2, as._3()); + } else { + return P.p(i - s3, as._4()); + } + } + } + } } diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index 4428eb8f..e051c8f0 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -3,6 +3,9 @@ import fj.F; import fj.F2; import fj.P2; +import fj.P3; +import fj.data.Option; + import static fj.Function.curry; /** @@ -63,6 +66,8 @@ Measured measured() { return m; } + abstract P3>, A, Option>> split1(final F predicate, final V acc); + public abstract P2 lookup(final F o, final int i); public abstract B match(final F, B> n2, final F, B> n3); diff --git a/core/src/main/java/fj/data/fingertrees/Node2.java b/core/src/main/java/fj/data/fingertrees/Node2.java index 73e72cd9..81b6738d 100644 --- a/core/src/main/java/fj/data/fingertrees/Node2.java +++ b/core/src/main/java/fj/data/fingertrees/Node2.java @@ -1,9 +1,16 @@ package fj.data.fingertrees; +import fj.P; +import fj.P3; +import fj.data.Option; import fj.data.vector.V2; import fj.F; import fj.P2; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.fingertrees.FingerTree.mkTree; + /** * A two-element inner tree node. */ @@ -27,9 +34,24 @@ public Digit toDigit() { return new Two(measured(), as); } - @SuppressWarnings({"ReturnOfNull"}) + P3>, A, Option>> split1(final F predicate, final V acc) { + final Measured m = measured(); + final MakeTree mk = mkTree(m); + if (predicate.f(m.sum(acc, m.measure().f(as._1())))) { + return P.p(none(), as._1(), some(mk.one(as._2()))); + } else { + return P.p(some(mk.one(as._1())), as._2(), none()); + } + } + @Override public P2 lookup(final F o, final int i) { - return null; // TODO + final F m = measured().measure(); + final int s1 = o.f(m.f(as._1())); + if (i < s1) { + return P.p(i, as._1()); + } else { + return P.p(i - s1, as._2()); + } } public B match(final F, B> n2, final F, B> n3) { diff --git a/core/src/main/java/fj/data/fingertrees/Node3.java b/core/src/main/java/fj/data/fingertrees/Node3.java index 01a74d31..ae83a6f9 100644 --- a/core/src/main/java/fj/data/fingertrees/Node3.java +++ b/core/src/main/java/fj/data/fingertrees/Node3.java @@ -1,9 +1,16 @@ package fj.data.fingertrees; +import fj.P; +import fj.P3; +import fj.data.Option; import fj.data.vector.V3; import fj.F; import fj.P2; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.fingertrees.FingerTree.mkTree; + /** * A three-element inner tree node. */ @@ -31,9 +38,32 @@ public Digit toDigit() { return new Three(measured(), as); } - @SuppressWarnings({"ReturnOfNull"}) - public P2 lookup(final F o, final int i) { - return null; //TODO + P3>, A, Option>> split1(final F predicate, final V acc) { + final Measured m = measured(); + final MakeTree mk = mkTree(m); + final V acc1 = m.sum(acc, m.measure().f(as._1())); + if (predicate.f(acc1)) { + return P.p(none(), as._1(), some(mk.two(as._2(), as._3()))); + } else if (predicate.f(m.sum(acc1, m.measure().f(as._2())))) { + return P.p(some(mk.one(as._1())), as._2(), some(mk.one(as._3()))); + } else { + return P.p(some(mk.two(as._1(), as._2())), as._3(), none()); + } + } + + @Override public P2 lookup(final F o, final int i) { + final F m = measured().measure(); + final int s1 = o.f(m.f(as._1())); + if (i < s1) { + return P.p(i, as._1()); + } else { + final int s2 = s1 + o.f(m.f(as._2())); + if (i < s2) { + return P.p(i - s1, as._2()); + } else { + return P.p(i - s2, as._3()); + } + } } public V3 toVector() { diff --git a/core/src/main/java/fj/data/fingertrees/One.java b/core/src/main/java/fj/data/fingertrees/One.java index 6df76834..953cf60c 100644 --- a/core/src/main/java/fj/data/fingertrees/One.java +++ b/core/src/main/java/fj/data/fingertrees/One.java @@ -1,6 +1,12 @@ package fj.data.fingertrees; import fj.F; +import fj.P; +import fj.P2; +import fj.P3; +import fj.data.Option; + +import static fj.data.Option.none; /** * A single-element prefix or suffix of a finger tree. @@ -35,4 +41,12 @@ public B foldLeft(final F> bff, final B z) { public A value() { return a; } + + @Override P3>, A, Option>> split1(final F predicate, final V acc) { + return P.p(none(), a, none()); + } + + @Override public P2 lookup(final F o, final int i) { + return P.p(i, a); + } } diff --git a/core/src/main/java/fj/data/fingertrees/Single.java b/core/src/main/java/fj/data/fingertrees/Single.java index 9fb2819c..c42f79e4 100644 --- a/core/src/main/java/fj/data/fingertrees/Single.java +++ b/core/src/main/java/fj/data/fingertrees/Single.java @@ -1,7 +1,10 @@ package fj.data.fingertrees; import fj.F; +import fj.P; import fj.P2; +import fj.P3; + import static fj.P.p; /** @@ -64,14 +67,25 @@ public V measure() { return mk.deep(mk.one(a), new Empty>(measured().nodeMeasured()), mk.one(b)); } + @Override public A head() { return a; } + + @Override public A last() { return a; } + + @Override public FingerTree tail() { return new Empty<>(measured()); } + + @Override public FingerTree init() { return new Empty<>(measured()); } + @Override public FingerTree append(final FingerTree t) { return t.cons(a); } - @Override public P2 lookup(final F o, final int i) { - return p(i, a); + @Override P3, A, FingerTree> split1(final F predicate, final V acc) { + final Empty empty = new Empty<>(measured()); + return P.p(empty, a, empty); } + @Override public P2 lookup(final F o, final int i) { return p(i, a); } + /** * Returns the single element of this tree. * diff --git a/core/src/main/java/fj/data/fingertrees/Three.java b/core/src/main/java/fj/data/fingertrees/Three.java index 16f0296e..6f7c8e93 100644 --- a/core/src/main/java/fj/data/fingertrees/Three.java +++ b/core/src/main/java/fj/data/fingertrees/Three.java @@ -1,8 +1,16 @@ package fj.data.fingertrees; +import fj.P; +import fj.P2; +import fj.P3; +import fj.data.Option; import fj.data.vector.V3; import fj.F; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.fingertrees.FingerTree.mkTree; + /** * A three-element prefix or suffix of a finger tree. */ @@ -36,4 +44,33 @@ public B foldLeft(final F> bff, final B z) { public V3 values() { return as; } + + @Override P3>, A, Option>> split1(final F predicate, final V acc) { + final Measured m = measured(); + final MakeTree mk = mkTree(m); + final F measure = m.measure(); + final V acc1 = m.sum(acc, measure.f(as._1())); + if (predicate.f(acc1)) { + return P.p(none(), as._1(), some(mk.two(as._2(), as._3()))); + } else if (predicate.f(m.sum(acc1, measure.f(as._2())))) { + return P.p(some(mk.one(as._1())), as._2(), some(mk.one(as._3()))); + } else { + return P.p(some(mk.two(as._1(), as._2())), as._3(), none()); + } + } + + @Override public P2 lookup(F o, int i) { + final F m = measured().measure(); + final int s1 = o.f(m.f(as._1())); + if (i < s1) { + return P.p(i, as._1()); + } else { + final int s2 = s1 + o.f(m.f(as._2())); + if (i < s2) { + return P.p(i - s1, as._2()); + } else { + return P.p(i - s2, as._3()); + } + } + } } diff --git a/core/src/main/java/fj/data/fingertrees/Two.java b/core/src/main/java/fj/data/fingertrees/Two.java index 08108820..7b2e35fd 100644 --- a/core/src/main/java/fj/data/fingertrees/Two.java +++ b/core/src/main/java/fj/data/fingertrees/Two.java @@ -1,8 +1,16 @@ package fj.data.fingertrees; +import fj.P; +import fj.P2; +import fj.P3; +import fj.data.Option; import fj.data.vector.V2; import fj.F; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.fingertrees.FingerTree.mkTree; + /** * A two-element prefix or suffix of a finger tree. */ @@ -36,4 +44,24 @@ public B foldLeft(final F> bff, final B z) { public V2 values() { return as; } + + @Override P3>, A, Option>> split1(final F predicate, final V acc) { + final Measured m = measured(); + final MakeTree mk = mkTree(m); + if (predicate.f(m.sum(acc, m.measure().f(as._1())))) { + return P.p(none(), as._1(), some(mk.one(as._2()))); + } else { + return P.p(some(mk.one(as._1())), as._2(), none()); + } + } + + @Override public P2 lookup(F o, int i) { + final F m = measured().measure(); + final int s1 = o.f(m.f(as._1())); + if (i < s1) { + return P.p(i, as._1()); + } else { + return P.p(i - s1, as._2()); + } + } } From 16d3c0dd60ecc8eb7cba52962040741495ee41b4 Mon Sep 17 00:00:00 2001 From: orionll Date: Tue, 26 May 2015 19:36:48 +0600 Subject: [PATCH 286/811] Fixed errors in FingerTree.append() and FingerTree.split1(). Added Seq.update() --- core/src/main/java/fj/data/Seq.java | 19 +++++++++++++++++-- .../main/java/fj/data/fingertrees/Deep.java | 19 ++++++++----------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index b4553753..cbd68817 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -211,11 +211,26 @@ public P2, Seq> split(final int i) { * @return The element at the given index, or throws an error if the index is out of bounds. */ public A index(final int i) { - if (i < 0 || i >= length()) - throw error("Index " + i + " is out of bounds."); + checkBounds(i); return ftree.lookup(Function.identity(), i)._2(); } + /** + * Replace the element at the given index with the supplied value. This is an O(log(n)) operation. + * + * @param i The index of the element to update. + * @param a The new value. + * + * @return The updated sequence, or throws an error if the index is out of bounds. + */ + public Seq update(final int i, final A a) { + checkBounds(i); + final P3, A, FingerTree> lxr = ftree.split1(index -> index > i); + return new Seq<>(lxr._1().append(lxr._3().cons(a))); + } + + private void checkBounds(final int i) { if (i < 0 || i >= length()) throw error("Index " + i + " is out of bounds."); } + public B foldLeft(final F2 f, final B z) { return ftree.foldLeft(f, z); } diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index aa5e87cd..eaa43c24 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -5,6 +5,8 @@ import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; + +import static fj.Function.constant; import static fj.data.List.list; import static fj.Function.flip; @@ -152,23 +154,18 @@ private static final FingerTree deepR(final Measured measured @Override public FingerTree append(final FingerTree t) { final Measured m = measured(); - return t.match(Function., FingerTree>constant(t), new F, FingerTree>() { - public FingerTree f(final Single single) { - return t.snoc(single.value()); - } - }, new F, FingerTree>() { - public FingerTree f(final Deep deep) { - return new Deep(m, m.sum(measure(), deep.measure()), prefix, - addDigits0(m, middle, suffix, deep.prefix, deep.middle), deep.suffix); - } - }); + return t.match( + constant(t), + single -> snoc(single.value()), + deep -> new Deep<>(m, m.sum(measure(), deep.measure()), prefix, + addDigits0(m, middle, suffix, deep.prefix, deep.middle), deep.suffix)); } @Override P3, A, FingerTree> split1(final F predicate, final V acc) { final Measured m = measured(); final V accL = m.sum(acc, prefix.measure()); if (predicate.f(accL)) { - final P3>, A, Option>> lxr = prefix.split1(predicate, accL); + final P3>, A, Option>> lxr = prefix.split1(predicate, acc); return P.p(lxr._1().option(new Empty<>(m), Digit::toTree), lxr._2(), deepL(m, lxr._3(), middle, suffix)); } else { final V accM = m.sum(accL, middle.measure()); From bc5913e3c9e00d71a445414436093e4b637145e6 Mon Sep 17 00:00:00 2001 From: orionll Date: Tue, 26 May 2015 19:58:11 +0600 Subject: [PATCH 287/811] Added Seq.take and Seq.drop --- core/src/main/java/fj/data/Seq.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index cbd68817..fbad7092 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -229,6 +229,24 @@ public Seq update(final int i, final A a) { return new Seq<>(lxr._1().append(lxr._3().cons(a))); } + /** + * Takes the given number of elements from the head of this sequence if they are available. + * + * @param n The maximum number of elements to take from this sequence. + * @return A sequence consisting only of the first n elements of this sequence, or else the whole sequence, + * if it has less than n elements. + */ + public Seq take(final int n) { return split(n)._1(); } + + /** + * Drops the given number of elements from the head of this sequence if they are available. + * + * @param n The number of elements to drop from this sequence. + * @return A sequence consisting of all elements of this sequence except the first n ones, or else the empty sequence, + * if this sequence has less than n elements. + */ + public Seq drop(final int n) { return split(n)._2(); } + private void checkBounds(final int i) { if (i < 0 || i >= length()) throw error("Index " + i + " is out of bounds."); } public B foldLeft(final F2 f, final B z) { From 1d52ca309ffd42dd9e2e34c7fb3099f8872d5f4d Mon Sep 17 00:00:00 2001 From: orionll Date: Wed, 27 May 2015 19:16:52 +0600 Subject: [PATCH 288/811] Fixed some methods that were implemented inefficiently or failed with StackOverflow. --- core/src/main/java/fj/data/LazyString.java | 11 +++++------ core/src/main/java/fj/data/List.java | 9 ++++++--- core/src/main/java/fj/data/Stream.java | 12 ++---------- core/src/test/java/fj/data/ListTest.java | 14 ++++++++++++++ core/src/test/java/fj/data/SeqTest.java | 14 ++++++++++++++ core/src/test/java/fj/data/StreamTest.java | 17 +++++++++++++++++ 6 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 core/src/test/java/fj/data/StreamTest.java diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index d95ae8ed..acfc9573 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -1,13 +1,10 @@ package fj.data; -import fj.Equal; -import fj.F; -import fj.F2; +import fj.*; + import static fj.Function.compose; import static fj.Function.curry; import static fj.P.p; -import fj.P1; -import fj.P2; import static fj.data.Option.none; import static fj.data.Option.some; import static fj.data.Stream.join; @@ -108,7 +105,9 @@ public CharSequence subSequence(final int start, final int end) { * @return The String representation of this lazy string. */ public String toString() { - return new StringBuilder(length() + 16).append(this).toString(); + final StringBuilder builder = new StringBuilder(length() + 16); + s.foreachDoEffect(c -> builder.append(c.charValue())); + return builder.toString(); } /** diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fc993523..5dd117b1 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -159,8 +159,7 @@ public final Either toEither(final P1 x) { * @return A stream projection of this list. */ public final Stream toStream() { - final Stream nil = Stream.nil(); - return foldRight(a -> as -> as.cons(a), nil); + return isEmpty() ? Stream.nil() : Stream.cons(head(), P.lazy(() -> tail().toStream())); } /** @@ -1569,7 +1568,11 @@ public static List replicate(final int n, final A a) { * to value (exclusive). */ public static List range(final int from, final int to) { - return from >= to ? List.nil() : cons(from, range(from + 1, to)); + final Buffer buf = Buffer.empty(); + for (int i = from; i < to; i++) { + buf.snoc(i); + } + return buf.toList(); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 7abbf765..4ed69a44 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -386,13 +386,7 @@ public final F> mapM(final F> f) { * @return A new stream after performing the map, then final join. */ public final Stream bind(final F> f) { - return map(f).foldLeft((accumulator, element) -> { - Stream result = accumulator; - for (B single : element) { - result = result.cons(single); - } - return result; - }, Stream.nil()).reverse(); + return foldRight(h -> (t -> f.f(h).append(t)), nil()); } /** @@ -1554,9 +1548,7 @@ public static Stream cons(final A head, final P1> tail) { * @param o The stream of streams to join. * @return A new stream that is the join of the given streams. */ - public static Stream join(final Stream> o) { - return Monoid.streamMonoid().sumRight(o); - } + public static Stream join(final Stream> o) { return o.bind(identity()); } /** * A first-class version of join diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index cfb049bf..c04beee5 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -4,6 +4,7 @@ import java.util.Arrays; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -39,4 +40,17 @@ public void integration() { } + @Test + public void convertToString() { + final int n = 10000; + final StringBuilder expected = new StringBuilder("List("); + for (int i = 0; i < n; i++) { + expected.append(i); + if (i < n - 1) { + expected.append(','); + } + } + expected.append(')'); + assertEquals(expected.toString(), List.range(0, n).toString()); + } } diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java index 9339a52a..633ae321 100644 --- a/core/src/test/java/fj/data/SeqTest.java +++ b/core/src/test/java/fj/data/SeqTest.java @@ -2,6 +2,7 @@ import org.junit.Test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -20,4 +21,17 @@ public void objectMethods() { } + @Test + public void convertToString() { + final int n = 10000; + final StringBuilder expected = new StringBuilder("Seq("); + for (int i = 0; i < n; i++) { + expected.append(i); + if (i < n - 1) { + expected.append(','); + } + } + expected.append(')'); + assertEquals(expected.toString(), Seq.seq(Array.range(0, 10000).array()).toString()); + } } diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java new file mode 100644 index 00000000..6e1b590a --- /dev/null +++ b/core/src/test/java/fj/data/StreamTest.java @@ -0,0 +1,17 @@ +package fj.data; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Created by Zheka Kozlov on 27.05.2015. + */ +public class StreamTest { + + @Test + public void infiniteStream() { + Stream s = Stream.forever(Enumerator.intEnumerator, 0).bind(Stream::single); + assertEquals(List.range(0, 5), s.take(5).toList()); + } +} From 02f4a60f0a6c79fb3e3fdbcf325dd9d958083bde Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 May 2015 21:16:56 +1000 Subject: [PATCH 289/811] Attempt to fix #108 --- core/src/main/java/fj/P1.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 5ae82a97..844e4482 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -9,7 +9,7 @@ import fj.data.Option; import fj.data.Validation; //import fj.data.*; -import fj.function.Try0; + public abstract class P1 implements F0 { @@ -216,22 +216,22 @@ public P1 memo() { final P1 self = this; return new P1() { private final Object latch = new Object(); - @SuppressWarnings({"InstanceVariableMayNotBeInitialized"}) - private volatile SoftReference v; + private volatile SoftReference> v = null; public A _1() { - A a = v != null ? v.get() : null; - if (a == null) + Option o = v != null ? v.get() : null; + if (o == null) { synchronized (latch) { - if (v == null || v.get() == null) { - a = self._1(); - v = new SoftReference(a); - } else { - a = v.get(); + o = v != null ? v.get() : null; + if (o == null) { + o = Option.some(self._1()); + v = new SoftReference<>(o); } } - return a; + } + return o.some(); } + }; } From b07073d3e013ba347bda51ace61fba0504f9fc54 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 28 May 2015 22:14:32 +1000 Subject: [PATCH 290/811] Override memo for an already memoised P1 --- core/src/main/java/fj/P1.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 844e4482..ddb0d04d 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -218,6 +218,7 @@ public P1 memo() { private final Object latch = new Object(); private volatile SoftReference> v = null; + @Override public A _1() { Option o = v != null ? v.get() : null; if (o == null) { @@ -232,6 +233,11 @@ public A _1() { return o.some(); } + @Override + public P1 memo() { + return this; + } + }; } From 70fb0fb820f450c1966093c6a660eaa2d188659e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 29 May 2015 23:10:30 +1000 Subject: [PATCH 291/811] issue #143: Upgrade to gradle 2.4 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f96025de..12967230 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip From 435cdac93bee544a93f5db9dabbaa0ec693e14e6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 30 May 2015 23:00:43 +1000 Subject: [PATCH 292/811] Update changes for 4.4-SNAPSHOT, future 4.4 release notes --- README.adoc | 16 ++++---- etc/CONTRIBUTORS | 8 +++- etc/release-notes/release-notes-4.4.adoc | 50 ++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 etc/release-notes/release-notes-4.4.adoc diff --git a/README.adoc b/README.adoc index 556947da..c08e7304 100644 --- a/README.adoc +++ b/README.adoc @@ -12,7 +12,7 @@ Functional Java provides abstractions for the following types: * Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). * Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list. -* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing, actors, concurrency and type conversion. +* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing, actors, lenses, concurrency and type conversion. == URLs @@ -20,6 +20,7 @@ Important URLs for the project are: * Website, http://www.functionaljava.org * Website repository, http://github.com/functionaljava/functionaljava.github.io +* Travis continuous integration build, https://travis-ci.org/functionaljava/functionaljava == Downloading @@ -30,10 +31,10 @@ The Functional Java artifact is published to Maven Central using the group `org. * the core library (`functionaljava`) * Java 8 specific support (`functionaljava-java8`) -The latest version is `4.3`. This can be added to your Gradle project by adding the dependencies: +The latest version is `4.4-SNAPSHOT`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.3" -compile "org.functionaljava:functionaljava-java8:4.3" +compile "org.functionaljava:functionaljava:4.4-SNAPSHOT" +compile "org.functionaljava:functionaljava-java8:4.4-SNAPSHOT" ---- and in Maven: @@ -41,12 +42,12 @@ and in Maven: org.functionaljava functionaljava - 4.3 + 4.4-SNAPSHOT org.functionaljava functionaljava-java8 - 4.3 + 4.4-SNAPSHOT ---- @@ -54,7 +55,7 @@ and in Maven: FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 7 bytecode. This requires access to both JDK 7 and 8. The build system requires the environment variables `JAVA7_HOME` and `JAVA8_HOME` to refer to the appropriate directories. -Building is done using Gradle 2.2.1. In the root directory run: +Building is done using Gradle 2.4. In the root directory run: ---- ./gradlew ---- @@ -97,6 +98,7 @@ A more complete description of the features mentioned above are: ** Zipper implementations for streams and trees. ** Automated specification-based testing framework (`fj.test`). ** Fully operational Actors for parallel computations (`fj.control.parallel`) and layered abstractions such as parallel-map, map-reduce, parallel-zip. +** Lenses, for updating immutable data. == License diff --git a/etc/CONTRIBUTORS b/etc/CONTRIBUTORS index c4dc5934..63be1827 100644 --- a/etc/CONTRIBUTORS +++ b/etc/CONTRIBUTORS @@ -196,7 +196,7 @@ marc.siegel@timgroup.com Gary Pamparà gpampara@gmail.com -kenji yoshida +Kenji Yoshida 6b656e6a69@gmail.com etorreborre @@ -208,3 +208,9 @@ gliptak@gmail.com Greg Row gregrow@users.noreply.github.com +Jean-Baptiste Giraudeau +jb@giraudeau.info + +Zheka Kozlov +@orionll + diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc new file mode 100644 index 00000000..7401713a --- /dev/null +++ b/etc/release-notes/release-notes-4.4.adoc @@ -0,0 +1,50 @@ + += Release 4.4 + +Proposed Release Date: June 2015 + +== Enhancements + +* Added optics lenses inspired from the Monocle Scala library (#130, 131, 132). +* Added functionality to FingerTree and Seq: head, last, tail, init, split, split1, update, toJavaList, Iterable (#140). +* Added OrdComparator and fixed TreeMap.toMutableMap (#110). +* Added bimap to Either (#121). +* Added monoid composition. + +== Fixes + +* Fixed LazyString.toString for Android (#109) +* Fixed exhausted ScalaCheck tests (#115). +* Fixed overflow in standard Rand (#112). +* Fixed equals for anonymous classes (#122). +* Fixed List.init (#128). +* Fixed Effect.f ignoring argument (#133). +* Made Effect.comap static (#135). +* Fixed Class.inheritance infinite list (#137). +* Fixed Stream.toString to human readable representation (#138). +* Fixed P1.memo cache in threaded environment (#141). +* Fixed Stream join and bind for infinite streams (#140). + +== Internal + +* Added Travis build (#115). +* Upgraded to Gradle 2.4 (#143). +* Added Gradle uptodate plugin (#119). +* Updated Scala and ScalaCheck to 2.11.6 and 1.12.2 respectively (#120). +* Replaced P1 by F0 in various APIs (#136). + +== Breaking Changes + +== Documentation + +== Contributors + +* Mark Perry +* daneko +* Dobes Vandermeer +* Kenji Yoshida +* Jean-Baptiste Giraudeau +* Runar Bjarnason +* Paul Horn +* Zheka Kozlov + From 3845b217f966b03bb3a6bab75f2d02b8359c3be2 Mon Sep 17 00:00:00 2001 From: orionll Date: Mon, 1 Jun 2015 16:46:51 +0600 Subject: [PATCH 293/811] Fixed bug in FingerTree.append(). Added PropertyTestRunner, SeqProperties and Arbitrary.arbSeq(). --- .../main/java/fj/data/fingertrees/Deep.java | 2 +- core/src/main/java/fj/test/Arbitrary.java | 10 ++ .../fj/data/properties/SeqProperties.java | 122 ++++++++++++++++++ .../java/fj/runner/PropertyTestRunner.java | 55 ++++++++ 4 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/fj/data/properties/SeqProperties.java create mode 100644 core/src/test/java/fj/runner/PropertyTestRunner.java diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index eaa43c24..f0754e62 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -155,7 +155,7 @@ private static final FingerTree deepR(final Measured measured @Override public FingerTree append(final FingerTree t) { final Measured m = measured(); return t.match( - constant(t), + constant(this), single -> snoc(single.value()), deep -> new Deep<>(m, m.sum(measure(), deep.measure()), prefix, addDigits0(m, middle, suffix, deep.prefix, deep.middle), deep.suffix)); diff --git a/core/src/main/java/fj/test/Arbitrary.java b/core/src/main/java/fj/test/Arbitrary.java index e7545fe6..79255e31 100644 --- a/core/src/main/java/fj/test/Arbitrary.java +++ b/core/src/main/java/fj/test/Arbitrary.java @@ -761,6 +761,16 @@ public Array f(final List as) { })); } + /** + * Returns an arbitrary implementation for sequences. + * + * @param aa An arbitrary implementation for the type over which the sequence is defined. + * @return An arbitrary implementation for sequences. + */ + public static Arbitrary> arbSeq(final Arbitrary aa) { + return arbitrary(arbArray(aa).gen.map(array -> Seq.seq((A[]) array.array()))); + } + /** * Returns an arbitrary implementation for throwables. * diff --git a/core/src/test/java/fj/data/properties/SeqProperties.java b/core/src/test/java/fj/data/properties/SeqProperties.java new file mode 100644 index 00000000..352a4b2b --- /dev/null +++ b/core/src/test/java/fj/data/properties/SeqProperties.java @@ -0,0 +1,122 @@ +package fj.data.properties; + + +import fj.Function; +import fj.P; +import fj.P2; +import fj.data.Option; +import fj.data.Seq; +import fj.runner.PropertyTestRunner; +import fj.test.Arbitrary; +import fj.test.Gen; +import fj.test.Property; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import static fj.Function.identity; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbSeq; +import static fj.test.Property.implies; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by Zheka Kozlov on 01.06.2015. + */ +@RunWith(PropertyTestRunner.class) +public class SeqProperties { + + public Property consHead() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.cons(n).head().equals(n))); + } + + public Property consLength() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.cons(n).length() == seq.length() + 1)); + } + + public Property snocLast() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.snoc(n).last().equals(n))); + } + + public Property snocLength() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.snoc(n).length() == seq.length() + 1)); + } + + public Property appendEmptyLeft() { + return property(arbSeq(arbInteger), seq -> prop(Seq.empty().append(seq).equals(seq))); + } + + public Property appendEmptyRight() { + return property(arbSeq(arbInteger), seq -> prop(seq.append(Seq.empty()).equals(seq))); + } + + public Property appendLength() { + return property(arbSeq(arbInteger), arbSeq(arbInteger), (seq1, seq2) -> + prop(seq1.append(seq2).length() == seq1.length() + seq2.length())); + } + + public Property consNotEmpty() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(!seq.cons(n).isEmpty())); + } + + public Property snocNotEmpty() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(!seq.snoc(n).isEmpty())); + } + + public Property appendSingleLeft() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(Seq.single(n).append(seq).equals(seq.cons(n)))); + } + + public Property appendSingleRight() { + return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.append(Seq.single(n)).equals(seq.snoc(n)))); + } + + public Property splitLength() { + return property(arbSeq(arbInteger), arbInteger, (seq, i) -> prop(seq.length() == seq.split(i)._1().length() + seq.split(i)._2().length())); + } + + public Property tailLength() { + return property(arbSeq(arbInteger), seq -> + Property.implies(!seq.isEmpty(), P.lazy(() -> prop(seq.length() == 1 + seq.tail().length())))); + } + + public Property initLength() { + return property(arbSeq(arbInteger), seq -> + Property.implies(!seq.isEmpty(), P.lazy(() -> prop(seq.length() == seq.init().length() + 1)))); + } + + public Property mapId() { + return property(arbSeq(arbInteger), seq -> prop(seq.map(identity()).equals(seq))); + } + + public Property updateAndIndex() { + final Gen, Option>> gen = arbSeq(arbInteger).gen.bind(seq -> { + if (seq.isEmpty()) { + return Gen.value(P.p(seq, none())); + } else { + return Gen.choose(0, seq.length() - 1).map(i -> P.p(seq, some(i))); + } + }); + + return property(Arbitrary.arbitrary(gen), arbInteger, (pair, n) -> + implies(pair._2().isSome(), P.lazy(() -> { + final Seq seq = pair._1(); + final int index = pair._2().some(); + return prop(seq.update(index, n).index(index).equals(n)); + }))); + } + + public Property foldLeft() { + return property(arbSeq(Arbitrary.arbitrary(Gen.value(1))), seq -> + prop(seq.foldLeft((acc, i) -> acc + i, 0) == seq.length())); + } + + public Property foldRight() { + return property(arbSeq(Arbitrary.arbitrary(Gen.value(1))), seq -> + prop(seq.foldRight((i, acc) -> acc + i, 0) == seq.length())); + } +} diff --git a/core/src/test/java/fj/runner/PropertyTestRunner.java b/core/src/test/java/fj/runner/PropertyTestRunner.java new file mode 100644 index 00000000..ba5e2359 --- /dev/null +++ b/core/src/test/java/fj/runner/PropertyTestRunner.java @@ -0,0 +1,55 @@ +package fj.runner; + +import org.junit.runner.Description; +import org.junit.runner.Runner; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunNotifier; + +import fj.P3; +import fj.data.Option; +import fj.test.CheckResult; +import fj.test.Property; +import fj.test.reflect.Check; +import fj.test.reflect.CheckParams; + +public class PropertyTestRunner extends Runner { + private final Class clas; + + public PropertyTestRunner(Class clas) { + this.clas = clas; + } + + @Override + public Description getDescription() { + Description suite = Description.createSuiteDescription(clas); + for (P3> p : Check.properties(clas)) { + suite.addChild(Description.createTestDescription(clas, p._2())); + } + return suite; + } + + @Override + public void run(RunNotifier notifier) { + for (P3> p : Check.properties(clas)) { + Description desc = Description.createTestDescription(clas, p._2()); + notifier.fireTestStarted(desc); + CheckResult result = checkProperty(p._1(), p._3()); + + try { + CheckResult.summaryEx.showS(result); + } catch (Throwable t) { + notifier.fireTestFailure(new Failure(desc, t)); + } + + notifier.fireTestFinished(desc); + } + } + + private static CheckResult checkProperty(Property prop, Option params) { + for (CheckParams ps : params) { + return prop.check(ps.minSuccessful(), ps.maxDiscarded(), ps.minSize(), ps.maxSize()); + } + + return prop.check(); + } +} From 69b38656347f64ae4d5abb4665fc58eacbbd3b28 Mon Sep 17 00:00:00 2001 From: orionll Date: Tue, 2 Jun 2015 14:29:05 +0600 Subject: [PATCH 294/811] Fixed bugs in standard random generator, Gen.listOf(). Added Arbitrary.arbNonEmptyList(), NonEmptyList.tail(), NonEmptyList.head(), NonEmptyList.equals(), NonEmptyList.toString(), NonEmptyListProperties. --- core/src/main/java/fj/data/NonEmptyList.java | 38 ++++++++++++--- core/src/main/java/fj/test/Arbitrary.java | 4 ++ core/src/main/java/fj/test/Gen.java | 12 +---- core/src/main/java/fj/test/Rand.java | 43 ++++------------- .../properties/NonEmptyListProperties.java | 48 +++++++++++++++++++ .../fj/data/properties/SeqProperties.java | 12 ++--- 6 files changed, 99 insertions(+), 58 deletions(-) create mode 100644 core/src/test/java/fj/data/properties/NonEmptyListProperties.java diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index fdf69815..30a6e3b3 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -1,15 +1,17 @@ package fj.data; +import fj.Equal; import fj.F; import fj.F1Functions; +import fj.Show; import fj.function.Effect1; -import static fj.data.Option.some; -import static fj.data.Option.somes; - import java.util.Collection; import java.util.Iterator; +import static fj.data.Option.some; +import static fj.data.Option.somes; + /** * Provides an in-memory, immutable, singly linked list with total head and tail. * @@ -26,17 +28,19 @@ public Iterator iterator() { return toCollection().iterator(); } + private final A head; + + private final List tail; + /** * The first element of this linked list. */ - @SuppressWarnings({"PublicField", "ClassEscapesDefinedScope"}) - public final A head; + public A head() { return head; } /** * This list without the first element. */ - @SuppressWarnings({"PublicField"}) - public final List tail; + public List tail() { return tail; } private NonEmptyList(final A head, final List tail) { this.head = head; @@ -53,6 +57,13 @@ public NonEmptyList cons(final A a) { return nel(a, tail.cons(head)); } + /** + * The length of this list. + * + * @return The length of this list. + */ + public int length() { return 1 + tail.length(); } + /** * Appends the given list to this list. * @@ -203,4 +214,17 @@ public static Option> fromList(final List as) { Option.>none() : some(nel(as.head(), as.tail())); } + + /** + * Perform an equality test on this list which delegates to the .equals() method of the member instances. + * This is implemented with Equal.nonEmptyListEqual using the anyEqual rule. + * + * @param obj the other object to check for equality against. + * @return true if this list is equal to the provided argument + */ + @Override public boolean equals( final Object obj ) { + return Equal.equals0(NonEmptyList.class, this, obj, () -> Equal.nonEmptyListEqual(Equal.anyEqual())); + } + + @Override public String toString() { return Show.nonEmptyListShow(Show.anyShow()).showS(this); } } diff --git a/core/src/main/java/fj/test/Arbitrary.java b/core/src/main/java/fj/test/Arbitrary.java index 79255e31..6ca573e9 100644 --- a/core/src/main/java/fj/test/Arbitrary.java +++ b/core/src/main/java/fj/test/Arbitrary.java @@ -733,6 +733,10 @@ public static Arbitrary> arbList(final Arbitrary aa) { return arbitrary(listOf(aa.gen)); } + public static Arbitrary> arbNonEmptyList(final Arbitrary aa) { + return arbitrary(Gen.listOf1(aa.gen).map(list -> NonEmptyList.fromList(list).some())); + } + /** * Returns an arbitrary implementation for streams. * diff --git a/core/src/main/java/fj/test/Gen.java b/core/src/main/java/fj/test/Gen.java index 67ea4beb..7b582a2a 100644 --- a/core/src/main/java/fj/test/Gen.java +++ b/core/src/main/java/fj/test/Gen.java @@ -554,15 +554,7 @@ public Gen f(final Integer i) { * @return A generator of lists whose values come from the given generator. */ public static Gen> listOf(final Gen g, final int x) { - return sized(new F>>() { - public Gen> f(final Integer size) { - return choose(x, size).bind(new F>>() { - public Gen> f(final Integer n) { - return sequenceN(n, g); - } - }); - } - }); + return sized(size -> choose(x, max(x, size)).bind(n -> sequenceN(n, g))); } /** @@ -576,7 +568,7 @@ public static Gen> listOf(final Gen g) { } /** - * Returns a generator of lists whose values come from the given generator. + * Returns a generator of non empty lists whose values come from the given generator. * * @param g The generator to produce values from for the returned generator. * @return A generator of lists whose values come from the given generator. diff --git a/core/src/main/java/fj/test/Rand.java b/core/src/main/java/fj/test/Rand.java index 57e90a0e..500d04eb 100644 --- a/core/src/main/java/fj/test/Rand.java +++ b/core/src/main/java/fj/test/Rand.java @@ -124,38 +124,15 @@ public Random f(final Long x) { /** * A standard random generator that uses {@link Random}. */ - public static final Rand standard = new Rand(new F, F>>() { - public F> f(final Option seed) { - return new F>() { - public F f(final Integer from) { - return new F() { - public Integer f(final Integer to) { - if(from == to){ - return from; - }else{ - final int f = min(from, to); - final int t = max(from, to); - final int x = Math.abs(t - f); - return f + seed.map(fr).orSome(new Random()).nextInt(x == Integer.MIN_VALUE ? Integer.MAX_VALUE : x); - } - } - }; - } - }; - } - }, new F, F>>() { - public F> f(final Option seed) { - return new F>() { - public F f(final Double from) { - return new F() { - public Double f(final Double to) { - final double f = min(from, to); - final double t = max(from, to); - return seed.map(fr).orSome(new Random()).nextDouble() * (t - f) + f; - } - }; - } - }; - } + public static final Rand standard = new Rand(seed -> from -> to -> { + final int min = min(from, to); + final int max = max(from, to); + final Random random = seed.map(fr).orSome(new Random()); + return (int) ((random.nextLong() & Long.MAX_VALUE) % (1L + max - min)) + min; + }, seed -> from -> to -> { + final double min = min(from, to); + final double max = max(from, to); + final Random random = seed.map(fr).orSome(new Random()); + return random.nextDouble() * (max - min) + min; }); } diff --git a/core/src/test/java/fj/data/properties/NonEmptyListProperties.java b/core/src/test/java/fj/data/properties/NonEmptyListProperties.java new file mode 100644 index 00000000..9d89a0da --- /dev/null +++ b/core/src/test/java/fj/data/properties/NonEmptyListProperties.java @@ -0,0 +1,48 @@ +package fj.data.properties; + +import fj.runner.PropertyTestRunner; +import fj.test.Property; +import org.junit.runner.RunWith; + +import static fj.Function.identity; +import static fj.data.NonEmptyList.nel; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbNonEmptyList; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by Zheka Kozlov on 02.06.2015. + */ +@RunWith(PropertyTestRunner.class) +public class NonEmptyListProperties { + + public Property consHead() { + return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(list.cons(n).head().equals(n))); + } + + public Property consLength() { + return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(list.cons(n).length() == list.length() + 1)); + } + + public Property positiveLength() { + return property(arbNonEmptyList(arbInteger), list -> prop(list.length() > 0)); + } + + public Property appendLength() { + return property(arbNonEmptyList(arbInteger), arbNonEmptyList(arbInteger), (list1, list2) -> + prop(list1.append(list2).length() == list1.length() + list2.length())); + } + + public Property appendSingle() { + return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(nel(n).append(list).equals(list.cons(n)))); + } + + public Property tailLength() { + return property(arbNonEmptyList(arbInteger), list -> prop(list.length() == 1 + list.tail().length())); + } + + public Property mapId() { + return property(arbNonEmptyList(arbInteger), list -> prop(list.map(identity()).equals(list))); + } +} diff --git a/core/src/test/java/fj/data/properties/SeqProperties.java b/core/src/test/java/fj/data/properties/SeqProperties.java index 352a4b2b..098cd87d 100644 --- a/core/src/test/java/fj/data/properties/SeqProperties.java +++ b/core/src/test/java/fj/data/properties/SeqProperties.java @@ -1,7 +1,6 @@ package fj.data.properties; -import fj.Function; import fj.P; import fj.P2; import fj.data.Option; @@ -10,10 +9,7 @@ import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; -import org.junit.Assert; -import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.BlockJUnit4ClassRunner; import static fj.Function.identity; import static fj.data.Option.none; @@ -81,12 +77,12 @@ public Property splitLength() { public Property tailLength() { return property(arbSeq(arbInteger), seq -> - Property.implies(!seq.isEmpty(), P.lazy(() -> prop(seq.length() == 1 + seq.tail().length())))); + implies(!seq.isEmpty(), () -> prop(seq.length() == 1 + seq.tail().length()))); } public Property initLength() { return property(arbSeq(arbInteger), seq -> - Property.implies(!seq.isEmpty(), P.lazy(() -> prop(seq.length() == seq.init().length() + 1)))); + implies(!seq.isEmpty(), () -> prop(seq.length() == seq.init().length() + 1))); } public Property mapId() { @@ -103,11 +99,11 @@ public Property updateAndIndex() { }); return property(Arbitrary.arbitrary(gen), arbInteger, (pair, n) -> - implies(pair._2().isSome(), P.lazy(() -> { + implies(pair._2().isSome(), () -> { final Seq seq = pair._1(); final int index = pair._2().some(); return prop(seq.update(index, n).index(index).equals(n)); - }))); + })); } public Property foldLeft() { From c2a126a53de92e837acc78b00b5f405e4c32abc0 Mon Sep 17 00:00:00 2001 From: orionll Date: Tue, 2 Jun 2015 18:04:34 +0600 Subject: [PATCH 295/811] Added NonEmptyList.hashCode(), Hash.bigintHash, Hash.bigdecimalHash --- core/src/main/java/fj/Hash.java | 13 +++++++++++++ core/src/main/java/fj/data/NonEmptyList.java | 9 +++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index fee25e0a..3c11a6ca 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -11,6 +11,9 @@ import fj.data.vector.V7; import fj.data.vector.V8; +import java.math.BigDecimal; +import java.math.BigInteger; + /** * Produces a hash code for an object which should attempt uniqueness. * @@ -102,6 +105,16 @@ public static Hash anyHash() { */ public static final Hash shortHash = anyHash(); + /** + * A hash instance for the BigInteger type. + */ + public static final Hash bigintHash = anyHash(); + + /** + * A hash instance for the BigDecimal type. + */ + public static final Hash bigdecimalHash = anyHash(); + /** * A hash instance for the String type. */ diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 30a6e3b3..ef67c27c 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -1,9 +1,6 @@ package fj.data; -import fj.Equal; -import fj.F; -import fj.F1Functions; -import fj.Show; +import fj.*; import fj.function.Effect1; import java.util.Collection; @@ -226,5 +223,9 @@ public static Option> fromList(final List as) { return Equal.equals0(NonEmptyList.class, this, obj, () -> Equal.nonEmptyListEqual(Equal.anyEqual())); } + @Override public int hashCode() { + return Hash.nonEmptyListHash(Hash.anyHash()).hash(this); + } + @Override public String toString() { return Show.nonEmptyListShow(Show.anyShow()).showS(this); } } From 74103b440080e15d93c78f264d13c426410e41a0 Mon Sep 17 00:00:00 2001 From: orionll Date: Wed, 3 Jun 2015 00:27:56 +0600 Subject: [PATCH 296/811] Added methods for NonEmptyList: snoc(), reverse(), intersperse(), sort(), zipIndex(), zipWith(), unzip(), join(). Added variable arguments to NonEmptyList.nel(). --- core/src/main/java/fj/data/NonEmptyList.java | 58 +++++++++++++++-- .../properties/NonEmptyListProperties.java | 64 ++++++++++++++++++- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index ef67c27c..cc98868a 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -6,6 +6,7 @@ import java.util.Collection; import java.util.Iterator; +import static fj.Function.identity; import static fj.data.Option.some; import static fj.data.Option.somes; @@ -54,6 +55,10 @@ public NonEmptyList cons(final A a) { return nel(a, tail.cons(head)); } + public NonEmptyList snoc(final A a) { + return nel(head, tail.snoc(a)); + } + /** * The length of this list. * @@ -143,6 +148,46 @@ public NonEmptyList mapTails(final F, B> f) { return tails().map(f); } + public NonEmptyList intersperse(final A a) { + final List list = toList().intersperse(a); + return nel(list.head(), list.tail()); + } + + public NonEmptyList reverse() { + final List list = toList().reverse(); + return nel(list.head(), list.tail()); + } + + public NonEmptyList sort(final Ord o) { + final List list = toList().sort(o); + return nel(list.head(), list.tail()); + } + + public NonEmptyList> zip(final NonEmptyList bs) { + final List> list = toList().zip(bs.toList()); + return nel(list.head(), list.tail()); + } + + public NonEmptyList> zipIndex() { + final List> list = toList().zipIndex(); + return nel(list.head(), list.tail()); + } + + public NonEmptyList zipWith(final List bs, final F> f) { + final List list = toList().zipWith(bs, f); + return nel(list.head(), list.tail()); + } + + public NonEmptyList zipWith(final List bs, final F2 f) { + final List list = toList().zipWith(bs, f); + return nel(list.head(), list.tail()); + } + + public static P2, NonEmptyList> unzip(final NonEmptyList> xs) { + final P2, List> p = List.unzip(xs.toList()); + return P.p(nel(p._1().head(), p._1().tail()), nel(p._2().head(), p._2().tail())); + } + /** * Returns a List projection of this list. * @@ -182,13 +227,14 @@ public static NonEmptyList nel(final A head, final List tail) { } /** - * Return a non-empty list with the given value. + * Constructs a non empty list from the given elements. * - * @param head The value in the non-empty list. - * @return A non-empty list with the given value. + * @param head The first in the non-empty list. + * @param tail The elements to construct a list's tail with. + * @return A non-empty list with the given elements. */ - public static NonEmptyList nel(final A head) { - return nel(head, List.nil()); + public static NonEmptyList nel(final A head, final A... tail) { + return nel(head, List.list(tail)); } /** @@ -212,6 +258,8 @@ public static Option> fromList(final List as) { some(nel(as.head(), as.tail())); } + public static NonEmptyList join(final NonEmptyList> o) { return o.bind(identity()); } + /** * Perform an equality test on this list which delegates to the .equals() method of the member instances. * This is implemented with Equal.nonEmptyListEqual using the anyEqual rule. diff --git a/core/src/test/java/fj/data/properties/NonEmptyListProperties.java b/core/src/test/java/fj/data/properties/NonEmptyListProperties.java index 9d89a0da..0781637a 100644 --- a/core/src/test/java/fj/data/properties/NonEmptyListProperties.java +++ b/core/src/test/java/fj/data/properties/NonEmptyListProperties.java @@ -1,15 +1,28 @@ package fj.data.properties; +import fj.Equal; +import fj.Ord; +import fj.P2; +import fj.data.List; +import fj.data.NonEmptyList; import fj.runner.PropertyTestRunner; import fj.test.Property; import org.junit.runner.RunWith; +import java.util.ArrayList; +import java.util.Collections; + +import static fj.Equal.intEqual; +import static fj.Equal.listEqual; +import static fj.Equal.nonEmptyListEqual; import static fj.Function.identity; import static fj.data.NonEmptyList.nel; +import static fj.data.NonEmptyList.unzip; import static fj.test.Arbitrary.arbInteger; import static fj.test.Arbitrary.arbNonEmptyList; import static fj.test.Property.prop; import static fj.test.Property.property; +import static java.lang.Math.min; /** * Created by Zheka Kozlov on 02.06.2015. @@ -17,8 +30,11 @@ @RunWith(PropertyTestRunner.class) public class NonEmptyListProperties { + private static final Equal> eq = nonEmptyListEqual(intEqual); + private static final Equal> listEq = listEqual(intEqual); + public Property consHead() { - return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(list.cons(n).head().equals(n))); + return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(intEqual.eq(list.cons(n).head(), n))); } public Property consLength() { @@ -35,7 +51,7 @@ public Property appendLength() { } public Property appendSingle() { - return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(nel(n).append(list).equals(list.cons(n)))); + return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> prop(eq.eq(nel(n).append(list), list.cons(n)))); } public Property tailLength() { @@ -43,6 +59,48 @@ public Property tailLength() { } public Property mapId() { - return property(arbNonEmptyList(arbInteger), list -> prop(list.map(identity()).equals(list))); + return property(arbNonEmptyList(arbInteger), list -> prop(eq.eq(list.map(identity()), list))); + } + + public Property reverse() { + return property(arbNonEmptyList(arbInteger), list -> + prop(listEq.eq(list.reverse().toList(), list.tail().reverse().snoc(list.head())))); + } + + public Property doubleReverse() { + return property(arbNonEmptyList(arbInteger), list -> prop(eq.eq(list.reverse().reverse(), list))); + } + + public Property sort() { + return property(arbNonEmptyList(arbInteger), list -> { + java.util.List javaList = list.sort(Ord.intOrd).toList().toJavaList(); + java.util.List copy = new ArrayList<>(javaList); + Collections.sort(copy); + return prop(javaList.equals(copy)); + }); + } + + public Property intersperseLength() { + return property(arbNonEmptyList(arbInteger), arbInteger, (list, n) -> + prop(list.intersperse(n).length() == 2 * list.length() - 1)); + } + + public Property zip() { + return property(arbNonEmptyList(arbInteger), arbNonEmptyList(arbInteger), (list1, list2) -> { + final int size = min(list1.length(), list2.length()); + final NonEmptyList> zipped = list1.zip(list2); + return prop(listEq.eq(zipped.map(P2::_1).toList(), list1.toList().take(size))) + .and(prop(listEq.eq(zipped.map(P2::_2).toList(), list2.toList().take(size)))); + }); + } + + public Property zipUnzip() { + return property(arbNonEmptyList(arbInteger), arbNonEmptyList(arbInteger), (list1, list2) -> { + final P2, NonEmptyList> unzipped = unzip(list1.zip(list2)); + final int size = min(list1.length(), list2.length()); + return prop(listEq.eq(unzipped._1().toList(), list1.toList().take(size))) + .and(prop(listEq.eq(unzipped._2().toList(), list2.toList().take(size)))); + }); + } } From 82e3773d4c4412a603fd1ead811b315ec35c87f1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 14 May 2015 19:07:56 +0200 Subject: [PATCH 297/811] Simplify monomorphic Prism and Optional constructors. and various small optimizations --- core/src/main/java/fj/data/optic/Fold.java | 2 +- .../src/main/java/fj/data/optic/Optional.java | 119 +++++++++++++++++- core/src/main/java/fj/data/optic/PIso.java | 2 +- core/src/main/java/fj/data/optic/PLens.java | 4 +- .../main/java/fj/data/optic/POptional.java | 48 +++---- core/src/main/java/fj/data/optic/PPrism.java | 4 +- core/src/main/java/fj/data/optic/PSetter.java | 3 +- .../main/java/fj/data/optic/PTraversal.java | 2 +- core/src/main/java/fj/data/optic/Prism.java | 21 +++- 9 files changed, 167 insertions(+), 38 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Fold.java b/core/src/main/java/fj/data/optic/Fold.java index 8a8d417f..94b8aaf6 100644 --- a/core/src/main/java/fj/data/optic/Fold.java +++ b/core/src/main/java/fj/data/optic/Fold.java @@ -44,7 +44,7 @@ public final F> find(final F p) { /** get the first target of a {@link Fold} */ public final Option headOption(final S s) { - return find(__ -> true).f(s); + return find(Function.constant(Boolean.TRUE)).f(s); } /** check if at least one target satisfies the predicate */ diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index a699a063..ac9306fe 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -1,12 +1,16 @@ package fj.data.optic; import fj.F; +import fj.Function; +import fj.P; import fj.P1; import fj.P2; import fj.control.Trampoline; import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; import fj.data.Either; import fj.data.IO; +import fj.data.IOFunctions; import fj.data.List; import fj.data.Option; import fj.data.Stream; @@ -166,9 +170,118 @@ public static Optional id() { return new Optional<>(POptional.pId()); } - /** create a {@link Optional} using the canonical functions: getOrModify and set */ - public static final Optional optional(final F> getOrModify, final F> set) { - return new Optional<>(POptional.pOptional(getOrModify, set)); + public static final Optional optional(final F> getOption, final F> set) { + return new Optional<>(new POptional() { + + @Override + public Either getOrModify(final S s) { + return getOption.f(s).option(Either.left(s), Either. right_()); + } + + @Override + public F set(final A a) { + return set.f(a); + } + + @Override + public Option getOption(final S s) { + return getOption.f(s); + } + + @Override + public F> modifyFunctionF(final F> f) { + return s -> getOrModify(s).either( + Function.constant(), + a -> Function.compose(b -> set.f(b).f(s), f.f(a)) + ); + } + + @Override + public F> modifyEitherF(final F> f) { + return s -> getOrModify(s).either( + Either.right_(), + t -> f.f(t).right().map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyIOF(final F> f) { + return s -> getOrModify(s).either( + IOFunctions::unit, + t -> IOFunctions. map(f.f(t), b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyTrampolineF(final F> f) { + return s -> getOrModify(s).either( + Trampoline.pure(), + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyPromiseF(final F> f) { + return s -> getOrModify(s).either( + t -> Promise.promise(Strategy.idStrategy(), P.p(t)), + t -> f.f(t).fmap(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyListF(final F> f) { + return s -> getOrModify(s).either( + List::single, + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyOptionF(final F> f) { + return s -> getOrModify(s).either( + Option.some_(), + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyStreamF(final F> f) { + return s -> getOrModify(s).either( + Stream.single(), + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyP1F(final F> f) { + return s -> getOrModify(s).either( + P.p1(), + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyValidationF(final F> f) { + return s -> getOrModify(s).either( + t -> Validation. success(t), + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F> modifyV2F(final F> f) { + return s -> getOrModify(s).either( + t -> V2.p(P.p(t, t)), + t -> f.f(t).map(b -> set.f(b).f(s)) + ); + } + + @Override + public F modify(final F f) { + return s -> getOrModify(s).either(Function.identity(), a -> set.f(f.f(a)).f(s)); + } + + }); } } diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java index 46716bb1..0ba2ca30 100644 --- a/core/src/main/java/fj/data/optic/PIso.java +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -126,7 +126,7 @@ public final F modify(final F f) { /** set polymorphically the target of a {@link PIso} with a value */ public final F set(final B b) { - return __ -> reverseGet(b); + return Function.constant(reverseGet(b)); } /** pair two disjoint {@link PIso} */ diff --git a/core/src/main/java/fj/data/optic/PLens.java b/core/src/main/java/fj/data/optic/PLens.java index 31d3bc4d..ade9b9e7 100644 --- a/core/src/main/java/fj/data/optic/PLens.java +++ b/core/src/main/java/fj/data/optic/PLens.java @@ -440,7 +440,7 @@ public F set(final B b) { @Override public F> modifyFunctionF(final F> f) { - return s -> Function.compose(b -> set.f(b).f(s), f.f(get(s))); + return s -> Function.compose(b -> set.f(b).f(s), f.f(get.f(s))); } @Override @@ -495,7 +495,7 @@ public F> modifyV2F(final F> f) { @Override public F modify(final F f) { - return s -> set(f.f(get.f(s))).f(s); + return s -> set.f(f.f(get.f(s))).f(s); } }; } diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java index 1ba31459..b1b0fa6e 100644 --- a/core/src/main/java/fj/data/optic/POptional.java +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -110,12 +110,12 @@ public abstract class POptional { * matching */ public final F> modifyOption(final F f) { - return s -> getOption(s).map(__ -> modify(f).f(s)); + return s -> getOption(s).map(Function.constant(modify(f).f(s))); } /** set polymorphically the target of a {@link POptional} with a value. return empty if the {@link POptional} is not matching */ public final F> setOption(final B b) { - return modifyOption(__ -> b); + return modifyOption(Function.constant(b)); } /** check if a {@link POptional} has a target */ @@ -385,89 +385,89 @@ public Option getOption(final S s) { @Override public F> modifyFunctionF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( Function.constant(), - a -> Function.compose(b -> set(b).f(s), f.f(a)) + a -> Function.compose(b -> set.f(b).f(s), f.f(a)) ); } @Override public F> modifyEitherF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( Either.right_(), - t -> f.f(t).right().map(b -> set(b).f(s)) + t -> f.f(t).right().map(b -> set.f(b).f(s)) ); } @Override public F> modifyIOF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( IOFunctions::unit, - t -> IOFunctions. map(f.f(t), b -> set(b).f(s)) + t -> IOFunctions. map(f.f(t), b -> set.f(b).f(s)) ); } @Override public F> modifyTrampolineF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( Trampoline.pure(), - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyPromiseF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( t -> Promise.promise(Strategy.idStrategy(), P.p(t)), - t -> f.f(t).fmap(b -> set(b).f(s)) + t -> f.f(t).fmap(b -> set.f(b).f(s)) ); } @Override public F> modifyListF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( List::single, - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyOptionF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( Option.some_(), - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyStreamF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( Stream.single(), - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyP1F(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( P.p1(), - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyValidationF(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( t -> Validation. success(t), - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyV2F(final F> f) { - return s -> getOrModify(s).either( + return s -> getOrModify.f(s).either( t -> V2.p(P.p(t, t)), - t -> f.f(t).map(b -> set(b).f(s)) + t -> f.f(t).map(b -> set.f(b).f(s)) ); } diff --git a/core/src/main/java/fj/data/optic/PPrism.java b/core/src/main/java/fj/data/optic/PPrism.java index d00a56f3..476758a7 100644 --- a/core/src/main/java/fj/data/optic/PPrism.java +++ b/core/src/main/java/fj/data/optic/PPrism.java @@ -151,12 +151,12 @@ public final F> modifyOption(final F f) { /** set polymorphically the target of a {@link PPrism} with a value */ public final F set(final B b) { - return modify(__ -> b); + return modify(Function.constant(b)); } /** set polymorphically the target of a {@link PPrism} with a value. return empty if the {@link PPrism} is not matching */ public final F> setOption(final B b) { - return modifyOption(__ -> b); + return modifyOption(Function.constant(b)); } /** check if a {@link PPrism} has a target */ diff --git a/core/src/main/java/fj/data/optic/PSetter.java b/core/src/main/java/fj/data/optic/PSetter.java index 71443a53..ad8e3ea8 100644 --- a/core/src/main/java/fj/data/optic/PSetter.java +++ b/core/src/main/java/fj/data/optic/PSetter.java @@ -1,6 +1,7 @@ package fj.data.optic; import fj.F; +import fj.Function; import fj.data.Either; /** @@ -96,7 +97,7 @@ public F modify(final F f) { @Override public F set(final B b) { - return modify(__ -> b); + return modify.f(Function.constant(b)); } }; } diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index 60fd1393..8e98cf2f 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -109,7 +109,7 @@ public final F> find(final F p) { /** get the first target of a {@link PTraversal} */ public final Option headOption(final S s) { - return find(__ -> true).f(s); + return find(Function.constant(Boolean.TRUE)).f(s); } /** check if at least one target satisfies the predicate */ diff --git a/core/src/main/java/fj/data/optic/Prism.java b/core/src/main/java/fj/data/optic/Prism.java index 82204c51..409bfc6d 100644 --- a/core/src/main/java/fj/data/optic/Prism.java +++ b/core/src/main/java/fj/data/optic/Prism.java @@ -90,9 +90,24 @@ public static Prism id() { return new Prism<>(PPrism.pId()); } - /** create a {@link Prism} using the canonical functions: getOrModify and reverseGet */ - public static Prism prism(final F> getOrModify, final F reverseGet) { - return new Prism<>(PPrism.pPrism(getOrModify, reverseGet)); + public static Prism prism(final F> getOption, final F reverseGet) { + return new Prism<>(new PPrism() { + + @Override + public Either getOrModify(final S s) { + return getOption.f(s).option(Either.left(s), Either. right_()); + } + + @Override + public S reverseGet(final A a) { + return reverseGet.f(a); + } + + @Override + public Option getOption(final S s) { + return getOption.f(s); + } + }); } } \ No newline at end of file From 14d7065aba4c58b23b9274289a9b5254fa10d63c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 15 May 2015 14:33:46 +0200 Subject: [PATCH 298/811] Added common optics on List --- core/src/main/java/fj/data/List.java | 152 +++++++++++++++++++ tests/src/main/scala/fj/ArbitraryP.scala | 5 +- tests/src/main/scala/fj/ArbitraryUnit.scala | 9 ++ tests/src/main/scala/fj/package.scala | 14 +- tests/src/test/scala/fj/data/CheckList.scala | 25 ++- 5 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 tests/src/main/scala/fj/ArbitraryUnit.scala diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index de99c8b4..9201e5cc 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -26,11 +26,21 @@ import static fj.data.List.Buffer.*; import static fj.data.Option.none; import static fj.data.Option.some; +import static fj.data.optic.Optional.optional; +import static fj.data.optic.Prism.prism; +import static fj.data.vector.V.v; import static fj.function.Booleans.not; import static fj.Ordering.GT; import static fj.Ord.intOrd; import fj.Ordering; import fj.control.Trampoline; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.optic.Optional; +import fj.data.optic.PTraversal; +import fj.data.optic.Prism; +import fj.data.optic.Traversal; +import fj.data.vector.V2; import fj.function.Effect1; import java.util.AbstractCollection; @@ -608,6 +618,119 @@ public IO> traverseIO(F> f) { ); } + public F> traverseF(F> f) { + return this.foldRight( + (a, acc) -> Function.bind(acc, + (bs) -> Function.> compose(b -> bs.cons(b), f.f(a))), + Function.constant(List. nil()) + ); + } + + public Trampoline> traverseTrampoline(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), + Trampoline.pure(List. nil())); + } + + public Promise> traversePromise(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.fmap(bs -> bs.cons(b))), + Promise.promise(Strategy.idStrategy(), p(List. nil()))); + } + + public List> traverseList(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), + List.single(List. nil())); + } + + public Validation> traverseValidation(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), + Validation.success(List. nil())); + } + + public V2> traverseV2(final F> f) { + return foldRight( + (a, acc) -> acc.apply(f.f(a).map(e -> es -> es.cons(e))), + v(List. nil(), List. nil())); + } + + /** + * polymorphic traversal + */ + public static PTraversal, List, A, B> _pTraversal() { + return new PTraversal, List, A, B>() { + + @Override + public F, F>> modifyFunctionF(F> f) { + return l -> l.traverseF(f); + } + + @Override + public F, Either>> modifyEitherF(F> f) { + return l -> l.traverseEither(f); + } + + @Override + public F, IO>> modifyIOF(F> f) { + return l -> l.traverseIO(f); + } + + @Override + public F, Trampoline>> modifyTrampolineF(F> f) { + return l -> l.traverseTrampoline(f); + } + + @Override + public F, Promise>> modifyPromiseF(F> f) { + return l -> l.traversePromise(f); + } + + @Override + public F, List>> modifyListF(F> f) { + return l -> l.traverseList(f); + } + + @Override + public F, Option>> modifyOptionF(F> f) { + return l -> l.traverseOption(f); + } + + @Override + public F, Stream>> modifyStreamF(F> f) { + return l -> l.traverseStream(f); + } + + @Override + public F, P1>> modifyP1F(F> f) { + return l -> l.traverseP1(f); + } + + @Override + public F, Validation>> modifyValidationF(F> f) { + return l -> l.traverseValidation(f); + } + + @Override + public F, V2>> modifyV2F(F> f) { + return l -> l.traverseV2(f); + } + + @Override + public F, M> foldMap(Monoid monoid, F f) { + return l -> monoid.sumLeft(l.map(f)); + } + }; + } + + /** + * monomorphic traversal + */ + public static Traversal, A> _traversal() { + return new Traversal<>(_pTraversal()); + } + /** * Performs function application within a list (applicative functor pattern). * @@ -1054,6 +1177,13 @@ public final List nub(final Ord o) { return sort(o).group(o.equal()).map(List.head_()); } + /** + * Optional targeted on Cons head. + */ + public static Optional, A> _head() { + return optional(l -> l.toOption(), a -> l -> l.> list(l, constant(cons_(a)))); + } + /** * First-class head function. * @@ -1063,6 +1193,14 @@ public static F, A> head_() { return list -> list.head(); } + /** + * Optional targeted on Cons tail. + */ + public static Optional, List> _tail() { + return optional(l -> l.>> list(none(), h -> tail -> some(tail)), + tail -> l -> l.list(l, h -> constant(cons(h, tail)))); + } + /** * First-class tail function. * @@ -1434,6 +1572,13 @@ public static List nil() { return (Nil) Nil.INSTANCE; } + /** + * Nil prism + */ + public static Prism, Unit> _nil() { + return prism(l -> l.isEmpty() ? some(unit()) : none(), constant(nil())); + } + /** * Returns a function that prepends (cons) an element to a list to produce a new list. * @@ -1443,6 +1588,13 @@ public static F, List>> cons() { return a -> tail -> cons(a, tail); } + /** + * Cons prism + */ + public static Prism, P2>> _cons() { + return prism(l -> l.>>> list(none(), h -> tail -> some(P.p(h, tail))), c -> cons(c._1(), c._2())); + } + public static F2, List> cons_() { return (a, listA) -> cons(a, listA); } diff --git a/tests/src/main/scala/fj/ArbitraryP.scala b/tests/src/main/scala/fj/ArbitraryP.scala index 30588f96..8da8d864 100644 --- a/tests/src/main/scala/fj/ArbitraryP.scala +++ b/tests/src/main/scala/fj/ArbitraryP.scala @@ -5,7 +5,10 @@ import org.scalacheck.Arbitrary.arbitrary object ArbitraryP { implicit def arbitraryP1[A](implicit a: Arbitrary[A]): Arbitrary[P1[A]] = - Arbitrary(arbitrary[A].map(a => new P1[A]{ + Arbitrary(arbitrary[A].map(a => new P1[A] { def _1 = a })) + + implicit def arbitraryP2[A, B](implicit a: Arbitrary[A], b: Arbitrary[B]): Arbitrary[P2[A,B]] = + Arbitrary(arbitrary[A].flatMap(a => arbitrary[B].map(b => P.p(a, b)))) } \ No newline at end of file diff --git a/tests/src/main/scala/fj/ArbitraryUnit.scala b/tests/src/main/scala/fj/ArbitraryUnit.scala new file mode 100644 index 00000000..ca68da1c --- /dev/null +++ b/tests/src/main/scala/fj/ArbitraryUnit.scala @@ -0,0 +1,9 @@ +package fj + +import org.scalacheck.Arbitrary +import org.scalacheck.Arbitrary.arbitrary + +object ArbitraryUnit { + implicit def arbitraryUnit: Arbitrary[Unit] = + Arbitrary(Unit.unit()) +} \ No newline at end of file diff --git a/tests/src/main/scala/fj/package.scala b/tests/src/main/scala/fj/package.scala index 1fac989f..5a3b9bfc 100644 --- a/tests/src/main/scala/fj/package.scala +++ b/tests/src/main/scala/fj/package.scala @@ -1,4 +1,5 @@ - +import fj.Equal +import fj.data.List package object fj { implicit def Function1F[A, B](g: A => B): F[A, B] = new F[A, B] { def f(a: A) = g(a) @@ -9,4 +10,15 @@ package object fj { def f(b: B) = g(a, b) } } + + implicit def stringEqual: Equal[String] = Equal.stringEqual + + implicit def intEqual: Equal[Int] = Equal.equal({(i1:Int, i2:Int) => Boolean.box((i1 == i2))}) + + implicit def unitEqual: Equal[Unit] = Equal.anyEqual() + + implicit def listEqual[A](implicit aEq: Equal[A]): Equal[List[A]] = Equal.listEqual(aEq) + + implicit def p2Equal[A, B](implicit aEq: Equal[A], bEq: Equal[B]): Equal[P2[A, B]] = Equal.p2Equal(aEq, bEq) + } \ No newline at end of file diff --git a/tests/src/test/scala/fj/data/CheckList.scala b/tests/src/test/scala/fj/data/CheckList.scala index 3692fa9c..8eab68ca 100644 --- a/tests/src/test/scala/fj/data/CheckList.scala +++ b/tests/src/test/scala/fj/data/CheckList.scala @@ -2,16 +2,20 @@ package fj package data import java.lang - import fj.Monoid import org.scalacheck.Prop._ -import ArbitraryList.arbitraryList -import ArbitraryP.arbitraryP1 +import ArbitraryList._ +import ArbitraryP._ +import ArbitraryUnit._ import Equal.{listEqual, stringEqual, p2Equal} import P.p import Unit.unit import List.{nil, single, join, iterateWhile} import org.scalacheck.Properties +import fj.data.optic.PrismLaws +import fj.data.optic.OptionalLaws +import fj.data.optic.TraversalLaws +import fj.data.optic.Traversal object CheckList extends Properties("List") { property("isEmpty") = forAll((a: List[Int]) => @@ -200,8 +204,19 @@ object CheckList extends Properties("List") { map((x: Int) => x:lang.Integer). foldLeft(Function.uncurryF2[lang.Integer, lang.Integer, lang.Integer](Monoid.intAdditionMonoid.sum), Monoid.intAdditionMonoid.zero()): lang.Boolean) }) - - + + + property("_nil") = PrismLaws[List[String], Unit](List._nil()) + + property("_cons") = PrismLaws[List[String], P2[String, List[String]]](List._cons()) + + property("_head") = OptionalLaws[List[String], String](List._head()) + + property("_tail") = OptionalLaws[List[String], List[String]](List._tail()) + + property("_traversal") = TraversalLaws[List[String], String](List._traversal()) + + /*property("iterateWhile") = forAll((n: Int) => n > 0 ==> (iterateWhile(((x:Int) => x - 1), ((x:Int) => ((x > 0): java.lang.Boolean)), n).length == n))*/ } From ec2c333a1ac947d144fe1736d8342621160be789 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 15 May 2015 14:34:19 +0200 Subject: [PATCH 299/811] Added P2 lenses --- core/src/main/java/fj/P2.java | 32 ++++++++++++++++++++++++++- tests/src/test/scala/fj/CheckP2.scala | 21 ++++++++++++++++++ tests/src/test/scala/fj/Tests.scala | 1 + 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/src/test/scala/fj/CheckP2.scala diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index a6fa05f7..82f51461 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -1,8 +1,10 @@ package fj; import static fj.Function.*; - +import static fj.data.optic.PLens.pLens; import fj.data.*; +import fj.data.optic.Lens; +import fj.data.optic.PLens; /** * A product-2. @@ -342,6 +344,34 @@ public static F2 untuple(final F, C> f) { return (a, b) -> f.f(P.p(a, b)); } + /** + * Polyomorphic lens targeted on _1. + */ + public static PLens, P2, A, C> _1pLens() { + return pLens(__1(), a -> p2 -> P.p(a, p2._2())); + } + + /** + * Monomorphic lens targeted on _1. + */ + public static Lens, A> _1Lens() { + return new Lens<>(_1pLens()); + } + + /** + * Polyomorphic lens targeted on _2. + */ + public static PLens, P2, B, C> _2pLens() { + return pLens(__2(), b -> p2 -> P.p(p2._1(), b)); + } + + /** + * Monomorphic lens targeted on _1. + */ + public static Lens, B> _2Lens() { + return new Lens<>(_2pLens()); + } + @Override public String toString() { return Show.p2Show(Show.anyShow(), Show.anyShow()).showS(this); diff --git a/tests/src/test/scala/fj/CheckP2.scala b/tests/src/test/scala/fj/CheckP2.scala new file mode 100644 index 00000000..4191b29d --- /dev/null +++ b/tests/src/test/scala/fj/CheckP2.scala @@ -0,0 +1,21 @@ +package fj + +import java.lang +import org.scalacheck.Prop._ +import data.ArbitraryList._ +import ArbitraryP.arbitraryP2 +import ArbitraryUnit._ +import P.p +import Unit.unit +import org.scalacheck.Properties +import fj.data.optic.PrismLaws +import fj.data.optic.OptionalLaws +import fj.data.optic.LensLaws + +object CheckP2 extends Properties("P2") { + + property("_1Lens") = LensLaws[P2[String, Int], String](P2._1Lens()) + + property("_2Lens") = LensLaws[P2[String, Int], Int](P2._2Lens()) + +} diff --git a/tests/src/test/scala/fj/Tests.scala b/tests/src/test/scala/fj/Tests.scala index 2110fa6c..3f353e52 100644 --- a/tests/src/test/scala/fj/Tests.scala +++ b/tests/src/test/scala/fj/Tests.scala @@ -2,6 +2,7 @@ package fj object Tests { def tests = List ( + CheckP2.properties, fj.data.CheckArray.properties, fj.data.CheckIO.properties, fj.data.CheckIteratee.properties, From c515983a4e72e5cb7ab540e53f78829234f8db65 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 15 May 2015 15:58:07 +0200 Subject: [PATCH 300/811] Help type inference for old javac. --- core/src/main/java/fj/data/List.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 9201e5cc..8e480b04 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -652,7 +652,7 @@ public Validation> traverseValidation(final F V2> traverseV2(final F> f) { return foldRight( - (a, acc) -> acc.apply(f.f(a).map(e -> es -> es.cons(e))), + (a, acc) -> acc.apply(f.f(a)., List>> map(e -> es -> es.cons(e))), v(List. nil(), List. nil())); } From ba6ad5f2a7f7e526c868b772da67b255dc6896dd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 18 May 2015 13:27:42 +0200 Subject: [PATCH 301/811] optimize Optional --- core/src/main/java/fj/data/optic/Optional.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index ac9306fe..bfe98a12 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -206,10 +206,7 @@ public F> modifyEitherF(final F> f) { @Override public F> modifyIOF(final F> f) { - return s -> getOrModify(s).either( - IOFunctions::unit, - t -> IOFunctions. map(f.f(t), b -> set.f(b).f(s)) - ); + return s -> getOption.f(s).option(IOFunctions.unit(s), a -> IOFunctions. map(f.f(a), b -> set.f(b).f(s))); } @Override @@ -278,7 +275,7 @@ public F> modifyV2F(final F> f) { @Override public F modify(final F f) { - return s -> getOrModify(s).either(Function.identity(), a -> set.f(f.f(a)).f(s)); + return s -> getOption.f(s).option(s, a -> set.f(f.f(a)).f(s)); } }); From ab5acf2c893767ad2083003f885a88d4022d1b3d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 2 Jun 2015 21:18:37 +0200 Subject: [PATCH 302/811] Avoid unecessary indirections in Optional modifyF --- .../src/main/java/fj/data/optic/Optional.java | 46 ++++++++++--------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index bfe98a12..c148b520 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -15,6 +15,7 @@ import fj.data.Option; import fj.data.Stream; import fj.data.Validation; +import fj.data.vector.V; import fj.data.vector.V2; /** {@link POptional} restricted to monomorphic update */ @@ -190,85 +191,88 @@ public Option getOption(final S s) { @Override public F> modifyFunctionF(final F> f) { - return s -> getOrModify(s).either( - Function.constant(), + return s -> getOption.f(s).option( + (C __) -> s, a -> Function.compose(b -> set.f(b).f(s), f.f(a)) ); } @Override public F> modifyEitherF(final F> f) { - return s -> getOrModify(s).either( - Either.right_(), + return s -> getOption.f(s).option( + Either.right(s), t -> f.f(t).right().map(b -> set.f(b).f(s)) ); } @Override public F> modifyIOF(final F> f) { - return s -> getOption.f(s).option(IOFunctions.unit(s), a -> IOFunctions. map(f.f(a), b -> set.f(b).f(s))); + return s -> getOption.f(s).option( + IOFunctions.unit(s), + a -> IOFunctions. map(f.f(a), b -> set.f(b).f(s)) + ); } @Override public F> modifyTrampolineF(final F> f) { - return s -> getOrModify(s).either( - Trampoline.pure(), + return s -> getOption.f(s).option( + Trampoline.pure(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyPromiseF(final F> f) { - return s -> getOrModify(s).either( - t -> Promise.promise(Strategy.idStrategy(), P.p(t)), + return s -> getOption.f(s).option( + () -> Promise.promise(Strategy.idStrategy(), P.p(s)), t -> f.f(t).fmap(b -> set.f(b).f(s)) ); } @Override public F> modifyListF(final F> f) { - return s -> getOrModify(s).either( - List::single, + return s -> getOption.f(s).option( + () -> List.single(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyOptionF(final F> f) { - return s -> getOrModify(s).either( - Option.some_(), + return s -> getOption.f(s).option( + Option.some(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyStreamF(final F> f) { - return s -> getOrModify(s).either( - Stream.single(), + return s -> getOption.f(s).option( + () -> Stream.single(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyP1F(final F> f) { - return s -> getOrModify(s).either( - P.p1(), + return s -> getOption.f(s).> option( + P.p(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyValidationF(final F> f) { - return s -> getOrModify(s).either( - t -> Validation. success(t), + return s -> getOption.f(s).option( + () -> Validation. success(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } @Override public F> modifyV2F(final F> f) { - return s -> getOrModify(s).either( - t -> V2.p(P.p(t, t)), + return s -> getOption.f(s).option( + () -> V.v(s, s), t -> f.f(t).map(b -> set.f(b).f(s)) ); } From 93057486e7582ffe465b9fa444c4303a4d9074b5 Mon Sep 17 00:00:00 2001 From: orionll Date: Wed, 3 Jun 2015 13:48:49 +0600 Subject: [PATCH 303/811] Added JavaDoc for new NonEmptyList methods. --- core/src/main/java/fj/data/NonEmptyList.java | 66 ++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index cc98868a..b9dbb903 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -55,6 +55,12 @@ public NonEmptyList cons(final A a) { return nel(a, tail.cons(head)); } + /** + * Appends (snoc) the given element to this non empty list to produce a new non empty list. O(n). + * + * @param a The element to append to this non empty list. + * @return A new non empty list with the given element appended. + */ public NonEmptyList snoc(final A a) { return nel(head, tail.snoc(a)); } @@ -148,41 +154,95 @@ public NonEmptyList mapTails(final F, B> f) { return tails().map(f); } + /** + * Intersperses the given argument between each element of this non empty list. + * + * @param a The separator to intersperse in this non empty list. + * @return A non empty list with the given separator interspersed. + */ public NonEmptyList intersperse(final A a) { final List list = toList().intersperse(a); return nel(list.head(), list.tail()); } + /** + * Reverse this non empty list in constant stack space. + * + * @return A new non empty list with the elements in reverse order. + */ public NonEmptyList reverse() { final List list = toList().reverse(); return nel(list.head(), list.tail()); } + /** + * Sorts this non empty list using the given order over elements using a merge sort algorithm. + * + * @param o The order over the elements of this non empty list. + * @return A sorted non empty list according to the given order. + */ public NonEmptyList sort(final Ord o) { final List list = toList().sort(o); return nel(list.head(), list.tail()); } + /** + * Zips this non empty list with the given non empty list to produce a list of pairs. If this list and the given list + * have different lengths, then the longer list is normalised so this function never fails. + * + * @param bs The non empty list to zip this non empty list with. + * @return A new non empty list with a length the same as the shortest of this list and the given list. + */ public NonEmptyList> zip(final NonEmptyList bs) { final List> list = toList().zip(bs.toList()); return nel(list.head(), list.tail()); } + /** + * Zips this non empty list with the index of its element as a pair. + * + * @return A new non empty list with the same length as this list. + */ public NonEmptyList> zipIndex() { final List> list = toList().zipIndex(); return nel(list.head(), list.tail()); } + /** + * Zips this non empty list with the given non empty list using the given function to produce a new list. If this list + * and the given list have different lengths, then the longer list is normalised so this function + * never fails. + * + * @param bs The non empty list to zip this non empty list with. + * @param f The function to zip this non empty list and the given non empty list with. + * @return A new non empty list with a length the same as the shortest of this list and the given list. + */ public NonEmptyList zipWith(final List bs, final F> f) { final List list = toList().zipWith(bs, f); return nel(list.head(), list.tail()); } + /** + * Zips this non empty list with the given non empty list using the given function to produce a new list. If this list + * and the given list have different lengths, then the longer list is normalised so this function + * never fails. + * + * @param bs The non empty list to zip this non empty list with. + * @param f The function to zip this non empty list and the given non empty list with. + * @return A new non empty list with a length the same as the shortest of this list and the given list. + */ public NonEmptyList zipWith(final List bs, final F2 f) { final List list = toList().zipWith(bs, f); return nel(list.head(), list.tail()); } + /** + * Transforms a non empty list of pairs into a non empty list of first components and + * a non empty list of second components. + * + * @param xs The non empty list of pairs to transform. + * @return A non empty list of first components and a non empty list of second components. + */ public static P2, NonEmptyList> unzip(final NonEmptyList> xs) { final P2, List> p = List.unzip(xs.toList()); return P.p(nel(p._1().head(), p._1().tail()), nel(p._2().head(), p._2().tail())); @@ -258,6 +318,12 @@ public static Option> fromList(final List as) { some(nel(as.head(), as.tail())); } + /** + * Concatenate (join) a non empty list of non empty lists. + * + * @param o The non empty list of non empty lists to join. + * @return A new non empty list that is the concatenation of the given lists. + */ public static NonEmptyList join(final NonEmptyList> o) { return o.bind(identity()); } /** From 9333f45fd91ed260bc1e62641da669b49bb544fe Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 3 Jun 2015 13:46:15 +0200 Subject: [PATCH 304/811] Help type inference for old Javac compilers --- core/src/main/java/fj/data/optic/Optional.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index c148b520..7e981189 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -191,7 +191,7 @@ public Option getOption(final S s) { @Override public F> modifyFunctionF(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( (C __) -> s, a -> Function.compose(b -> set.f(b).f(s), f.f(a)) ); @@ -199,7 +199,7 @@ public F> modifyFunctionF(final F> f) { @Override public F> modifyEitherF(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( Either.right(s), t -> f.f(t).right().map(b -> set.f(b).f(s)) ); @@ -231,7 +231,7 @@ public F> modifyPromiseF(final F> f) { @Override public F> modifyListF(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( () -> List.single(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); @@ -247,7 +247,7 @@ public F> modifyOptionF(final F> f) { @Override public F> modifyStreamF(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( () -> Stream.single(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); @@ -263,7 +263,7 @@ public F> modifyP1F(final F> f) { @Override public F> modifyValidationF(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( () -> Validation. success(s), t -> f.f(t).map(b -> set.f(b).f(s)) ); @@ -271,7 +271,7 @@ public F> modifyValidationF(final F> @Override public F> modifyV2F(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( () -> V.v(s, s), t -> f.f(t).map(b -> set.f(b).f(s)) ); From 98b1fb239cd82542a57c68cb2f114cd27bdb69a6 Mon Sep 17 00:00:00 2001 From: John Sullivan Date: Wed, 3 Jun 2015 19:47:25 -0400 Subject: [PATCH 305/811] Fixed bug in arrayShow --- core/src/main/java/fj/Show.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index fe1efe32..7c39a427 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -393,7 +393,7 @@ public static F, Stream> streamShow_(final Show sa, */ public static Show> arrayShow(final Show sa) { return show(as -> { - Stream b = nil(); + Stream b = fromString("Array("); for (int i = 0; i < as.length(); i++) { b = b.append(sa.f.f(as.get(i))); @@ -402,9 +402,7 @@ public static Show> arrayShow(final Show sa) { b = b.append(fromString(",")); } - b = b.append(fromString("Array(")); - - return fromString(")").append(p(b)); + return b.append(fromString(")")); }); } From 0613eb9e959a128073920909e47cae1ca133d6fb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Jun 2015 11:32:22 +1000 Subject: [PATCH 306/811] Added simple test for array show --- core/src/test/java/fj/ShowTest.java | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 core/src/test/java/fj/ShowTest.java diff --git a/core/src/test/java/fj/ShowTest.java b/core/src/test/java/fj/ShowTest.java new file mode 100644 index 00000000..e271f5a1 --- /dev/null +++ b/core/src/test/java/fj/ShowTest.java @@ -0,0 +1,25 @@ +package fj; + +import fj.data.Array; +import org.junit.Test; + +import static fj.data.Array.array; +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 4/06/2015. + */ +public class ShowTest { + + + + @Test + public void arrayShow() { + Array a = array(3, 5, 7); + String s = Show.arrayShow(Show.intShow).showS(a); + System.out.println(s); + assertTrue(s.equals("Array(3,5,7)")); + + } + +} From fa9e8039096f9a53573d3873e798bd0e2c51e83d Mon Sep 17 00:00:00 2001 From: orionll Date: Thu, 4 Jun 2015 15:27:26 +0600 Subject: [PATCH 307/811] Added Equal.notEq(), List.isPrefixOf(), List.isSuffix() --- core/src/main/java/fj/Equal.java | 11 ++++ core/src/main/java/fj/data/List.java | 26 +++++++++ .../fj/data/properties/ListProperties.java | 57 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 core/src/test/java/fj/data/properties/ListProperties.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index a89f4a7c..fb5204c1 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -38,6 +38,17 @@ public boolean eq(final A a1, final A a2) { return f.f(a1).f(a2); } + /** + * Returns true if the two given arguments are not equal, false otherwise. + * + * @param a1 An object to test for inequality against another. + * @param a2 An object to test for inequality against another. + * @return true if the two given arguments are not equal, false otherwise. + */ + public boolean notEq(final A a1, final A a2) { + return !eq(a1, a2); + } + /** * First-class equality check. * diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index de99c8b4..1793af95 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1301,6 +1301,32 @@ public boolean allEqual(final Equal eq) { return isEmpty() || tail().isEmpty() || eq.eq(head(), tail().head()) && tail().allEqual(eq); } + public final boolean isPrefixOf(final Equal eq, final List xs) { + final Iterator i = iterator(); + final Iterator j = xs.iterator(); + + while (i.hasNext() && j.hasNext()) { + if (!eq.eq(i.next(), j.next())) { + return false; + } + } + + return !i.hasNext(); + } + + public final boolean isSuffixOf(final Equal eq, final List xs) { + final Iterator i = iterator(); + final Iterator j = xs.drop(xs.length() - length()).iterator(); + + while (i.hasNext() && j.hasNext()) { + if (!eq.eq(i.next(), j.next())) { + return false; + } + } + + return !i.hasNext(); + } + /** * First-class length. * diff --git a/core/src/test/java/fj/data/properties/ListProperties.java b/core/src/test/java/fj/data/properties/ListProperties.java new file mode 100644 index 00000000..b786ba06 --- /dev/null +++ b/core/src/test/java/fj/data/properties/ListProperties.java @@ -0,0 +1,57 @@ +package fj.data.properties; + +import fj.Equal; +import fj.P; +import fj.P2; +import fj.data.List; +import fj.runner.PropertyTestRunner; +import fj.test.Gen; +import fj.test.Property; +import org.junit.runner.RunWith; + +import static fj.test.Arbitrary.*; +import static fj.test.Property.implies; +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static fj.Equal.intEqual; + +/** + * Created by Zheka Kozlov on 02.06.2015. + */ +@RunWith(PropertyTestRunner.class) +public class ListProperties { + + public Property isPrefixOf() { + final Gen, Integer>> gen = arbList(arbInteger).gen.bind(list -> + Gen.choose(0, list.length()).map(i -> P.p(list, i))); + + return property(arbitrary(gen), pair -> prop(pair._1().take(pair._2()).isPrefixOf(intEqual, pair._1()))); + } + + public Property isSuffixOf() { + final Gen, Integer>> gen = arbList(arbInteger).gen.bind(list -> + Gen.choose(0, list.length()).map(i -> P.p(list, i))); + + return property(arbitrary(gen), pair -> prop(pair._1().drop(pair._2()).isSuffixOf(intEqual, pair._1()))); + } + + public Property isPrefixOfShorter() { + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + implies(list1.length() > list2.length(), () -> prop(!list1.isPrefixOf(intEqual, list2)))); + } + + public Property isSuffixOfShorter() { + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + implies(list1.length() > list2.length(), () -> prop(!list1.isSuffixOf(intEqual, list2)))); + } + + public Property isPrefixOfDifferentHeads() { + return property(arbList(arbInteger), arbList(arbInteger), arbInteger, arbInteger, (list1, list2, h1, h2) -> + implies(intEqual.notEq(h1, h2), () -> prop(!list1.cons(h1).isPrefixOf(intEqual, list2.cons(h2))))); + } + + public Property isSuffixOfDifferentHeads() { + return property(arbList(arbInteger), arbList(arbInteger), arbInteger, arbInteger, (list1, list2, h1, h2) -> + implies(intEqual.notEq(h1, h2), () -> prop(!list1.snoc(h1).isSuffixOf(intEqual, list2.snoc(h2))))); + } +} From 4f483178dd7c97a01f65ffff770eae51165d09ec Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Jun 2015 19:44:38 +1000 Subject: [PATCH 308/811] Test that Rand.standard's choose method is inclusive of max parameter --- core/src/test/java/fj/test/TestRand.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core/src/test/java/fj/test/TestRand.java diff --git a/core/src/test/java/fj/test/TestRand.java b/core/src/test/java/fj/test/TestRand.java new file mode 100644 index 00000000..9df9639a --- /dev/null +++ b/core/src/test/java/fj/test/TestRand.java @@ -0,0 +1,24 @@ +package fj.test; + +import fj.Ord; +import fj.data.Stream; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 4/06/2015. + */ +public class TestRand { + + @Test + public void testRandLowHighInclusive() { + int min = 5; + int max = 10; + int n = 100; + Stream s = Stream.range(0, n).map(i -> Rand.standard.choose(min, max)).sort(Ord.intOrd); +// System.out.println(s); + assertTrue(s.head() == min && s.last() == max); + } + +} From 71ab66b2f98d0a5dd99b7ac9a869ddcbb306dd2d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Jun 2015 21:50:15 +1000 Subject: [PATCH 309/811] issue #147: Split property tests into separate component --- build.gradle | 2 +- core/src/test/java/fj/data/BooleansTest.java | 1 - demo/build.gradle | 1 + quickcheck/build.gradle | 13 +++++++++++++ .../src/main/java/fj/test/Arbitrary.java | 0 {core => quickcheck}/src/main/java/fj/test/Arg.java | 0 .../src/main/java/fj/test/Bool.java | 0 .../src/main/java/fj/test/CheckResult.java | 0 .../src/main/java/fj/test/Coarbitrary.java | 0 {core => quickcheck}/src/main/java/fj/test/Gen.java | 0 .../src/main/java/fj/test/Property.java | 0 .../src/main/java/fj/test/Rand.java | 0 .../src/main/java/fj/test/Result.java | 0 .../src/main/java/fj/test/Shrink.java | 0 .../src/main/java/fj/test/Variant.java | 0 .../src/main/java/fj/test/package-info.java | 0 .../src/main/java/fj/test/reflect/Category.java | 0 .../src/main/java/fj/test/reflect/Check.java | 0 .../src/main/java/fj/test/reflect/CheckParams.java | 0 .../src/main/java/fj/test/reflect/Main.java | 0 .../src/main/java/fj/test/reflect/Name.java | 0 .../src/main/java/fj/test/reflect/NoCheck.java | 0 .../src/main/java/fj/test/reflect/package-info.java | 0 settings.gradle | 2 +- tests-quickcheck/build.gradle | 13 +++++++++++++ .../src/test/java/fj/MemoisationTest.java | 0 .../src/test/java/fj/data/ReaderTest.java | 0 .../src/test/java/fj/data/TestRngState.java | 0 .../src/test/java/fj/data/WriterTest.java | 0 .../java/fj/data/properties/ListProperties.java | 0 .../fj/data/properties/NonEmptyListProperties.java | 0 .../test/java/fj/data/properties/SeqProperties.java | 0 .../src/test/java/fj/data/test/PropertyAssert.java | 0 .../src/test/java/fj/data/test/TestCheck.java | 0 .../src/test/java/fj/data/test/TestNull.java | 0 .../src/test/java/fj/data}/test/TestRand.java | 0 .../src/test/java/fj/runner/PropertyTestRunner.java | 0 37 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 quickcheck/build.gradle rename {core => quickcheck}/src/main/java/fj/test/Arbitrary.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Arg.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Bool.java (100%) rename {core => quickcheck}/src/main/java/fj/test/CheckResult.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Coarbitrary.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Gen.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Property.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Rand.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Result.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Shrink.java (100%) rename {core => quickcheck}/src/main/java/fj/test/Variant.java (100%) rename {core => quickcheck}/src/main/java/fj/test/package-info.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/Category.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/Check.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/CheckParams.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/Main.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/Name.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/NoCheck.java (100%) rename {core => quickcheck}/src/main/java/fj/test/reflect/package-info.java (100%) create mode 100644 tests-quickcheck/build.gradle rename {core => tests-quickcheck}/src/test/java/fj/MemoisationTest.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/ReaderTest.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/TestRngState.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/WriterTest.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/properties/ListProperties.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/properties/NonEmptyListProperties.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/properties/SeqProperties.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/test/PropertyAssert.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/test/TestCheck.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/data/test/TestNull.java (100%) rename {core/src/test/java/fj => tests-quickcheck/src/test/java/fj/data}/test/TestRand.java (100%) rename {core => tests-quickcheck}/src/test/java/fj/runner/PropertyTestRunner.java (100%) diff --git a/build.gradle b/build.gradle index 86020a73..8bf09b4f 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ subprojects { } } -configure(subprojects) { +configure(subprojects.findAll { it.name != "tests-quickcheck" }) { apply plugin: "maven" apply plugin: "signing" diff --git a/core/src/test/java/fj/data/BooleansTest.java b/core/src/test/java/fj/data/BooleansTest.java index c2a799e7..b924a7c8 100644 --- a/core/src/test/java/fj/data/BooleansTest.java +++ b/core/src/test/java/fj/data/BooleansTest.java @@ -2,7 +2,6 @@ import fj.F; import fj.function.Booleans; -import fj.test.Property; import org.junit.Assert; import org.junit.Test; diff --git a/demo/build.gradle b/demo/build.gradle index 6d95183f..b8372c79 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -13,5 +13,6 @@ retrolambda { dependencies { compile project(":core") + compile project(":quickcheck") testCompile dependencyJunit } diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle new file mode 100644 index 00000000..6796a7cd --- /dev/null +++ b/quickcheck/build.gradle @@ -0,0 +1,13 @@ + +apply plugin: 'me.tatarka.retrolambda' + +retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 +} + +dependencies { + compile project(":core") + testCompile dependencyJunit +} diff --git a/core/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java similarity index 100% rename from core/src/main/java/fj/test/Arbitrary.java rename to quickcheck/src/main/java/fj/test/Arbitrary.java diff --git a/core/src/main/java/fj/test/Arg.java b/quickcheck/src/main/java/fj/test/Arg.java similarity index 100% rename from core/src/main/java/fj/test/Arg.java rename to quickcheck/src/main/java/fj/test/Arg.java diff --git a/core/src/main/java/fj/test/Bool.java b/quickcheck/src/main/java/fj/test/Bool.java similarity index 100% rename from core/src/main/java/fj/test/Bool.java rename to quickcheck/src/main/java/fj/test/Bool.java diff --git a/core/src/main/java/fj/test/CheckResult.java b/quickcheck/src/main/java/fj/test/CheckResult.java similarity index 100% rename from core/src/main/java/fj/test/CheckResult.java rename to quickcheck/src/main/java/fj/test/CheckResult.java diff --git a/core/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java similarity index 100% rename from core/src/main/java/fj/test/Coarbitrary.java rename to quickcheck/src/main/java/fj/test/Coarbitrary.java diff --git a/core/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java similarity index 100% rename from core/src/main/java/fj/test/Gen.java rename to quickcheck/src/main/java/fj/test/Gen.java diff --git a/core/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java similarity index 100% rename from core/src/main/java/fj/test/Property.java rename to quickcheck/src/main/java/fj/test/Property.java diff --git a/core/src/main/java/fj/test/Rand.java b/quickcheck/src/main/java/fj/test/Rand.java similarity index 100% rename from core/src/main/java/fj/test/Rand.java rename to quickcheck/src/main/java/fj/test/Rand.java diff --git a/core/src/main/java/fj/test/Result.java b/quickcheck/src/main/java/fj/test/Result.java similarity index 100% rename from core/src/main/java/fj/test/Result.java rename to quickcheck/src/main/java/fj/test/Result.java diff --git a/core/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java similarity index 100% rename from core/src/main/java/fj/test/Shrink.java rename to quickcheck/src/main/java/fj/test/Shrink.java diff --git a/core/src/main/java/fj/test/Variant.java b/quickcheck/src/main/java/fj/test/Variant.java similarity index 100% rename from core/src/main/java/fj/test/Variant.java rename to quickcheck/src/main/java/fj/test/Variant.java diff --git a/core/src/main/java/fj/test/package-info.java b/quickcheck/src/main/java/fj/test/package-info.java similarity index 100% rename from core/src/main/java/fj/test/package-info.java rename to quickcheck/src/main/java/fj/test/package-info.java diff --git a/core/src/main/java/fj/test/reflect/Category.java b/quickcheck/src/main/java/fj/test/reflect/Category.java similarity index 100% rename from core/src/main/java/fj/test/reflect/Category.java rename to quickcheck/src/main/java/fj/test/reflect/Category.java diff --git a/core/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java similarity index 100% rename from core/src/main/java/fj/test/reflect/Check.java rename to quickcheck/src/main/java/fj/test/reflect/Check.java diff --git a/core/src/main/java/fj/test/reflect/CheckParams.java b/quickcheck/src/main/java/fj/test/reflect/CheckParams.java similarity index 100% rename from core/src/main/java/fj/test/reflect/CheckParams.java rename to quickcheck/src/main/java/fj/test/reflect/CheckParams.java diff --git a/core/src/main/java/fj/test/reflect/Main.java b/quickcheck/src/main/java/fj/test/reflect/Main.java similarity index 100% rename from core/src/main/java/fj/test/reflect/Main.java rename to quickcheck/src/main/java/fj/test/reflect/Main.java diff --git a/core/src/main/java/fj/test/reflect/Name.java b/quickcheck/src/main/java/fj/test/reflect/Name.java similarity index 100% rename from core/src/main/java/fj/test/reflect/Name.java rename to quickcheck/src/main/java/fj/test/reflect/Name.java diff --git a/core/src/main/java/fj/test/reflect/NoCheck.java b/quickcheck/src/main/java/fj/test/reflect/NoCheck.java similarity index 100% rename from core/src/main/java/fj/test/reflect/NoCheck.java rename to quickcheck/src/main/java/fj/test/reflect/NoCheck.java diff --git a/core/src/main/java/fj/test/reflect/package-info.java b/quickcheck/src/main/java/fj/test/reflect/package-info.java similarity index 100% rename from core/src/main/java/fj/test/reflect/package-info.java rename to quickcheck/src/main/java/fj/test/reflect/package-info.java diff --git a/settings.gradle b/settings.gradle index 0476f8a9..df29ba3e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = "functionaljava" -include 'core', 'demo', "tests", "consume", "java8" +include 'core', 'demo', "tests", "consume", "java8", "quickcheck", "tests-quickcheck" diff --git a/tests-quickcheck/build.gradle b/tests-quickcheck/build.gradle new file mode 100644 index 00000000..961d08da --- /dev/null +++ b/tests-quickcheck/build.gradle @@ -0,0 +1,13 @@ + +apply plugin: 'me.tatarka.retrolambda' + +retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 +} + +dependencies { + compile project(":quickcheck") + testCompile dependencyJunit +} diff --git a/core/src/test/java/fj/MemoisationTest.java b/tests-quickcheck/src/test/java/fj/MemoisationTest.java similarity index 100% rename from core/src/test/java/fj/MemoisationTest.java rename to tests-quickcheck/src/test/java/fj/MemoisationTest.java diff --git a/core/src/test/java/fj/data/ReaderTest.java b/tests-quickcheck/src/test/java/fj/data/ReaderTest.java similarity index 100% rename from core/src/test/java/fj/data/ReaderTest.java rename to tests-quickcheck/src/test/java/fj/data/ReaderTest.java diff --git a/core/src/test/java/fj/data/TestRngState.java b/tests-quickcheck/src/test/java/fj/data/TestRngState.java similarity index 100% rename from core/src/test/java/fj/data/TestRngState.java rename to tests-quickcheck/src/test/java/fj/data/TestRngState.java diff --git a/core/src/test/java/fj/data/WriterTest.java b/tests-quickcheck/src/test/java/fj/data/WriterTest.java similarity index 100% rename from core/src/test/java/fj/data/WriterTest.java rename to tests-quickcheck/src/test/java/fj/data/WriterTest.java diff --git a/core/src/test/java/fj/data/properties/ListProperties.java b/tests-quickcheck/src/test/java/fj/data/properties/ListProperties.java similarity index 100% rename from core/src/test/java/fj/data/properties/ListProperties.java rename to tests-quickcheck/src/test/java/fj/data/properties/ListProperties.java diff --git a/core/src/test/java/fj/data/properties/NonEmptyListProperties.java b/tests-quickcheck/src/test/java/fj/data/properties/NonEmptyListProperties.java similarity index 100% rename from core/src/test/java/fj/data/properties/NonEmptyListProperties.java rename to tests-quickcheck/src/test/java/fj/data/properties/NonEmptyListProperties.java diff --git a/core/src/test/java/fj/data/properties/SeqProperties.java b/tests-quickcheck/src/test/java/fj/data/properties/SeqProperties.java similarity index 100% rename from core/src/test/java/fj/data/properties/SeqProperties.java rename to tests-quickcheck/src/test/java/fj/data/properties/SeqProperties.java diff --git a/core/src/test/java/fj/data/test/PropertyAssert.java b/tests-quickcheck/src/test/java/fj/data/test/PropertyAssert.java similarity index 100% rename from core/src/test/java/fj/data/test/PropertyAssert.java rename to tests-quickcheck/src/test/java/fj/data/test/PropertyAssert.java diff --git a/core/src/test/java/fj/data/test/TestCheck.java b/tests-quickcheck/src/test/java/fj/data/test/TestCheck.java similarity index 100% rename from core/src/test/java/fj/data/test/TestCheck.java rename to tests-quickcheck/src/test/java/fj/data/test/TestCheck.java diff --git a/core/src/test/java/fj/data/test/TestNull.java b/tests-quickcheck/src/test/java/fj/data/test/TestNull.java similarity index 100% rename from core/src/test/java/fj/data/test/TestNull.java rename to tests-quickcheck/src/test/java/fj/data/test/TestNull.java diff --git a/core/src/test/java/fj/test/TestRand.java b/tests-quickcheck/src/test/java/fj/data/test/TestRand.java similarity index 100% rename from core/src/test/java/fj/test/TestRand.java rename to tests-quickcheck/src/test/java/fj/data/test/TestRand.java diff --git a/core/src/test/java/fj/runner/PropertyTestRunner.java b/tests-quickcheck/src/test/java/fj/runner/PropertyTestRunner.java similarity index 100% rename from core/src/test/java/fj/runner/PropertyTestRunner.java rename to tests-quickcheck/src/test/java/fj/runner/PropertyTestRunner.java From c0f5131aeac0a78f53ed13e76d2b7e1fd2a28d59 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Jun 2015 22:23:42 +1000 Subject: [PATCH 310/811] Set artifact name for quickcheck module --- quickcheck/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 6796a7cd..f44b1931 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'me.tatarka.retrolambda' +archivesBaseName = "${project.projectName}-${project.name}" + retrolambda { jdk System.getenv("JAVA8_HOME") oldJdk System.getenv("JAVA7_HOME") From 64fc2cc97efa97d69292fecf0bd5929a957aa934 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 4 Jun 2015 22:40:34 +1000 Subject: [PATCH 311/811] #147: Renamed test component name --- build.gradle | 2 +- {tests => props-core-scalacheck}/build.gradle | 0 .../src/main/scala/fj/ArbitraryP.scala | 0 .../src/main/scala/fj/control/parallel/ArbitraryParModule.scala | 0 .../src/main/scala/fj/control/parallel/ArbitraryStrategy.scala | 0 .../src/main/scala/fj/data/ArbitraryArray.scala | 0 .../src/main/scala/fj/data/ArbitraryHashMap.scala | 0 .../src/main/scala/fj/data/ArbitraryHashSet.scala | 0 .../src/main/scala/fj/data/ArbitraryList.scala | 0 .../src/main/scala/fj/data/ArbitraryOption.scala | 0 .../src/main/scala/fj/data/ArbitrarySet.scala | 0 .../src/main/scala/fj/data/ArbitraryStream.scala | 0 .../src/main/scala/fj/data/ArbitraryTree.scala | 0 .../src/main/scala/fj/data/ArbitraryTreeMap.scala | 0 .../src/main/scala/fj/data/optic/IsoLaws.scala | 0 .../src/main/scala/fj/data/optic/LensLaws.scala | 0 .../src/main/scala/fj/data/optic/OptionalLaws.scala | 0 .../src/main/scala/fj/data/optic/PrismLaws.scala | 0 .../src/main/scala/fj/data/optic/SetterLaws.scala | 0 .../src/main/scala/fj/data/optic/TraversalLaws.scala | 0 .../src/main/scala/fj/package.scala | 0 .../src/test/scala/fj/FunctionalJavaJUnitTest.java | 0 .../src/test/scala/fj/Implicit.scala | 0 {tests => props-core-scalacheck}/src/test/scala/fj/Tests.scala | 0 .../src/test/scala/fj/control/parallel/CheckParModule.scala | 0 .../src/test/scala/fj/control/parallel/CheckStrategy.scala | 0 .../src/test/scala/fj/data/CheckArray.scala | 0 .../src/test/scala/fj/data/CheckHashMap.scala | 0 .../src/test/scala/fj/data/CheckHashSet.scala | 0 .../src/test/scala/fj/data/CheckIO.scala | 0 .../src/test/scala/fj/data/CheckIteratee.scala | 0 .../src/test/scala/fj/data/CheckList.scala | 0 .../src/test/scala/fj/data/CheckOption.scala | 0 .../src/test/scala/fj/data/CheckSet.scala | 0 .../src/test/scala/fj/data/CheckStream.scala | 0 .../src/test/scala/fj/data/CheckTree.scala | 0 .../src/test/scala/fj/data/CheckTreeMap.scala | 0 {tests-quickcheck => props-core}/build.gradle | 0 .../src/test/java/fj/MemoisationTest.java | 0 .../src/test/java/fj/data/ReaderTest.java | 0 .../src/test/java/fj/data/TestRngState.java | 0 .../src/test/java/fj/data/WriterTest.java | 0 .../src/test/java/fj/data/properties/ListProperties.java | 0 .../test/java/fj/data/properties/NonEmptyListProperties.java | 0 .../src/test/java/fj/data/properties/SeqProperties.java | 0 .../src/test/java/fj/data/test/PropertyAssert.java | 0 .../src/test/java/fj/data/test/TestCheck.java | 0 .../src/test/java/fj/data/test/TestNull.java | 0 .../src/test/java/fj/data/test/TestRand.java | 0 .../src/test/java/fj/runner/PropertyTestRunner.java | 0 settings.gradle | 2 +- 51 files changed, 2 insertions(+), 2 deletions(-) rename {tests => props-core-scalacheck}/build.gradle (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/ArbitraryP.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/control/parallel/ArbitraryParModule.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryArray.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryHashMap.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryHashSet.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryList.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryOption.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitrarySet.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryStream.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryTree.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/ArbitraryTreeMap.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/optic/IsoLaws.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/optic/LensLaws.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/optic/OptionalLaws.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/optic/PrismLaws.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/optic/SetterLaws.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/data/optic/TraversalLaws.scala (100%) rename {tests => props-core-scalacheck}/src/main/scala/fj/package.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/FunctionalJavaJUnitTest.java (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/Implicit.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/Tests.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/control/parallel/CheckParModule.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/control/parallel/CheckStrategy.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckArray.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckHashMap.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckHashSet.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckIO.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckIteratee.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckList.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckOption.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckSet.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckStream.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckTree.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/data/CheckTreeMap.scala (100%) rename {tests-quickcheck => props-core}/build.gradle (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/MemoisationTest.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/ReaderTest.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/TestRngState.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/WriterTest.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/properties/ListProperties.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/properties/NonEmptyListProperties.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/properties/SeqProperties.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/test/PropertyAssert.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/test/TestCheck.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/test/TestNull.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/data/test/TestRand.java (100%) rename {tests-quickcheck => props-core}/src/test/java/fj/runner/PropertyTestRunner.java (100%) diff --git a/build.gradle b/build.gradle index 8bf09b4f..5a2f1472 100644 --- a/build.gradle +++ b/build.gradle @@ -85,7 +85,7 @@ subprojects { } } -configure(subprojects.findAll { it.name != "tests-quickcheck" }) { +configure(subprojects.findAll { it.name != "props-core" }) { apply plugin: "maven" apply plugin: "signing" diff --git a/tests/build.gradle b/props-core-scalacheck/build.gradle similarity index 100% rename from tests/build.gradle rename to props-core-scalacheck/build.gradle diff --git a/tests/src/main/scala/fj/ArbitraryP.scala b/props-core-scalacheck/src/main/scala/fj/ArbitraryP.scala similarity index 100% rename from tests/src/main/scala/fj/ArbitraryP.scala rename to props-core-scalacheck/src/main/scala/fj/ArbitraryP.scala diff --git a/tests/src/main/scala/fj/control/parallel/ArbitraryParModule.scala b/props-core-scalacheck/src/main/scala/fj/control/parallel/ArbitraryParModule.scala similarity index 100% rename from tests/src/main/scala/fj/control/parallel/ArbitraryParModule.scala rename to props-core-scalacheck/src/main/scala/fj/control/parallel/ArbitraryParModule.scala diff --git a/tests/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala b/props-core-scalacheck/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala similarity index 100% rename from tests/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala rename to props-core-scalacheck/src/main/scala/fj/control/parallel/ArbitraryStrategy.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryArray.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryArray.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryArray.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryArray.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryHashMap.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryHashMap.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryHashMap.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryHashMap.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryHashSet.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryHashSet.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryHashSet.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryHashSet.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryList.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryList.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryList.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryList.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryOption.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryOption.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryOption.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryOption.scala diff --git a/tests/src/main/scala/fj/data/ArbitrarySet.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitrarySet.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitrarySet.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitrarySet.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryStream.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryStream.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryStream.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryStream.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryTree.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryTree.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryTree.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryTree.scala diff --git a/tests/src/main/scala/fj/data/ArbitraryTreeMap.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryTreeMap.scala similarity index 100% rename from tests/src/main/scala/fj/data/ArbitraryTreeMap.scala rename to props-core-scalacheck/src/main/scala/fj/data/ArbitraryTreeMap.scala diff --git a/tests/src/main/scala/fj/data/optic/IsoLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/IsoLaws.scala similarity index 100% rename from tests/src/main/scala/fj/data/optic/IsoLaws.scala rename to props-core-scalacheck/src/main/scala/fj/data/optic/IsoLaws.scala diff --git a/tests/src/main/scala/fj/data/optic/LensLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/LensLaws.scala similarity index 100% rename from tests/src/main/scala/fj/data/optic/LensLaws.scala rename to props-core-scalacheck/src/main/scala/fj/data/optic/LensLaws.scala diff --git a/tests/src/main/scala/fj/data/optic/OptionalLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/OptionalLaws.scala similarity index 100% rename from tests/src/main/scala/fj/data/optic/OptionalLaws.scala rename to props-core-scalacheck/src/main/scala/fj/data/optic/OptionalLaws.scala diff --git a/tests/src/main/scala/fj/data/optic/PrismLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/PrismLaws.scala similarity index 100% rename from tests/src/main/scala/fj/data/optic/PrismLaws.scala rename to props-core-scalacheck/src/main/scala/fj/data/optic/PrismLaws.scala diff --git a/tests/src/main/scala/fj/data/optic/SetterLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/SetterLaws.scala similarity index 100% rename from tests/src/main/scala/fj/data/optic/SetterLaws.scala rename to props-core-scalacheck/src/main/scala/fj/data/optic/SetterLaws.scala diff --git a/tests/src/main/scala/fj/data/optic/TraversalLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/TraversalLaws.scala similarity index 100% rename from tests/src/main/scala/fj/data/optic/TraversalLaws.scala rename to props-core-scalacheck/src/main/scala/fj/data/optic/TraversalLaws.scala diff --git a/tests/src/main/scala/fj/package.scala b/props-core-scalacheck/src/main/scala/fj/package.scala similarity index 100% rename from tests/src/main/scala/fj/package.scala rename to props-core-scalacheck/src/main/scala/fj/package.scala diff --git a/tests/src/test/scala/fj/FunctionalJavaJUnitTest.java b/props-core-scalacheck/src/test/scala/fj/FunctionalJavaJUnitTest.java similarity index 100% rename from tests/src/test/scala/fj/FunctionalJavaJUnitTest.java rename to props-core-scalacheck/src/test/scala/fj/FunctionalJavaJUnitTest.java diff --git a/tests/src/test/scala/fj/Implicit.scala b/props-core-scalacheck/src/test/scala/fj/Implicit.scala similarity index 100% rename from tests/src/test/scala/fj/Implicit.scala rename to props-core-scalacheck/src/test/scala/fj/Implicit.scala diff --git a/tests/src/test/scala/fj/Tests.scala b/props-core-scalacheck/src/test/scala/fj/Tests.scala similarity index 100% rename from tests/src/test/scala/fj/Tests.scala rename to props-core-scalacheck/src/test/scala/fj/Tests.scala diff --git a/tests/src/test/scala/fj/control/parallel/CheckParModule.scala b/props-core-scalacheck/src/test/scala/fj/control/parallel/CheckParModule.scala similarity index 100% rename from tests/src/test/scala/fj/control/parallel/CheckParModule.scala rename to props-core-scalacheck/src/test/scala/fj/control/parallel/CheckParModule.scala diff --git a/tests/src/test/scala/fj/control/parallel/CheckStrategy.scala b/props-core-scalacheck/src/test/scala/fj/control/parallel/CheckStrategy.scala similarity index 100% rename from tests/src/test/scala/fj/control/parallel/CheckStrategy.scala rename to props-core-scalacheck/src/test/scala/fj/control/parallel/CheckStrategy.scala diff --git a/tests/src/test/scala/fj/data/CheckArray.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckArray.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckArray.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckArray.scala diff --git a/tests/src/test/scala/fj/data/CheckHashMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckHashMap.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala diff --git a/tests/src/test/scala/fj/data/CheckHashSet.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashSet.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckHashSet.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckHashSet.scala diff --git a/tests/src/test/scala/fj/data/CheckIO.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckIO.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckIO.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckIO.scala diff --git a/tests/src/test/scala/fj/data/CheckIteratee.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckIteratee.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala diff --git a/tests/src/test/scala/fj/data/CheckList.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckList.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckList.scala diff --git a/tests/src/test/scala/fj/data/CheckOption.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckOption.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala diff --git a/tests/src/test/scala/fj/data/CheckSet.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckSet.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala diff --git a/tests/src/test/scala/fj/data/CheckStream.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckStream.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckStream.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckStream.scala diff --git a/tests/src/test/scala/fj/data/CheckTree.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckTree.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckTree.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckTree.scala diff --git a/tests/src/test/scala/fj/data/CheckTreeMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala similarity index 100% rename from tests/src/test/scala/fj/data/CheckTreeMap.scala rename to props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala diff --git a/tests-quickcheck/build.gradle b/props-core/build.gradle similarity index 100% rename from tests-quickcheck/build.gradle rename to props-core/build.gradle diff --git a/tests-quickcheck/src/test/java/fj/MemoisationTest.java b/props-core/src/test/java/fj/MemoisationTest.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/MemoisationTest.java rename to props-core/src/test/java/fj/MemoisationTest.java diff --git a/tests-quickcheck/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/ReaderTest.java rename to props-core/src/test/java/fj/data/ReaderTest.java diff --git a/tests-quickcheck/src/test/java/fj/data/TestRngState.java b/props-core/src/test/java/fj/data/TestRngState.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/TestRngState.java rename to props-core/src/test/java/fj/data/TestRngState.java diff --git a/tests-quickcheck/src/test/java/fj/data/WriterTest.java b/props-core/src/test/java/fj/data/WriterTest.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/WriterTest.java rename to props-core/src/test/java/fj/data/WriterTest.java diff --git a/tests-quickcheck/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/properties/ListProperties.java rename to props-core/src/test/java/fj/data/properties/ListProperties.java diff --git a/tests-quickcheck/src/test/java/fj/data/properties/NonEmptyListProperties.java b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/properties/NonEmptyListProperties.java rename to props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java diff --git a/tests-quickcheck/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/properties/SeqProperties.java rename to props-core/src/test/java/fj/data/properties/SeqProperties.java diff --git a/tests-quickcheck/src/test/java/fj/data/test/PropertyAssert.java b/props-core/src/test/java/fj/data/test/PropertyAssert.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/test/PropertyAssert.java rename to props-core/src/test/java/fj/data/test/PropertyAssert.java diff --git a/tests-quickcheck/src/test/java/fj/data/test/TestCheck.java b/props-core/src/test/java/fj/data/test/TestCheck.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/test/TestCheck.java rename to props-core/src/test/java/fj/data/test/TestCheck.java diff --git a/tests-quickcheck/src/test/java/fj/data/test/TestNull.java b/props-core/src/test/java/fj/data/test/TestNull.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/test/TestNull.java rename to props-core/src/test/java/fj/data/test/TestNull.java diff --git a/tests-quickcheck/src/test/java/fj/data/test/TestRand.java b/props-core/src/test/java/fj/data/test/TestRand.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/data/test/TestRand.java rename to props-core/src/test/java/fj/data/test/TestRand.java diff --git a/tests-quickcheck/src/test/java/fj/runner/PropertyTestRunner.java b/props-core/src/test/java/fj/runner/PropertyTestRunner.java similarity index 100% rename from tests-quickcheck/src/test/java/fj/runner/PropertyTestRunner.java rename to props-core/src/test/java/fj/runner/PropertyTestRunner.java diff --git a/settings.gradle b/settings.gradle index df29ba3e..cd29326d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = "functionaljava" -include 'core', 'demo', "tests", "consume", "java8", "quickcheck", "tests-quickcheck" +include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck" From a3407f62b6cc0f75319345af4276790f67511973 Mon Sep 17 00:00:00 2001 From: JB Giraudeau Date: Thu, 4 Jun 2015 15:29:24 +0200 Subject: [PATCH 312/811] Help type inference for old Javac compilers --- core/src/main/java/fj/data/optic/Optional.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index 7e981189..de63fc2d 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -223,7 +223,7 @@ public F> modifyTrampolineF(final F> f) { @Override public F> modifyPromiseF(final F> f) { - return s -> getOption.f(s).option( + return s -> getOption.f(s).> option( () -> Promise.promise(Strategy.idStrategy(), P.p(s)), t -> f.f(t).fmap(b -> set.f(b).f(s)) ); From 4509683abf75790d6d391ad840ec142e35c57dc5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Jun 2015 13:53:24 +1000 Subject: [PATCH 313/811] #147: Refactor to move quick tests from props-core --- quickcheck/build.gradle | 2 +- .../src/main}/java/fj/data/test/PropertyAssert.java | 0 .../src/main}/java/fj/runner/PropertyTestRunner.java | 0 .../src/test/java/fj/data/test/TestCheck.java | 0 .../src/test/java/fj/data/test/TestNull.java | 0 .../fj/data => quickcheck/src/test/java/fj}/test/TestRand.java | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename {props-core/src/test => quickcheck/src/main}/java/fj/data/test/PropertyAssert.java (100%) rename {props-core/src/test => quickcheck/src/main}/java/fj/runner/PropertyTestRunner.java (100%) rename {props-core => quickcheck}/src/test/java/fj/data/test/TestCheck.java (100%) rename {props-core => quickcheck}/src/test/java/fj/data/test/TestNull.java (100%) rename {props-core/src/test/java/fj/data => quickcheck/src/test/java/fj}/test/TestRand.java (100%) diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index f44b1931..25fd2e80 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -11,5 +11,5 @@ retrolambda { dependencies { compile project(":core") - testCompile dependencyJunit + compile dependencyJunit } diff --git a/props-core/src/test/java/fj/data/test/PropertyAssert.java b/quickcheck/src/main/java/fj/data/test/PropertyAssert.java similarity index 100% rename from props-core/src/test/java/fj/data/test/PropertyAssert.java rename to quickcheck/src/main/java/fj/data/test/PropertyAssert.java diff --git a/props-core/src/test/java/fj/runner/PropertyTestRunner.java b/quickcheck/src/main/java/fj/runner/PropertyTestRunner.java similarity index 100% rename from props-core/src/test/java/fj/runner/PropertyTestRunner.java rename to quickcheck/src/main/java/fj/runner/PropertyTestRunner.java diff --git a/props-core/src/test/java/fj/data/test/TestCheck.java b/quickcheck/src/test/java/fj/data/test/TestCheck.java similarity index 100% rename from props-core/src/test/java/fj/data/test/TestCheck.java rename to quickcheck/src/test/java/fj/data/test/TestCheck.java diff --git a/props-core/src/test/java/fj/data/test/TestNull.java b/quickcheck/src/test/java/fj/data/test/TestNull.java similarity index 100% rename from props-core/src/test/java/fj/data/test/TestNull.java rename to quickcheck/src/test/java/fj/data/test/TestNull.java diff --git a/props-core/src/test/java/fj/data/test/TestRand.java b/quickcheck/src/test/java/fj/test/TestRand.java similarity index 100% rename from props-core/src/test/java/fj/data/test/TestRand.java rename to quickcheck/src/test/java/fj/test/TestRand.java From d57372b3b0c71cfc9e58e02f0b71710a56c92e8a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Jun 2015 14:17:59 +1000 Subject: [PATCH 314/811] #147: Moved PropertyTestRunner to fj.test.runner --- .../src/test/java/fj/data/properties/ListProperties.java | 3 +-- .../test/java/fj/data/properties/NonEmptyListProperties.java | 2 +- props-core/src/test/java/fj/data/properties/SeqProperties.java | 2 +- .../src/main/java/fj/{ => test}/runner/PropertyTestRunner.java | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) rename quickcheck/src/main/java/fj/{ => test}/runner/PropertyTestRunner.java (98%) diff --git a/props-core/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java index b786ba06..6cc9053b 100644 --- a/props-core/src/test/java/fj/data/properties/ListProperties.java +++ b/props-core/src/test/java/fj/data/properties/ListProperties.java @@ -1,10 +1,9 @@ package fj.data.properties; -import fj.Equal; import fj.P; import fj.P2; import fj.data.List; -import fj.runner.PropertyTestRunner; +import fj.test.runner.PropertyTestRunner; import fj.test.Gen; import fj.test.Property; import org.junit.runner.RunWith; diff --git a/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java index 0781637a..70de05a2 100644 --- a/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java +++ b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java @@ -5,7 +5,7 @@ import fj.P2; import fj.data.List; import fj.data.NonEmptyList; -import fj.runner.PropertyTestRunner; +import fj.test.runner.PropertyTestRunner; import fj.test.Property; import org.junit.runner.RunWith; diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 098cd87d..5a4e298c 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -5,7 +5,7 @@ import fj.P2; import fj.data.Option; import fj.data.Seq; -import fj.runner.PropertyTestRunner; +import fj.test.runner.PropertyTestRunner; import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; diff --git a/quickcheck/src/main/java/fj/runner/PropertyTestRunner.java b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java similarity index 98% rename from quickcheck/src/main/java/fj/runner/PropertyTestRunner.java rename to quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java index ba5e2359..81c37754 100644 --- a/quickcheck/src/main/java/fj/runner/PropertyTestRunner.java +++ b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java @@ -1,4 +1,4 @@ -package fj.runner; +package fj.test.runner; import org.junit.runner.Description; import org.junit.runner.Runner; From 80c75abe24fe7e5f1933bdba7eaf0189f540925a Mon Sep 17 00:00:00 2001 From: orionll Date: Sun, 7 Jun 2015 21:40:04 +0600 Subject: [PATCH 315/811] Removed unnecessary wrapping into SoftReference --- core/src/main/java/fj/P.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 789f1d34..661d48a9 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -33,9 +33,10 @@ public P1 f(final A a) { */ public static P1 p(final A a) { return new P1() { - public A _1() { + @Override public A _1() { return a; } + @Override public P1 memo() { return this; } }; } From eaa03ca76ab57b2368b6a6d93ddfa29b3e1a4443 Mon Sep 17 00:00:00 2001 From: orionll Date: Mon, 8 Jun 2015 15:51:41 +0600 Subject: [PATCH 316/811] Replaced SoftReference with WeakReference for performance --- core/src/main/java/fj/P1.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 3e649103..5f5f1031 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -1,6 +1,6 @@ package fj; -import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; import fj.data.Array; import fj.data.List; @@ -216,7 +216,7 @@ public P1 memo() { final P1 self = this; return new P1() { private final Object latch = new Object(); - private volatile SoftReference> v = null; + private volatile WeakReference> v = null; @Override public A _1() { @@ -226,7 +226,7 @@ public A _1() { o = v != null ? v.get() : null; if (o == null) { o = Option.some(self._1()); - v = new SoftReference<>(o); + v = new WeakReference<>(o); } } } From 05f7dbf017b4816e3d96e049e0dda7b360e3608e Mon Sep 17 00:00:00 2001 From: orionll Date: Tue, 9 Jun 2015 15:46:02 +0600 Subject: [PATCH 317/811] Changed memo() to use strong references. Added weakMemo() and softMemo(). --- core/src/main/java/fj/P.java | 2 + core/src/main/java/fj/P1.java | 116 +++++++++++++++++-------- core/src/main/java/fj/data/Stream.java | 2 +- 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 661d48a9..cb732bce 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -37,6 +37,8 @@ public static P1 p(final A a) { return a; } @Override public P1 memo() { return this; } + @Override public P1 weakMemo() { return this; } + @Override public P1 softMemo() { return this; } }; } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 5f5f1031..0cd9fb62 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -1,5 +1,7 @@ package fj; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import fj.data.Array; @@ -208,53 +210,93 @@ public P1 map(final F f) { } /** - * Provides a memoising P1 that remembers its value. - * - * @return A P1 that calls this P1 once and remembers the value for subsequent calls. - */ - public P1 memo() { - final P1 self = this; - return new P1() { - private final Object latch = new Object(); - private volatile WeakReference> v = null; - - @Override - public A _1() { - Option o = v != null ? v.get() : null; - if (o == null) { - synchronized (latch) { - o = v != null ? v.get() : null; - if (o == null) { - o = Option.some(self._1()); - v = new WeakReference<>(o); - } - } - } - return o.some(); - } + * Returns a P1 that remembers its value. + * + * @return A P1 that calls this P1 once and remembers the value for subsequent calls. + */ + public P1 memo() { return new Memo<>(this); } - @Override - public P1 memo() { - return this; - } + /** + * Like memo, but the memoized value is wrapped into a WeakReference + */ + public P1 weakMemo() { return new WeakReferenceMemo<>(this); } - }; - } + /** + * Like memo, but the memoized value is wrapped into a SoftReference + */ + public P1 softMemo() { return new SoftReferenceMemo<>(this); } static P1 memo(F f) { return P.lazy(f).memo(); } - /** - * Returns a constant function that always uses this value. - * - * @return A constant function that always uses this value. - */ - public F constant() { + static class Memo extends P1 { + private final P1 self; + private volatile boolean initialized; + private A value; + + Memo(P1 self) { this.self = self; } + + @Override public A _1() { + if (!initialized) { + synchronized (this) { + if (!initialized) { + A a = self._1(); + value = a; + initialized = true; + return a; + } + } + } + return value; + } + + @Override public P1 memo() { return this; } + } + + abstract static class ReferenceMemo extends P1 { + private final P1 self; + private final Object latch = new Object(); + private volatile Reference> v = null; + + ReferenceMemo(final P1 self) { this.self = self; } - return b -> P1.this._1(); + @Override public A _1() { + Option o = v != null ? v.get() : null; + if (o == null) { + synchronized (latch) { + o = v != null ? v.get() : null; + if (o == null) { + o = Option.some(self._1()); + v = newReference(o); + } + } + } + return o.some(); } + abstract Reference> newReference(Option o); + } + + static class WeakReferenceMemo extends ReferenceMemo { + WeakReferenceMemo(P1 self) { super(self); } + @Override Reference> newReference(final Option o) { return new WeakReference<>(o); } + @Override public P1 weakMemo() { return this; } + } + + static class SoftReferenceMemo extends ReferenceMemo { + SoftReferenceMemo(P1 self) { super(self); } + @Override Reference> newReference(final Option o) { return new SoftReference<>(o); } + @Override public P1 softMemo() { return this; } + } + + /** + * Returns a constant function that always uses this value. + * + * @return A constant function that always uses this value. + */ + public F constant() { return Function.constant(_1()); } + @Override public String toString() { return Show.p1Show(Show.anyShow()).showS(this); diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 14f3803d..c74e7977 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1430,7 +1430,7 @@ private static final class Cons extends Stream { Cons(final A head, final P1> tail) { this.head = head; - this.tail = tail.memo(); + this.tail = tail.weakMemo(); } public A head() { From 5007203a77109c0a5978333f32b62f3e6c858d12 Mon Sep 17 00:00:00 2001 From: orionll Date: Thu, 11 Jun 2015 18:24:48 +0600 Subject: [PATCH 318/811] Fixed some methods that were implemented inefficiently or failed with StackOverflow. Added Ordering.reverse(), Ord.reverse(). --- core/src/main/java/fj/Ord.java | 27 ++++++++++++++----- core/src/main/java/fj/Ordering.java | 9 +++++++ core/src/main/java/fj/data/List.java | 19 ++++++------- core/src/main/java/fj/data/Stream.java | 5 +++- .../fj/data/properties/ListProperties.java | 13 +++++++++ .../properties/NonEmptyListProperties.java | 2 ++ .../fj/data/properties/SeqProperties.java | 2 ++ quickcheck/src/main/java/fj/test/Gen.java | 10 +------ .../src/main/java/fj/test/reflect/Check.java | 4 +-- 9 files changed, 63 insertions(+), 28 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 36ac45f4..fa612288 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -157,6 +157,8 @@ public A min(final A a1, final A a2) { */ public final F> min = curry((a, a1) -> min(a, a1)); + public final Ord reverse() { return ord(Function.flip(f)); } + /** * Returns an order instance that uses the given equality test and ordering function. * @@ -343,14 +345,25 @@ public static Ord> validationOrd(final Ord oa, final */ public static Ord> listOrd(final Ord oa) { return ord(l1 -> l2 -> { - if (l1.isEmpty()) - return l2.isEmpty() ? Ordering.EQ : Ordering.LT; - else if (l2.isEmpty()) - return l1.isEmpty() ? Ordering.EQ : Ordering.GT; - else { - final Ordering c = oa.compare(l1.head(), l2.head()); - return c == Ordering.EQ ? listOrd(oa).f.f(l1.tail()).f(l2.tail()) : c; + List x1 = l1; + List x2 = l2; + + while (x1.isNotEmpty() && x2.isNotEmpty()) { + final Ordering o = oa.compare(x1.head(), x2.head()); + if (o == Ordering.LT || o == Ordering.GT) { + return o; } + x1 = x1.tail(); + x2 = x2.tail(); + } + + if (x1.isEmpty() && x2.isEmpty()) { + return Ordering.EQ; + } else if (x1.isEmpty()) { + return Ordering.LT; + } else { + return Ordering.GT; + } }); } diff --git a/core/src/main/java/fj/Ordering.java b/core/src/main/java/fj/Ordering.java index 3e938181..b22bcfcb 100644 --- a/core/src/main/java/fj/Ordering.java +++ b/core/src/main/java/fj/Ordering.java @@ -23,6 +23,15 @@ public enum Ordering { GT; public int toInt() { return ordinal() - 1 ; } + + public Ordering reverse() { + switch (this) { + case LT: return GT; + case GT: return LT; + } + return EQ; + } + public static Ordering fromInt(int cmp) { return cmp == 0 ? EQ : cmp > 0 ? GT : LT; } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 1793af95..cf255fed 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -15,10 +15,8 @@ import fj.P2; import fj.Show; import fj.Unit; -import static fj.Function.curry; -import static fj.Function.constant; -import static fj.Function.identity; -import static fj.Function.compose; + +import static fj.Function.*; import static fj.P.p; import static fj.P.p2; import static fj.Unit.unit; @@ -169,9 +167,10 @@ public final Stream toStream() { */ @SuppressWarnings({"unchecked"}) public final Array toArray() { - final Object[] a = new Object[length()]; + final int length = length(); + final Object[] a = new Object[length]; List x = this; - for (int i = 0; i < length(); i++) { + for (int i = 0; i < length; i++) { a[i] = x.head(); x = x.tail(); } @@ -629,14 +628,14 @@ public final List append(final List as) { } /** - * Performs a right-fold reduction across this list. This function uses O(length) stack space. + * Performs a right-fold reduction across this list. * * @param f The function to apply on each element of the list. * @param b The beginning value to start the application from. * @return The final result after the right-fold reduction. */ public final B foldRight(final F> f, final B b) { - return isEmpty() ? b : f.f(head()).f(tail().foldRight(f, b)); + return reverse().foldLeft(flip(f), b); } /** @@ -1581,7 +1580,9 @@ public static P2, List> unzip(final List> xs) { * @return A list of the given value replicated the given number of times. */ public static List replicate(final int n, final A a) { - return n <= 0 ? List.nil() : replicate(n - 1, a).cons(a); + List list = List.nil(); + for (int i = 0; i < n; i++) { list = list.cons(a); } + return list; } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index c74e7977..9cf033b2 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1233,7 +1233,10 @@ public final A index(final int i) { * false otherwise. */ public final boolean forall(final F f) { - return isEmpty() || f.f(head()) && tail()._1().forall(f); + for (final A a : this) { + if (!f.f(a)) return false; + } + return true; } @Override diff --git a/props-core/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java index 6cc9053b..974d63e2 100644 --- a/props-core/src/test/java/fj/data/properties/ListProperties.java +++ b/props-core/src/test/java/fj/data/properties/ListProperties.java @@ -1,8 +1,10 @@ package fj.data.properties; +import fj.Ord; import fj.P; import fj.P2; import fj.data.List; +import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; import fj.test.Gen; import fj.test.Property; @@ -18,6 +20,7 @@ * Created by Zheka Kozlov on 02.06.2015. */ @RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) public class ListProperties { public Property isPrefixOf() { @@ -53,4 +56,14 @@ public Property isSuffixOfDifferentHeads() { return property(arbList(arbInteger), arbList(arbInteger), arbInteger, arbInteger, (list1, list2, h1, h2) -> implies(intEqual.notEq(h1, h2), () -> prop(!list1.snoc(h1).isSuffixOf(intEqual, list2.snoc(h2))))); } + + public Property listOrdEqual() { + return property(arbList(arbInteger), list -> prop(Ord.listOrd(Ord.intOrd).equal().eq(list, list))); + } + + public Property listOrdReverse() { + final Ord> ord = Ord.listOrd(Ord.intOrd); + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + prop(ord.compare(list1, list2) == ord.reverse().compare(list1, list2).reverse())); + } } diff --git a/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java index 70de05a2..256fb3a8 100644 --- a/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java +++ b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java @@ -5,6 +5,7 @@ import fj.P2; import fj.data.List; import fj.data.NonEmptyList; +import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; import fj.test.Property; import org.junit.runner.RunWith; @@ -28,6 +29,7 @@ * Created by Zheka Kozlov on 02.06.2015. */ @RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) public class NonEmptyListProperties { private static final Equal> eq = nonEmptyListEqual(intEqual); diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 5a4e298c..9ce0bdc3 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -5,6 +5,7 @@ import fj.P2; import fj.data.Option; import fj.data.Seq; +import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; import fj.test.Arbitrary; import fj.test.Gen; @@ -24,6 +25,7 @@ * Created by Zheka Kozlov on 01.06.2015. */ @RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) public class SeqProperties { public Property consHead() { diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 7b582a2a..b56e080c 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -337,15 +337,7 @@ public static Gen gen(final F> f) { * @return A generator of lists after sequencing the given generators. */ public static Gen> sequence(final List> gs) { - return gs.foldRight(new F, F>, Gen>>>() { - public F>, Gen>> f(final Gen ga) { - return new F>, Gen>>() { - public Gen> f(final Gen> gas) { - return ga.bind(gas, List.cons()); - } - }; - } - }, value(List.nil())); + return gen(i -> r -> gs.map(g -> g.gen(i, r))); } /** diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index b2adb9c9..199f399a 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -273,7 +273,7 @@ public T f(final Constructor ctor) { ctor.setAccessible(true); return ctor.newInstance(); } catch(Exception e) { - throw error(e.toString()); + throw new Error(e.getMessage(), e); } } }); @@ -324,7 +324,7 @@ public P3> f(final PropertyMember m) { final String name = fromNull(m.element().getAnnotation(Name.class)).map(nameS).orSome(m.name()); return p(m.invoke(t.orSome(P.p(null))), name, params); } catch(Exception e) { - throw error(e.toString()); + throw new Error(e.getMessage(), e); } } }); From 81daa763849a0e4f313a57d9770a93d1e47daaf8 Mon Sep 17 00:00:00 2001 From: orionll Date: Fri, 12 Jun 2015 14:23:14 +0600 Subject: [PATCH 319/811] Added Monoid.multiply() --- core/src/main/java/fj/Monoid.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 71750f00..4809ef2c 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -89,6 +89,18 @@ public A zero() { return zero; } + /** + * Returns a value summed n times (a + a + ... + a) + * @param n multiplier + * @param a the value to multiply + * @return a summed n times. If n <= 0, returns zero() + */ + public A multiply(final int n, final A a) { + A m = zero(); + for (int i = 0; i < n; i++) { m = sum(m, a); } + return m; + } + /** * Sums the given values with right-fold. * From 0906174c819614637b91187e8a03427f76d0b4ea Mon Sep 17 00:00:00 2001 From: orionll Date: Fri, 12 Jun 2015 17:22:46 +0600 Subject: [PATCH 320/811] List.append() was implemented ineffectively. Added Buffer.isEmpty(), Buffer.prependToList(). --- core/src/main/java/fj/data/List.java | 32 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index cf255fed..720c49ce 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -624,7 +624,7 @@ public final List apply(final List> lf) { * @return A new list that has appended the given list. */ public final List append(final List as) { - return fromList(this).append(as).toList(); + return Buffer.fromList(this).prependToList(as); } /** @@ -1787,7 +1787,7 @@ public Iterator iterator() { * Appends (snoc) the given element to this buffer to produce a new buffer. * * @param a The element to append to this buffer. - * @return A new buffer with the given element appended. + * @return This buffer. */ public Buffer snoc(final A a) { if (exported) @@ -1806,10 +1806,10 @@ public Buffer snoc(final A a) { } /** - * Appends the given buffer to this buffer. + * Appends the given list to this buffer. * - * @param as The buffer to append to this one. - * @return A new buffer that has appended the given buffer. + * @param as The list to append to this buffer. + * @return This buffer. */ public Buffer append(final List as) { for (List xs = as; xs.isNotEmpty(); xs = xs.tail()) @@ -1818,6 +1818,28 @@ public Buffer append(final List as) { return this; } + /** + * Prepends the elements of this buffer to the given list. + * + * @param as the list to which elements are prepended. + */ + public List prependToList(final List as) { + if (isEmpty()) { + return as; + } else { + if (exported) + copy(); + + tail.tail(as); + return toList(); + } + } + + /** + * Returns true if this buffer is empty, false otherwise. + */ + public boolean isEmpty() { return start.isEmpty(); } + /** * Returns an immutable list projection of this buffer. Modifications to the underlying buffer * will not be reflected in returned lists. From b0318d33102c78362ca4096b2fa2167dacaab54a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 8 Jun 2015 23:13:23 +1000 Subject: [PATCH 321/811] Implemented real world haskell IO (chapter 7) demonstration, implementing interact for IO. Various changes to support lazy IO and infinite streams. Made P1 toString lazy, this was causing problems in the debugger using infinite structures. Made LazyString.toString lazy, returning the first character. Added map, bind and eval methods to LazyString. Added IO wrapper, implementing static methods from IOFunctions as instance methods. Made Stream.take evaluate one less element, made toString lazy. Added Strings methods lines and unlines. Implemented IOFunctions interact and getContents. Made sequenceWhile lazy, suitable for IO. Test that toString for an infinite stream is lazy. Demonstrate lazy use of sequenceWhile. Refactor from changes to IOFunctions. Test converting an infinite stream of lazy strings to a string. Ensure no stack overflow occurs as in version 4.3. Added demonstrations of IOFunctions.interact --- core/src/main/java/fj/Show.java | 8 + core/src/main/java/fj/Try.java | 2 +- core/src/main/java/fj/data/IOFunctions.java | 797 ++++++++++-------- core/src/main/java/fj/data/IOW.java | 50 ++ core/src/main/java/fj/data/LazyString.java | 37 +- core/src/main/java/fj/data/Stream.java | 14 +- core/src/main/java/fj/function/Strings.java | 21 + .../src/test/java/fj/data/LazyStringTest.java | 21 + core/src/test/java/fj/data/StreamTest.java | 14 + demo/src/main/java/fj/demo/IODemo.java | 59 ++ demo/src/main/java/fj/demo/Stream_Test.java | 32 +- .../main/java/fj/demo/realworld/Chapter7.java | 29 + 12 files changed, 707 insertions(+), 377 deletions(-) create mode 100644 core/src/main/java/fj/data/IOW.java create mode 100644 core/src/test/java/fj/data/LazyStringTest.java create mode 100644 demo/src/main/java/fj/demo/IODemo.java create mode 100644 demo/src/main/java/fj/demo/realworld/Chapter7.java diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 7c39a427..df8b5bdd 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -422,6 +422,14 @@ public static Show> classShow() { * @return A show instance for the {@link P1 tuple-1} type. */ public static Show> p1Show(final Show sa) { + return p1ShowLazy(sa); + } + + public static Show> p1ShowLazy(final Show sa) { + return show(p -> Stream.fromString("(?)")); + } + + public static Show> p1ShowEager(final Show sa) { return show(p -> cons('(', p(sa.show(p._1()))).snoc(')')); } diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index ed454b5a..69e9c19d 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -160,7 +160,7 @@ public static F8 IO io(Try0 t) { - return IOFunctions.io(t); + return IOFunctions.fromTry(t); } } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index a5445d48..da103b05 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -25,11 +25,10 @@ * without indirection in between). * * @author Martin Grotzke - * */ public class IOFunctions { - - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + + private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; public static Try0 toTry(IO io) { return () -> io.run(); @@ -39,120 +38,143 @@ public static P1> p(IO io) { return Try.f(toTry(io)); } - public static IO io(F0 p) { + public static IO fromF(F0 p) { return p::f; } - public static IO io(Try0 t) { + public static IO fromTry(Try0 t) { return () -> t.f(); } public static final F> closeReader = - new F>() { - @Override - public IO f(final Reader r) { - return closeReader(r); - } - }; - - public static IO closeReader(final Reader r) { - return new IO() { - @Override - public Unit run() throws IOException { - r.close(); - return Unit.unit(); - } - }; - } - - /** - * An IO monad that reads lines from the given file (using a {@link BufferedReader}) and passes - * lines to the provided iteratee. May not be suitable for files with very long - * lines, consider to use {@link #enumFileCharChunks} or {@link #enumFileChars} - * as an alternative. - * - * @param f the file to read, must not be null - * @param encoding the encoding to use, {@link Option#none()} means platform default - * @param i the iteratee that is fed with lines read from the file - */ - public static IO> enumFileLines(final File f, final Option encoding, final IterV i) { - return bracket(bufferedReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IOFunctions.lineReader(), i)); - } - - /** - * An IO monad that reads char chunks from the given file and passes them to the given iteratee. - * - * @param f the file to read, must not be null - * @param encoding the encoding to use, {@link Option#none()} means platform default - * @param i the iteratee that is fed with char chunks read from the file - */ - public static IO> enumFileCharChunks(final File f, final Option encoding, final IterV i) { - return bracket(fileReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IOFunctions.charChunkReader(), i)); - } - - /** - * An IO monad that reads char chunks from the given file and passes single chars to the given iteratee. - * - * @param f the file to read, must not be null - * @param encoding the encoding to use, {@link Option#none()} means platform default - * @param i the iteratee that is fed with chars read from the file - */ - public static IO> enumFileChars(final File f, final Option encoding, final IterV i) { - return bracket(fileReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IOFunctions.charChunkReader2(), i)); - } - - public static IO bufferedReader(final File f, final Option encoding) { - return IOFunctions.map(fileReader(f, encoding), new F() { - @Override - public BufferedReader f(final Reader a) { - return new BufferedReader(a); - }}); - } - - public static IO fileReader(final File f, final Option encoding) { - return new IO() { - @Override - public Reader run() throws IOException { - final FileInputStream fis = new FileInputStream(f); - return encoding.isNone() ? new InputStreamReader(fis) : new InputStreamReader(fis, encoding.some()); - } - }; - } - - public static final IO bracket(final IO init, final F> fin, final F> body) { - return new IO() { - @Override - public C run() throws IOException { - final A a = init.run(); - try { - return body.f(a).run(); - } catch (final IOException e) { - throw e; - } finally { - fin.f(a); - } - } - }; - } - - public static final IO unit(final A a) { - return new IO() { - @Override - public A run() throws IOException { - return a; - } - }; - } - - public static final IO lazy(final F0 p) { - return io(p); - } + new F>() { + @Override + public IO f(final Reader r) { + return closeReader(r); + } + }; + + /** + * Convert io to a SafeIO, throwing any IOException wrapped inside a RuntimeException + * @param io + */ + public static SafeIO toSafe(IO io) { + return () -> { + try { + return io.run(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }; + } + + /** + * Run io, rethrowing any IOException wrapped in a RuntimeException + * @param io + */ + public static A runSafe(IO io) { + return toSafe(io).run(); + } + + public static IO closeReader(final Reader r) { + return new IO() { + @Override + public Unit run() throws IOException { + r.close(); + return Unit.unit(); + } + }; + } + + /** + * An IO monad that reads lines from the given file (using a {@link BufferedReader}) and passes + * lines to the provided iteratee. May not be suitable for files with very long + * lines, consider to use {@link #enumFileCharChunks} or {@link #enumFileChars} + * as an alternative. + * + * @param f the file to read, must not be null + * @param encoding the encoding to use, {@link Option#none()} means platform default + * @param i the iteratee that is fed with lines read from the file + */ + public static IO> enumFileLines(final File f, final Option encoding, final IterV i) { + return bracket(bufferedReader(f, encoding) + , Function.>vary(closeReader) + , partialApply2(IOFunctions.lineReader(), i)); + } + + /** + * An IO monad that reads char chunks from the given file and passes them to the given iteratee. + * + * @param f the file to read, must not be null + * @param encoding the encoding to use, {@link Option#none()} means platform default + * @param i the iteratee that is fed with char chunks read from the file + */ + public static IO> enumFileCharChunks(final File f, final Option encoding, final IterV i) { + return bracket(fileReader(f, encoding) + , Function.>vary(closeReader) + , partialApply2(IOFunctions.charChunkReader(), i)); + } + + /** + * An IO monad that reads char chunks from the given file and passes single chars to the given iteratee. + * + * @param f the file to read, must not be null + * @param encoding the encoding to use, {@link Option#none()} means platform default + * @param i the iteratee that is fed with chars read from the file + */ + public static IO> enumFileChars(final File f, final Option encoding, final IterV i) { + return bracket(fileReader(f, encoding) + , Function.>vary(closeReader) + , partialApply2(IOFunctions.charChunkReader2(), i)); + } + + public static IO bufferedReader(final File f, final Option encoding) { + return IOFunctions.map(fileReader(f, encoding), new F() { + @Override + public BufferedReader f(final Reader a) { + return new BufferedReader(a); + } + }); + } + + public static IO fileReader(final File f, final Option encoding) { + return new IO() { + @Override + public Reader run() throws IOException { + final FileInputStream fis = new FileInputStream(f); + return encoding.isNone() ? new InputStreamReader(fis) : new InputStreamReader(fis, encoding.some()); + } + }; + } + + public static final IO bracket(final IO init, final F> fin, final F> body) { + return new IO() { + @Override + public C run() throws IOException { + final A a = init.run(); + try { + return body.f(a).run(); + } catch (final IOException e) { + throw e; + } finally { + fin.f(a); + } + } + }; + } + + public static final IO unit(final A a) { + return new IO() { + @Override + public A run() throws IOException { + return a; + } + }; + } + + public static final IO lazy(final F0 p) { + return fromF(p); + } public static final IO lazy(final F f) { return () -> f.f(Unit.unit()); @@ -167,267 +189,308 @@ public static final SafeIO lazySafe(final F0 f) { } /** - * A function that feeds an iteratee with lines read from a {@link BufferedReader}. - */ - public static F, IO>>> lineReader() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return new F, IO>>>() { - @Override - public F, IO>> f(final BufferedReader r) { - return new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - IterV i = it; - while (!isDone.f(i)) { - final String s = r.readLine(); - if (s == null) { return i; } - final Input input = Input.el(s); - final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); - i = i.fold(done, cont)._1(); - } - return i; - } - }; - } + * A function that feeds an iteratee with lines read from a {@link BufferedReader}. + */ + public static F, IO>>> lineReader() { + final F, Boolean> isDone = + new F, Boolean>() { + final F>, P1> done = constant(P.p(true)); + final F, IterV>, P1> cont = constant(P.p(false)); + + @Override + public Boolean f(final IterV i) { + return i.fold(done, cont)._1(); + } + }; + + return new F, IO>>>() { + @Override + public F, IO>> f(final BufferedReader r) { + return new F, IO>>() { + final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return new IO>() { + @Override + public IterV run() throws IOException { + IterV i = it; + while (!isDone.f(i)) { + final String s = r.readLine(); + if (s == null) { + return i; + } + final Input input = Input.el(s); + final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); + i = i.fold(done, cont)._1(); + } + return i; + } + }; + } + }; + } + }; + } + + /** + * A function that feeds an iteratee with character chunks read from a {@link Reader} + * (char[] of size {@link #DEFAULT_BUFFER_SIZE}). + */ + public static F, IO>>> charChunkReader() { + final F, Boolean> isDone = + new F, Boolean>() { + final F>, P1> done = constant(P.p(true)); + final F, IterV>, P1> cont = constant(P.p(false)); + + @Override + public Boolean f(final IterV i) { + return i.fold(done, cont)._1(); + } + }; + + return new F, IO>>>() { + @Override + public F, IO>> f(final Reader r) { + return new F, IO>>() { + final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return new IO>() { + @Override + public IterV run() throws IOException { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { + return i; + } + if (numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); + } + final Input input = Input.el(buffer); + final F, IterV>, P1>> cont = + F1Functions.lazy(Function., IterV>apply(input)); + i = i.fold(done, cont)._1(); + } + return i; + } + }; + } + }; + } }; - } - }; - } - - /** - * A function that feeds an iteratee with character chunks read from a {@link Reader} - * (char[] of size {@link #DEFAULT_BUFFER_SIZE}). - */ - public static F, IO>>> charChunkReader() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return new F, IO>>>() { - @Override - public F, IO>> f(final Reader r) { - return new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { return i; } - if(numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - final Input input = Input.el(buffer); - final F, IterV>, P1>> cont = - F1Functions.lazy(Function., IterV>apply(input)); - i = i.fold(done, cont)._1(); + } + + /** + * A function that feeds an iteratee with characters read from a {@link Reader} + * (chars are read in chunks of size {@link #DEFAULT_BUFFER_SIZE}). + */ + public static F, IO>>> charChunkReader2() { + final F, Boolean> isDone = + new F, Boolean>() { + final F>, P1> done = constant(P.p(true)); + final F, IterV>, P1> cont = constant(P.p(false)); + + @Override + public Boolean f(final IterV i) { + return i.fold(done, cont)._1(); + } + }; + + return new F, IO>>>() { + @Override + public F, IO>> f(final Reader r) { + return new F, IO>>() { + final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ + + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return new IO>() { + @Override + public IterV run() throws IOException { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { + return i; + } + if (numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); + } + for (int c = 0; c < buffer.length; c++) { + final Input input = Input.el(buffer[c]); + final F, IterV>, IterV> cont = + Function., IterV>apply(input); + i = i.fold(done, cont); + } + } + return i; + } + }; + } + }; + } + }; + } + + public static final IO map(final IO io, final F f) { + return new IO() { + @Override + public B run() throws IOException { + return f.f(io.run()); + } + }; + } + + public static final IO bind(final IO io, final F> f) { + return new IO() { + @Override + public B run() throws IOException { + return f.f(io.run()).run(); + } + }; + } + + /** + * Evaluate each action in the sequence from left to right, and collect the results. + */ + public static IO> sequence(List> list) { + F2, IO>, IO>> f2 = (io, ioList) -> + IOFunctions.bind(ioList, (xs) -> map(io, x -> List.cons(x, xs))); + return list.foldRight(f2, IOFunctions.unit(List.nil())); + } + + + public static IO> sequence(Stream> stream) { + F2>, IO, IO>> f2 = (ioList, io) -> + IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, P.lazy(() -> xs)))); + return stream.foldLeft(f2, IOFunctions.unit(Stream.nil())); + } + + + public static IO join(IO> io1) { + return bind(io1, io2 -> io2); + } + + public static SafeIO> toSafeValidation(IO io) { + return () -> Try.f(() -> io.run())._1(); + } + + public static IO append(final IO io1, final IO io2) { + return () -> { + io1.run(); + return io2.run(); + }; + } + + public static IO left(final IO io1, final IO io2) { + return () -> { + A a = io1.run(); + io2.run(); + return a; + }; + } + + public static IO flatMap(final IO io, final F> f) { + return bind(io, f); + } + + public static IO> sequenceWhileEager(final Stream> stream, final F f) { + return new IO>() { + @Override + public Stream run() throws IOException { + boolean loop = true; + Stream> input = stream; + Stream result = Stream.nil(); + while (loop) { + if (input.isEmpty()) { + loop = false; + } else { + A a = input.head().run(); + if (!f.f(a)) { + loop = false; + } else { + input = input.tail()._1(); + result = result.cons(a); + } + } } - return i; - } - }; - } + return result.reverse(); + } }; - } - }; - } - - /** - * A function that feeds an iteratee with characters read from a {@link Reader} - * (chars are read in chunks of size {@link #DEFAULT_BUFFER_SIZE}). - */ - public static F, IO>>> charChunkReader2() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return new F, IO>>>() { - @Override - public F, IO>> f(final Reader r) { - return new F, IO>>() { - final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { return i; } - if(numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - for(int c = 0; c < buffer.length; c++) { - final Input input = Input.el(buffer[c]); - final F, IterV>, IterV> cont = - Function., IterV>apply(input); - i = i.fold(done, cont); - } + } + + public static IO> sequenceWhile(final Stream> stream, final F f) { + return new IO>() { + @Override + public Stream run() throws IOException { + if (stream.isEmpty()) { + return Stream.nil(); + } else { + IO io = stream.head(); + A a = io.run(); + if (!f.f(a)) { + return Stream.nil(); + } else { + IO> io2 = sequenceWhile(stream.tail()._1(), f); + SafeIO> s3 = toSafe(() -> io2.run()); + return Stream.cons(a, P.lazy(() -> s3.run())); + } } - return i; - } - }; - } + } + }; + } + + public static IO apply(IO io, IO> iof) { + return bind(iof, f -> map(io, a -> f.f(a))); + } + + public static IO liftM2(IO ioa, IO iob, F2 f) { + return bind(ioa, a -> map(iob, b -> f.f(a, b))); + } + + public static IO> replicateM(IO ioa, int n) { + return sequence(List.replicate(n, ioa)); + } + + public static IO>> readerState() { + return () -> State.unit((BufferedReader r) -> P.p(r, Try.f((BufferedReader r2) -> r2.readLine()).f(r))); + } + + public static final BufferedReader stdinBufferedReader = new BufferedReader(new InputStreamReader(System.in)); + + public static IO stdinReadLine() { + return () -> stdinBufferedReader.readLine(); + } + + public static IO stdoutPrintln(final String s) { + return () -> { + System.out.println(s); + return Unit.unit(); }; - } - }; - } - - public static final IO map(final IO io, final F f) { - return new IO() { - @Override - public B run() throws IOException { - return f.f(io.run()); - } - }; - } - - public static final IO bind(final IO io, final F> f) { - return new IO() { - @Override - public B run() throws IOException { - return f.f(io.run()).run(); - } - }; - } - - /** - * Evaluate each action in the sequence from left to right, and collect the results. - */ - public static IO> sequence(List> list) { - F2, IO>, IO>> f2 = (io, ioList) -> - IOFunctions.bind(ioList, (xs) -> map(io, x -> List.cons(x, xs))); - return list.foldRight(f2, IOFunctions.unit(List.nil())); - } - - - public static IO> sequence(Stream> stream) { - F2>, IO, IO>> f2 = (ioList, io) -> - IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, P.lazy(() -> xs)))); - return stream.foldLeft(f2, IOFunctions.unit(Stream.nil())); - } - - - public static IO join(IO> io1) { - return bind(io1, io2 -> io2); - } - - public static SafeIO> toSafeIO(IO io) { - return () -> Try.f(() -> io.run())._1(); - } - - public static IO append(final IO io1, final IO io2) { - return () -> { - io1.run(); - return io2.run(); - }; - } - - public static IO left(final IO io1, final IO io2) { - return () -> { - A a = io1.run(); - io2.run(); - return a; - }; - } - - public static IO flatMap(final IO io, final F> f) { - return bind(io, f); - } - - static IO> sequenceWhile(final Stream> stream, final F f) { - return new IO>() { - @Override - public Stream run() throws IOException { - boolean loop = true; - Stream> input = stream; - Stream result = Stream.nil(); - while (loop) { - if (input.isEmpty()) { - loop = false; - } else { - A a = input.head().run(); - if (!f.f(a)) { - loop = false; - } else { - input = input.tail()._1(); - result = result.cons(a); - } - } - } - return result.reverse(); - } - }; - } - - public static IO apply(IO io, IO> iof) { - return bind(iof, f -> map(io, a -> f.f(a))); - } - - public static IO liftM2(IO ioa, IO iob, F2 f) { - return bind(ioa, a -> map(iob, b -> f.f(a, b))); - } - - public static IO> replicateM(IO ioa, int n) { - return sequence(List.replicate(n, ioa)); - } - - public static IO>> readerState() { - return () -> State.unit((BufferedReader r) -> P.p(r, Try.f((BufferedReader r2) -> r2.readLine()).f(r))); - } - - public static final BufferedReader stdinBufferedReader = new BufferedReader(new InputStreamReader(System.in)); - - public static IO stdinReadLine() { - return () -> stdinBufferedReader.readLine(); - } - - public static IO stdoutPrintln(final String s) { - return () -> { - System.out.println(s); - return Unit.unit(); - }; - } + } + + public static IO getContents() { + Stream> s = Stream.>repeat(() -> (int) stdinBufferedReader.read()); + return IOFunctions.map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> { + return (char) i.intValue(); + }))); + } + + public static IO interact(F f) { + return bind(getContents(), ls1 -> { + LazyString ls2 = f.f(ls1); + return stdoutPrintln(ls2.toString()); + }); + } } diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java new file mode 100644 index 00000000..5364f49e --- /dev/null +++ b/core/src/main/java/fj/data/IOW.java @@ -0,0 +1,50 @@ +package fj.data; + +import fj.F; +import fj.Unit; + +import java.io.IOException; + +/** + * Created by MarkPerry on 9/06/2015. + */ +public class IOW implements IO { + + private IO io; + + private IOW(IO in) { + io = in; + } + + public static IOW lift(IO io) { + return new IOW<>(io); + } + + @Override + public A run() throws IOException { + return io.run(); + } + + public IOW map(F f) { + return lift(() -> f.f(io.run())); + } + + public IOW bind(F> f) throws IOException { + return lift(f.f(io.run())); + } + + public IOW append(IO iob) { + return lift(() -> { + io.run(); + return iob.run(); + }); + } + + public IOW getContents() { + return lift(() -> IOFunctions.getContents().run()); + } + + public IOW interact(F f) { + return IOW.lift(() -> IOFunctions.interact(f).run()); + } +} diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index acfc9573..43a93b02 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -104,12 +104,25 @@ public CharSequence subSequence(final int start, final int end) { * * @return The String representation of this lazy string. */ - public String toString() { + public String toStringEager() { final StringBuilder builder = new StringBuilder(length() + 16); s.foreachDoEffect(c -> builder.append(c.charValue())); return builder.toString(); } + public String toStringLazy() { + return s.isEmpty() ? "" : "LazyString(" + Show.charShow.showS(s.head()) + ", ?)"; + } + + @Override + public String toString() { + return toStringLazy(); + } + + public String eval() { + return toStringEager(); + } + /** * Appends the given lazy string to the end of this lazy string. * @@ -253,6 +266,14 @@ public Stream _1() { }); } + public LazyString map(F f) { + return fromStream(s.map(f)); + } + + public LazyString bind(F f) { + return fromStream(s.bind(c -> f.f(c).toStream())); + } + /** * Splits this lazy string by the given delimiter character. * @@ -281,6 +302,10 @@ public Stream lines() { return split('\n'); } + public static F> lines_() { + return LazyString::lines; + } + /** * Joins the given stream of lazy strings into one, separated by newlines. * @@ -291,6 +316,10 @@ public static LazyString unlines(final Stream str) { return fromStream(join(str.intersperse(str("\n")).map(toStream))); } + public static F, LazyString> unlines_() { + return LazyString::unlines; + } + /** * Joins the given stream of lazy strings into one, separated by spaces. * @@ -305,19 +334,19 @@ public static LazyString unwords(final Stream str) { * First-class conversion from lazy strings to streams. */ public static final F> toStream = - string -> string.toStream(); + LazyString::toStream; /** * First-class conversion from lazy strings to String. */ public static final F toString = - string -> string.toString(); + LazyString::toString; /** * First-class conversion from character streams to lazy strings. */ public static final F, LazyString> fromStream = - s -> fromStream(s); + LazyString::fromStream; private static final Equal> eqS = streamEqual(charEqual); diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 14f3803d..fe583628 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -994,7 +994,9 @@ public Stream _1() { * @return A string from the given stream of characters. */ public static String asString(final Stream cs) { - return LazyString.fromStream(cs).toString(); + StringBuilder sb = new StringBuilder(); + cs.foreachDoEffect(c -> sb.append(c)); + return sb.toString(); } /** @@ -1039,7 +1041,7 @@ public final Stream take(final int n) { Stream.nil() : cons(head(), new P1>() { public Stream _1() { - return tail()._1().take(n - 1); + return n <= 1 ? Stream.nil() : tail()._1().take(n - 1); } }); } @@ -1248,6 +1250,14 @@ public int hashCode() { @Override public String toString() { + return toStringLazy(); + } + + public String toStringLazy() { + return isEmpty() ? "Nil()" : "Cons(" + Show.anyShow().showS(head()) + ", ?)"; + } + + public String toStringEager() { return Show.streamShow(Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index c1381f06..02558450 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -2,6 +2,7 @@ import fj.F; import fj.F2; +import fj.data.List; import fj.data.Stream; import static fj.Function.curry; import static fj.function.Booleans.not; @@ -17,6 +18,8 @@ private Strings() { throw new UnsupportedOperationException(); } + public static final String lineSeparator = System.getProperty("line.separator"); + /** * This function checks if a given String contains any non-whitespace character * (according to {@link Character#isWhitespace(char)}) and if it's also not @@ -110,4 +113,22 @@ public Boolean f(final String s1, final String s2) { } }); + public static List lines(String s) { + return List.list(s.split("\\r?\\n")); + } + + public static F> lines() { + return s -> lines(s); + } + + public static String unlines(List list) { + StringBuilder sb = new StringBuilder(); + list.intersperse(lineSeparator).forEach(s -> sb.append(s)); + return sb.toString(); + } + + public static F, String> unlines() { + return l -> unlines(l); + } + } diff --git a/core/src/test/java/fj/data/LazyStringTest.java b/core/src/test/java/fj/data/LazyStringTest.java new file mode 100644 index 00000000..4f6325af --- /dev/null +++ b/core/src/test/java/fj/data/LazyStringTest.java @@ -0,0 +1,21 @@ +package fj.data; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Created by MarkPerry on 11/06/2015. + */ +public class LazyStringTest { + + @Test + public void testToString() { + Stream s = Stream.repeat(LazyString.str("abc")); + // FJ 4.3 blows the stack when printing infinite streams of lazy strings. + assertThat(s.toString(), is(equalTo("Cons(LazyString(a, ?), ?)"))); + } + +} diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index 6e1b590a..8968748c 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -2,7 +2,14 @@ import org.junit.Test; +import java.io.IOException; + +import static fj.data.IOFunctions.stdinReadLine; +import static java.lang.System.out; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; /** * Created by Zheka Kozlov on 27.05.2015. @@ -14,4 +21,11 @@ public void infiniteStream() { Stream s = Stream.forever(Enumerator.intEnumerator, 0).bind(Stream::single); assertEquals(List.range(0, 5), s.take(5).toList()); } + + @Test + public void testToString() { + Stream range = Stream.range(1); + assertThat(range.toString(), is(equalTo("Cons(1, ?)"))); + } + } diff --git a/demo/src/main/java/fj/demo/IODemo.java b/demo/src/main/java/fj/demo/IODemo.java new file mode 100644 index 00000000..316eafc4 --- /dev/null +++ b/demo/src/main/java/fj/demo/IODemo.java @@ -0,0 +1,59 @@ +package fj.demo; + +import fj.F; +import fj.data.IOFunctions; +import fj.data.LazyString; + +import static fj.F1W.lift; +import static fj.data.IOFunctions.interact; +import static fj.data.IOFunctions.runSafe; +import static fj.data.LazyString.lines_; +import static fj.data.LazyString.unlines_; +import static java.lang.System.out; + +/** + * Created by MarkPerry on 13/06/2015. + */ +public class IODemo { + + public static void main(String[] args) { + IODemo d = new IODemo(); +// d.readFirstShortLine(); +// d.readFirstLine(); +// d.simpleInteract(); + d.getContents(); + } + + /** + * Reads from standard input until the line length is less than three + * and prints that last line. + */ + public void readFirstShortLine() { + F f = lift(lines_()).andThen(l -> l.filter(s -> s.length() < 3)).andThen(unlines_()); + runSafe(interact(f)); + } + + /** + * Read a stream of input lazily using interact, in effect reading the first line + */ + public void readFirstLine() { + F f = lift((LazyString s) -> s.lines()).andThen(unlines_()); + runSafe(interact(f)); + } + + /** + * Demonstrate use of interact, just echoing the lazy string. Reading lines is done + * lazily, so just the first line is read. + */ + public void simpleInteract() { + runSafe(interact(s -> s)); + } + + /** + * Demonstrate that getContents returns a lazy string. + */ + public void getContents() { + out.println(runSafe(IOFunctions.getContents())); + } + +} diff --git a/demo/src/main/java/fj/demo/Stream_Test.java b/demo/src/main/java/fj/demo/Stream_Test.java index 47dd5937..eb22bcb3 100644 --- a/demo/src/main/java/fj/demo/Stream_Test.java +++ b/demo/src/main/java/fj/demo/Stream_Test.java @@ -1,16 +1,42 @@ package fj.demo; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.List; +import fj.data.Stream; + import static fj.data.Enumerator.naturalEnumerator; +import static fj.data.IOFunctions.runSafe; +import static fj.data.IOFunctions.stdinReadLine; import static fj.data.Natural.natural; import static fj.data.Stream.forever; import static fj.Show.naturalShow; import static fj.Show.unlineShow; +import static java.lang.System.out; -/** - * Produces natural numbers forever. - */ public class Stream_Test { + public static void main(final String[] args) { + sequenceWhile(); +// foreverNaturals(); + } + + /** + * Produces natural numbers forever. + */ + static void foreverNaturals() { unlineShow(naturalShow).println(forever(naturalEnumerator, natural(3).some(), 2)); } + + /** + * Reads lines from standard input until a line's length is less than two or three lines + * have been read. + */ + static void sequenceWhile() { + Stream> s = Stream.repeat(stdinReadLine()); + IO> io = IOFunctions.sequenceWhile(s, s2 -> s2.length() > 1); + List list = runSafe(io).take(3).toList(); + out.println("list: " + list + " size: " + list.length()); + } + } diff --git a/demo/src/main/java/fj/demo/realworld/Chapter7.java b/demo/src/main/java/fj/demo/realworld/Chapter7.java new file mode 100644 index 00000000..81902d09 --- /dev/null +++ b/demo/src/main/java/fj/demo/realworld/Chapter7.java @@ -0,0 +1,29 @@ +package fj.demo.realworld; + +import fj.data.LazyString; +import fj.data.Stream; + +import static fj.data.IOFunctions.*; + +/** + * Created by MarkPerry on 11/06/2015. + * + * Examples from Chapter 7 of Real World Haskell, http://book.realworldhaskell.org/. + */ +public class Chapter7 { + + public static void main(String[] args) { + interactToUpper(); + } + + /** + * Lazy interact to upper, shows the first lazy string line. + */ + public static void interactToUpper() { + runSafe(interact(ls -> { + Stream stream = ls.lines().map((LazyString ls2) -> ls2.eval().toUpperCase()); + return LazyString.unlines(stream.map(s -> LazyString.str(s))); + })); + } + +} From 51bf76061aa6b163c163d47c85af4051ad4e4e82 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Jun 2015 20:59:50 +1000 Subject: [PATCH 322/811] Moved files in old tests module to props-core-scalacheck --- .../src/main/scala/fj/ArbitraryUnit.scala | 0 {tests => props-core-scalacheck}/src/test/scala/fj/CheckP2.scala | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {tests => props-core-scalacheck}/src/main/scala/fj/ArbitraryUnit.scala (100%) rename {tests => props-core-scalacheck}/src/test/scala/fj/CheckP2.scala (100%) diff --git a/tests/src/main/scala/fj/ArbitraryUnit.scala b/props-core-scalacheck/src/main/scala/fj/ArbitraryUnit.scala similarity index 100% rename from tests/src/main/scala/fj/ArbitraryUnit.scala rename to props-core-scalacheck/src/main/scala/fj/ArbitraryUnit.scala diff --git a/tests/src/test/scala/fj/CheckP2.scala b/props-core-scalacheck/src/test/scala/fj/CheckP2.scala similarity index 100% rename from tests/src/test/scala/fj/CheckP2.scala rename to props-core-scalacheck/src/test/scala/fj/CheckP2.scala From e727b77a9d6e8a82cabadde4430956c41617f5a9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Jun 2015 23:46:48 +1000 Subject: [PATCH 323/811] Added IOFunctions.interactWhile and some sequence and traverse methods for Stream to support interactive IO from stdin to stdout --- core/src/main/java/fj/data/IOFunctions.java | 14 +++++ core/src/main/java/fj/data/Stream.java | 54 ++++++++++++++++++- .../main/java/fj/demo/realworld/Chapter7.java | 25 ++++++++- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index da103b05..d2d82883 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -172,6 +172,8 @@ public A run() throws IOException { }; } + public static final IO ioUnit = unit(Unit.unit()); + public static final IO lazy(final F0 p) { return fromF(p); } @@ -404,6 +406,18 @@ public static IO flatMap(final IO io, final F> f) { return bind(io, f); } + /** + * Read lines from stdin until condition is not met, transforming each line and printing + * the result to stdout. + * @param condition Read lines until a line does not satisfy condition + * @param transform Function to change line value + */ + public static IO interactWhile(F condition, F transform) { + Stream> s1 = Stream.repeat(IOFunctions.stdinReadLine()); + IO> io = sequenceWhile(s1, condition); + return () -> runSafe(io).foreach(s -> runSafe(stdoutPrintln(transform.f(s)))); + } + public static IO> sequenceWhileEager(final Stream> stream, final F f) { return new IO>() { @Override diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index fe583628..7b8403f3 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -365,7 +365,7 @@ public final Stream removeAll(final F f) { */ public static F> sequence_(final Stream> fs) { return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), Function.curry((a, stream) -> cons(a, p(stream)))), Function - .>constant(Stream.nil())); + .>constant(Stream.nil())); } /** @@ -527,6 +527,36 @@ public final Stream sequence(final Stream bs) { return bind(c); } + /** + * Sequence through the Stream monad. + * + * @param io The IO stream to sequence. + * @return The stream of IOs after sequencing. + */ + public static Stream> sequence(final IO> io) { + return IOFunctions.runSafe(io).map(a -> IOFunctions.unit(a)); + } + + /** + * Sequence through the Stream monad. + * + * @param p The lazy stream to sequence. + * @return The stream of (pre-calculated) lazy values after sequencing. + */ + public static Stream> sequence(final P1> p) { + return p._1().map(a -> P.p(a)); + } + + /** + * Sequence through the Stream monad. + * + * @param o The optional stream to sequence. + * @return The stream of options after sequencing. + */ + public static Stream> sequence(final Option> o) { + return o.isNone() ? Stream.nil() : o.some().map(a -> Option.some(a)); + } + /** * Performs function application within a stream (applicative functor pattern). * @@ -1082,6 +1112,28 @@ public Stream _1() { Stream.nil(); } + /** + * Traversable instance of Stream for IO. + * + * @return traversed value + */ + public final IO> traverseIO(F> f) { + return this.foldRight1((a, acc) -> + IOFunctions.bind(acc, (Stream bs) -> + IOFunctions.map(f.f(a), b -> + bs.cons(b))), IOFunctions.unit(Stream.nil())); + + } + + /** + * Traversable instance of Stream for Option. + * + * @return traversed value + */ + public final Option> traverseOption(F> f) { + return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(b -> bs.cons(b))), some(Stream.nil())); + } + /** * Removes elements from the head of this stream that do not match the given predicate function * until an element is found that does match or the stream is exhausted. diff --git a/demo/src/main/java/fj/demo/realworld/Chapter7.java b/demo/src/main/java/fj/demo/realworld/Chapter7.java index 81902d09..433bf9de 100644 --- a/demo/src/main/java/fj/demo/realworld/Chapter7.java +++ b/demo/src/main/java/fj/demo/realworld/Chapter7.java @@ -1,5 +1,7 @@ package fj.demo.realworld; +import fj.data.IO; +import fj.data.IOFunctions; import fj.data.LazyString; import fj.data.Stream; @@ -13,17 +15,36 @@ public class Chapter7 { public static void main(String[] args) { - interactToUpper(); +// toUpperLazy(); +// toUpperByLine(); + toUpperInteract(); } /** * Lazy interact to upper, shows the first lazy string line. */ - public static void interactToUpper() { + public static void toUpperLazy() { runSafe(interact(ls -> { Stream stream = ls.lines().map((LazyString ls2) -> ls2.eval().toUpperCase()); return LazyString.unlines(stream.map(s -> LazyString.str(s))); })); } + /** + * Read each line, convert to uppercase and print on stdout, until an empty line + */ + public static void toUpperByLine() { + Stream> s1 = Stream.repeat(IOFunctions.stdinReadLine()); + IO> io = sequenceWhile(s1, s -> s.trim().length() > 0); + runSafe(io).foreachDoEffect(s -> runSafe(stdoutPrintln(s.toUpperCase()))); + } + + /** + * Read from stdin each line, whilst each line is not empty, print + * uppercase line to stdout + */ + public static void toUpperInteract() { + runSafe(interactWhile(s -> s.trim().length() > 0, s -> s.toUpperCase())); + } + } From f2710c76525eda68f8d2fabbf1c1ac23316e141c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Jun 2015 23:53:18 +1000 Subject: [PATCH 324/811] Added example comment for ch 7 of real world haskell --- demo/src/main/java/fj/demo/realworld/Chapter7.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demo/src/main/java/fj/demo/realworld/Chapter7.java b/demo/src/main/java/fj/demo/realworld/Chapter7.java index 433bf9de..2f6ed8a4 100644 --- a/demo/src/main/java/fj/demo/realworld/Chapter7.java +++ b/demo/src/main/java/fj/demo/realworld/Chapter7.java @@ -11,6 +11,8 @@ * Created by MarkPerry on 11/06/2015. * * Examples from Chapter 7 of Real World Haskell, http://book.realworldhaskell.org/. + * + * Currently just ch07/toupper-lazy4.hs. */ public class Chapter7 { From 51f036bd279914e870df5de9ffcbadb7e28b38e1 Mon Sep 17 00:00:00 2001 From: orionll Date: Mon, 15 Jun 2015 13:41:53 +0600 Subject: [PATCH 325/811] Added possibility to run individual tests --- .../fj/test/runner/PropertyTestRunner.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java index 81c37754..3537fe92 100644 --- a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java +++ b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java @@ -2,38 +2,45 @@ import org.junit.runner.Description; import org.junit.runner.Runner; +import org.junit.runner.manipulation.Filter; +import org.junit.runner.manipulation.Filterable; +import org.junit.runner.manipulation.NoTestsRemainException; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; +import fj.P; import fj.P3; +import fj.data.List; import fj.data.Option; import fj.test.CheckResult; import fj.test.Property; import fj.test.reflect.Check; import fj.test.reflect.CheckParams; -public class PropertyTestRunner extends Runner { +public class PropertyTestRunner extends Runner implements Filterable { private final Class clas; + private final List, Description>> allTests; + private volatile List, Description>> filteredTests; public PropertyTestRunner(Class clas) { this.clas = clas; + this.allTests = Check.properties(clas).map(p -> P.p(p._1(), p._3(), Description.createTestDescription(clas, p._2()))); + this.filteredTests = allTests; } @Override public Description getDescription() { Description suite = Description.createSuiteDescription(clas); - for (P3> p : Check.properties(clas)) { - suite.addChild(Description.createTestDescription(clas, p._2())); - } + filteredTests.foreachDoEffect(p -> suite.addChild(p._3())); return suite; } @Override public void run(RunNotifier notifier) { - for (P3> p : Check.properties(clas)) { - Description desc = Description.createTestDescription(clas, p._2()); + filteredTests.foreachDoEffect(p -> { + Description desc = p._3(); notifier.fireTestStarted(desc); - CheckResult result = checkProperty(p._1(), p._3()); + CheckResult result = checkProperty(p._1(), p._2()); try { CheckResult.summaryEx.showS(result); @@ -42,7 +49,7 @@ public void run(RunNotifier notifier) { } notifier.fireTestFinished(desc); - } + }); } private static CheckResult checkProperty(Property prop, Option params) { @@ -52,4 +59,10 @@ private static CheckResult checkProperty(Property prop, Option para return prop.check(); } + + @Override + public void filter(Filter filter) throws NoTestsRemainException { + filteredTests = allTests.filter(p -> filter.shouldRun(p._3())); + if (filteredTests.isEmpty()) { throw new NoTestsRemainException(); } + } } From 221c0d6fd9c7c419bd48e96fd3c4c104f5777f4e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 19 Jun 2015 18:55:21 +1000 Subject: [PATCH 326/811] Added quickcheck test for stream properties that matches unstable scalacheck test. Increased timeout for TestCheck --- .../test/java/fj/data/StreamProperties.java | 30 +++++++++++++++++++ .../src/test/java/fj/data/test/TestCheck.java | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 props-core/src/test/java/fj/data/StreamProperties.java diff --git a/props-core/src/test/java/fj/data/StreamProperties.java b/props-core/src/test/java/fj/data/StreamProperties.java new file mode 100644 index 00000000..f7bc0e30 --- /dev/null +++ b/props-core/src/test/java/fj/data/StreamProperties.java @@ -0,0 +1,30 @@ +package fj.data; + +import fj.Equal; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.test.Arbitrary.*; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by MarkPerry on 18/06/2015. + */ +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class StreamProperties { + + public Property bindStackOverflow() { + int max = 5000; + return property(arbitrary(Gen.choose(1, max)), (n) -> { + Stream s1 = Stream.range(1, n); + Stream s2 = s1.bind(j -> Stream.single(j)); + return prop(s1.zip(s2).forall(p2 -> Equal.intEqual.eq(p2._1(), p2._2()))); + }); + } + +} diff --git a/quickcheck/src/test/java/fj/data/test/TestCheck.java b/quickcheck/src/test/java/fj/data/test/TestCheck.java index 8292ff61..10c59a1c 100644 --- a/quickcheck/src/test/java/fj/data/test/TestCheck.java +++ b/quickcheck/src/test/java/fj/data/test/TestCheck.java @@ -20,7 +20,7 @@ public class TestCheck { - @Test(timeout=1000 /*ms*/) + @Test(timeout=5000 /*ms*/) public void testExceptionsThrownFromGeneratorsArePropagated() { Gen failingGen = Gen.value(0).map((i) -> { throw new RuntimeException("test failure"); From 7b170beb95ac75ba82da2ad7e419e4cdbacd5634 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 19 Jun 2015 18:56:10 +1000 Subject: [PATCH 327/811] Create variable to enable/disable retrolambda --- build.gradle | 2 ++ core/build.gradle | 15 ++++++++++----- demo/build.gradle | 16 ++++++++++------ props-core/build.gradle | 12 +++++++----- quickcheck/build.gradle | 16 +++++++++------- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/build.gradle b/build.gradle index 5a2f1472..0ab1651e 100644 --- a/build.gradle +++ b/build.gradle @@ -43,6 +43,7 @@ allprojects { fjConsumeVersion = "4.3" signModule = false + useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" @@ -61,6 +62,7 @@ allprojects { primaryEmail = "functionaljava@googlegroups.com" dependencyJunit = "junit:junit:4.11" + } version = fjVersion diff --git a/core/build.gradle b/core/build.gradle index 1d6e6b76..7bd8c184 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,5 +1,8 @@ -apply plugin: 'me.tatarka.retrolambda' +if (useRetroLambda) { + apply plugin: 'me.tatarka.retrolambda' +} + ext { signModule = true @@ -16,8 +19,10 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true -retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 +if (useRetroLambda) { + retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 + } } diff --git a/demo/build.gradle b/demo/build.gradle index b8372c79..7af49271 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,14 +1,18 @@ apply plugin: 'application' -apply plugin: 'me.tatarka.retrolambda' -mainClassName = "fj.demo.euler.Problem2" +if (useRetroLambda) { + apply plugin: 'me.tatarka.retrolambda' +} +mainClassName = "fj.demo.euler.Problem2" -retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 +if (useRetroLambda) { + retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 + } } dependencies { diff --git a/props-core/build.gradle b/props-core/build.gradle index 961d08da..f9f7fbb9 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -1,10 +1,12 @@ -apply plugin: 'me.tatarka.retrolambda' +if (useRetroLambda) { + apply plugin: 'me.tatarka.retrolambda' -retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 + } } dependencies { diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 25fd2e80..07da8478 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -1,14 +1,16 @@ -apply plugin: 'me.tatarka.retrolambda' +if (useRetroLambda) { + apply plugin: 'me.tatarka.retrolambda' -archivesBaseName = "${project.projectName}-${project.name}" - -retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + retrolambda { + jdk System.getenv("JAVA8_HOME") + oldJdk System.getenv("JAVA7_HOME") + javaVersion JavaVersion.VERSION_1_7 + } } +archivesBaseName = "${project.projectName}-${project.name}" + dependencies { compile project(":core") compile dependencyJunit From bef50e689299035f005fb4a87b6dfc69147fa6f2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 20 Jun 2015 08:03:39 +1000 Subject: [PATCH 328/811] Added hard memo. Default memo to soft --- core/src/main/java/fj/P1.java | 6 +++++- core/src/main/java/fj/data/Stream.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 0cd9fb62..887541cb 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -209,12 +209,16 @@ public P1 map(final F f) { return P.lazy(() -> f.f(self._1())); } + public P1 memo() { + return softMemo(); + } + /** * Returns a P1 that remembers its value. * * @return A P1 that calls this P1 once and remembers the value for subsequent calls. */ - public P1 memo() { return new Memo<>(this); } + public P1 hardMemo() { return new Memo<>(this); } /** * Like memo, but the memoized value is wrapped into a WeakReference diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index ed38d118..4d2408d8 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1495,7 +1495,7 @@ private static final class Cons extends Stream { Cons(final A head, final P1> tail) { this.head = head; - this.tail = tail.weakMemo(); + this.tail = tail.memo(); } public A head() { From fa6b5f09ca4a6ede60bfc40b82ecbf2469944226 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 20 Jun 2015 12:32:46 +1000 Subject: [PATCH 329/811] Turn retro lambda back on --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0ab1651e..32ee5244 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ allprojects { fjConsumeVersion = "4.3" signModule = false - useRetroLambda = false + useRetroLambda = true projectTitle = "Functional Java" projectName = "functionaljava" From 558653eb98302767307f766efb23c05afe853f7a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 20 Jun 2015 13:03:42 +1000 Subject: [PATCH 330/811] Changed memo from soft to weak --- core/src/main/java/fj/P1.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 887541cb..5c7d1d90 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -210,7 +210,7 @@ public P1 map(final F f) { } public P1 memo() { - return softMemo(); + return weakMemo(); } /** From 478b5190005e2d048956933ae86d105d89b2bbd6 Mon Sep 17 00:00:00 2001 From: orionll Date: Mon, 22 Jun 2015 15:00:28 +0600 Subject: [PATCH 331/811] Added Seq.isNotEmpty(). Properties for List, Stream and Array. --- core/src/main/java/fj/data/Seq.java | 9 + .../test/java/fj/data/StreamProperties.java | 30 -- .../fj/data/properties/ArrayProperties.java | 209 ++++++++++++++ .../fj/data/properties/ListProperties.java | 270 +++++++++++++++++- .../fj/data/properties/SeqProperties.java | 31 +- .../fj/data/properties/StreamProperties.java | 205 +++++++++++++ 6 files changed, 698 insertions(+), 56 deletions(-) delete mode 100644 props-core/src/test/java/fj/data/StreamProperties.java create mode 100644 props-core/src/test/java/fj/data/properties/ArrayProperties.java create mode 100644 props-core/src/test/java/fj/data/properties/StreamProperties.java diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 69dffe22..b701ae3f 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -189,6 +189,15 @@ public boolean isEmpty() { return ftree.isEmpty(); } + /** + * Checks if this sequence is not empty. + * + * @return True if this sequence is not empty, otherwise false. + */ + public boolean isNotEmpty() { + return !ftree.isEmpty(); + } + /** * Returns the number of elements in this sequence. * diff --git a/props-core/src/test/java/fj/data/StreamProperties.java b/props-core/src/test/java/fj/data/StreamProperties.java deleted file mode 100644 index f7bc0e30..00000000 --- a/props-core/src/test/java/fj/data/StreamProperties.java +++ /dev/null @@ -1,30 +0,0 @@ -package fj.data; - -import fj.Equal; -import fj.test.Gen; -import fj.test.Property; -import fj.test.reflect.CheckParams; -import fj.test.runner.PropertyTestRunner; -import org.junit.runner.RunWith; - -import static fj.test.Arbitrary.*; -import static fj.test.Property.prop; -import static fj.test.Property.property; - -/** - * Created by MarkPerry on 18/06/2015. - */ -@RunWith(PropertyTestRunner.class) -@CheckParams(maxSize = 10000) -public class StreamProperties { - - public Property bindStackOverflow() { - int max = 5000; - return property(arbitrary(Gen.choose(1, max)), (n) -> { - Stream s1 = Stream.range(1, n); - Stream s2 = s1.bind(j -> Stream.single(j)); - return prop(s1.zip(s2).forall(p2 -> Equal.intEqual.eq(p2._1(), p2._2()))); - }); - } - -} diff --git a/props-core/src/test/java/fj/data/properties/ArrayProperties.java b/props-core/src/test/java/fj/data/properties/ArrayProperties.java new file mode 100644 index 00000000..c6aea391 --- /dev/null +++ b/props-core/src/test/java/fj/data/properties/ArrayProperties.java @@ -0,0 +1,209 @@ +package fj.data.properties; + +import fj.*; +import fj.data.Array; +import fj.data.Either; +import fj.test.Arbitrary; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static fj.Equal.arrayEqual; +import static fj.Equal.intEqual; +import static fj.Function.compose; +import static fj.Function.identity; +import static fj.data.Array.array; +import static fj.data.Array.empty; +import static fj.test.Arbitrary.*; +import static fj.test.Property.implies; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class ArrayProperties { + + private static final Equal> eq = arrayEqual(intEqual); + + private static final Arbitrary, Integer>> arbArrayWithIndex = arbitrary(arbArray(arbInteger).gen + .filter(Array::isNotEmpty) + .bind(array -> Gen.choose(0, array.length() - 1).map(i -> P.p(array, i)))); + + public Property isEmpty() { + return property(arbArray(arbInteger), array -> prop(array.isEmpty() != array.isNotEmpty())); + } + + public Property isNotEmpty() { + return property(arbArray(arbInteger), array -> prop(array.length() > 0 == array.isNotEmpty())); + } + + public Property toOption() { + return property(arbArray(arbInteger), array -> + prop(array.toOption().isNone() || intEqual.eq(array.toOption().some(), array.get(0)))); + } + + public Property toEither() { + return property(arbArray(arbInteger), arbP1(arbInteger), (array, n) -> { + final Either e = array.toEither(n); + return prop(e.isLeft() && intEqual.eq(e.left().value(), n._1()) || + intEqual.eq(e.right().value(), array.get(0))); + }); + } + + public Property mapId() { + return property(arbArray(arbInteger), array -> prop(eq.eq(array.map(identity()), array))); + } + + public Property mapCompose() { + final F f = x -> x + 3; + final F g = x -> x * 4; + return property(arbArray(arbInteger), array -> + prop(eq.eq(array.map(compose(f, g)), array.map(g).map(f)))); + } + + public Property foreachDoEffect() { + return property(arbArray(arbInteger), array -> { + int[] acc = {0}; + array.foreachDoEffect(x -> acc[0] += x); + + int acc2 = 0; + for (int x : array) { acc2 += x; } + + return prop(intEqual.eq(acc[0], acc2)); + }); + } + + public Property filter() { + final F predicate = (x -> x % 2 == 0); + return property(arbArray(arbInteger), array -> prop(array.filter(predicate).forall(predicate))); + } + + public Property filterLength() { + final F predicate = (x -> x % 2 == 0); + return property(arbArray(arbInteger), array -> prop(array.filter(predicate).length() <= array.length())); + } + + public Property bindLeftIdentity() { + final F> f = (i -> array(-i)); + return property(arbArray(arbInteger), arbInteger, (array, i) -> + prop(eq.eq(array(i).bind(f), f.f(i)))); + } + + public Property bindRightIdentity() { + return property(arbArray(arbInteger), array -> prop(eq.eq(array.bind(Array::array), array))); + } + + public Property bindAssociativity() { + final F> f = x -> array(x + 3); + final F> g = x -> array(x * 4); + return property(arbArray(arbInteger), array -> + prop(eq.eq(array.bind(f).bind(g), array.bind(i -> f.f(i).bind(g))))); + } + + public Property foldRight() { + return property(arbArray(arbInteger), array -> + prop(eq.eq(array.foldRight((i, s) -> array(i).append(s), empty()), array))); + } + + public Property foldLeft() { + return property(arbArray(arbInteger), array -> + prop(eq.eq(array.foldLeft((s, i) -> array(i).append(s), empty()), + array.reverse().foldRight((i, s) -> array(i).append(s), empty())))); + } + + public Property scans() { + return property(arbArray(arbInteger), arbInteger, (array, z) -> { + final F> add = x -> y -> x + y; + final Array left = array.scanLeft(add, z); + final Array right = array.reverse().scanRight(add, z).reverse(); + return prop(eq.eq(left, right)); + }); + } + + public Property scans1() { + return property(arbArray(arbInteger), array -> + implies(array.isNotEmpty(), () -> { + final F> add = x -> y -> x + y; + final Array left = array.scanLeft1(add); + final Array right = array.reverse().scanRight1(add).reverse(); + return prop(eq.eq(left, right)); + })); + } + + @CheckParams(maxSize = 100) + public Property sequence() { + return property(arbArray(arbInteger), arbArray(arbInteger), (array1, array2) -> + prop(eq.eq(array1.sequence(array2), array1.bind(__ -> array2)))); + } + + public Property reverseIdentity() { + return property(arbArray(arbInteger), array -> + prop(eq.eq(array.reverse().reverse(), array))); + } + + public Property reverse() { + return property(arbArray(arbInteger), arbArray(arbInteger), (array1, array2) -> + prop(eq.eq(array1.append(array2).reverse(), array2.reverse().append(array1.reverse())))); + } + + @CheckParams(minSize = 1) + public Property reverseIndex() { + return property(arbArrayWithIndex, p -> { + final Array array = p._1(); + final Integer i = p._2(); + return prop(intEqual.eq(array.reverse().get(i), array.get(array.length() - i - 1))); + }); + } + + public Property appendLeftIdentity() { + return property(arbArray(arbInteger), array -> prop(eq.eq(Array. empty().append(array), array))); + } + + public Property appendRightIdentity() { + return property(arbArray(arbInteger), array -> prop(eq.eq(array.append(empty()), array))); + } + + public Property appendAssociativity() { + return property(arbArray(arbInteger), arbArray(arbInteger), arbArray(arbInteger), (array1, array2, array3) -> + prop(eq.eq(array1.append(array2).append(array3), array1.append(array2.append(array3))))); + } + + public Property appendLength() { + return property(arbArray(arbInteger), arbArray(arbInteger), (array1, array2) -> + prop(array1.append(array2).length() == array1.length() + array2.length())); + } + + public Property arrayLength() { + return property(arbArray(arbInteger), array -> prop(array.length() == array.array().length)); + } + + @CheckParams(minSize = 1) + public Property index() { + return property(arbArrayWithIndex, p -> { + final Array array = p._1(); + final Integer i = p._2(); + return prop(intEqual.eq(array.get(i), array.array(Integer[].class)[i])); + }); + } + + public Property forallExists() { + return property(arbArray(arbInteger), array -> + prop(array.forall(x -> x % 2 == 0) == !array.exists(x -> x % 2 != 0))); + } + + public Property find() { + return property(arbArray(arbInteger), array -> prop(array.find(x -> x % 2 == 0).forall(x -> x % 2 == 0))); + } + + @CheckParams(maxSize = 500) + public Property join() { + return property(arbArray(arbArray(arbInteger)), (Array> array) -> + prop(eq.eq(array.foldRight(Array::append, empty()), Array.join(array)))); + } +} diff --git a/props-core/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java index 974d63e2..f4ab1476 100644 --- a/props-core/src/test/java/fj/data/properties/ListProperties.java +++ b/props-core/src/test/java/fj/data/properties/ListProperties.java @@ -1,38 +1,291 @@ package fj.data.properties; -import fj.Ord; -import fj.P; -import fj.P2; +import fj.*; import fj.data.List; +import fj.data.Stream; +import fj.data.TreeMap; +import fj.test.Arbitrary; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; import fj.test.Gen; import fj.test.Property; import org.junit.runner.RunWith; +import java.util.ArrayList; +import java.util.Collections; + +import static fj.Equal.listEqual; +import static fj.Equal.p2Equal; +import static fj.Function.compose; +import static fj.Function.identity; +import static fj.P.p; +import static fj.data.List.nil; +import static fj.data.List.single; import static fj.test.Arbitrary.*; import static fj.test.Property.implies; import static fj.test.Property.prop; import static fj.test.Property.property; import static fj.Equal.intEqual; +import static fj.Monoid.intAdditionMonoid; +import static fj.Ord.booleanOrd; +import static fj.Ord.intOrd; -/** - * Created by Zheka Kozlov on 02.06.2015. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class ListProperties { + private static final Equal> eq = listEqual(intEqual); + + private static final Arbitrary, Integer>> arbListWithIndex = arbitrary(arbList(arbInteger).gen + .filter(List::isNotEmpty) + .bind(list -> Gen.choose(0, list.length() - 1).map(i -> p(list, i)))); + + public Property isEmpty() { + return property(arbList(arbInteger), list -> prop(list.isEmpty() != list.isNotEmpty())); + } + + public Property isNotEmpty() { + return property(arbList(arbInteger), list -> prop(list.length() > 0 == list.isNotEmpty())); + } + + public Property orHead() { + return property(arbList(arbInteger), arbInteger, (list, n) -> + implies(list.isNotEmpty(), () -> prop(intEqual.eq(list.orHead(() -> n), list.head())))); + } + + public Property orTail() { + return property(arbList(arbInteger), arbP1(arbList(arbInteger)), (list, list2) -> + implies(list.isNotEmpty(), () -> prop(eq.eq(list.orTail(list2), list.tail())))); + } + + public Property toOption() { + return property(arbList(arbInteger), list -> + prop(list.toOption().isNone() || intEqual.eq(list.toOption().some(), list.head()))); + } + + public Property consHead() { + return property(arbList(arbInteger), arbInteger, (list, n) -> prop(intEqual.eq(list.cons(n).head(), n))); + } + + public Property consLength() { + return property(arbList(arbInteger), arbInteger, (list, n) -> prop(list.cons(n).length() == list.length() + 1)); + } + + public Property mapId() { + return property(arbList(arbInteger), list -> prop(eq.eq(list.map(identity()), list))); + } + + public Property mapCompose() { + final F f = x -> x + 3; + final F g = x -> x * 4; + return property(arbList(arbInteger), list -> + prop(eq.eq(list.map(compose(f, g)), list.map(g).map(f)))); + } + + public Property foreachDoEffect() { + return property(arbList(arbInteger), list -> { + int[] acc = {0}; + list.foreachDoEffect(x -> acc[0] += x); + + int acc2 = 0; + for (int x : list) { acc2 += x; } + + return prop(intEqual.eq(acc[0], acc2)); + }); + } + + public Property filter() { + final F predicate = (x -> x % 2 == 0); + return property(arbList(arbInteger), list -> prop(list.filter(predicate).forall(predicate))); + } + + public Property filterLength() { + final F predicate = (x -> x % 2 == 0); + return property(arbList(arbInteger), list -> prop(list.filter(predicate).length() <= list.length())); + } + + public Property bindLeftIdentity() { + final F> f = (i -> single(-i)); + return property(arbList(arbInteger), arbInteger, (list, i) -> + prop(eq.eq(single(i).bind(f), f.f(i)))); + } + + public Property bindRightIdentity() { + return property(arbList(arbInteger), list -> prop(eq.eq(list.bind(List::list), list))); + } + + public Property bindAssociativity() { + final F> f = x -> single(x + 3); + final F> g = x -> single(x * 4); + return property(arbList(arbInteger), list -> + prop(eq.eq(list.bind(f).bind(g), list.bind(i -> f.f(i).bind(g))))); + } + + public Property foldRight() { + return property(arbList(arbInteger), list -> + prop(eq.eq(list.foldRight((i, s) -> single(i).append(s), nil()), list))); + } + + public Property foldLeft() { + return property(arbList(arbInteger), list -> + prop(eq.eq(list.foldLeft((s, i) -> single(i).append(s), nil()), + list.reverse().foldRight((i, s) -> single(i).append(s), nil())))); + } + + public Property tailLength() { + return property(arbList(arbInteger), list -> + implies(list.isNotEmpty(), () -> prop(list.tail().length() == list.length() - 1))); + } + + public Property reverseIdentity() { + return property(arbList(arbInteger), list -> prop(eq.eq(list.reverse().reverse(), list))); + } + + public Property reverse() { + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + prop(eq.eq(list1.append(list2).reverse(), list2.reverse().append(list1.reverse())))); + } + + @CheckParams(maxSize = 100) + public Property sequence() { + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + prop(eq.eq(list1.sequence(list2), list1.bind(__ -> list2)))); + } + + public Property appendLeftIdentity() { + return property(arbList(arbInteger), list -> prop(eq.eq(List. nil().append(list), list))); + } + + public Property appendRightIdentity() { + return property(arbList(arbInteger), list -> prop(eq.eq(list.append(nil()), list))); + } + + public Property appendAssociativity() { + return property(arbList(arbInteger), arbList(arbInteger), arbList(arbInteger), (list1, list2, list3) -> + prop(eq.eq(list1.append(list2).append(list3), list1.append(list2.append(list3))))); + } + + public Property appendLength() { + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + prop(list1.append(list2).length() == list1.length() + list2.length())); + } + + @CheckParams(minSize = 2, maxSize = 10000) + public Property indexTail() { + final Gen, Integer>> gen = arbList(arbInteger).gen + .filter(list -> list.length() > 1) + .bind(list -> Gen.choose(1, list.length() - 1).map(i -> p(list, i))); + + return property(Arbitrary.arbitrary(gen), pair -> { + final List list = pair._1(); + final int i = pair._2(); + return prop(intEqual.eq(list.index(i), list.tail().index(i - 1))); + }); + } + + public Property snoc() { + return property(arbList(arbInteger), arbInteger, (list, n) -> prop(eq.eq(list.snoc(n), list.append(single(n))))); + } + + public Property take() { + return property(arbList(arbInteger), arbInteger, (list, n) -> prop(list.take(n).length() <= list.length())); + } + + public Property drop() { + return property(arbList(arbInteger), arbInteger, (list, n) -> prop(list.drop(n).length() <= list.length())); + } + + public Property splitAt() { + return property(arbList(arbInteger), arbInteger, (list, n) -> + prop(p2Equal(eq, eq).eq(list.splitAt(n), p(list.take(n), list.drop(n))))); + } + + @CheckParams(minSize = 1, maxSize = 2000) + public Property partition() { + return property(arbListWithIndex, p -> implies(p._2() > 0, () -> { + final List list = p._1(); + final Integer i = p._2(); + final List> partition = list.partition(i); + return prop(eq.eq(list, List.join(partition))).and(prop(partition.forall(part -> part.length() <= i))); + })); + } + + @CheckParams(minSize = 1, maxSize = 2000) + public Property tails() { + return property(arbList(arbInteger), list -> implies(list.isNotEmpty(), () -> + prop(list.tails().length() == list.length() + 1 && + List.join(list.inits()).length() == Stream.range(1, list.length() + 1).foldLeft((acc, i) -> acc + i, 0)))); + } + + @CheckParams(minSize = 1, maxSize = 2000) + public Property inits() { + return property(arbList(arbInteger), list -> implies(list.isNotEmpty(), () -> + prop(list.inits().length() == list.length() + 1 && + List.join(list.tails()).length() == Stream.range(1, list.length() + 1).foldLeft((acc, i) -> acc + i, 0)))); + } + + public Property sort() { + return property(arbList(arbInteger), list -> { + java.util.List javaList = list.sort(intOrd).toJavaList(); + java.util.List copy = new ArrayList<>(javaList); + Collections.sort(copy); + return prop(javaList.equals(copy)); + }); + } + + public Property forallExists() { + return property(arbList(arbInteger), list -> + prop(list.forall(x -> x % 2 == 0) == !list.exists(x -> x % 2 != 0))); + } + + public Property find() { + return property(arbList(arbInteger), list -> prop(list.find(x -> x % 2 == 0).forall(x -> x % 2 == 0))); + } + + @CheckParams(maxSize = 500) + public Property join() { + return property(arbList(arbList(arbInteger)), (List> lists) -> + prop(eq.eq(lists.foldLeft(List::append, nil()), List.join(lists)))); + } + + @CheckParams(maxSize = 2000) + public Property nub() { + return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> + prop(eq.eq(list1.append(list2).nub(), list1.nub().append(list2.nub()).nub()))); + } + + public Property groupBy() { + return property(arbList(arbInteger), list -> { + final TreeMap> map = list.groupBy(i -> i % 2 == 0); + final List list1 = map.get(true).orSome(nil()); + final List list2 = map.get(false).orSome(nil()); + return prop(list.length() == list1.length() + list2.length()) + .and(prop(list1.forall(i -> i % 2 == 0))) + .and(prop(list2.forall(i -> i % 2 != 0))) + .and(prop(list.map(i -> i % 2 == 0).nub().length() == map.size())); + }); + } + + public Property groupByMonoid() { + return property(arbList(arbInteger), list -> { + final TreeMap map = list.groupBy(i -> i % 2 == 0, identity(), intAdditionMonoid, booleanOrd); + final int sum1 = map.get(true).orSome(0); + final int sum2 = map.get(false).orSome(0); + return prop(list.filter(i -> i % 2 == 0).foldLeft((acc, i) -> acc + i, 0) == sum1) + .and(prop(list.filter(i -> i % 2 != 0).foldLeft((acc, i) -> acc + i, 0) == sum2)); + }); + } + public Property isPrefixOf() { final Gen, Integer>> gen = arbList(arbInteger).gen.bind(list -> - Gen.choose(0, list.length()).map(i -> P.p(list, i))); + Gen.choose(0, list.length()).map(i -> p(list, i))); return property(arbitrary(gen), pair -> prop(pair._1().take(pair._2()).isPrefixOf(intEqual, pair._1()))); } public Property isSuffixOf() { final Gen, Integer>> gen = arbList(arbInteger).gen.bind(list -> - Gen.choose(0, list.length()).map(i -> P.p(list, i))); + Gen.choose(0, list.length()).map(i -> p(list, i))); return property(arbitrary(gen), pair -> prop(pair._1().drop(pair._2()).isSuffixOf(intEqual, pair._1()))); } @@ -66,4 +319,5 @@ public Property listOrdReverse() { return property(arbList(arbInteger), arbList(arbInteger), (list1, list2) -> prop(ord.compare(list1, list2) == ord.reverse().compare(list1, list2).reverse())); } + } diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 9ce0bdc3..6bc5b97b 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -3,6 +3,7 @@ import fj.P; import fj.P2; +import fj.data.Array; import fj.data.Option; import fj.data.Seq; import fj.test.reflect.CheckParams; @@ -17,17 +18,19 @@ import static fj.data.Option.some; import static fj.test.Arbitrary.arbInteger; import static fj.test.Arbitrary.arbSeq; +import static fj.test.Arbitrary.arbitrary; import static fj.test.Property.implies; import static fj.test.Property.prop; import static fj.test.Property.property; -/** - * Created by Zheka Kozlov on 01.06.2015. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class SeqProperties { + private static final Arbitrary, Integer>> arbSeqWithIndex = arbitrary(arbSeq(arbInteger).gen + .filter(Seq::isNotEmpty) + .bind(seq -> Gen.choose(0, seq.length() - 1).map(i -> P.p(seq, i)))); + public Property consHead() { return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.cons(n).head().equals(n))); } @@ -91,30 +94,22 @@ public Property mapId() { return property(arbSeq(arbInteger), seq -> prop(seq.map(identity()).equals(seq))); } + @CheckParams(minSize = 1) public Property updateAndIndex() { - final Gen, Option>> gen = arbSeq(arbInteger).gen.bind(seq -> { - if (seq.isEmpty()) { - return Gen.value(P.p(seq, none())); - } else { - return Gen.choose(0, seq.length() - 1).map(i -> P.p(seq, some(i))); - } + return property(arbSeqWithIndex, arbInteger, (pair, n) -> { + final Seq seq = pair._1(); + final int index = pair._2(); + return prop(seq.update(index, n).index(index).equals(n)); }); - - return property(Arbitrary.arbitrary(gen), arbInteger, (pair, n) -> - implies(pair._2().isSome(), () -> { - final Seq seq = pair._1(); - final int index = pair._2().some(); - return prop(seq.update(index, n).index(index).equals(n)); - })); } public Property foldLeft() { - return property(arbSeq(Arbitrary.arbitrary(Gen.value(1))), seq -> + return property(arbSeq(arbitrary(Gen.value(1))), seq -> prop(seq.foldLeft((acc, i) -> acc + i, 0) == seq.length())); } public Property foldRight() { - return property(arbSeq(Arbitrary.arbitrary(Gen.value(1))), seq -> + return property(arbSeq(arbitrary(Gen.value(1))), seq -> prop(seq.foldRight((i, acc) -> acc + i, 0) == seq.length())); } } diff --git a/props-core/src/test/java/fj/data/properties/StreamProperties.java b/props-core/src/test/java/fj/data/properties/StreamProperties.java new file mode 100644 index 00000000..f68df0bc --- /dev/null +++ b/props-core/src/test/java/fj/data/properties/StreamProperties.java @@ -0,0 +1,205 @@ +package fj.data.properties; + +import fj.*; +import fj.data.Either; +import fj.data.Stream; +import fj.test.Arbitrary; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.Equal.intEqual; +import static fj.Equal.p1Equal; +import static fj.Equal.streamEqual; +import static fj.Function.compose; +import static fj.Function.identity; +import static fj.Ord.intOrd; +import static fj.data.Stream.nil; +import static fj.data.Stream.single; +import static fj.test.Arbitrary.*; +import static fj.test.Property.implies; +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static java.lang.Math.abs; + +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class StreamProperties { + + private static final Equal> eq = streamEqual(intEqual); + + public Property isEmpty() { + return property(arbStream(arbInteger), stream -> prop(stream.isEmpty() != stream.isNotEmpty())); + } + + public Property isNotEmpty() { + return property(arbStream(arbInteger), stream -> + prop(stream.length() > 0 == stream.isNotEmpty())); + } + + public Property orHead() { + return property(arbStream(arbInteger), arbInteger, (stream, n) -> + implies(stream.isNotEmpty(), () -> prop(intEqual.eq(stream.orHead(() -> n), stream.head())))); + } + + public Property orTail() { + final Equal>> eq = p1Equal(streamEqual(intEqual)); + return property(arbStream(arbInteger), arbP1(arbStream(arbInteger)), (stream, stream2) -> + implies(stream.isNotEmpty(), () -> prop(eq.eq(stream.orTail(stream2), stream.tail())))); + } + + public Property bindStackOverflow() { + return property(arbInteger, n -> { + final Stream stream = Stream.range(1, abs(n)); + final Stream bound = stream.bind(Stream::single); + return prop(stream.zip(bound).forall(p2 -> intEqual.eq(p2._1(), p2._2()))); + }); + } + + public Property toOption() { + return property(arbStream(arbInteger), stream -> + prop(stream.toOption().isNone() || intEqual.eq(stream.toOption().some(), stream.head()))); + } + + public Property toEither() { + return property(arbStream(arbInteger), arbP1(arbInteger), (stream, n) -> { + final Either e = stream.toEither(n); + return prop(e.isLeft() && intEqual.eq(e.left().value(), n._1()) || + intEqual.eq(e.right().value(), stream.head())); + }); + } + + public Property consHead() { + return property(arbStream(arbInteger), arbInteger, (stream, n) -> + prop(intEqual.eq(stream.cons(n).head(), n))); + } + + public Property consLength() { + return property(arbStream(arbInteger), arbInteger, (stream, n) -> + prop(stream.cons(n).length() == stream.length() + 1)); + } + + public Property mapId() { + return property(arbStream(arbInteger), stream -> prop(eq.eq(stream.map(identity()), stream))); + } + + public Property mapCompose() { + final F f = x -> x + 3; + final F g = x -> x * 4; + return property(arbStream(arbInteger), stream -> + prop(eq.eq(stream.map(compose(f, g)), stream.map(g).map(f)))); + } + + public Property foreachDoEffect() { + return property(arbStream(arbInteger), stream -> { + int[] acc = {0}; + stream.foreachDoEffect(x -> acc[0] += x); + + int acc2 = 0; + for (int x : stream) { acc2 += x; } + + return prop(intEqual.eq(acc[0], acc2)); + }); + } + + public Property filter() { + final F predicate = (x -> x % 2 == 0); + return property(arbStream(arbInteger), stream -> prop(stream.filter(predicate).forall(predicate))); + } + + public Property filterLength() { + final F predicate = (x -> x % 2 == 0); + return property(arbStream(arbInteger), stream -> prop(stream.filter(predicate).length() <= stream.length())); + } + + public Property bindLeftIdentity() { + final F> f = (i -> single(-i)); + return property(arbStream(arbInteger), arbInteger, (stream, i) -> + prop(eq.eq(single(i).bind(f), f.f(i)))); + } + + public Property bindRightIdentity() { + return property(arbStream(arbInteger), stream -> prop(eq.eq(stream.bind(Stream::single), stream))); + } + + public Property bindAssociativity() { + final F> f = x -> single(x + 3); + final F> g = x -> single(x * 4); + return property(arbStream(arbInteger), stream -> + prop(eq.eq(stream.bind(f).bind(g), stream.bind(i -> f.f(i).bind(g))))); + } + + @CheckParams(maxSize = 100) + public Property sequence() { + return property(arbStream(arbInteger), arbStream(arbInteger), (stream1, stream2) -> + prop(eq.eq(stream1.sequence(stream2), stream1.bind(__ -> stream2)))); + } + + public Property append() { + return property(arbStream(arbInteger), arbInteger, (stream, i) -> + prop(eq.eq(single(i).append(stream), stream.cons(i)))); + } + + public Property foldRight() { + return property(arbStream(arbInteger), stream -> + prop(eq.eq(stream.foldRight((i, s) -> single(i).append(s), nil()), stream))); + } + + public Property foldLeft() { + return property(arbStream(arbInteger), stream -> + prop(eq.eq(stream.foldLeft((s, i) -> single(i).append(s), nil()), + stream.reverse().foldRight((i, s) -> single(i).append(s), nil())))); + } + + public Property tailLength() { + return property(arbStream(arbInteger), stream -> + implies(stream.isNotEmpty(), () -> prop(stream.tail()._1().length() == stream.length() - 1))); + } + + public Property reverseIdentity() { + return property(arbStream(arbInteger), stream -> + prop(eq.eq(stream.reverse().reverse(), stream))); + } + + public Property reverse() { + return property(arbStream(arbInteger), arbStream(arbInteger), (stream1, stream2) -> + prop(eq.eq(stream1.append(stream2).reverse(), stream2.reverse().append(stream1.reverse())))); + } + + @CheckParams(minSize = 2, maxSize = 10000) + public Property indexTail() { + final Gen, Integer>> gen = arbStream(arbInteger).gen + .filter(stream -> stream.length() > 1) + .bind(stream -> Gen.choose(1, stream.length() - 1).map(i -> P.p(stream, i))); + + return property(Arbitrary.arbitrary(gen), pair -> { + final Stream stream = pair._1(); + final int i = pair._2(); + return prop(intEqual.eq(stream.index(i), stream.tail()._1().index(i - 1))); + }); + } + + public Property forallExists() { + return property(arbStream(arbInteger), stream -> + prop(stream.forall(x -> x % 2 == 0) == !stream.exists(x -> x % 2 != 0))); + } + + public Property find() { + return property(arbStream(arbInteger), stream -> prop(stream.find(x -> x % 2 == 0).forall(x -> x % 2 == 0))); + } + + @CheckParams(maxSize = 500) + public Property join() { + return property(arbStream(arbStream(arbInteger)), (Stream> stream) -> + prop(eq.eq(stream.foldRight((Stream i, P1> s) -> i.append(s._1()), nil()), + Stream.join(stream)))); + } + + @CheckParams(maxSize = 1000) + public Property sort() { + return property(arbStream(arbInteger), (Stream stream) -> + prop(eq.eq(stream.sort(intOrd), stream.toList().sort(intOrd).toStream()))); + } +} From f41234e1738f8d00a3b4619a101d4b91a434bea7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 23 Jun 2015 23:00:08 +1000 Subject: [PATCH 332/811] Moved optic instances to nested class. Added optic example --- core/src/main/java/fj/P2.java | 65 +++--- core/src/main/java/fj/data/List.java | 219 ++++++++++-------- core/src/main/java/fj/data/optic/PIso.java | 4 +- .../main/java/fj/data/optic/package-info.java | 11 + .../main/java/fj/demo/optic/LensPerson.java | 83 +++++++ .../src/test/scala/fj/CheckP2.scala | 4 +- .../src/test/scala/fj/data/CheckList.scala | 10 +- 7 files changed, 258 insertions(+), 138 deletions(-) create mode 100644 core/src/main/java/fj/data/optic/package-info.java create mode 100644 demo/src/main/java/fj/demo/optic/LensPerson.java diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 82f51461..c3ebe8cd 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -344,37 +344,50 @@ public static F2 untuple(final F, C> f) { return (a, b) -> f.f(P.p(a, b)); } - /** - * Polyomorphic lens targeted on _1. - */ - public static PLens, P2, A, C> _1pLens() { - return pLens(__1(), a -> p2 -> P.p(a, p2._2())); - } - /** - * Monomorphic lens targeted on _1. - */ - public static Lens, A> _1Lens() { - return new Lens<>(_1pLens()); - } + @Override + public String toString() { + return Show.p2Show(Show.anyShow(), Show.anyShow()).showS(this); + } /** - * Polyomorphic lens targeted on _2. - */ - public static PLens, P2, B, C> _2pLens() { - return pLens(__2(), b -> p2 -> P.p(p2._1(), b)); - } + * Optic factory methods for a P2 - /** - * Monomorphic lens targeted on _1. */ - public static Lens, B> _2Lens() { - return new Lens<>(_2pLens()); - } + public static final class Optic { - @Override - public String toString() { - return Show.p2Show(Show.anyShow(), Show.anyShow()).showS(this); - } + private Optic() { + throw new UnsupportedOperationException(); + } + + /** + * Polyomorphic lens targeted on _1. + */ + public static PLens, P2, A, C> _1p() { + return pLens(__1(), a -> p2 -> P.p(a, p2._2())); + } + + /** + * Monomorphic lens targeted on _1. + */ + public static Lens, A> _1() { + return new Lens<>(_1p()); + } + + /** + * Polyomorphic lens targeted on _2. + */ + public static PLens, P2, B, C> _2p() { + return pLens(__2(), b -> p2 -> P.p(p2._1(), b)); + } + + /** + * Monomorphic lens targeted on _1. + */ + public static Lens, B> _2() { + return new Lens<>(_2p()); + } + + } } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index b8d68f67..a42d4998 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -655,81 +655,6 @@ public V2> traverseV2(final F> f) { v(List. nil(), List. nil())); } - /** - * polymorphic traversal - */ - public static PTraversal, List, A, B> _pTraversal() { - return new PTraversal, List, A, B>() { - - @Override - public F, F>> modifyFunctionF(F> f) { - return l -> l.traverseF(f); - } - - @Override - public F, Either>> modifyEitherF(F> f) { - return l -> l.traverseEither(f); - } - - @Override - public F, IO>> modifyIOF(F> f) { - return l -> l.traverseIO(f); - } - - @Override - public F, Trampoline>> modifyTrampolineF(F> f) { - return l -> l.traverseTrampoline(f); - } - - @Override - public F, Promise>> modifyPromiseF(F> f) { - return l -> l.traversePromise(f); - } - - @Override - public F, List>> modifyListF(F> f) { - return l -> l.traverseList(f); - } - - @Override - public F, Option>> modifyOptionF(F> f) { - return l -> l.traverseOption(f); - } - - @Override - public F, Stream>> modifyStreamF(F> f) { - return l -> l.traverseStream(f); - } - - @Override - public F, P1>> modifyP1F(F> f) { - return l -> l.traverseP1(f); - } - - @Override - public F, Validation>> modifyValidationF(F> f) { - return l -> l.traverseValidation(f); - } - - @Override - public F, V2>> modifyV2F(F> f) { - return l -> l.traverseV2(f); - } - - @Override - public F, M> foldMap(Monoid monoid, F f) { - return l -> monoid.sumLeft(l.map(f)); - } - }; - } - - /** - * monomorphic traversal - */ - public static Traversal, A> _traversal() { - return new Traversal<>(_pTraversal()); - } - /** * Performs function application within a list (applicative functor pattern). * @@ -1176,12 +1101,6 @@ public final List nub(final Ord o) { return sort(o).group(o.equal()).map(List.head_()); } - /** - * Optional targeted on Cons head. - */ - public static Optional, A> _head() { - return optional(l -> l.toOption(), a -> l -> l.> list(l, constant(cons_(a)))); - } /** * First-class head function. @@ -1192,14 +1111,6 @@ public static F, A> head_() { return list -> list.head(); } - /** - * Optional targeted on Cons tail. - */ - public static Optional, List> _tail() { - return optional(l -> l.>> list(none(), h -> tail -> some(tail)), - tail -> l -> l.list(l, h -> constant(cons(h, tail)))); - } - /** * First-class tail function. * @@ -1597,13 +1508,6 @@ public static List nil() { return (Nil) Nil.INSTANCE; } - /** - * Nil prism - */ - public static Prism, Unit> _nil() { - return prism(l -> l.isEmpty() ? some(unit()) : none(), constant(nil())); - } - /** * Returns a function that prepends (cons) an element to a list to produce a new list. * @@ -1613,13 +1517,6 @@ public static F, List>> cons() { return a -> tail -> cons(a, tail); } - /** - * Cons prism - */ - public static Prism, P2>> _cons() { - return prism(l -> l.>>> list(none(), h -> tail -> some(P.p(h, tail))), c -> cons(c._1(), c._2())); - } - public static F2, List> cons_() { return (a, listA) -> cons(a, listA); } @@ -2105,4 +2002,120 @@ public int hashCode() { public boolean isSingle() { return isNotEmpty() && tail().isEmpty(); } + + /** + * Optic factory methods for a List + */ + public static final class Optic { + + private Optic() { + throw new UnsupportedOperationException(); + } + + /** + * Polymorphic traversal + */ + public static PTraversal, List, A, B> pTraversal() { + return new PTraversal, List, A, B>() { + + @Override + public F, F>> modifyFunctionF(F> f) { + return l -> l.traverseF(f); + } + + @Override + public F, Either>> modifyEitherF(F> f) { + return l -> l.traverseEither(f); + } + + @Override + public F, IO>> modifyIOF(F> f) { + return l -> l.traverseIO(f); + } + + @Override + public F, Trampoline>> modifyTrampolineF(F> f) { + return l -> l.traverseTrampoline(f); + } + + @Override + public F, Promise>> modifyPromiseF(F> f) { + return l -> l.traversePromise(f); + } + + @Override + public F, List>> modifyListF(F> f) { + return l -> l.traverseList(f); + } + + @Override + public F, Option>> modifyOptionF(F> f) { + return l -> l.traverseOption(f); + } + + @Override + public F, Stream>> modifyStreamF(F> f) { + return l -> l.traverseStream(f); + } + + @Override + public F, P1>> modifyP1F(F> f) { + return l -> l.traverseP1(f); + } + + @Override + public F, Validation>> modifyValidationF(F> f) { + return l -> l.traverseValidation(f); + } + + @Override + public F, V2>> modifyV2F(F> f) { + return l -> l.traverseV2(f); + } + + @Override + public F, M> foldMap(Monoid monoid, F f) { + return l -> monoid.sumLeft(l.map(f)); + } + }; + } + + /** + * Monomorphic traversal + */ + public static Traversal, A> traversal() { + return new Traversal<>(pTraversal()); + } + + /** + * Optional targeted on Cons head. + */ + public static Optional, A> head() { + return optional(l -> l.toOption(), a -> l -> l.>list(l, constant(cons_(a)))); + } + + /** + * Optional targeted on Cons tail. + */ + public static Optional, List> tail() { + return optional(l -> l.>> list(none(), h -> tail -> some(tail)), + tail -> l -> l.list(l, h -> constant(List.cons(h, tail)))); + } + + /** + * Nil prism + */ + public static Prism, Unit> nil() { + return prism((List l) -> l.isEmpty() ? some(unit()) : none(), constant(List.nil())); + } + + /** + * Cons prism + */ + public static Prism, P2>> cons() { + return prism(l -> l.>>> list(none(), h -> tail -> some(P.p(h, tail))), c -> List.cons(c._1(), c._2())); + } + + } + } diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java index 0ba2ca30..850dedb6 100644 --- a/core/src/main/java/fj/data/optic/PIso.java +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -33,11 +33,11 @@ * *
  *     S           T                                   S           T
- *     |           ↑                                   ↑           |
+ *     |           |                                   |           |
  *     |           |                                   |           |
  * get |           | reverseGet     reverse.reverseGet |           | reverse.get
  *     |           |                                   |           |
- *     ↓     f     |                                   |     g     ↓
+ *     |     f     |                                   |     g     |
  *     A --------> B                                   A <-------- B
  * 
* diff --git a/core/src/main/java/fj/data/optic/package-info.java b/core/src/main/java/fj/data/optic/package-info.java new file mode 100644 index 00000000..d12f58ae --- /dev/null +++ b/core/src/main/java/fj/data/optic/package-info.java @@ -0,0 +1,11 @@ +/** + * + * Optic data types adapted from the
Scala Monocle library + * and inspired by the + * Haskell Lens library. See the Monocle Github + * page for an overview of the package. + * + * @version %build.number% + * @see Monocle + */ +package fj.data.optic; diff --git a/demo/src/main/java/fj/demo/optic/LensPerson.java b/demo/src/main/java/fj/demo/optic/LensPerson.java new file mode 100644 index 00000000..107ef659 --- /dev/null +++ b/demo/src/main/java/fj/demo/optic/LensPerson.java @@ -0,0 +1,83 @@ +package fj.demo.optic; + +import fj.Equal; +import fj.data.optic.Lens; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Created by MarkPerry on 23/06/2015. + */ +public class LensPerson { + + static final class Person { + String name; + Address address; + + Person(String name, Address address) { + this.name = name; + this.address = address; + } + } + + static final class Address { + int number; + String street; + + public Address(int number, String street) { + this.number = number; + this.street = street; + } + } + + static Lens personNameLens = Lens.lens(p -> p.name, s -> p -> new Person(s, p.address)); + static Lens personAddressLens = Lens.lens(p -> p.address, a -> p -> new Person(p.name, a)); + static Lens addressNumberLens = Lens.lens(a -> a.number, n -> a -> new Address(n, a.street)); + static Lens addressStreetLens = Lens.lens(a -> a.street, s -> a -> new Address(a.number, s)); + static Lens personNumberLens = personAddressLens.composeLens(addressNumberLens); + static Lens personStreetLens = personAddressLens.composeLens(addressStreetLens); + + static Equal
addressEqual = Equal.equal(a1 -> a2 -> a1.number == a2.number && a1.street.equals(a2.street)); + static Equal personEqual = Equal.equal(p1 -> p2 -> p1.name.equals(p2.name) && addressEqual.eq(p1.address, p2.address)); + + static final String oldName = "Joe"; + static final int oldNumber = 10; + static final String oldStreet = "Main St"; + static final Address oldAddress = new Address(oldNumber, oldStreet); + static final Person oldPerson = new Person(oldName, oldAddress); + + @Test + public void get() { + assertTrue(personNameLens.get(oldPerson).equals(oldName)); + assertTrue(personNumberLens.get(oldPerson) == oldNumber); + assertTrue(personStreetLens.get(oldPerson) == oldStreet); + } + + @Test + public void setName() { + String newName = "Bill"; + Person p = personNameLens.set(newName).f(oldPerson); + assertTrue(p.name.equals(newName)); + assertTrue(addressEqual.eq(p.address, oldPerson.address)); + } + + @Test + public void setNumber() { + int newNumber = 20; + Person p = personNumberLens.set(newNumber).f(oldPerson); + assertTrue(p.name.equals(oldName)); + assertTrue(p.address.number == newNumber); + assertTrue(p.address.street.equals(oldStreet)); + } + + @Test + public void setStreet() { + String newStreet = "First St"; + Person p = personStreetLens.set(newStreet).f(oldPerson); + assertTrue(p.name.equals(oldName)); + assertTrue(p.address.number == oldPerson.address.number); + assertTrue(p.address.street.equals(newStreet)); + } + +} diff --git a/props-core-scalacheck/src/test/scala/fj/CheckP2.scala b/props-core-scalacheck/src/test/scala/fj/CheckP2.scala index 4191b29d..8aa7bdeb 100644 --- a/props-core-scalacheck/src/test/scala/fj/CheckP2.scala +++ b/props-core-scalacheck/src/test/scala/fj/CheckP2.scala @@ -14,8 +14,8 @@ import fj.data.optic.LensLaws object CheckP2 extends Properties("P2") { - property("_1Lens") = LensLaws[P2[String, Int], String](P2._1Lens()) + property("Optic._1") = LensLaws[P2[String, Int], String](P2.Optic._1()) - property("_2Lens") = LensLaws[P2[String, Int], Int](P2._2Lens()) + property("Optic._2") = LensLaws[P2[String, Int], Int](P2.Optic._2()) } diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala index 8eab68ca..a3cfa2b5 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala @@ -206,15 +206,15 @@ object CheckList extends Properties("List") { }) - property("_nil") = PrismLaws[List[String], Unit](List._nil()) + property("Optic.nil") = PrismLaws[List[String], Unit](List.Optic.nil()) - property("_cons") = PrismLaws[List[String], P2[String, List[String]]](List._cons()) + property("Optic.cons") = PrismLaws[List[String], P2[String, List[String]]](List.Optic.cons()) - property("_head") = OptionalLaws[List[String], String](List._head()) + property("Optic.head") = OptionalLaws[List[String], String](List.Optic.head()) - property("_tail") = OptionalLaws[List[String], List[String]](List._tail()) + property("Optic.tail") = OptionalLaws[List[String], List[String]](List.Optic.tail()) - property("_traversal") = TraversalLaws[List[String], String](List._traversal()) + property("Optic.traversal") = TraversalLaws[List[String], String](List.Optic.traversal()) /*property("iterateWhile") = forAll((n: Int) => n > 0 ==> From ed7007e9513e9a8b49b19c7f1e36788b19b52be9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 24 Jun 2015 22:31:34 +1000 Subject: [PATCH 333/811] Added List.partition --- core/src/main/java/fj/data/List.java | 16 ++++++++++++++++ core/src/test/java/fj/data/ListTest.java | 11 +++++++++++ 2 files changed, 27 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index a42d4998..667bb73f 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -854,6 +854,22 @@ public final List> partition(final int n) { return unfold(as -> as.isEmpty() ? Option., List>>none() : some(as.splitAt(n)), this); } + /** + * Partitions the list into a tuple where the first element contains the + * items that satisfy the the predicate f and the second element contains the + * items that does not. The relative order of the elements in the returned tuple + * is the same as the original list. + * + * @param f Predicate function. + */ + public P2, List> partition(F f) { + P2, List> p2 = foldLeft(acc -> a -> + f.f(a) ? P.p(acc._1().cons(a), acc._2()) : P.p(acc._1(), acc._2().cons(a)), + P.p(nil(), nil()) + ); + return P.p(p2._1().reverse(), p2._2().reverse()); + } + /** * Returns the list of initial segments of this list, shortest first. * diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index c04beee5..3639dddb 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -1,5 +1,7 @@ package fj.data; +import fj.Equal; +import fj.P2; import org.junit.Test; import java.util.Arrays; @@ -53,4 +55,13 @@ public void convertToString() { expected.append(')'); assertEquals(expected.toString(), List.range(0, n).toString()); } + + @Test + public void partition() { + P2, List> p = List.range(1, 5).partition(i -> i % 2 == 0); + Equal> e = Equal.listEqual(Equal.intEqual); + assertTrue(e.eq(p._1(), List.list(2, 4))); + assertTrue(e.eq(p._2(), List.list(1, 3))); + } + } From 21d3701adb1abd284c0c71cecfbc8c5819bad9db Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 3 Jul 2015 20:54:26 +1000 Subject: [PATCH 334/811] Implemented Validation.partition and arbitrary validations --- core/src/main/java/fj/data/Validation.java | 10 ++++++ .../data/properties/ValidationProperties.java | 33 +++++++++++++++++++ .../src/main/java/fj/test/Arbitrary.java | 7 ++++ 3 files changed, 50 insertions(+) create mode 100644 props-core/src/test/java/fj/data/properties/ValidationProperties.java diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index fb268a7a..03e9269f 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -1287,6 +1287,16 @@ public Validation f(final String s) { } }; + /** + * Partitions the list into the list of fails and the list of successes + */ + public static P2, List> partition(List> list) { + return P.p( + list.filter(v -> v.isFail()).map(v -> v.fail()), + list.filter(v -> v.isSuccess()).map(v -> v.success()) + ); + } + @Override public String toString() { return Show.validationShow(Show.anyShow(), Show.anyShow()).showS(this); diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java new file mode 100644 index 00000000..2b3ba3c7 --- /dev/null +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -0,0 +1,33 @@ +package fj.data.properties; + +import fj.P2; +import fj.data.List; +import fj.data.Validation; +import fj.test.Arbitrary; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static fj.test.Arbitrary.*; + +/** + * Created by MarkPerry on 3/07/2015. + */ +@RunWith(PropertyTestRunner.class) +public class ValidationProperties { + + public Property partition() { + Arbitrary>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); + return Property.property(al, list -> { + P2, List> p = Validation.partition(list); + boolean b1 = p._1().length() + p._2().length() == list.length(); + boolean b2 = p._1().map(s -> Validation.fail(s)).equals(list.filter(v -> v.isFail())); + boolean b3 = p._2().map(s -> Validation.success(s)).equals(list.filter(v -> v.isSuccess())); + return Property.prop(b1 && b2 && b3); + }); + } + +} diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 6ca573e9..26bfe8c3 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -737,6 +737,13 @@ public static Arbitrary> arbNonEmptyList(final Arbitrary return arbitrary(Gen.listOf1(aa.gen).map(list -> NonEmptyList.fromList(list).some())); } + /** + * Returns an arbitrary Validation for the given arbitrary parameters. + */ + public static Arbitrary> arbValidation(final Arbitrary aa, final Arbitrary ab) { + return arbitrary(arbBoolean.gen.bind(bool -> bool ? ab.gen.map(b -> Validation.success(b)) : aa.gen.map(a -> Validation.fail(a)))); + } + /** * Returns an arbitrary implementation for streams. * From b5f439d9dbf0c205a17303d2e38249660d50fa6b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 3 Jul 2015 22:10:03 +1000 Subject: [PATCH 335/811] Fixed Validation.sequence method --- core/src/main/java/fj/data/Validation.java | 24 +++++++++---------- .../data/properties/ValidationProperties.java | 23 ++++++++++++++---- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 03e9269f..b8afe268 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -801,19 +801,19 @@ public Validation, D> accumulate(Validation v2, Validati } } - - + /** + * If the list contains a failure, returns a Validation of the fails in the + * list, otherwise returns a successful Validation with the list of + * successful values. + */ public static Validation, List> sequence(List> list) { - F2, Validation, List>, Validation, List>> f2 = (v, acc) -> { - if (acc.isFail() && v.isFail()) { - return Validation.validation(acc.toEither().left().map(l -> l.cons(v.fail()))); - } else if (acc.isSuccess() && v.isSuccess()) { - return acc.map(l -> l.cons(v.success())); - } else { - return acc; - } - }; - return list.foldRight(f2, Validation.success(List.nil())); + if (list.exists(v -> v.isFail())) { + F2, Validation, List> f = (acc, v) -> acc.cons(v.fail()); + return Validation.fail(list.filter(v -> v.isFail()).foldLeft(f, List.nil()).reverse()); + } else { + F2, Validation, List> f = (acc, v) -> acc.cons(v.success()); + return Validation.success(list.filter(v -> v.isSuccess()).foldLeft(f, List.nil()).reverse()); + } } public List> traverseList(F> f){ diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java index 2b3ba3c7..aa55ecc1 100644 --- a/props-core/src/test/java/fj/data/properties/ValidationProperties.java +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -5,13 +5,12 @@ import fj.data.Validation; import fj.test.Arbitrary; import fj.test.Property; -import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; -import org.junit.Assert; -import org.junit.Test; import org.junit.runner.RunWith; import static fj.test.Arbitrary.*; +import static fj.test.Property.implies; +import static fj.test.Property.prop; /** * Created by MarkPerry on 3/07/2015. @@ -26,7 +25,23 @@ public Property partition() { boolean b1 = p._1().length() + p._2().length() == list.length(); boolean b2 = p._1().map(s -> Validation.fail(s)).equals(list.filter(v -> v.isFail())); boolean b3 = p._2().map(s -> Validation.success(s)).equals(list.filter(v -> v.isSuccess())); - return Property.prop(b1 && b2 && b3); + return prop(b1 && b2 && b3); + }); + } + + public Property sequence() { + Arbitrary>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); + return Property.property(al, list -> { + Validation, List> v = Validation.sequence(list); + Property p1 = implies( + list.exists(v1 -> v1.isFail()), + () -> prop(v.fail().equals(list.filter(v2 -> v2.isFail()).map(v2 -> v2.fail()))) + ); + Property p2 = implies( + list.forall(v1 -> v1.isSuccess()), + () -> prop(v.success().equals(list.filter(v2 -> v2.isSuccess()).map(v2 -> v2.success()))) + ); + return p1.and(p2); }); } From dacb2323ddff923c1580060bfc27479389924b0a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 3 Jul 2015 22:54:48 +1000 Subject: [PATCH 336/811] Renamed sequence to sequenceReduce --- core/src/main/java/fj/data/Validation.java | 2 +- .../test/java/fj/data/properties/ValidationProperties.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index b8afe268..e421b088 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -806,7 +806,7 @@ public Validation, D> accumulate(Validation v2, Validati * list, otherwise returns a successful Validation with the list of * successful values. */ - public static Validation, List> sequence(List> list) { + public static Validation, List> sequenceReduce(List> list) { if (list.exists(v -> v.isFail())) { F2, Validation, List> f = (acc, v) -> acc.cons(v.fail()); return Validation.fail(list.filter(v -> v.isFail()).foldLeft(f, List.nil()).reverse()); diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java index aa55ecc1..4fcf57d8 100644 --- a/props-core/src/test/java/fj/data/properties/ValidationProperties.java +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -29,10 +29,10 @@ public Property partition() { }); } - public Property sequence() { + public Property sequenceReduce() { Arbitrary>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); return Property.property(al, list -> { - Validation, List> v = Validation.sequence(list); + Validation, List> v = Validation.sequenceReduce(list); Property p1 = implies( list.exists(v1 -> v1.isFail()), () -> prop(v.fail().equals(list.filter(v2 -> v2.isFail()).map(v2 -> v2.fail()))) From 35f81787f2d3a650e5bdb40a3a2f529ef8208f89 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 4 Jul 2015 00:46:54 +1000 Subject: [PATCH 337/811] #163: Implemented Validation.sequence using a semigroup --- core/src/main/java/fj/data/Validation.java | 12 ++++++++++++ .../fj/data/properties/ValidationProperties.java | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index e421b088..5bfb5f43 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -200,6 +200,18 @@ public Validation sequence(final Validation v) { return bind(Function.>constant(v)); } + /** + * If list contains a failure, returns a failure of the reduction of + * all the failures using the semigroup, otherwise returns the successful list. + */ + public static Validation> sequence(final Semigroup s, final List> list) { + if (list.exists(v -> v.isFail())) { + return Validation.>fail(list.filter(v -> v.isFail()).map(v -> v.fail()).foldLeft1((e1, e2) -> s.sum(e1, e2))); + } else { + return Validation.success(list.foldLeft((List acc, Validation v) -> acc.cons(v.success()), List.nil()).reverse()); + } + } + /** * Returns None if this is a failure or if the given predicate p does not hold for the * success value, otherwise, returns a success in Some. diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java index 4fcf57d8..e9c1510a 100644 --- a/props-core/src/test/java/fj/data/properties/ValidationProperties.java +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -1,6 +1,7 @@ package fj.data.properties; import fj.P2; +import fj.Semigroup; import fj.data.List; import fj.data.Validation; import fj.test.Arbitrary; @@ -45,4 +46,18 @@ public Property sequenceReduce() { }); } + public Property sequence() { + return Property.property(arbList(arbValidation(arbString, arbInteger)), list -> { + Validation> v = Validation.sequence(Semigroup.stringSemigroup, list); + Property p1 = implies(list.exists((Validation v2) -> v2.isFail()), () -> prop(v.isFail())); + boolean b = list.forall((Validation v2) -> v2.isSuccess()); + Property p2 = implies(b, () -> { + List l2 = list.map((Validation v2) -> v2.success()); + boolean b2 = v.success().equals(l2); + return prop(b2); + }); + return p1.and(p2); + }); + } + } From 73b0c700feceb555f36d13988d5d0021b0287536 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 4 Jul 2015 20:56:28 +1000 Subject: [PATCH 338/811] #168: Replaced iterable with Stream.range and works reliably --- .../src/test/scala/fj/data/CheckStream.scala | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckStream.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckStream.scala index 8d97600d..3a272953 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckStream.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckStream.scala @@ -51,13 +51,15 @@ object CheckStream extends Properties("Stream") { val length = Gen.choose(0, 5000) property("bindStackOverflow") = forAll(length)(size => { - val stream = iterableStream(JavaConversions.asJavaIterable((1 to size))) - val bound: Stream[Int] = stream.bind(new F[Int, Stream[Int]] { - def f(a: Int) = single(a) + val stream = Stream.range(1, size + 1) + val bound: Stream[Integer] = stream.bind(new F[Integer, Stream[Integer]] { + def f(a: Integer) = single(a) }) - stream.zip(bound).forall(new F[P2[Int, Int], java.lang.Boolean] { - def f(a: P2[Int, Int]) = a._1() == a._2() + val zipped = stream.zip(bound) + val allmatch = zipped.forall(new F[P2[Integer, Integer], java.lang.Boolean] { + def f(a: P2[Integer, Integer]) = a._1() == a._2() }) + allmatch && zipped.length() == size }) property("foreach") = forAll((a: Stream[Int]) => { From 141352b2f46050a311699da4a5b2995201fc75fc Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 4 Jul 2015 22:38:59 +1000 Subject: [PATCH 339/811] #142: Renamed comap to contramap --- core/src/main/java/fj/Effect.java | 2 +- core/src/main/java/fj/Equal.java | 22 ++++++++--------- core/src/main/java/fj/F1Functions.java | 21 ++++++++-------- core/src/main/java/fj/F1W.java | 24 ++++++++----------- core/src/main/java/fj/Hash.java | 24 +++++++++---------- core/src/main/java/fj/Ord.java | 12 +++++----- core/src/main/java/fj/Show.java | 21 ++++++++-------- .../main/java/fj/control/parallel/Actor.java | 2 +- .../java/fj/control/parallel/Promise.java | 2 +- .../java/fj/control/parallel/Strategy.java | 23 +++++++++--------- core/src/main/java/fj/data/Enumerator.java | 2 +- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/TreeMap.java | 8 +++---- core/src/main/java/fj/data/TreeZipper.java | 4 ++-- core/src/main/java/fj/data/Zipper.java | 7 +++--- core/src/test/java/fj/data/BooleansTest.java | 2 +- .../src/test/scala/fj/data/CheckHashMap.scala | 4 ++-- .../src/test/scala/fj/data/CheckHashSet.scala | 4 ++-- .../src/test/scala/fj/data/CheckSet.scala | 2 +- .../src/test/scala/fj/data/CheckTreeMap.scala | 2 +- .../src/main/java/fj/test/Coarbitrary.java | 8 +++---- 21 files changed, 95 insertions(+), 103 deletions(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index ef4cd547..aec3e442 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -95,7 +95,7 @@ public static F5 f(Effect5 z * @param f The function to map over the effect. * @return An effect after a contra-variant map. */ - public static final Effect1 comap(Effect1 e1, final F f) { + public static final Effect1 contramap(Effect1 e1, final F f) { return b -> e1.f(f.f(b)); } diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index fb5204c1..60fcb86d 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -74,7 +74,7 @@ public F eq(final A a) { * @param f The function to map. * @return A new equal. */ - public Equal comap(final F f) { + public Equal contramap(final F f) { return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } @@ -202,7 +202,7 @@ public static Equal> eitherEqual(final Equal ea, final Eq * @return An equal instance for the {@link Validation} type. */ public static Equal> validationEqual(final Equal ea, final Equal eb) { - return eitherEqual(ea, eb).comap(Validation.either()); + return eitherEqual(ea, eb).contramap(Validation.either()); } /** @@ -235,7 +235,7 @@ public static Equal> listEqual(final Equal ea) { * @return An equal instance for the {@link NonEmptyList} type. */ public static Equal> nonEmptyListEqual(final Equal ea) { - return listEqual(ea).comap(NonEmptyList.toList_()); + return listEqual(ea).contramap(NonEmptyList.toList_()); } /** @@ -443,7 +443,7 @@ public static Equal> p5Equal(final Equal ea * @return An equal instance for a vector-2. */ public static Equal> v2Equal(final Equal ea) { - return streamEqual(ea).comap(V2.toStream_()); + return streamEqual(ea).contramap(V2.toStream_()); } /** @@ -453,7 +453,7 @@ public static Equal> v2Equal(final Equal ea) { * @return An equal instance for a vector-3. */ public static Equal> v3Equal(final Equal ea) { - return streamEqual(ea).comap(V3.toStream_()); + return streamEqual(ea).contramap(V3.toStream_()); } /** @@ -463,7 +463,7 @@ public static Equal> v3Equal(final Equal ea) { * @return An equal instance for a vector-4. */ public static Equal> v4Equal(final Equal ea) { - return streamEqual(ea).comap(V4.toStream_()); + return streamEqual(ea).contramap(V4.toStream_()); } /** @@ -473,7 +473,7 @@ public static Equal> v4Equal(final Equal ea) { * @return An equal instance for a vector-5. */ public static Equal> v5Equal(final Equal ea) { - return streamEqual(ea).comap(V5.toStream_()); + return streamEqual(ea).contramap(V5.toStream_()); } /** @@ -483,7 +483,7 @@ public static Equal> v5Equal(final Equal ea) { * @return An equal instance for a vector-6. */ public static Equal> v6Equal(final Equal ea) { - return streamEqual(ea).comap(V6.toStream_()); + return streamEqual(ea).contramap(V6.toStream_()); } /** @@ -493,7 +493,7 @@ public static Equal> v6Equal(final Equal ea) { * @return An equal instance for a vector-7. */ public static Equal> v7Equal(final Equal ea) { - return streamEqual(ea).comap(V7.toStream_()); + return streamEqual(ea).contramap(V7.toStream_()); } /** @@ -503,13 +503,13 @@ public static Equal> v7Equal(final Equal ea) { * @return An equal instance for a vector-8. */ public static Equal> v8Equal(final Equal ea) { - return streamEqual(ea).comap(V8.toStream_()); + return streamEqual(ea).contramap(V8.toStream_()); } /** * An equal instance for lazy strings. */ - public static final Equal eq = streamEqual(charEqual).comap(LazyString.toStream); + public static final Equal eq = streamEqual(charEqual).contramap(LazyString.toStream); /** * An equal instance for the empty heterogeneous list. diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 6f0f4a07..2d3c56d4 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -4,7 +4,6 @@ import fj.control.parallel.Promise; import fj.control.parallel.Strategy; import fj.data.*; -import fj.function.Try1; import java.util.ArrayList; import java.util.LinkedList; @@ -224,12 +223,12 @@ static public F, Array> mapArray(final F f) { } /** - * Returns a function that comaps over a given actor. + * Returns a function that contramaps over a given actor. * - * @return A function that comaps over a given actor. + * @return A function that contramaps over a given actor. */ - static public F, Actor> comapActor(final F f) { - return a -> a.comap(f); + static public F, Actor> contramapActor(final F f) { + return a -> a.contramap(f); } /** @@ -502,8 +501,8 @@ static public F, Zipper> mapZipper(final F f) { * * @return This function promoted to map over an Equal as a contravariant functor. */ - static public F, Equal> comapEqual(final F f) { - return e -> e.comap(f); + static public F, Equal> contramapEqual(final F f) { + return e -> e.contramap(f); } /** @@ -511,8 +510,8 @@ static public F, Equal> comapEqual(final F f) { * * @return This function promoted to map over a Hash as a contravariant functor. */ - static public F, Hash> comapHash(final F f) { - return h -> h.comap(f); + static public F, Hash> contramapHash(final F f) { + return h -> h.contramap(f); } /** @@ -520,8 +519,8 @@ static public F, Hash> comapHash(final F f) { * * @return This function promoted to map over a Show as a contravariant functor. */ - static public F, Show> comapShow(final F f) { - return s -> s.comap(f); + static public F, Show> contramapShow(final F f) { + return s -> s.contramap(f); } /** diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java index a0522bab..73545411 100644 --- a/core/src/main/java/fj/F1W.java +++ b/core/src/main/java/fj/F1W.java @@ -11,10 +11,6 @@ import java.util.TreeSet; import java.util.concurrent.*; -import static fj.data.Option.some; -import static fj.data.Stream.iterableStream; -import static fj.data.Zipper.fromStream; - /** * Created by MarkPerry on 22/01/2015. */ @@ -225,12 +221,12 @@ public F1W, Array> mapArray() { } /** - * Returns a function that comaps over a given actor. + * Returns a function that contramaps over a given actor. * - * @return A function that comaps over a given actor. + * @return A function that contramaps over a given actor. */ - public F1W, Actor> comapActor() { - return lift(F1Functions.comapActor(this)); + public F1W, Actor> contramapActor() { + return lift(F1Functions.contramapActor(this)); } /** @@ -501,8 +497,8 @@ public F1W, Zipper> mapZipper() { * * @return This function promoted to map over an Equal as a contravariant functor. */ - public F1W, Equal> comapEqual() { - return lift(F1Functions.comapEqual(this)); + public F1W, Equal> contramapEqual() { + return lift(F1Functions.contramapEqual(this)); } /** @@ -510,8 +506,8 @@ public F1W, Equal> comapEqual() { * * @return This function promoted to map over a Hash as a contravariant functor. */ - public F1W, Hash> comapHash() { - return lift(F1Functions.comapHash(this)); + public F1W, Hash> contramapHash() { + return lift(F1Functions.contramapHash(this)); } /** @@ -519,8 +515,8 @@ public F1W, Hash> comapHash() { * * @return This function promoted to map over a Show as a contravariant functor. */ - public F1W, Show> comapShow() { - return lift(F1Functions.comapShow(this)); + public F1W, Show> contramapShow() { + return lift(F1Functions.contramapShow(this)); } /** diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 3c11a6ca..26f42049 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -42,7 +42,7 @@ public int hash(final A a) { * @param g The function to map. * @return A new hash. */ - public Hash comap(final F g) { + public Hash contramap(final F g) { return hash(compose(f, g)); } @@ -165,7 +165,7 @@ public static Hash> eitherHash(final Hash ha, final Hash< * @return A hash instance for the {@link Validation} type. */ public static Hash> validationHash(final Hash ha, final Hash hb) { - return eitherHash(ha, hb).comap(Validation.either()); + return eitherHash(ha, hb).contramap(Validation.either()); } /** @@ -196,7 +196,7 @@ public static Hash> listHash(final Hash ha) { * @return A hash instance for the {@link NonEmptyList} type. */ public static Hash> nonEmptyListHash(final Hash ha) { - return listHash(ha).comap(NonEmptyList.toList_()); + return listHash(ha).contramap(NonEmptyList.toList_()); } /** @@ -264,7 +264,7 @@ public static Hash> arrayHash(final Hash ha) { * @return A hash instance for the {@link Tree} type. */ public static Hash> treeHash(final Hash ha) { - return streamHash(ha).comap(Tree.flatten_()); + return streamHash(ha).contramap(Tree.flatten_()); } public static Hash> treeMapHash(final Hash h, final Hash v) { @@ -278,7 +278,7 @@ public static Hash> treeMapHash(final Hash h, final Hash * @return A hash instance for a product-1. */ public static Hash> p1Hash(final Hash ha) { - return ha.comap(P1.__1()); + return ha.contramap(P1.__1()); } /** @@ -473,7 +473,7 @@ public static Hash> p5Hash(final Hash ha, f * @return A hash instance for a vector-2. */ public static Hash> v2Hash(final Hash ea) { - return streamHash(ea).comap(V2.toStream_()); + return streamHash(ea).contramap(V2.toStream_()); } /** @@ -483,7 +483,7 @@ public static Hash> v2Hash(final Hash ea) { * @return A hash instance for a vector-3. */ public static Hash> v3Hash(final Hash ea) { - return streamHash(ea).comap(V3.toStream_()); + return streamHash(ea).contramap(V3.toStream_()); } /** @@ -493,7 +493,7 @@ public static Hash> v3Hash(final Hash ea) { * @return A hash instance for a vector-4. */ public static Hash> v4Hash(final Hash ea) { - return streamHash(ea).comap(V4.toStream_()); + return streamHash(ea).contramap(V4.toStream_()); } /** @@ -503,7 +503,7 @@ public static Hash> v4Hash(final Hash ea) { * @return A hash instance for a vector-5. */ public static Hash> v5Hash(final Hash ea) { - return streamHash(ea).comap(V5.toStream_()); + return streamHash(ea).contramap(V5.toStream_()); } /** @@ -513,7 +513,7 @@ public static Hash> v5Hash(final Hash ea) { * @return A hash instance for a vector-6. */ public static Hash> v6Hash(final Hash ea) { - return streamHash(ea).comap(V6.toStream_()); + return streamHash(ea).contramap(V6.toStream_()); } /** @@ -523,7 +523,7 @@ public static Hash> v6Hash(final Hash ea) { * @return A hash instance for a vector-7. */ public static Hash> v7Hash(final Hash ea) { - return streamHash(ea).comap(V7.toStream_()); + return streamHash(ea).contramap(V7.toStream_()); } /** @@ -533,6 +533,6 @@ public static Hash> v7Hash(final Hash ea) { * @return A hash instance for a vector-8. */ public static Hash> v8Hash(final Hash ea) { - return streamHash(ea).comap(V8.toStream_()); + return streamHash(ea).contramap(V8.toStream_()); } } diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index fa612288..0d24a768 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -74,7 +74,7 @@ public Equal equal() { * @param f The function to map. * @return A new ord. */ - public Ord comap(final F f) { + public Ord contramap(final F f) { return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } @@ -334,7 +334,7 @@ public static Ord> eitherOrd(final Ord oa, final Ord o * @return An order instance for the {@link Validation} type. */ public static Ord> validationOrd(final Ord oa, final Ord ob) { - return eitherOrd(oa, ob).comap(Validation.either()); + return eitherOrd(oa, ob).contramap(Validation.either()); } /** @@ -374,7 +374,7 @@ public static Ord> listOrd(final Ord oa) { * @return An order instance for the {@link NonEmptyList} type. */ public static Ord> nonEmptyListOrd(final Ord oa) { - return listOrd(oa).comap(NonEmptyList.toList_()); + return listOrd(oa).contramap(NonEmptyList.toList_()); } /** @@ -428,7 +428,7 @@ public static Ord> arrayOrd(final Ord oa) { * @return An order instance for the {@link Set} type. */ public static Ord> setOrd(final Ord oa) { - return streamOrd(oa).comap(as -> as.toStream()); + return streamOrd(oa).contramap(as -> as.toStream()); } /** @@ -443,7 +443,7 @@ public static Ord> setOrd(final Ord oa) { * @return An order instance for a product-1. */ public static Ord> p1Ord(final Ord oa) { - return oa.comap(P1.__1()); + return oa.contramap(P1.__1()); } @@ -475,7 +475,7 @@ public static Ord> p3Ord(final Ord oa, final Ord ob, /** * An order instance for the Natural type. */ - public static final Ord naturalOrd = bigintOrd.comap(Natural.bigIntegerValue); + public static final Ord naturalOrd = bigintOrd.contramap(Natural.bigIntegerValue); /** diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index df8b5bdd..b67f662a 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -19,7 +19,6 @@ import static fj.data.Stream.cons; import static fj.data.Stream.fromString; import static fj.data.Stream.join; -import static fj.data.Stream.nil; import static fj.data.Stream.single; /** @@ -40,7 +39,7 @@ private Show(final F> f) { * @param f The function to map. * @return A new show. */ - public Show comap(final F f) { + public Show contramap(final F f) { return show(compose(this.f, f)); } @@ -283,7 +282,7 @@ public static Show> listShow(final Show sa) { * @return A show instance for the {@link NonEmptyList} type. */ public static Show> nonEmptyListShow(final Show sa) { - return listShow(sa).comap(NonEmptyList.toList_()); + return listShow(sa).contramap(NonEmptyList.toList_()); } /** @@ -558,7 +557,7 @@ public static Show> p5Show(final Show sa, f * @return A show instance for a vector-2. */ public static Show> v2Show(final Show ea) { - return streamShow(ea, "V2(", ",", ")").comap(V2.toStream_()); + return streamShow(ea, "V2(", ",", ")").contramap(V2.toStream_()); } /** @@ -568,7 +567,7 @@ public static Show> v2Show(final Show ea) { * @return A show instance for a vector-3. */ public static Show> v3Show(final Show ea) { - return streamShow(ea, "V3(", ",", ")").comap(V3.toStream_()); + return streamShow(ea, "V3(", ",", ")").contramap(V3.toStream_()); } /** @@ -578,7 +577,7 @@ public static Show> v3Show(final Show ea) { * @return A show instance for a vector-4. */ public static Show> v4Show(final Show ea) { - return streamShow(ea, "V4(", ",", ")").comap(V4.toStream_()); + return streamShow(ea, "V4(", ",", ")").contramap(V4.toStream_()); } /** @@ -588,7 +587,7 @@ public static Show> v4Show(final Show ea) { * @return A show instance for a vector-5. */ public static Show> v5Show(final Show ea) { - return streamShow(ea, "V5(", ",", ")").comap(V5.toStream_()); + return streamShow(ea, "V5(", ",", ")").contramap(V5.toStream_()); } /** @@ -598,7 +597,7 @@ public static Show> v5Show(final Show ea) { * @return A show instance for a vector-6. */ public static Show> v6Show(final Show ea) { - return streamShow(ea, "V6(", ",", ")").comap(V6.toStream_()); + return streamShow(ea, "V6(", ",", ")").contramap(V6.toStream_()); } /** @@ -608,7 +607,7 @@ public static Show> v6Show(final Show ea) { * @return A show instance for a vector-7. */ public static Show> v7Show(final Show ea) { - return streamShow(ea, "V7(", ",", ")").comap(V7.toStream_()); + return streamShow(ea, "V7(", ",", ")").contramap(V7.toStream_()); } /** @@ -618,13 +617,13 @@ public static Show> v7Show(final Show ea) { * @return A show instance for a vector-8. */ public static Show> v8Show(final Show ea) { - return streamShow(ea, "V8(", ",", ")").comap(V8.toStream_()); + return streamShow(ea, "V8(", ",", ")").contramap(V8.toStream_()); } /** * A show instance for natural numbers. */ - public static final Show naturalShow = bigintShow.comap(Natural::bigIntegerValue); + public static final Show naturalShow = bigintShow.contramap(Natural::bigIntegerValue); /** * A show instance for streams that splits into lines. diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 91ee72d0..77d4fe2d 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -122,7 +122,7 @@ public P1 act(final A a) { * @param f The function to use for the transformation * @return A new actor which passes its messages through the given function, to this actor. */ - public Actor comap(final F f) { + public Actor contramap(final F f) { return actor(s, (B b) -> act(f.f(b))); } diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index ac768b59..2f93d5e7 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -195,7 +195,7 @@ public void f(final B b) { r.actor.act(P.p(Either., Actor>left(P.p(b)), r)); } }); - to(ab.promise().comap(f)); + to(ab.promise().contramap(f)); return r; } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index ad6e3923..f93b4d89 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -1,6 +1,5 @@ package fj.control.parallel; -import fj.Effect; import fj.F; import fj.F2; import fj.Function; @@ -429,7 +428,7 @@ public Strategy map(final F, P1> f) { * @param f A transformation from the resulting strategy's domain to this strategy's domain. * @return A new strategy that applies the given transformation before each application of this strategy. */ - public Strategy comap(final F, P1> f) { + public Strategy contramap(final F, P1> f) { return xmap(Function.>identity(), f); } @@ -453,15 +452,15 @@ public Strategy errorStrategy(final Effect1 e) { * @return A strategy that captures any runtime errors with a side-effect. */ public static Strategy errorStrategy(final Strategy s, final Effect1 e) { - return s.comap(a -> P.lazy(() -> { - try { - return a._1(); - } catch (Throwable t) { - final Error error = new Error(t); - e.f(error); - throw error; - } - }) + return s.contramap(a -> P.lazy(() -> { + try { + return a._1(); + } catch (Throwable t) { + final Error error = new Error(t); + e.f(error); + throw error; + } + }) ); } @@ -472,7 +471,7 @@ public static Strategy errorStrategy(final Strategy s, final Effect1 Strategy> callableStrategy(final Strategy> s) { - return s.comap(a -> P1.curry(Callables.normalise()).f(a._1())); + return s.contramap(a -> P1.curry(Callables.normalise()).f(a._1())); } } diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index 67697ed4..a3067e06 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -174,7 +174,7 @@ public Option f(final Option o) { compose(compose(of, predecessor), g), max.map(f), min.map(f), - order.comap(g), + order.contramap(g), compose(compose(Function., Option>compose().f(of), plus), g)); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 667bb73f..89bcd4e5 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1247,7 +1247,7 @@ public final List insertBy(final F> f, final A x) { * @return The most common element in this list. */ public final A mode(final Ord o) { - return sort(o).group(o.equal()).maximum(intOrd.comap(List.length_())).head(); + return sort(o).group(o.equal()).maximum(intOrd.contramap(List.length_())).head(); } /** diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 4bede107..33d2438d 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -23,7 +23,7 @@ private TreeMap(final Set>> tree) { } private static Ord> ord(final Ord keyOrd) { - return keyOrd.comap(P2.__1()); + return keyOrd.contramap(P2.__1()); } /** @@ -174,7 +174,7 @@ public Iterator> iterator() { */ public Map toMutableMap() { final F>> fakePair = k -> P.p(k, Option.none()); - final Comparator comparator = tree.ord().comap(fakePair).toComparator(); + final Comparator comparator = tree.ord().contramap(fakePair).toComparator(); final Map m = new java.util.TreeMap(comparator); for (final P2 e : this) { m.put(e._1(), e._2()); @@ -290,7 +290,7 @@ private static TreeMap treeMap(Ord ord, Set>> s) */ public P3, Option, TreeMap> splitLookup(final K k) { P3>>, Option>>, Set>>> p3 = tree.split(P.p(k, get(k))); - Ord o = tree.ord().comap(k2 -> P.p(k2, Option.none())); + Ord o = tree.ord().contramap(k2 -> P.p(k2, Option.none())); return P.p(treeMap(o, p3._1()), get(k), treeMap(o, p3._3())); } @@ -304,7 +304,7 @@ public P3, Option, TreeMap> splitLookup(final K k) { public TreeMap map(final F f) { final F>, P2>> g = P2.map2_(F1Functions.mapOption(f)); final F>> coord = flip(P.>p2()).f(Option.none()); - final Ord o = tree.ord().comap(coord); + final Ord o = tree.ord().contramap(coord); return new TreeMap(tree.map(TreeMap.>ord(o), g)); } diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 96874799..959de5a7 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -114,7 +114,7 @@ public static Equal> eq(final Equal e) { treeEqual(e), streamEqual(treeEqual(e)), streamEqual(treeEqual(e)), - streamEqual(p3Equal(streamEqual(treeEqual(e)), e, streamEqual(treeEqual(e))))).comap(TreeZipper.p_()); + streamEqual(p3Equal(streamEqual(treeEqual(e)), e, streamEqual(treeEqual(e))))).contramap(TreeZipper.p_()); } /** @@ -128,7 +128,7 @@ public static Show> show(final Show s) { treeShow(s), streamShow(treeShow(s)), streamShow(treeShow(s)), - streamShow(p3Show(streamShow(treeShow(s)), s, streamShow(treeShow(s))))).comap(TreeZipper.p_()); + streamShow(p3Show(streamShow(treeShow(s)), s, streamShow(treeShow(s))))).contramap(TreeZipper.p_()); } private static Stream> combChildren(final Stream> ls, diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index c4219a4d..a4377507 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -25,7 +25,6 @@ import static fj.data.Option.some; import static fj.data.Stream.nil; import static fj.data.Stream.repeat; -import static fj.F2Functions.*; /** * Provides a pointed stream, which is a non-empty zipper-like stream structure that tracks an index (focus) @@ -104,7 +103,7 @@ public static F, P3, A, Stream>> p_() { */ public static Ord> ord(final Ord o) { final Ord> so = Ord.streamOrd(o); - return Ord.p3Ord(so, o, so).comap(Zipper.p_()); + return Ord.p3Ord(so, o, so).contramap(Zipper.p_()); } /** @@ -115,7 +114,7 @@ public static Ord> ord(final Ord o) { */ public static Equal> eq(final Equal e) { final Equal> se = Equal.streamEqual(e); - return Equal.p3Equal(se, e, se).comap(Zipper.p_()); + return Equal.p3Equal(se, e, se).contramap(Zipper.p_()); } /** @@ -126,7 +125,7 @@ public static Equal> eq(final Equal e) { */ public static Show> show(final Show s) { final Show> ss = Show.streamShow(s); - return Show.p3Show(ss, s, ss).comap(Zipper.p_()); + return Show.p3Show(ss, s, ss).contramap(Zipper.p_()); } /** diff --git a/core/src/test/java/fj/data/BooleansTest.java b/core/src/test/java/fj/data/BooleansTest.java index b924a7c8..b0d3f969 100644 --- a/core/src/test/java/fj/data/BooleansTest.java +++ b/core/src/test/java/fj/data/BooleansTest.java @@ -41,7 +41,7 @@ public void testOr(){ } @Test - public void testComap(){ + public void testContramap(){ F f1 = a -> a.length() > 3; F f2 = a -> a.toString(); diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala index ecf09174..58656779 100755 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala @@ -15,8 +15,8 @@ import org.scalacheck.Arbitrary._ import java.util.Map object CheckHashMap extends Properties("HashMap") { - implicit val equalInt: Equal[Int] = intEqual comap ((x: Int) => (x: java.lang.Integer)) - implicit val hashInt: Hash[Int] = intHash comap ((x: Int) => (x: java.lang.Integer)) + implicit val equalInt: Equal[Int] = intEqual contramap ((x: Int) => (x: java.lang.Integer)) + implicit val hashInt: Hash[Int] = intHash contramap ((x: Int) => (x: java.lang.Integer)) implicit def arbitraryListOfIterableP2: Arbitrary[java.lang.Iterable[P2[Int, String]]] = Arbitrary(listOf(arbitrary[(Int, String)]) diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckHashSet.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashSet.scala index 5c711aea..d774ff74 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckHashSet.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckHashSet.scala @@ -8,8 +8,8 @@ import Hash.intHash import org.scalacheck.Properties object CheckHashSet extends Properties("List") { - implicit val equalInt: Equal[Int] = intEqual comap ((x: Int) => (x: java.lang.Integer)) - implicit val hashInt: Hash[Int] = intHash comap ((x: Int) => (x: java.lang.Integer)) + implicit val equalInt: Equal[Int] = intEqual contramap ((x: Int) => (x: java.lang.Integer)) + implicit val hashInt: Hash[Int] = intHash contramap ((x: Int) => (x: java.lang.Integer)) property("eq") = forAll((s: HashSet[Int], x: Int, y: Int) => s.eq(x, y) == equalInt.eq(x, y)) diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala index af90480a..96bce311 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala @@ -16,7 +16,7 @@ import org.scalacheck.Properties object CheckSet extends Properties("Set") { def idInt(n: Int) = n:java.lang.Integer - implicit def oi : Ord[Int] = intOrd.comap(idInt _) + implicit def oi : Ord[Int] = intOrd.contramap(idInt _) implicit def os : Ord[String] = stringOrd property("isEmpty") = forAll((a: Set[Int]) => diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala index ed2a93b3..25a7719a 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala @@ -8,7 +8,7 @@ import org.scalacheck.Properties object CheckTreeMap extends Properties("TreeMap") { def idInt(n: Int) = n:java.lang.Integer - implicit def oi : Ord[Int] = intOrd.comap(idInt _) + implicit def oi : Ord[Int] = intOrd.contramap(idInt _) implicit def os : Ord[String] = stringOrd property("set") = forAll((m: TreeMap[Int, String], k: Int, v: String) => m.set(k, v).get(k).some == v) diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index 34b3f07a..8b778188 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -98,12 +98,12 @@ public Gen coarbitrary(final B b, final Gen g) { } /** - * Co-maps this coarbitrary using the given function. + * Contra-maps this coarbitrary using the given function. * * @param f The function to co-map with. - * @return A co-mapped coarbitrary. + * @return A contra-mapped coarbitrary. */ - public final Coarbitrary comap(final F f) { + public final Coarbitrary contramap(final F f) { return new Coarbitrary() { public Gen coarbitrary(final B b, final Gen g) { return Coarbitrary.this.coarbitrary(f.f(b), g); @@ -507,7 +507,7 @@ public Gen coarbitrary(final Array as, final Gen g) { * @return A coarbitrary for throwables. */ public static Coarbitrary coarbThrowable(final Coarbitrary cs) { - return cs.comap(new F() { + return cs.contramap(new F() { public String f(final Throwable t) { return t.getMessage(); } From e8b99a0c42eff833501fec35b23e138a816e144b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 5 Jul 2015 00:11:09 +1000 Subject: [PATCH 340/811] #171: Updated libraries --- build.gradle | 6 +++--- props-core-scalacheck/build.gradle | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 32ee5244..f1cd6887 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ ext { buildscript { ext { - uptodateVersion = "1.3.1" - retrolambdaVersion = "2.5.0" + uptodateVersion = "1.5.1" + retrolambdaVersion = "3.2.0" } repositories { @@ -61,7 +61,7 @@ allprojects { sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" - dependencyJunit = "junit:junit:4.11" + dependencyJunit = "junit:junit:4.12" } diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index e8c4c67b..d946a5e6 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -4,9 +4,9 @@ archivesBaseName = "${project.projectName}-${project.name}" apply plugin: 'scala' ext { - scalaVersion = "2.11.6" + scalaVersion = "2.11.7" scalacheckScalaVersion = "2.11" - scalacheckVersion = "1.12.2" + scalacheckVersion = "1.12.4" signModule = true } From 90f372972ef6a28f57e5bcd358affaad7fbbc117 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 5 Jul 2015 22:31:01 +1000 Subject: [PATCH 341/811] Documented 4.4 changes --- etc/release-notes/release-notes-4.4.adoc | 59 ++++++++++++++++++++---- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc index 7401713a..5c9632c2 100644 --- a/etc/release-notes/release-notes-4.4.adoc +++ b/etc/release-notes/release-notes-4.4.adoc @@ -1,50 +1,89 @@ = Release 4.4 -Proposed Release Date: June 2015 +Proposed Release Date: July 2015 == Enhancements -* Added optics lenses inspired from the Monocle Scala library (#130, 131, 132). +* Added optics lenses inspired from the Monocle Scala library, instances for List and P2 (#130, #131, #132, #159). * Added functionality to FingerTree and Seq: head, last, tail, init, split, split1, update, toJavaList, Iterable (#140). * Added OrdComparator and fixed TreeMap.toMutableMap (#110). * Added bimap to Either (#121). * Added monoid composition. +* Changed comap methods to contramap (#142, #170) +* Provide hard, soft and weak memoisation implementations, default to weak (#153, #151). +* Added optics (#154). +* Added Validation.sequence (#163, #167). +* Add PropertyTestRunner (#144). +* Added Equal.notEq, List.isPrefixOf, List.isSuffixOf (#146). +* Made enhancements to support Real World Haskell example (#155) + * made P1.toString lazy + * added IOFunctions.interact + * added IOFunctions.getContents + * added map, bind and eval to LazyString + * added IO wrapper with static methods from IOFunctions as instance methods + * Stream.take evaluates one those items necessary (one less than currently) + * Made Stream.toString lazy + * Added Strings methods lines and unlines + * Refactor 'from' + * Made IOFunctions.sequenceWhile lazy + * Changed IOFunctions io to be fromF and fromTry. +* Enhanced Property to run individual tests (#156). +* Added Seq.isNotEmpty (#158). +* Added List.partition (#161). +* Added Validation.partition, arbitrary validations for testing (#165). +* Added Validation.sequence (using semigroup) (#163, #167). == Fixes * Fixed LazyString.toString for Android (#109) * Fixed exhausted ScalaCheck tests (#115). * Fixed overflow in standard Rand (#112). -* Fixed equals for anonymous classes (#122). -* Fixed List.init (#128). -* Fixed Effect.f ignoring argument (#133). -* Made Effect.comap static (#135). +* Fixed equals for anonymous classes (#122, #125). +* Fixed List.init (#128, #129). +* Fixed Effect.f ignoring argument (#133, #134). +* Made Effect.comap static (#135, #134). * Fixed Class.inheritance infinite list (#137). * Fixed Stream.toString to human readable representation (#138). -* Fixed P1.memo cache in threaded environment (#141). +* Fixed P1.memo cache in threaded environment (#141, #108). * Fixed Stream join and bind for infinite streams (#140). +* Fixed Validation.sequence and renamed to sequenceReduce (#162). +* Scalacheck property Stream.bindStackOverflow sometimes fails (#168, #169). +* Fixed bug in FingerTree.append (#144). +* Fixed arrayShow (#145). +* Fixed Stream.bindStackOverflow test that occasionally failed (#157). == Internal * Added Travis build (#115). -* Upgraded to Gradle 2.4 (#143). +* Upgraded to Gradle 2.4 (#143, #118). * Added Gradle uptodate plugin (#119). * Updated Scala and ScalaCheck to 2.11.6 and 1.12.2 respectively (#120). * Replaced P1 by F0 in various APIs (#136). +* Split quickcheck property testing into separate module (#147, #148). +* Updated libraries used: Uptodate 1.5.1, Retrolambda plugin 3.2.0, JUnit 4.12, Scala 2.11.7, Scalacheck 1.12.4 (#171, #172). +* Fixed unnecessary P1.memo wrapping (#150). +* Added property tests for List, Stream and Array (#158). == Breaking Changes +* Comap methods renamed to contramap. +* Split quickcheck into separate module. +* Validation.sequence renamed to sequenceReduce. +* Changed IOFunctions io to be fromF and fromTry. + == Documentation == Contributors * Mark Perry +* Jean-Baptiste Giraudeau +* Zheka Kozlov * daneko * Dobes Vandermeer * Kenji Yoshida -* Jean-Baptiste Giraudeau * Runar Bjarnason * Paul Horn -* Zheka Kozlov +* John Sullivan + From 463ea81e0dcc267cd92a979585f6ac96d7b5a0fb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 5 Jul 2015 22:35:00 +1000 Subject: [PATCH 342/811] Added links to optics overview in Monocle and Haskell lens --- etc/release-notes/release-notes-4.4.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc index 5c9632c2..7451127b 100644 --- a/etc/release-notes/release-notes-4.4.adoc +++ b/etc/release-notes/release-notes-4.4.adoc @@ -12,7 +12,7 @@ Proposed Release Date: July 2015 * Added monoid composition. * Changed comap methods to contramap (#142, #170) * Provide hard, soft and weak memoisation implementations, default to weak (#153, #151). -* Added optics (#154). +* Added optics (See the Scala Monocle library https://github.com/julien-truffaut/Monocle and the Haskell lens lbrary https://github.com/ekmett/lens for an overview) (#154). * Added Validation.sequence (#163, #167). * Add PropertyTestRunner (#144). * Added Equal.notEq, List.isPrefixOf, List.isSuffixOf (#146). From 5793cdf252d4d2cbe63f8dfd9968974611728fa3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 00:07:52 +1000 Subject: [PATCH 343/811] Small tweak to release 4.4 doc --- etc/release-notes/release-notes-4.4.adoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc index 7451127b..1563347a 100644 --- a/etc/release-notes/release-notes-4.4.adoc +++ b/etc/release-notes/release-notes-4.4.adoc @@ -12,7 +12,7 @@ Proposed Release Date: July 2015 * Added monoid composition. * Changed comap methods to contramap (#142, #170) * Provide hard, soft and weak memoisation implementations, default to weak (#153, #151). -* Added optics (See the Scala Monocle library https://github.com/julien-truffaut/Monocle and the Haskell lens lbrary https://github.com/ekmett/lens for an overview) (#154). +* Added optics (see the Scala Monocle library https://github.com/julien-truffaut/Monocle and the Haskell lens lbrary https://github.com/ekmett/lens for an overview) (#154). * Added Validation.sequence (#163, #167). * Add PropertyTestRunner (#144). * Added Equal.notEq, List.isPrefixOf, List.isSuffixOf (#146). @@ -74,6 +74,8 @@ Proposed Release Date: July 2015 == Documentation +None. + == Contributors * Mark Perry From f70f286f290d1c618f3f33c139145736e84484e2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 00:17:58 +1000 Subject: [PATCH 344/811] #162: Renamed sequenceReduce to sequenceNonCumulative --- core/src/main/java/fj/data/Validation.java | 9 +++++---- .../java/fj/data/properties/ValidationProperties.java | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 5bfb5f43..138b5233 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -814,11 +814,12 @@ public Validation, D> accumulate(Validation v2, Validati } /** - * If the list contains a failure, returns a Validation of the fails in the - * list, otherwise returns a successful Validation with the list of - * successful values. + * If the list contains a failure, returns a Validation of the list of + * fails in the list, otherwise returns a successful Validation with + * the list of successful values. Does not accumulate the failures into a + * single failure using a semigroup. */ - public static Validation, List> sequenceReduce(List> list) { + public static Validation, List> sequenceNonCumulative(List> list) { if (list.exists(v -> v.isFail())) { F2, Validation, List> f = (acc, v) -> acc.cons(v.fail()); return Validation.fail(list.filter(v -> v.isFail()).foldLeft(f, List.nil()).reverse()); diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java index e9c1510a..d9580cc4 100644 --- a/props-core/src/test/java/fj/data/properties/ValidationProperties.java +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -30,10 +30,10 @@ public Property partition() { }); } - public Property sequenceReduce() { + public Property sequenceNonCumulative() { Arbitrary>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); return Property.property(al, list -> { - Validation, List> v = Validation.sequenceReduce(list); + Validation, List> v = Validation.sequenceNonCumulative(list); Property p1 = implies( list.exists(v1 -> v1.isFail()), () -> prop(v.fail().equals(list.filter(v2 -> v2.isFail()).map(v2 -> v2.fail()))) From 001cd1f0d2fbcacb5cd583c1173bf3afb74b5952 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 00:33:24 +1000 Subject: [PATCH 345/811] Changed release doc 4.4 after rename to Validation.sequenceNonCumulative --- etc/release-notes/release-notes-4.4.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc index 1563347a..8e46284d 100644 --- a/etc/release-notes/release-notes-4.4.adoc +++ b/etc/release-notes/release-notes-4.4.adoc @@ -47,7 +47,7 @@ Proposed Release Date: July 2015 * Fixed Stream.toString to human readable representation (#138). * Fixed P1.memo cache in threaded environment (#141, #108). * Fixed Stream join and bind for infinite streams (#140). -* Fixed Validation.sequence and renamed to sequenceReduce (#162). +* Fixed Validation.sequence and renamed to sequenceNonCumulative (#162). * Scalacheck property Stream.bindStackOverflow sometimes fails (#168, #169). * Fixed bug in FingerTree.append (#144). * Fixed arrayShow (#145). @@ -69,7 +69,7 @@ Proposed Release Date: July 2015 * Comap methods renamed to contramap. * Split quickcheck into separate module. -* Validation.sequence renamed to sequenceReduce. +* Validation.sequence renamed to sequenceNonCumulative. * Changed IOFunctions io to be fromF and fromTry. == Documentation From cd4c432662d6018f7ae60836a957c2e8df4df455 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 00:37:59 +1000 Subject: [PATCH 346/811] Fixed sub list tabbing in release notes --- etc/release-notes/release-notes-4.4.adoc | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc index 8e46284d..3f8a16e4 100644 --- a/etc/release-notes/release-notes-4.4.adoc +++ b/etc/release-notes/release-notes-4.4.adoc @@ -17,17 +17,16 @@ Proposed Release Date: July 2015 * Add PropertyTestRunner (#144). * Added Equal.notEq, List.isPrefixOf, List.isSuffixOf (#146). * Made enhancements to support Real World Haskell example (#155) - * made P1.toString lazy - * added IOFunctions.interact - * added IOFunctions.getContents - * added map, bind and eval to LazyString - * added IO wrapper with static methods from IOFunctions as instance methods - * Stream.take evaluates one those items necessary (one less than currently) - * Made Stream.toString lazy - * Added Strings methods lines and unlines - * Refactor 'from' - * Made IOFunctions.sequenceWhile lazy - * Changed IOFunctions io to be fromF and fromTry. + ** made P1.toString lazy + ** added IOFunctions.interact + ** added IOFunctions.getContents + ** added map, bind and eval to LazyString + ** added IO wrapper with static methods from IOFunctions as instance methods + ** Stream.take evaluates one those items necessary (one less than currently) + ** Made Stream.toString lazy + ** Added Strings methods lines and unlines + ** Made IOFunctions.sequenceWhile lazy + ** Changed IOFunctions io to be fromF and fromTry. * Enhanced Property to run individual tests (#156). * Added Seq.isNotEmpty (#158). * Added List.partition (#161). From 5805680a8341c3d7c3515b0ebd832e98845655a7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 21:17:28 +1000 Subject: [PATCH 347/811] Configure modules for uploading --- props-core-scalacheck/build.gradle | 2 -- quickcheck/build.gradle | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index d946a5e6..4d1a04e9 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -27,6 +27,4 @@ sourceCompatibility = "1.7" performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) -uploadArchives.enabled = true - diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 07da8478..d4543f38 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -1,4 +1,8 @@ +ext { + signModule = true +} + if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' @@ -15,3 +19,8 @@ dependencies { compile project(":core") compile dependencyJunit } + +performSigning(signingEnabled, signModule) +configureUpload(signingEnabled, signModule) + +uploadArchives.enabled = true From bdf53a5905ca6db31a8e594a9520e68635b3f76d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 21:20:44 +1000 Subject: [PATCH 348/811] Increased version to 4.4 --- build.gradle | 2 +- gradle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index f1cd6887..a508b4e2 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.4" snapshotAppendix = "-SNAPSHOT" diff --git a/gradle.properties b/gradle.properties index d4552a30..07c2b60c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false +signingEnabled = true From 9a9292c2a84d6963e0b15cd2b929a100e8705696 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 21:27:12 +1000 Subject: [PATCH 349/811] Increased version to 4.5-SNAPSHOT --- build.gradle | 6 +++--- gradle.properties | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a508b4e2..3852b57a 100644 --- a/build.gradle +++ b/build.gradle @@ -35,12 +35,12 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.4" + isSnapshot = true + fjBaseVersion = "4.5" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.3" + fjConsumeVersion = "4.4" signModule = false useRetroLambda = true diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From afbfb313aca84892fe993f4e0a1e4a4125f4c5e6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 21:49:13 +1000 Subject: [PATCH 350/811] Added release process --- etc/release-notes/release-notes-4.4.adoc | 2 +- etc/release-notes/release-notes-4.5.adoc | 28 +++++++++++++ etc/release-notes/release-notes-template.adoc | 28 +++++++++++++ etc/release-process.txt | 40 +++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 etc/release-notes/release-notes-4.5.adoc create mode 100644 etc/release-notes/release-notes-template.adoc create mode 100644 etc/release-process.txt diff --git a/etc/release-notes/release-notes-4.4.adoc b/etc/release-notes/release-notes-4.4.adoc index 3f8a16e4..54184076 100644 --- a/etc/release-notes/release-notes-4.4.adoc +++ b/etc/release-notes/release-notes-4.4.adoc @@ -1,7 +1,7 @@ = Release 4.4 -Proposed Release Date: July 2015 +Released: 6 July 2015 == Enhancements diff --git a/etc/release-notes/release-notes-4.5.adoc b/etc/release-notes/release-notes-4.5.adoc new file mode 100644 index 00000000..32118535 --- /dev/null +++ b/etc/release-notes/release-notes-4.5.adoc @@ -0,0 +1,28 @@ + += Release 4.5 + +Proposed release: last quarter 2015 + +== Enhancements + +* TODO. + +== Fixes + +* TODO. + +== Internal + +* TODO. + +== Breaking Changes + +* TODO. + +== Documentation + +* TODO. + +== Contributors + +* TODO. diff --git a/etc/release-notes/release-notes-template.adoc b/etc/release-notes/release-notes-template.adoc new file mode 100644 index 00000000..22dbc552 --- /dev/null +++ b/etc/release-notes/release-notes-template.adoc @@ -0,0 +1,28 @@ + += Release + +Proposed release: + +== Enhancements + +* TODO. + +== Fixes + +* TODO. + +== Internal + +* TODO. + +== Breaking Changes + +* TODO. + +== Documentation + +* TODO. + +== Contributors + +* TODO. diff --git a/etc/release-process.txt b/etc/release-process.txt new file mode 100644 index 00000000..62f7e383 --- /dev/null +++ b/etc/release-process.txt @@ -0,0 +1,40 @@ + +Current Release Process +======================= + +Update build.gradle: +* set isSnapshot to false + +Update gradle.properties: +* Set signingEnabled to true + +Run the build command: +gradlew clean build upload + +Login to Sonatype and verify the release: +* Login to https://oss.sonatype.org +* Choose Staging Repositories and find the Functional Java release +* Tick the release and click Close +* Wait until closed +* Tick the release and click Release + +Commit changes + +Increase the version: +* Edit build.gradle: update isSnapshot to true, increase fjBaseVersion, update fjConsumeVersion +* Edit gradle.properties: set signingEnabled to false + +Commit changes and push. + +Create tag: +* Create tag using gitk with the format v. +* Push the tag with: git push --tags + +Create the next version of the release notes with empty fields using the template. + +Upload the javadoc, TODO. + +Update the website, TODO. + +Send a message to the group and social media about the release, TODO. + From 0b82ce88b635340a985569d5604b35cab8991519 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 6 Jul 2015 22:07:00 +1000 Subject: [PATCH 351/811] Updated readme for 4.4, updated release process --- README.adoc | 28 ++++++++++++++++++---------- etc/release-process.txt | 4 ++-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/README.adoc b/README.adoc index c08e7304..242043e4 100644 --- a/README.adoc +++ b/README.adoc @@ -6,13 +6,13 @@ image::http://www.functionaljava.org/img/logo-600x144.png[] Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. -The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8. +The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8. Functional Java provides abstractions for the following types: * Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). * Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list. -* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing, actors, lenses, concurrency and type conversion. +* Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing (quickcheck), actors, optics (lens, prism, fold, traversal and others), concurrency and type conversion. == URLs @@ -21,20 +21,23 @@ Important URLs for the project are: * Website, http://www.functionaljava.org * Website repository, http://github.com/functionaljava/functionaljava.github.io * Travis continuous integration build, https://travis-ci.org/functionaljava/functionaljava +* Jenkins Cloudbees CI build, https://functionaljava.ci.cloudbees.com == Downloading The recommended way to download and use the project is through your build tool. -The Functional Java artifact is published to Maven Central using the group `org.functionaljava` with two published artifacts: +The Functional Java artifact is published to Maven Central using the group `org.functionaljava` with three published artifacts: * the core library (`functionaljava`) * Java 8 specific support (`functionaljava-java8`) +* property based testing (`functionaljava-quickcheck`) -The latest version is `4.4-SNAPSHOT`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.4`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.4-SNAPSHOT" -compile "org.functionaljava:functionaljava-java8:4.4-SNAPSHOT" +compile "org.functionaljava:functionaljava:4.4" +compile "org.functionaljava:functionaljava-java8:4.4" +compile "org.functionaljava:functionaljava-quickcheck:4.4" ---- and in Maven: @@ -42,12 +45,17 @@ and in Maven: org.functionaljava functionaljava - 4.4-SNAPSHOT + 4.4 org.functionaljava functionaljava-java8 - 4.4-SNAPSHOT + 4.4 + + + org.functionaljava + functionaljava-quickcheck + 4.4 ---- @@ -59,7 +67,7 @@ Building is done using Gradle 2.4. In the root directory run: ---- ./gradlew ---- -This will download the Gradle build tool and necessary dependencies and build FunctionalJava. +This requires access to Java and will download the Gradle build tool and necessary dependencies and build FunctionalJava. == Features @@ -98,7 +106,7 @@ A more complete description of the features mentioned above are: ** Zipper implementations for streams and trees. ** Automated specification-based testing framework (`fj.test`). ** Fully operational Actors for parallel computations (`fj.control.parallel`) and layered abstractions such as parallel-map, map-reduce, parallel-zip. -** Lenses, for updating immutable data. +** Optics for updating immutable data including lens, prism, iso, optional, traversal, getter, fold and setter. Inspired by the Scala Monocle library (https://github.com/julien-truffaut/Monocle) and the Haskell lens library (https://github.com/ekmett/lens). == License diff --git a/etc/release-process.txt b/etc/release-process.txt index 62f7e383..da0ffb0e 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -24,7 +24,7 @@ Increase the version: * Edit build.gradle: update isSnapshot to true, increase fjBaseVersion, update fjConsumeVersion * Edit gradle.properties: set signingEnabled to false -Commit changes and push. +Commit changes and push. Notes that CI builds using Travis and Jenkins will fail with the release due to lack of configured signing. Create tag: * Create tag using gitk with the format v. @@ -34,7 +34,7 @@ Create the next version of the release notes with empty fields using the templat Upload the javadoc, TODO. -Update the website, TODO. +Update the website and Github README.adoc, TODO. Send a message to the group and social media about the release, TODO. From 27963aedbc33b67f478473a3bff8799c78bcde52 Mon Sep 17 00:00:00 2001 From: orionll Date: Wed, 8 Jul 2015 12:19:50 +0600 Subject: [PATCH 352/811] Added @SafeVarargs to suppress unchecked warnings. Added Seq.toList() and Seq.delete() --- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/NonEmptyList.java | 2 +- core/src/main/java/fj/data/Seq.java | 34 ++++++++++++++++++- core/src/main/java/fj/data/Set.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/TreeMap.java | 2 +- .../fj/data/properties/SeqProperties.java | 9 +++++ 7 files changed, 47 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 89bcd4e5..fe62fdcb 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1501,7 +1501,7 @@ private void tail(final List tail) { * @param as The elements to construct a list with. * @return A list with the given elements. */ - public static List list(final A... as) { + @SafeVarargs public static List list(final A... as) { return Array.array(as).toList(); } diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index b9dbb903..f7953ab6 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -293,7 +293,7 @@ public static NonEmptyList nel(final A head, final List tail) { * @param tail The elements to construct a list's tail with. * @return A non-empty list with the given elements. */ - public static NonEmptyList nel(final A head, final A... tail) { + @SafeVarargs public static NonEmptyList nel(final A head, final A... tail) { return nel(head, List.list(tail)); } diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index b701ae3f..a1026e34 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -6,6 +6,7 @@ import static fj.Monoid.intAdditionMonoid; import static fj.data.fingertrees.FingerTree.measured; +import fj.data.List.Buffer; import fj.data.fingertrees.FingerTree; import fj.data.fingertrees.MakeTree; import fj.data.fingertrees.Measured; @@ -64,7 +65,7 @@ public static Seq single(final A a) { return new Seq(Seq.mkTree().single(a)); } - public static Seq seq(final A... as) { + @SafeVarargs public static Seq seq(final A... as) { return seq(List.list(as)); } @@ -124,10 +125,22 @@ public Seq init() { return (length() == 1) ? empty() : new Seq<>(ftree.init()); } + /** + * Converts this sequence to a Stream + */ public Stream toStream() { return ftree.foldLeft((b, a) -> b.cons(a), Stream.nil()).reverse(); } + /** + * Converts this sequence to a List + */ + public List toList() { + final Buffer buf = Buffer.empty(); + for (final A a : this) { buf.snoc(a); } + return buf.toList(); + } + public final java.util.List toJavaList() { return new AbstractList() { @Override public A get(int i) { return index(i); } @@ -207,6 +220,12 @@ public int length() { return ftree.measure(); } + /** + * Splits this sequence into a pair of sequences at the given position. This is a O(log(n)) operation. + * + * @return Pair: the subsequence containing elements with indices less than i + * and the subsequence containing elements with indices greater than or equal to i. + */ public P2, Seq> split(final int i) { final P2, FingerTree> lr = ftree.split(index -> index > i); return P.p(new Seq<>(lr._1()), new Seq<>(lr._2())); @@ -237,6 +256,19 @@ public Seq update(final int i, final A a) { return new Seq<>(lxr._1().append(lxr._3().cons(a))); } + /** + * Delete the element at the given index. This is an O(log(n)) operation. + * + * @param i The index of the element to update. + * + * @return The updated sequence, or throws an error if the index is out of bounds. + */ + public Seq delete(final int i) { + checkBounds(i); + final P3, A, FingerTree> lxr = ftree.split1(index -> index > i); + return new Seq<>(lxr._1().append(lxr._3())); + } + /** * Takes the given number of elements from the head of this sequence if they are available. * diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index ad437a11..8892ca63 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -475,7 +475,7 @@ public static Set iterableSet(final Ord o, final Iterable as) { * @param as The elements to add to a set. * @return A new set containing the elements of the given iterable. */ - public static Set set(final Ord o, final A ... as) { + @SafeVarargs public static Set set(final Ord o, final A ... as) { Set s = empty(o); for (final A a : as) s = s.insert(a); diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 4d2408d8..4fc6d4da 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -733,7 +733,7 @@ public Stream _1() { * @param as The elements which which to construct a stream. * @return a new stream with the given elements. */ - public static Stream stream(final A... as) { + @SafeVarargs public static Stream stream(final A... as) { return as.length == 0 ? Stream.nil() : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.>>none() : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0)); diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 33d2438d..01c5bc6f 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -58,7 +58,7 @@ public String toString() { * @param p2s The elements to construct the tree map with. * @return a TreeMap with the given elements. */ - public static TreeMap treeMap(final Ord keyOrd, final P2... p2s) { + @SafeVarargs public static TreeMap treeMap(final Ord keyOrd, final P2... p2s) { return treeMap(keyOrd, List.list(p2s)); } diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 6bc5b97b..4e4a8144 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -103,6 +103,15 @@ public Property updateAndIndex() { }); } + @CheckParams(minSize = 1) + public Property delete() { + return property(arbSeqWithIndex, arbInteger, (pair, n) -> { + final Seq seq = pair._1(); + final int index = pair._2(); + return prop(seq.delete(index).length() == seq.length() - 1); + }); + } + public Property foldLeft() { return property(arbSeq(arbitrary(Gen.value(1))), seq -> prop(seq.foldLeft((acc, i) -> acc + i, 0) == seq.length())); From de8aa1d0cb9ae48ae7d851cda6c0134cfc603e19 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 9 Jul 2015 23:15:05 +1000 Subject: [PATCH 353/811] Added instructions to release process --- etc/release-process.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/release-process.txt b/etc/release-process.txt index da0ffb0e..5845037e 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -32,9 +32,9 @@ Create tag: Create the next version of the release notes with empty fields using the template. -Upload the javadoc, TODO. +Update the website and Github README.adoc. This includes adding any features to the home page and features page. Updating the doc page with javadoc links. Update the download page with a link to the latest release notes. -Update the website and Github README.adoc, TODO. +Copy the generated javadoc for each component to the website repositories' master branch under /javadoc/. Commit the javadoc and push. Send a message to the group and social media about the release, TODO. From 02d036590f74612cfce4b188cb8f5c71e5366141 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 23 Jul 2015 20:51:06 +0200 Subject: [PATCH 354/811] some minor improvements - avoid unecessary function creation - render inner class static --- core/src/main/java/fj/Function.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/Validation.java | 12 ++++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 843c5a55..9882a03d 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -734,7 +734,7 @@ public static F bind(final F ma, final F> f) { * @return A new function after applying the given higher-order function to the given function. */ public static F apply(final F> cab, final F ca) { - return bind(cab, f -> compose(a -> f.f(a), ca)); + return bind(cab, f -> compose(f, ca)); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 4fc6d4da..fb1d3df5 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -564,7 +564,7 @@ public static Stream> sequence(final Option> o) { * @return A new stream after applying the given stream of functions through this stream. */ public final Stream apply(final Stream> sf) { - return sf.bind(f -> map(a -> f.f(a))); + return sf.bind(f -> map(f)); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 138b5233..034aa927 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -85,7 +85,7 @@ public X validation(final F fail, final F success) { * @return a failing projection of this validation. */ public FailProjection f() { - return new FailProjection(this); + return new FailProjection<>(this); } /** @@ -231,11 +231,7 @@ public Option> filter(final F f) { * @return The result of function application in validation. */ public Validation apply(final Validation> v) { - return v.bind(new F, Validation>() { - public Validation f(final F f) { - return map(f); - } - }); + return v.bind(this::map); } /** @@ -871,7 +867,7 @@ public static List successes(List> list) { /** * A failing projection of a validation. */ - public final class FailProjection implements Iterable { + public static final class FailProjection implements Iterable { private final Validation v; private FailProjection(final Validation v) { @@ -1098,7 +1094,7 @@ public Validation, T> nel() { * @return A validation using the given either value. */ public static Validation validation(final Either e) { - return new Validation(e); + return new Validation<>(e); } /** From a648f750362f665cd188f14d80c2b36d80726fa0 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 23 Jul 2015 21:34:31 +0200 Subject: [PATCH 355/811] Fixed constructors of fixed length monomorphic traversal set paramter function had incorrect type --- .../main/java/fj/data/optic/Traversal.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java index 03503cf4..756a95ed 100644 --- a/core/src/main/java/fj/data/optic/Traversal.java +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -1,11 +1,11 @@ package fj.data.optic; import fj.F; -import fj.F2; import fj.F3; import fj.F4; import fj.F5; import fj.F6; +import fj.F7; import fj.Monoid; import fj.P1; import fj.control.Trampoline; @@ -123,33 +123,29 @@ public static Traversal, S> codiagonal() { return new Traversal<>(PTraversal.pCodiagonal()); } - public static Traversal traversal(final F get1, final F get2, final F2 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, (a1, a2, s) -> set.f(a1, a2))); + public static Traversal traversal(final F get1, final F get2, final F3 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F3 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, (a1, a2, a3, s) -> set.f(a1, a2, a3))); + final F4 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F get4, - final F4 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, (a1, a2, a3, a4, s) -> set.f(a1, a2, a3, a4))); + final F get4, final F5 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F get4, final F get5, - final F5 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, - (a1, a2, a3, a4, a5, s) -> set.f(a1, a2, a3, a4, a5))); + final F get4, final F get5, final F6 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F get4, final F get5, final F get6, - final F6 set) { + final F get4, final F get5, final F get6, final F7 set) { return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, get6, - (a1, a2, a3, a4, a5, a6, s) -> set.f(a1, a2, a3, a4, a5, a6))); + set)); } } From 159c4bc4e0ce23f4c44ed628ddd4df5ba8903d41 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 12 Aug 2015 23:29:27 +1000 Subject: [PATCH 356/811] Made small improvements to P1 --- core/src/main/java/fj/P1.java | 39 ++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 5c7d1d90..d3183208 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -39,14 +39,25 @@ public static F, A> __1() { /** * Promote any function to a transformation between P1s. * + * @deprecated As of release 4.5, use {@link #map_} * @param f A function to promote to a transformation between P1s. * @return A function promoted to operate on P1s. */ public static F, P1> fmap(final F f) { - return a -> a.map(f); + return map_(f); } - /** + /** + * Promote any function to a transformation between P1s. + * + * @param f A function to promote to a transformation between P1s. + * @return A function promoted to operate on P1s. + */ + public static F, P1> map_(final F f) { + return a -> a.map(f); + } + + /** * Binds the given function to the value in a product-1 with a final join. * * @param f A function to apply to the value in a product-1. @@ -89,6 +100,13 @@ public P1 bind(final P1 cb, final F> f) { return cb.apply(fmap(f).f(this)); } + /** + * Binds the given function to the values in the given P1s with a final join. + */ + public P1 bind(final P1 cb, final F2 f) { + return bind(cb, F2W.lift(f).curry()); + } + /** * Joins a P1 of a P1 with a bind operation. * @@ -109,6 +127,10 @@ public static F, F, P1>> liftM2(final F> f) return Function.curry((pa, pb) -> pa.bind(pb, f)); } + public P1 liftM2(P1 pb, F2 f) { + return P.lazy(() -> f.f(_1(), pb._1())); + } + /** * Turns a List of P1s into a single P1 of a List. * @@ -138,6 +160,13 @@ public static P1> sequence(final Stream> as) { return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); } + /** + * Turns an optional P1 into a lazy option. + */ + public static P1> sequence(final Option> o) { + return P.lazy(() -> o.map(p -> p._1())); + } + /** * Turns an array of P1s into a single P1 of an array. * @@ -204,7 +233,7 @@ public Stream> traverseStream(final F> f){ * @param f The function to map with. * @return A product with the given function applied. */ - public P1 map(final F f) { + public P1 map(final F f) { final P1 self = this; return P.lazy(() -> f.f(self._1())); } @@ -234,6 +263,10 @@ static P1 memo(F f) { return P.lazy(f).memo(); } + static P1 memo(F0 f) { + return P.lazy(f).memo(); + } + static class Memo extends P1 { private final P1 self; private volatile boolean initialized; From 519490277e3c7b0307ecdb77d535a36e9af2300b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 12 Aug 2015 23:35:26 +1000 Subject: [PATCH 357/811] Added headOption and tailOption to Option --- core/src/main/java/fj/data/Option.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 471933e6..a56850d8 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -846,6 +846,16 @@ public static F, F, Option>> liftM2(final F a.bind(b, f)); } + /** + * Lift the function of arity-2 through options. + * + * @param f A function to lift. + * @return An optional result. + */ + public Option liftM2(final Option ob, final F2 f) { + return bind(a -> ob.map(b -> f.f(a, b))); + } + /** * First-class bind function. * From 259c5937e15a5d6759a3cc18c462bd9d835110c1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 12 Aug 2015 23:36:25 +1000 Subject: [PATCH 358/811] Added headOption and tailOption to List --- core/src/main/java/fj/data/List.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fe62fdcb..69156bd5 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -142,7 +142,7 @@ public final List orTail(final F0> as) { /** * Returns an option projection of this list; None if empty, or the first element in - * Some. + * Some. Equivalent to {@link #headOption()}. * * @return An option projection of this list. */ @@ -1127,6 +1127,23 @@ public static F, A> head_() { return list -> list.head(); } + /** + * Returns the head of the list, if any. Equivalent to {@link #toOption()} . + * + * @return The optional head of the list. + */ + public Option headOption() { + return toOption(); + } + + /** + * Reutrns the tail of the list, if any. + * @return The optional tail of the list. + */ + public Option> tailOption() { + return isEmpty() ? none() : some(tail()); + } + /** * First-class tail function. * From 8e6ec8558f50251b96e333750bfa834465c6e5a5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 00:22:42 +1000 Subject: [PATCH 359/811] Replace P1 with F0 in some Stream method parameters --- core/src/main/java/fj/data/Stream.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 4fc6d4da..92fc8d99 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -218,8 +218,8 @@ public final A orHead(final F0 a) { * @param as The argument to return if this stream is empty. * @return The tail of this stream if there is one or the given argument if this stream is empty. */ - public final P1> orTail(final P1> as) { - return isEmpty() ? as : tail(); + public final P1> orTail(final F0> as) { + return isEmpty() ? P.lazy(as) : tail(); } /** @@ -543,8 +543,8 @@ public static Stream> sequence(final IO> io) { * @param p The lazy stream to sequence. * @return The stream of (pre-calculated) lazy values after sequencing. */ - public static Stream> sequence(final P1> p) { - return p._1().map(a -> P.p(a)); + public static Stream> sequence(final F0> p) { + return p.f().map(a -> P.p(a)); } /** @@ -1596,8 +1596,8 @@ public static F> single() { * @param tail The stream to prepend to. * @return The stream with the given element prepended. */ - public static Stream cons(final A head, final P1> tail) { - return new Cons(head, tail); + public static Stream cons(final A head, final F0> tail) { + return new Cons(head, P.lazy(tail)); } /** From 2bf99a472d04ddb6915cbc0f81dc6e56a6018695 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 00:23:21 +1000 Subject: [PATCH 360/811] Added compiler warning options --- build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build.gradle b/build.gradle index 3852b57a..4de149ca 100644 --- a/build.gradle +++ b/build.gradle @@ -85,6 +85,12 @@ subprojects { url sonatypeRepositoryUrl } } + + if (false) { + tasks.withType(JavaCompile) { + options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" + } + } } configure(subprojects.findAll { it.name != "props-core" }) { From ce3c16d0b3020618162d8c63bfa5f0c096c12829 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 23 Jul 2015 20:51:06 +0200 Subject: [PATCH 361/811] some minor improvements - avoid unecessary function creation - render inner class static --- core/src/main/java/fj/Function.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/Validation.java | 12 ++++-------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 843c5a55..9882a03d 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -734,7 +734,7 @@ public static F bind(final F ma, final F> f) { * @return A new function after applying the given higher-order function to the given function. */ public static F apply(final F> cab, final F ca) { - return bind(cab, f -> compose(a -> f.f(a), ca)); + return bind(cab, f -> compose(f, ca)); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 92fc8d99..c7613e01 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -564,7 +564,7 @@ public static Stream> sequence(final Option> o) { * @return A new stream after applying the given stream of functions through this stream. */ public final Stream apply(final Stream> sf) { - return sf.bind(f -> map(a -> f.f(a))); + return sf.bind(f -> map(f)); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 138b5233..034aa927 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -85,7 +85,7 @@ public X validation(final F fail, final F success) { * @return a failing projection of this validation. */ public FailProjection f() { - return new FailProjection(this); + return new FailProjection<>(this); } /** @@ -231,11 +231,7 @@ public Option> filter(final F f) { * @return The result of function application in validation. */ public Validation apply(final Validation> v) { - return v.bind(new F, Validation>() { - public Validation f(final F f) { - return map(f); - } - }); + return v.bind(this::map); } /** @@ -871,7 +867,7 @@ public static List successes(List> list) { /** * A failing projection of a validation. */ - public final class FailProjection implements Iterable { + public static final class FailProjection implements Iterable { private final Validation v; private FailProjection(final Validation v) { @@ -1098,7 +1094,7 @@ public Validation, T> nel() { * @return A validation using the given either value. */ public static Validation validation(final Either e) { - return new Validation(e); + return new Validation<>(e); } /** From 974847d84ef88157b3b3c48f1913b579424b616a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 23 Jul 2015 21:34:31 +0200 Subject: [PATCH 362/811] Fixed constructors of fixed length monomorphic traversal set paramter function had incorrect type --- .../main/java/fj/data/optic/Traversal.java | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java index 03503cf4..756a95ed 100644 --- a/core/src/main/java/fj/data/optic/Traversal.java +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -1,11 +1,11 @@ package fj.data.optic; import fj.F; -import fj.F2; import fj.F3; import fj.F4; import fj.F5; import fj.F6; +import fj.F7; import fj.Monoid; import fj.P1; import fj.control.Trampoline; @@ -123,33 +123,29 @@ public static Traversal, S> codiagonal() { return new Traversal<>(PTraversal.pCodiagonal()); } - public static Traversal traversal(final F get1, final F get2, final F2 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, (a1, a2, s) -> set.f(a1, a2))); + public static Traversal traversal(final F get1, final F get2, final F3 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F3 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, (a1, a2, a3, s) -> set.f(a1, a2, a3))); + final F4 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F get4, - final F4 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, (a1, a2, a3, a4, s) -> set.f(a1, a2, a3, a4))); + final F get4, final F5 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F get4, final F get5, - final F5 set) { - return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, - (a1, a2, a3, a4, a5, s) -> set.f(a1, a2, a3, a4, a5))); + final F get4, final F get5, final F6 set) { + return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, set)); } public static Traversal traversal(final F get1, final F get2, final F get3, - final F get4, final F get5, final F get6, - final F6 set) { + final F get4, final F get5, final F get6, final F7 set) { return new Traversal<>(PTraversal.pTraversal(get1, get2, get3, get4, get5, get6, - (a1, a2, a3, a4, a5, a6, s) -> set.f(a1, a2, a3, a4, a5, a6))); + set)); } } From ddc8fe4a9ffe5d6931a104699ece6f4ab1cd0452 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 08:56:35 +1000 Subject: [PATCH 363/811] Turn compiler warnings on. Suppress unchecked warnings on methods doing cast --- build.gradle | 3 ++- core/src/main/java/fj/Try.java | 9 +++++++++ core/src/main/java/fj/TryEffect.java | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4de149ca..89d382d9 100644 --- a/build.gradle +++ b/build.gradle @@ -63,6 +63,7 @@ allprojects { dependencyJunit = "junit:junit:4.12" + displayCompilerWarnings = true } version = fjVersion @@ -86,7 +87,7 @@ subprojects { } } - if (false) { + if (displayCompilerWarnings) { tasks.withType(JavaCompile) { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" } diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index 69e9c19d..5ed2673f 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -21,6 +21,7 @@ public class Try { * @param t A Try0 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ + @SuppressWarnings("unchecked") static public P1> f(final Try0 t) { return P.lazy(() -> { try { @@ -37,6 +38,7 @@ static public P1> f(final Try0 t * @param t A Try1 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ + @SuppressWarnings("unchecked") static public F> f(final Try1 t) { return a -> { try { @@ -53,6 +55,7 @@ static public F> f(final Try1 F2> f(final Try2 t) { return (a, b) -> { try { @@ -69,6 +72,7 @@ static public F2> f(final * @param t A Try3 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ + @SuppressWarnings("unchecked") static public F3> f(final Try3 t) { return (a, b, c) -> { try { @@ -85,6 +89,7 @@ static public F3> f( * @param t A Try4 to promote * @return A Validation with an Exception on the failure side and its result on the success side. */ + @SuppressWarnings("unchecked") static public F4> f(final Try4 t) { return (a, b, c, d) -> { try { @@ -101,6 +106,7 @@ static public F4 F5> f(final Try5 t) { return (a, b, c, d, e) -> { try { @@ -117,6 +123,7 @@ static public F5 F6> f(final Try6 t) { return (a, b, c, d, e, f) -> { try { @@ -133,6 +140,7 @@ static public F6 F7> f(final Try7 t) { return (a, b, c, d, e, f, g) -> { try { @@ -149,6 +157,7 @@ static public F7 F8> f(final Try8 t) { return (a, b, c, d, e, f, g, h) -> { try { diff --git a/core/src/main/java/fj/TryEffect.java b/core/src/main/java/fj/TryEffect.java index 22889338..02d4521f 100644 --- a/core/src/main/java/fj/TryEffect.java +++ b/core/src/main/java/fj/TryEffect.java @@ -14,6 +14,7 @@ public class TryEffect { private TryEffect(){} + @SuppressWarnings("unchecked") public static P1> f(TryEffect0 t) { return P.lazy(() -> { try { @@ -25,6 +26,7 @@ public static P1> f(TryEffect0 t }); } + @SuppressWarnings("unchecked") public static F> f(TryEffect1 t) { return a -> { try { @@ -37,6 +39,7 @@ public static F> f(TryEffect1 F2> f(TryEffect2 t) { return (a, b) -> { try { @@ -49,6 +52,7 @@ public static F2> f(TryEff } + @SuppressWarnings("unchecked") public static F3> f(TryEffect3 t) { return (a, b, c) -> { try { @@ -60,6 +64,7 @@ public static F3> f( }; } + @SuppressWarnings("unchecked") public static F4> f(TryEffect4 t) { return (a, b, c, d) -> { try { @@ -71,6 +76,7 @@ public static F4 F5> f(TryEffect5 t) { return (a, b, c, d, e) -> { try { @@ -82,6 +88,7 @@ public static F5 F6> f(TryEffect6 t) { return (a, b, c, d, e, f) -> { try { @@ -93,6 +100,7 @@ public static F5 F7> f(TryEffect7 t) { return (a, b, c, d, e, f, g) -> { try { @@ -104,6 +112,7 @@ public static F5 F8> f(TryEffect8 t) { return (a, b, c, d, e, f, g, h) -> { try { From 9853c6a26309cf9f4936d431a6bc65b4c37550b1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 09:10:04 +1000 Subject: [PATCH 364/811] Added unchecked and safe var args warning suppression --- core/src/main/java/fj/data/Array.java | 1 + quickcheck/src/main/java/fj/test/Arbitrary.java | 1 + quickcheck/src/main/java/fj/test/Gen.java | 1 + quickcheck/src/main/java/fj/test/Variant.java | 1 + 4 files changed, 4 insertions(+) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 8b4ade34..6d492212 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -571,6 +571,7 @@ public static Array empty() { * @param a The elements to construct the array with. * @return A new array of the given elements. */ + @SafeVarargs public static Array array(final A... a) { return new Array(a); } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 26bfe8c3..2be4040a 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -778,6 +778,7 @@ public Array f(final List as) { * @param aa An arbitrary implementation for the type over which the sequence is defined. * @return An arbitrary implementation for sequences. */ + @SuppressWarnings("unchecked") public static Arbitrary> arbSeq(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.map(array -> Seq.seq((A[]) array.array()))); } diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index b56e080c..556e10ca 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -514,6 +514,7 @@ public Gen f(final A a) { * @param as The values that the returned generator may produce. * @return A generator that produces values from the given arguments. */ + @SafeVarargs public static Gen elements(final A... as) { return array(as).isEmpty() ? Gen.fail() : choose(0, as.length - 1).map(new F() { public A f(final Integer i) { diff --git a/quickcheck/src/main/java/fj/test/Variant.java b/quickcheck/src/main/java/fj/test/Variant.java index 2612c14a..f50bf923 100644 --- a/quickcheck/src/main/java/fj/test/Variant.java +++ b/quickcheck/src/main/java/fj/test/Variant.java @@ -49,6 +49,7 @@ private Variant() { * @param g The generator to produce the new generator from. * @return A generator that is independent of the given generator using the given value. */ + @SuppressWarnings("unchecked") public static Gen variant(final long n, final Gen g) { final LongGen p = new LongGen(n, g); final Gen gx = variantMemo.get(p); From c4bd5548e238da7aeabe33fbfc97a71a8a860a42 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 09:13:46 +1000 Subject: [PATCH 365/811] Changed calls from P1.fmap to P1.map_ --- core/src/main/java/fj/control/parallel/Strategy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index f93b4d89..28bd6d32 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -219,7 +219,7 @@ public F, F, Array>> parMapArray1() { public static P1> parFlatMap(final Strategy> s, final F> f, final List as) { - return P1.fmap(List.join()).f(s.parMap(f, as)); + return P1.map_(List.join()).f(s.parMap(f, as)); } /** @@ -233,7 +233,7 @@ public static P1> parFlatMap(final Strategy> s, public static P1> parFlatMap(final Strategy> s, final F> f, final Array as) { - return P1.fmap(Array.join()).f(s.parMap(f, as)); + return P1.map_(Array.join()).f(s.parMap(f, as)); } /** @@ -248,7 +248,7 @@ public static P1> parFlatMap(final Strategy> s, public static P1> parListChunk(final Strategy> s, final int chunkLength, final List> as) { - return P1.fmap(List.join()).f(s.parList(as.partition(chunkLength).map(P1.sequenceList()))); + return P1.map_(List.join()).f(s.parList(as.partition(chunkLength).map(P1.sequenceList()))); } /** From 24fcb57a0a333d70cb9ccbb43ec6c85f90591460 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 09:23:35 +1000 Subject: [PATCH 366/811] Added extra javadoc to $._ --- core/src/main/java/fj/data/$.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 9418afd0..8d0931e3 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -15,10 +15,12 @@ public final class $ extends P1 { this.b = b; } - /** - * @deprecated JDK 8 warns '_' may not be supported after SE 8. Replaced by {@link #constant} and synonym {@link #__} (prefer constant). - */ - @Deprecated + /** + * Returns a function that given an argument, returns a function that ignores its argument. + * @deprecated JDK 8 warns '_' may not be supported after SE 8. As of release 4.5, use {@link #constant} (note the synonym {@link #__}). + * @return A function that given an argument, returns a function that ignores its argument. + */ + @Deprecated public static $ _(final B b) { return constant(b); } From 167152767270c4d475b69bd87daeb2fc98587b8b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 13 Aug 2015 09:32:16 +1000 Subject: [PATCH 367/811] Changed version on deprecation message for $._ --- core/src/main/java/fj/data/$.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 8d0931e3..3ddf92d3 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -17,7 +17,7 @@ public final class $ extends P1 { /** * Returns a function that given an argument, returns a function that ignores its argument. - * @deprecated JDK 8 warns '_' may not be supported after SE 8. As of release 4.5, use {@link #constant} (note the synonym {@link #__}). + * @deprecated JDK 8 warns '_' may not be supported after SE 8. As of release 4.4, use {@link #constant} (note the synonym {@link #__}). * @return A function that given an argument, returns a function that ignores its argument. */ @Deprecated From f82777fba8e4deabbdcb1a3e8bbd27df07daaa66 Mon Sep 17 00:00:00 2001 From: Zheka Kozlov Date: Mon, 17 Aug 2015 18:37:42 +0600 Subject: [PATCH 368/811] Fixed bug in Buffer.copy() --- core/src/main/java/fj/data/List.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 69156bd5..b9a11bef 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1986,6 +1986,7 @@ private void copy() { List s = start; final Cons t = tail; start = nil(); + tail = null; exported = false; while (s != t) { snoc(s.head()); From f68ce24a012c06afc0110e71b3bfb7b5d390184c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 17 Aug 2015 23:59:31 +1000 Subject: [PATCH 369/811] #181: Added test case --- .../src/test/java/fj/data/ListBufferTest.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core/src/test/java/fj/data/ListBufferTest.java diff --git a/core/src/test/java/fj/data/ListBufferTest.java b/core/src/test/java/fj/data/ListBufferTest.java new file mode 100644 index 00000000..1dfbbc39 --- /dev/null +++ b/core/src/test/java/fj/data/ListBufferTest.java @@ -0,0 +1,24 @@ +package fj.data; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by MarkPerry on 17/08/2015. + */ +public class ListBufferTest { + + @Test + public void testSnoc() { + // test case for #181 + List.Buffer buf = List.Buffer.empty(); + buf.snoc(1).snoc(2).snoc(3); + List list1 = buf.toList(); + buf.snoc(4); + List list2 = buf.toList(); + assertThat(list2, equalTo(Stream.range(1, 5).toList())); + } + +} From cfab9d2753fdd928c31a0110dbd37e7c02787366 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 18 Aug 2015 21:10:30 +1000 Subject: [PATCH 370/811] #182: Upgraded to Gradle 2.6. Had to update uptodate plugin as a result --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 89d382d9..5ef5c85e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ ext { buildscript { ext { - uptodateVersion = "1.5.1" + uptodateVersion = "1.6.0" retrolambdaVersion = "3.2.0" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 12967230..e60d0819 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip From 224f7121c4efa0332f4f0963ba459e9865b44169 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 18 Aug 2015 22:29:33 +1000 Subject: [PATCH 371/811] #173: Fixed order of foldMap for Set which switch the left and right branches --- core/src/main/java/fj/data/Set.java | 2 +- core/src/test/java/fj/data/SetTest.java | 26 ++++++++++++++++ core/src/test/java/fj/data/TestTreeMap.java | 26 ---------------- core/src/test/java/fj/data/TreeMapTest.java | 34 ++++++++++++++++++--- 4 files changed, 57 insertions(+), 31 deletions(-) create mode 100644 core/src/test/java/fj/data/SetTest.java delete mode 100644 core/src/test/java/fj/data/TestTreeMap.java diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 8892ca63..21723185 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -265,7 +265,7 @@ public final Set map(final Ord o, final F f) { public final B foldMap(final F f, final Monoid m) { return isEmpty() ? m.zero() : - m.sum(m.sum(r().foldMap(f, m), f.f(head())), l().foldMap(f, m)); + m.sum(m.sum(l().foldMap(f, m), f.f(head())), r().foldMap(f, m)); } /** diff --git a/core/src/test/java/fj/data/SetTest.java b/core/src/test/java/fj/data/SetTest.java new file mode 100644 index 00000000..78084bb4 --- /dev/null +++ b/core/src/test/java/fj/data/SetTest.java @@ -0,0 +1,26 @@ +package fj.data; + +import org.junit.Test; + +import static fj.Ord.intOrd; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by MarkPerry on 18/08/2015. + */ +public class SetTest { + + @Test + public void toStream() { + Set s = Set.set(intOrd, 1, 2, 3); + assertThat(s.toStream(), equalTo(Stream.stream(1, 2, 3))); + } + + @Test + public void testString() { + Set s = Set.set(intOrd, 1, 2, 3); + assertThat(s.toString(), equalTo("Set(1,2,3)")); + } + +} diff --git a/core/src/test/java/fj/data/TestTreeMap.java b/core/src/test/java/fj/data/TestTreeMap.java deleted file mode 100644 index d4dcf5ba..00000000 --- a/core/src/test/java/fj/data/TestTreeMap.java +++ /dev/null @@ -1,26 +0,0 @@ -package fj.data; - -import fj.Ord; -import fj.P2; -import org.junit.Test; - -import java.util.ArrayList; - -/** - * Created by MarkPerry on 2/06/2014. - */ -public class TestTreeMap { - - @Test - public void testLargeInserts() { - // check that inserting a large number of items performs ok - // taken from https://code.google.com/p/functionaljava/issues/detail?id=31 and - // https://github.com/functionaljava/functionaljava/pull/13/files - final int n = 10000; - TreeMap m = TreeMap.empty(Ord.intOrd); - for (int i = 0; i < n; i++) { - m = m.set(i, "abc " + i); - } - } - -} diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index e89f4a26..cbfec54e 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -6,12 +6,15 @@ import fj.Ord; import fj.P3; import fj.Show; -import fj.P; +import fj.P2; import org.junit.Test; +import static fj.P.p; import static fj.data.Option.some; +import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** @@ -42,7 +45,7 @@ public void split() { Equal> seq = Equal.setEqual(Equal.stringEqual); Set left = toSetString(List.range(1, pivot)); Set right = toSetString(List.range(pivot + 1, max + 1)); - P3, Option, Set> expected = P.p(left, some(Integer.toString(pivot)), right); + P3, Option, Set> expected = p(left, some(Integer.toString(pivot)), right); assertTrue(Equal.p3Equal(seq, Equal.optionEqual(Equal.stringEqual), seq).eq(p, expected)); } @@ -75,7 +78,7 @@ public void splitLookup() { // do the assert Equal> tme = Equal.treeMapEqual(Equal.intEqual, Equal.stringEqual); Equal, Option, TreeMap>> eq = Equal.p3Equal(tme, Equal.optionEqual(Equal.stringEqual), tme); - assertTrue(eq.eq(p3, P.p(leftMap, some(Integer.toString(pivot)), rightMap))); + assertTrue(eq.eq(p3, p(leftMap, some(Integer.toString(pivot)), rightMap))); } @Test @@ -84,6 +87,29 @@ public void toMutableMap() { List> l = List.range(1, max + 1).map(n -> List.single(n)); TreeMap, String> m2 = TreeMap.treeMap(Ord.listOrd(Ord.intOrd), l.zip(l.map(i -> i.toString()))); Map, String> mm = m2.toMutableMap(); - assertEquals(m2.keys().reverse(), List.iterableList(mm.keySet())); + assertEquals(m2.keys(), List.iterableList(mm.keySet())); } + + + @Test + public void testLargeInserts() { + // check that inserting a large number of items performs ok + // taken from https://code.google.com/p/functionaljava/issues/detail?id=31 and + // https://github.com/functionaljava/functionaljava/pull/13/files + final int n = 10000; + TreeMap m = TreeMap.empty(Ord.intOrd); + for (int i = 0; i < n; i++) { + m = m.set(i, "abc " + i); + } + } + + @Test + public void testString() { + TreeMap t = TreeMap.treeMap(Ord.intOrd, p(1, "a"), p(2, "b"), p(3, "c")); + TreeMap t2 = TreeMap.treeMap(Ord.intOrd, p(3, "c"), p(2, "b"), p(1, "a")); + Stream> s = Stream.stream(p(1, "a"), p(2, "b"), p(3, "c")); + assertThat(t.toStream(), equalTo(s)); + assertThat(t2.toStream(), equalTo(s)); + } + } From 48d4c8358f1257e2126726be0808b48568f372bf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 18 Aug 2015 22:58:25 +1000 Subject: [PATCH 372/811] Added Arbitrary.arbSet and sorted set property --- .../fj/data/properties/SetProperties.java | 26 +++++++++++++++++++ .../src/main/java/fj/test/Arbitrary.java | 5 ++++ 2 files changed, 31 insertions(+) create mode 100644 props-core/src/test/java/fj/data/properties/SetProperties.java diff --git a/props-core/src/test/java/fj/data/properties/SetProperties.java b/props-core/src/test/java/fj/data/properties/SetProperties.java new file mode 100644 index 00000000..ba807936 --- /dev/null +++ b/props-core/src/test/java/fj/data/properties/SetProperties.java @@ -0,0 +1,26 @@ +package fj.data.properties; + +import fj.Equal; +import fj.Ord; +import fj.data.Set; +import fj.test.Arbitrary; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.test.Property.property; + +/** + * Created by MarkPerry on 18/08/2015. + */ +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class SetProperties { + + Property setToListIsSorted() { + Arbitrary> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger); + return property(as, s -> Property.prop(s.toList().equals(s.toList().sort(Ord.intOrd)))); + } + +} diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 2be4040a..ab23f964 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -21,6 +21,7 @@ import fj.P8; import fj.data.*; import fj.LcgRng; +import fj.Ord; import static fj.data.Either.left; import static fj.data.Either.right; @@ -783,6 +784,10 @@ public static Arbitrary> arbSeq(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.map(array -> Seq.seq((A[]) array.array()))); } + public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { + return arbitrary(arbList(aa).gen.map(list -> Set.set(ord, list))); + } + /** * Returns an arbitrary implementation for throwables. * From 3f2b459faa7f5653b63ea0209e44cb5d1abb063c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 18 Aug 2015 23:36:54 +1000 Subject: [PATCH 373/811] #183: Added concrete arbitrary lists for boolean, integer and double --- .../src/main/java/fj/test/Arbitrary.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index ab23f964..571aa149 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -734,7 +734,35 @@ public static Arbitrary> arbList(final Arbitrary aa) { return arbitrary(listOf(aa.gen)); } - public static Arbitrary> arbNonEmptyList(final Arbitrary aa) { + /** + * Returns an arbitrary list of integers. + */ + public static Arbitrary> arbListInteger() { + return arbitrary(listOf(arbInteger.gen)); + } + + /** + * Returns an arbitrary list of strings. + */ + public static Arbitrary> arbListString() { + return arbitrary(listOf(arbString.gen)); + } + + /** + * Returns an arbitrary list of booleans. + */ + public static Arbitrary> arbListBoolean() { + return arbitrary(listOf(arbBoolean.gen)); + } + + /** + * Returns an arbitrary list of doubles. + */ + public static Arbitrary> arbListDouble() { + return arbitrary(listOf(arbDouble.gen)); + } + + public static Arbitrary> arbNonEmptyList(final Arbitrary aa) { return arbitrary(Gen.listOf1(aa.gen).map(list -> NonEmptyList.fromList(list).some())); } From 950dc407cd3f740bac3f58197ce84ec2ddbf3ef3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 19 Aug 2015 22:54:15 +1000 Subject: [PATCH 374/811] #180: Implemented Stream.toList using List.Buffer for performance --- core/src/main/java/fj/data/Stream.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index c7613e01..8e8b3f7f 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -944,16 +944,12 @@ public final Option toOption() { * * @return A list projection of this stream. */ - public final List toList() { - List as = List.nil(); - - for (Stream x = this; !x.isEmpty(); x = x.tail()._1()) { - as = as.snoc(x.head()); + public final List toList() { + List.Buffer buf = List.Buffer.empty(); + foreachDoEffect(a -> buf.snoc(a)); + return buf.toList(); } - return as; - } - /** * Returns a array projection of this stream. From d38a694f9f1728417cb178c685850f627b10bf5b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 20 Aug 2015 00:17:24 +1000 Subject: [PATCH 375/811] Created example of known problem of creating streams from mutable iterators --- core/src/test/java/fj/data/StreamTest.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index 8968748c..a37764c2 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -3,6 +3,8 @@ import org.junit.Test; import java.io.IOException; +import java.util.ArrayList; +import java.util.ConcurrentModificationException; import static fj.data.IOFunctions.stdinReadLine; import static java.lang.System.out; @@ -28,4 +30,23 @@ public void testToString() { assertThat(range.toString(), is(equalTo("Cons(1, ?)"))); } + /** + * This test demonstrates the known problem of creating streams from mutable structures. + * + * Some of the ways streams created in this way can fail is: + * - weak stream references getting garbage collected + * - underlying mutable data structure changes + * - iterator gets updated (e.g. iterator used to create 2 different streams). + */ + @Test(expected = ConcurrentModificationException.class) + public void iterableStreamWithStructureUpdate() { + java.util.List list = List.list(1, 2, 3).toJavaList(); + Stream s1 = Stream.iterableStream(list); + int x = s1.head(); + list.remove(1); + Stream s2 = s1.tail()._1(); + x = s2.head(); + } + + } From c850806b35ce18d1a41a9158321a015becc145ff Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 00:45:14 +1000 Subject: [PATCH 376/811] Added sonatype repo --- README.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.adoc b/README.adoc index 242043e4..aebe093a 100644 --- a/README.adoc +++ b/README.adoc @@ -21,6 +21,7 @@ Important URLs for the project are: * Website, http://www.functionaljava.org * Website repository, http://github.com/functionaljava/functionaljava.github.io * Travis continuous integration build, https://travis-ci.org/functionaljava/functionaljava +* Sonatype Repository, https://oss.sonatype.org/content/groups/public/org/functionaljava/ * Jenkins Cloudbees CI build, https://functionaljava.ci.cloudbees.com == Downloading From fd300ac96ba8f990f95263470d53b923738069c1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 10:01:18 +1000 Subject: [PATCH 377/811] Added 3.2.1 release notes --- etc/release-notes/release-notes-3.2.1.adoc | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 etc/release-notes/release-notes-3.2.1.adoc diff --git a/etc/release-notes/release-notes-3.2.1.adoc b/etc/release-notes/release-notes-3.2.1.adoc new file mode 100644 index 00000000..09ea6007 --- /dev/null +++ b/etc/release-notes/release-notes-3.2.1.adoc @@ -0,0 +1,29 @@ + += Release 3.2.1 + +Released 24 August 2015 + +== Enhancements + +None. + +== Fixes + +None. + +== Internal + +This release targets the 1.6 virtual machine. + +== Breaking Changes + +None. + +== Documentation + +None. + +== Contributors + +* Mark Perry. + From 718f0d45fe04f91e7656624f75196d813864fb84 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 19:55:23 +1000 Subject: [PATCH 378/811] Added some old release dates --- etc/release-notes/release-notes-2.17.adoc | 5 +++++ etc/release-notes/release-notes-2.18.adoc | 5 +++++ etc/release-notes/release-notes-2.5.adoc | 7 +++++++ 3 files changed, 17 insertions(+) create mode 100644 etc/release-notes/release-notes-2.17.adoc create mode 100644 etc/release-notes/release-notes-2.18.adoc create mode 100644 etc/release-notes/release-notes-2.5.adoc diff --git a/etc/release-notes/release-notes-2.17.adoc b/etc/release-notes/release-notes-2.17.adoc new file mode 100644 index 00000000..d2763b22 --- /dev/null +++ b/etc/release-notes/release-notes-2.17.adoc @@ -0,0 +1,5 @@ += Release 2.17 + +Released: 12 Dec 2008 + +* See SVN log diff --git a/etc/release-notes/release-notes-2.18.adoc b/etc/release-notes/release-notes-2.18.adoc new file mode 100644 index 00000000..1d34f5c6 --- /dev/null +++ b/etc/release-notes/release-notes-2.18.adoc @@ -0,0 +1,5 @@ += Release 2.18 + +Released: 23 Mar 2009 + +* See SVN log diff --git a/etc/release-notes/release-notes-2.5.adoc b/etc/release-notes/release-notes-2.5.adoc new file mode 100644 index 00000000..d15a0869 --- /dev/null +++ b/etc/release-notes/release-notes-2.5.adoc @@ -0,0 +1,7 @@ += Release 2.5 + +Released: 1 May 2008 + +Changes + +* Unknown From 6aa26bcb56dd43d36bede2e8c34cbb21f69c1c8a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 20:06:36 +1000 Subject: [PATCH 379/811] Use variables for configuring retro lambda --- build.gradle | 4 ++++ core/build.gradle | 6 +++--- demo/build.gradle | 6 +++--- props-core/build.gradle | 6 +++--- quickcheck/build.gradle | 6 +++--- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 5ef5c85e..28e7f84c 100644 --- a/build.gradle +++ b/build.gradle @@ -64,6 +64,10 @@ allprojects { dependencyJunit = "junit:junit:4.12" displayCompilerWarnings = true + + newJdkEnvVar = "JAVA8_HOME" + oldJdkEnvVar = "JAVA7_HOME" + retroLambdaTarget = JavaVersion.VERSION_1_7 } version = fjVersion diff --git a/core/build.gradle b/core/build.gradle index 7bd8c184..c77a40bb 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -21,8 +21,8 @@ uploadArchives.enabled = true if (useRetroLambda) { retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk System.getenv(newJdkEnvVar) + oldJdk System.getenv(oldJdkEnvVar) + javaVersion retroLambdaTarget } } diff --git a/demo/build.gradle b/demo/build.gradle index 7af49271..effe2de4 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -9,9 +9,9 @@ mainClassName = "fj.demo.euler.Problem2" if (useRetroLambda) { retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk System.getenv(newJdkEnvVar) + oldJdk System.getenv(oldJdkEnvVar) + javaVersion retroLambdaTarget } } diff --git a/props-core/build.gradle b/props-core/build.gradle index f9f7fbb9..85d200e8 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -3,9 +3,9 @@ if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk System.getenv(newJdkEnvVar) + oldJdk System.getenv(oldJdkEnvVar) + javaVersion retroLambdaTarget } } diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index d4543f38..9c05fe8e 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -7,9 +7,9 @@ if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk System.getenv(newJdkEnvVar) + oldJdk System.getenv(oldJdkEnvVar) + javaVersion retroLambdaTarget } } From fc6188cc07d775025ab8e59e9447dc758123e1b0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 20:19:09 +1000 Subject: [PATCH 380/811] Provide method for configuring retro lambda --- core/build.gradle | 9 ++------- lib.gradle | 12 ++++++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index c77a40bb..c79c148b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -19,10 +19,5 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true -if (useRetroLambda) { - retrolambda { - jdk System.getenv(newJdkEnvVar) - oldJdk System.getenv(oldJdkEnvVar) - javaVersion retroLambdaTarget - } -} +configureRetroLambda(useRetroLambda, newJdkEnvVar, oldJdkEnvVar, retroLambdaTarget) + diff --git a/lib.gradle b/lib.gradle index 39ce7a7e..3b3b56c0 100644 --- a/lib.gradle +++ b/lib.gradle @@ -77,9 +77,21 @@ void configureUpload(String signingEnabled, Boolean signModule) { } } +void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String oldJdkEnvVar, JavaVersion retroLambdaTarget) { + + if (useRetroLambda) { + retrolambda { + jdk System.getenv(newJdkEnvVar) + oldJdk System.getenv(oldJdkEnvVar) + javaVersion retroLambdaTarget + } + } +} + ext { findJavaCommand = this.&findJavaCommand doSigning = this.&doSigning performSigning = this.&performSigning configureUpload = this.&configureUpload + configureRetroLambda = this.&configureRetroLambda } From 03bb00403367ba781aa8c30dc8c3c29394dfba86 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 20:31:25 +1000 Subject: [PATCH 381/811] Provide fully applied function to configure retro lambda for a project --- core/build.gradle | 3 +-- lib.gradle | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index c79c148b..e22ee973 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -19,5 +19,4 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true -configureRetroLambda(useRetroLambda, newJdkEnvVar, oldJdkEnvVar, retroLambdaTarget) - +configureAllRetroLambda() diff --git a/lib.gradle b/lib.gradle index 3b3b56c0..261877c0 100644 --- a/lib.gradle +++ b/lib.gradle @@ -77,6 +77,10 @@ void configureUpload(String signingEnabled, Boolean signModule) { } } +void configureAllRetroLambda() { + configureRetroLambda(useRetroLambda, newJdkEnvVar, oldJdkEnvVar, retroLambdaTarget) +} + void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String oldJdkEnvVar, JavaVersion retroLambdaTarget) { if (useRetroLambda) { @@ -94,4 +98,5 @@ ext { performSigning = this.&performSigning configureUpload = this.&configureUpload configureRetroLambda = this.&configureRetroLambda + configureAllRetroLambda = this.&configureAllRetroLambda } From a02b0ead94cf903c7226a048ebb4056a52f1218c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 20:36:59 +1000 Subject: [PATCH 382/811] Use configured retro lambda from each submodule --- demo/build.gradle | 8 +------- props-core/build.gradle | 8 ++------ quickcheck/build.gradle | 8 ++------ 3 files changed, 5 insertions(+), 19 deletions(-) diff --git a/demo/build.gradle b/demo/build.gradle index effe2de4..9e201126 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -7,13 +7,7 @@ if (useRetroLambda) { mainClassName = "fj.demo.euler.Problem2" -if (useRetroLambda) { - retrolambda { - jdk System.getenv(newJdkEnvVar) - oldJdk System.getenv(oldJdkEnvVar) - javaVersion retroLambdaTarget - } -} +configureAllRetroLambda() dependencies { compile project(":core") diff --git a/props-core/build.gradle b/props-core/build.gradle index 85d200e8..c8d626c4 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -1,14 +1,10 @@ if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' - - retrolambda { - jdk System.getenv(newJdkEnvVar) - oldJdk System.getenv(oldJdkEnvVar) - javaVersion retroLambdaTarget - } } +configureAllRetroLambda() + dependencies { compile project(":quickcheck") testCompile dependencyJunit diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 9c05fe8e..9c50ead6 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -5,14 +5,10 @@ ext { if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' - - retrolambda { - jdk System.getenv(newJdkEnvVar) - oldJdk System.getenv(oldJdkEnvVar) - javaVersion retroLambdaTarget - } } +configureAllRetroLambda() + archivesBaseName = "${project.projectName}-${project.name}" dependencies { From 7b062dbdcd764f94a902fc786161604f5d978cbf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 21:06:20 +1000 Subject: [PATCH 383/811] Move application of retro lambda plugin to method --- core/build.gradle | 5 ----- demo/build.gradle | 4 ---- lib.gradle | 1 + props-core/build.gradle | 4 ---- quickcheck/build.gradle | 4 ---- 5 files changed, 1 insertion(+), 17 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index e22ee973..1a1763e7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,9 +1,4 @@ -if (useRetroLambda) { - apply plugin: 'me.tatarka.retrolambda' -} - - ext { signModule = true } diff --git a/demo/build.gradle b/demo/build.gradle index 9e201126..851ff614 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -1,10 +1,6 @@ apply plugin: 'application' -if (useRetroLambda) { - apply plugin: 'me.tatarka.retrolambda' -} - mainClassName = "fj.demo.euler.Problem2" configureAllRetroLambda() diff --git a/lib.gradle b/lib.gradle index 261877c0..dbaebe4d 100644 --- a/lib.gradle +++ b/lib.gradle @@ -84,6 +84,7 @@ void configureAllRetroLambda() { void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String oldJdkEnvVar, JavaVersion retroLambdaTarget) { if (useRetroLambda) { + apply plugin: 'me.tatarka.retrolambda' retrolambda { jdk System.getenv(newJdkEnvVar) oldJdk System.getenv(oldJdkEnvVar) diff --git a/props-core/build.gradle b/props-core/build.gradle index c8d626c4..c146bc36 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -1,8 +1,4 @@ -if (useRetroLambda) { - apply plugin: 'me.tatarka.retrolambda' -} - configureAllRetroLambda() dependencies { diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 9c50ead6..4d3a25be 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -3,10 +3,6 @@ ext { signModule = true } -if (useRetroLambda) { - apply plugin: 'me.tatarka.retrolambda' -} - configureAllRetroLambda() archivesBaseName = "${project.projectName}-${project.name}" From 5241e2659efb2a1d84a7f83e132f68efede5b561 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 21:10:08 +1000 Subject: [PATCH 384/811] Removed gradle wrapper task --- build.gradle | 5 ----- 1 file changed, 5 deletions(-) diff --git a/build.gradle b/build.gradle index 28e7f84c..81139aac 100644 --- a/build.gradle +++ b/build.gradle @@ -152,11 +152,6 @@ configure(subprojects.findAll { it.name != "props-core" }) { eclipseProject.dependsOn eclipsePluginManifest } - -task wrapper(type: Wrapper) { - gradleVersion = '2.0' -} - task env << { println System.getenv() } From e4a7cada88d07b40949bf8107efffe6e3d440717 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 21:36:00 +1000 Subject: [PATCH 385/811] Converted consume module to use lambdas --- consume/src/main/java/fj/consume/euler/Problem1.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/consume/src/main/java/fj/consume/euler/Problem1.java b/consume/src/main/java/fj/consume/euler/Problem1.java index 9868d37c..d3bf7962 100644 --- a/consume/src/main/java/fj/consume/euler/Problem1.java +++ b/consume/src/main/java/fj/consume/euler/Problem1.java @@ -1,8 +1,5 @@ package fj.consume.euler; -import fj.F; -import fj.data.Stream; - import static fj.data.List.range; import static fj.function.Integers.sum; @@ -14,13 +11,11 @@ public class Problem1 { public static void main(final String[] args) { - java7(); + calc(); } - public static void java7() { - out.println(sum(range(0, 1000).filter(new F() { - public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} - }))); + public static void calc() { + out.println(sum(range(0, 1000).filter(a -> a % 3 == 0 || a % 5 == 0))); } } From 7ee5960d4324ce8f3330a821e9ac8bd3dba6af45 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 21:36:27 +1000 Subject: [PATCH 386/811] Converted fj root to use lambdas --- core/src/main/java/fj/Function.java | 22 +- core/src/main/java/fj/Monoid.java | 18 +- core/src/main/java/fj/P.java | 6 +- core/src/main/java/fj/P3.java | 18 +- core/src/main/java/fj/P4.java | 24 +- core/src/main/java/fj/P5.java | 30 +-- core/src/main/java/fj/Primitive.java | 324 +++++---------------------- 7 files changed, 73 insertions(+), 369 deletions(-) diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 9882a03d..4d4b14a2 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -19,11 +19,7 @@ private Function() { * @return A function that is partially-applied to the given value. */ public static F, B> apply(final A a) { - return new F, B>() { - public B f(final F k) { - return k.f(a); - } - }; + return f -> f.f(a); } /** @@ -32,15 +28,7 @@ public B f(final F k) { * @return A function that composes two functions to produce a new function. */ public static F, F, F>> compose() { - return new F, F, F>>() { - public F, F> f(final F f) { - return new F, F>() { - public F f(final F g) { - return compose(f, g); - } - }; - } - }; + return f -> g -> compose(f, g); } /** @@ -555,11 +543,7 @@ public static F4 uncurryF4(final F F>>>>>>, F7> uncurryF7() { - return new F>>>>>>, F7>() { - public F7 f(final F>>>>>> f) { - return uncurryF7(f); - } - }; + return f -> uncurryF7(f); } /** diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 4809ef2c..ac10b79f 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -151,11 +151,7 @@ public A sumLeft(final Stream as) { * @return a function that sums the given values with left-fold. */ public F, A> sumLeft() { - return new F, A>() { - public A f(final List as) { - return sumLeft(as); - } - }; + return as -> sumLeft(as); } /** @@ -164,11 +160,7 @@ public A f(final List as) { * @return a function that sums the given values with right-fold. */ public F, A> sumRight() { - return new F, A>() { - public A f(final List as) { - return sumRight(as); - } - }; + return as -> sumRight(as); } /** @@ -177,11 +169,7 @@ public A f(final List as) { * @return a function that sums the given values with left-fold. */ public F, A> sumLeftS() { - return new F, A>() { - public A f(final Stream as) { - return sumLeft(as); - } - }; + return as -> sumLeft(as); } /** diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index cb732bce..4a203bba 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -18,11 +18,7 @@ private P() { * @return A function that puts an element in a product-1. */ public static F> p1() { - return new F>() { - public P1 f(final A a) { - return p(a); - } - }; + return a -> p(a); } /** diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 58d1898a..9f473f56 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -152,11 +152,7 @@ public C _3() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return new F, A>() { - public A f(final P3 p) { - return p._1(); - } - }; + return p -> p._1(); } /** @@ -165,11 +161,7 @@ public A f(final P3 p) { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return new F, B>() { - public B f(final P3 p) { - return p._2(); - } - }; + return p -> p._2(); } /** @@ -178,11 +170,7 @@ public B f(final P3 p) { * @return A function that returns the third element of a product. */ public static F, C> __3() { - return new F, C>() { - public C f(final P3 p) { - return p._3(); - } - }; + return p -> p._3(); } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 082ceec8..7ba55b5d 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -212,11 +212,7 @@ public D _4() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return new F, A>() { - public A f(final P4 p) { - return p._1(); - } - }; + return p -> p._1(); } /** @@ -225,11 +221,7 @@ public A f(final P4 p) { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return new F, B>() { - public B f(final P4 p) { - return p._2(); - } - }; + return p -> p._2(); } /** @@ -238,11 +230,7 @@ public B f(final P4 p) { * @return A function that returns the third element of a product. */ public static F, C> __3() { - return new F, C>() { - public C f(final P4 p) { - return p._3(); - } - }; + return p -> p._3(); } /** @@ -251,11 +239,7 @@ public C f(final P4 p) { * @return A function that returns the fourth element of a product. */ public static F, D> __4() { - return new F, D>() { - public D f(final P4 p) { - return p._4(); - } - }; + return p -> p._4(); } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 21b7523b..6059e22a 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -278,11 +278,7 @@ public E _5() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return new F, A>() { - public A f(final P5 p) { - return p._1(); - } - }; + return p -> p._1(); } /** @@ -291,11 +287,7 @@ public A f(final P5 p) { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return new F, B>() { - public B f(final P5 p) { - return p._2(); - } - }; + return p -> p._2(); } /** @@ -304,11 +296,7 @@ public B f(final P5 p) { * @return A function that returns the third element of a product. */ public static F, C> __3() { - return new F, C>() { - public C f(final P5 p) { - return p._3(); - } - }; + return p -> p._3(); } /** @@ -317,11 +305,7 @@ public C f(final P5 p) { * @return A function that returns the fourth element of a product. */ public static F, D> __4() { - return new F, D>() { - public D f(final P5 p) { - return p._4(); - } - }; + return p -> p._4(); } /** @@ -330,11 +314,7 @@ public D f(final P5 p) { * @return A function that returns the fifth element of a product. */ public static F, E> __5() { - return new F, E>() { - public E f(final P5 p) { - return p._5(); - } - }; + return p -> p._5(); } @Override diff --git a/core/src/main/java/fj/Primitive.java b/core/src/main/java/fj/Primitive.java index 52e8c73f..baf2bae7 100644 --- a/core/src/main/java/fj/Primitive.java +++ b/core/src/main/java/fj/Primitive.java @@ -15,65 +15,37 @@ private Primitive() { /** * A function that converts booleans to bytes. */ - public static final F Boolean_Byte = new F() { - public Byte f(final Boolean b) { - return (byte) (b ? 1 : 0); - } - }; + public static final F Boolean_Byte = b -> (byte) (b ? 1 : 0); /** * A function that converts booleans to characters. */ - public static final F Boolean_Character = new F() { - public Character f(final Boolean b) { - return (char) (b ? 1 : 0); - } - }; + public static final F Boolean_Character = b -> (char) (b ? 1 : 0); /** * A function that converts booleans to doubles. */ - public static final F Boolean_Double = new F() { - public Double f(final Boolean b) { - return b ? 1D : 0D; - } - }; + public static final F Boolean_Double = b -> b ? 1D : 0D; /** * A function that converts booleans to floats. */ - public static final F Boolean_Float = new F() { - public Float f(final Boolean b) { - return b ? 1F : 0F; - } - }; + public static final F Boolean_Float = b -> b ? 1F : 0F; /** * A function that converts booleans to integers. */ - public static final F Boolean_Integer = new F() { - public Integer f(final Boolean b) { - return b ? 1 : 0; - } - }; + public static final F Boolean_Integer = b -> b ? 1 : 0; /** * A function that converts booleans to longs. */ - public static final F Boolean_Long = new F() { - public Long f(final Boolean b) { - return b ? 1L : 0L; - } - }; + public static final F Boolean_Long = b -> b ? 1L : 0L; /** * A function that converts booleans to shorts. */ - public static final F Boolean_Short = new F() { - public Short f(final Boolean b) { - return (short) (b ? 1 : 0); - } - }; + public static final F Boolean_Short = b -> (short) (b ? 1 : 0); // END Boolean -> @@ -82,65 +54,37 @@ public Short f(final Boolean b) { /** * A function that converts bytes to booleans. */ - public static final F Byte_Boolean = new F() { - public Boolean f(final Byte b) { - return b != 0; - } - }; + public static final F Byte_Boolean = b -> b != 0; /** * A function that converts bytes to characters. */ - public static final F Byte_Character = new F() { - public Character f(final Byte b) { - return (char) (byte) b; - } - }; + public static final F Byte_Character = b -> (char) (byte) b; /** * A function that converts bytes to doubles. */ - public static final F Byte_Double = new F() { - public Double f(final Byte b) { - return (double) b; - } - }; + public static final F Byte_Double = b -> (double) b; /** * A function that converts bytes to floats. */ - public static final F Byte_Float = new F() { - public Float f(final Byte b) { - return (float) b; - } - }; + public static final F Byte_Float = b -> (float) b; /** * A function that converts bytes to integers. */ - public static final F Byte_Integer = new F() { - public Integer f(final Byte b) { - return (int) b; - } - }; + public static final F Byte_Integer = b -> (int) b; /** * A function that converts bytes to longs. */ - public static final F Byte_Long = new F() { - public Long f(final Byte b) { - return (long) b; - } - }; + public static final F Byte_Long = b -> (long) b; /** * A function that converts bytes to shorts. */ - public static final F Byte_Short = new F() { - public Short f(final Byte b) { - return (short) b; - } - }; + public static final F Byte_Short = b -> (short) b; // END Byte -> @@ -149,38 +93,22 @@ public Short f(final Byte b) { /** * A function that converts characters to booleans. */ - public static final F Character_Boolean = new F() { - public Boolean f(final Character c) { - return c != 0; - } - }; + public static final F Character_Boolean = c -> c != 0; /** * A function that converts characters to bytes. */ - public static final F Character_Byte = new F() { - public Byte f(final Character c) { - return (byte) (char) c; - } - }; + public static final F Character_Byte = c -> (byte) (char) c; /** * A function that converts characters to doubles. */ - public static final F Character_Double = new F() { - public Double f(final Character c) { - return (double) (char) c; - } - }; + public static final F Character_Double = c -> (double) (char) c; /** * A function that converts characters to floats. */ - public static final F Character_Float = new F() { - public Float f(final Character c) { - return (float) (char) c; - } - }; + public static final F Character_Float = c -> (float) (char) c; /** * A function that converts characters to integers. @@ -194,20 +122,12 @@ public Integer f(final Character c) { /** * A function that converts characters to longs. */ - public static final F Character_Long = new F() { - public Long f(final Character c) { - return (long) (char) c; - } - }; + public static final F Character_Long = c -> (long) (char) c; /** * A function that converts characters to shorts. */ - public static final F Character_Short = new F() { - public Short f(final Character c) { - return (short) (char) c; - } - }; + public static final F Character_Short = c -> (short) (char) c; // END Character -> @@ -216,11 +136,7 @@ public Short f(final Character c) { /** * A function that converts doubles to booleans. */ - public static final F Double_Boolean = new F() { - public Boolean f(final Double d) { - return d != 0D; - } - }; + public static final F Double_Boolean = d -> d != 0D; /** * A function that converts doubles to bytes. @@ -234,47 +150,27 @@ public Byte f(final Double d) { /** * A function that converts doubles to characters. */ - public static final F Double_Character = new F() { - public Character f(final Double d) { - return (char) (double) d; - } - }; + public static final F Double_Character = d -> (char) (double) d; /** * A function that converts doubles to floats. */ - public static final F Double_Float = new F() { - public Float f(final Double d) { - return (float) (double) d; - } - }; + public static final F Double_Float = d -> (float) (double) d; /** * A function that converts doubles to integers. */ - public static final F Double_Integer = new F() { - public Integer f(final Double d) { - return (int) (double) d; - } - }; + public static final F Double_Integer = d -> (int) (double) d; /** * A function that converts doubles to longs. */ - public static final F Double_Long = new F() { - public Long f(final Double d) { - return (long) (double) d; - } - }; + public static final F Double_Long = d -> (long) (double) d; /** * A function that converts doubles to shorts. */ - public static final F Double_Short = new F() { - public Short f(final Double d) { - return (short) (double) d; - } - }; + public static final F Double_Short = d -> (short) (double) d; // END Double -> @@ -283,65 +179,37 @@ public Short f(final Double d) { /** * A function that converts floats to booleans. */ - public static final F Float_Boolean = new F() { - public Boolean f(final Float f) { - return f != 0F; - } - }; + public static final F Float_Boolean = f -> f != 0F; /** * A function that converts floats to bytes. */ - public static final F Float_Byte = new F() { - public Byte f(final Float f) { - return (byte) (float) f; - } - }; + public static final F Float_Byte = f -> (byte) (float) f; /** * A function that converts floats to characters. */ - public static final F Float_Character = new F() { - public Character f(final Float f) { - return (char) (float) f; - } - }; + public static final F Float_Character = f -> (char) (float) f; /** * A function that converts floats to doubles. */ - public static final F Float_Double = new F() { - public Double f(final Float f) { - return (double) (float) f; - } - }; + public static final F Float_Double = f -> (double) (float) f; /** * A function that converts floats to integers. */ - public static final F Float_Integer = new F() { - public Integer f(final Float f) { - return (int) (float) f; - } - }; + public static final F Float_Integer = f -> (int) (float) f; /** * A function that converts floats to longs. */ - public static final F Float_Long = new F() { - public Long f(final Float f) { - return (long) (float) f; - } - }; + public static final F Float_Long = f -> (long) (float) f; /** * A function that converts floats to shorts. */ - public static final F Float_Short = new F() { - public Short f(final Float f) { - return (short) (float) f; - } - }; + public static final F Float_Short = f -> (short) (float) f; // END Float -> @@ -350,65 +218,37 @@ public Short f(final Float f) { /** * A function that converts integers to booleans. */ - public static final F Integer_Boolean = new F() { - public Boolean f(final Integer i) { - return i != 0; - } - }; + public static final F Integer_Boolean = i -> i != 0; /** * A function that converts integers to bytes. */ - public static final F Integer_Byte = new F() { - public Byte f(final Integer i) { - return (byte) (int) i; - } - }; + public static final F Integer_Byte = i -> (byte) (int) i; /** * A function that converts integers to characters. */ - public static final F Integer_Character = new F() { - public Character f(final Integer i) { - return (char) (int) i; - } - }; + public static final F Integer_Character = i -> (char) (int) i; /** * A function that converts integers to doubles. */ - public static final F Integer_Double = new F() { - public Double f(final Integer i) { - return (double) i; - } - }; + public static final F Integer_Double = i -> (double) i; /** * A function that converts integers to floats. */ - public static final F Integer_Float = new F() { - public Float f(final Integer i) { - return (float) i; - } - }; + public static final F Integer_Float = i -> (float) i; /** * A function that converts integers to longs. */ - public static final F Integer_Long = new F() { - public Long f(final Integer i) { - return (long) i; - } - }; + public static final F Integer_Long = i -> (long) i; /** * A function that converts integers to shorts. */ - public static final F Integer_Short = new F() { - public Short f(final Integer i) { - return (short) (int) i; - } - }; + public static final F Integer_Short = i -> (short) (int) i; // END Integer -> @@ -417,65 +257,37 @@ public Short f(final Integer i) { /** * A function that converts longs to booleans. */ - public static final F Long_Boolean = new F() { - public Boolean f(final Long l) { - return l != 0L; - } - }; + public static final F Long_Boolean = l -> l != 0L; /** * A function that converts longs to bytes. */ - public static final F Long_Byte = new F() { - public Byte f(final Long l) { - return (byte) (long) l; - } - }; + public static final F Long_Byte = l -> (byte) (long) l; /** * A function that converts longs to characters. */ - public static final F Long_Character = new F() { - public Character f(final Long l) { - return (char) (long) l; - } - }; + public static final F Long_Character = l -> (char) (long) l; /** * A function that converts longs to doubles. */ - public static final F Long_Double = new F() { - public Double f(final Long l) { - return (double) (long) l; - } - }; + public static final F Long_Double = l -> (double) (long) l; /** * A function that converts longs to floats. */ - public static final F Long_Float = new F() { - public Float f(final Long l) { - return (float) (long) l; - } - }; + public static final F Long_Float = l -> (float) (long) l; /** * A function that converts longs to integers. */ - public static final F Long_Integer = new F() { - public Integer f(final Long l) { - return (int) (long) l; - } - }; + public static final F Long_Integer = l -> (int) (long) l; /** * A function that converts longs to shorts. */ - public static final F Long_Short = new F() { - public Short f(final Long l) { - return (short) (long) l; - } - }; + public static final F Long_Short = l -> (short) (long) l; // END Long -> @@ -484,65 +296,37 @@ public Short f(final Long l) { /** * A function that converts shorts to booleans. */ - public static final F Short_Boolean = new F() { - public Boolean f(final Short s) { - return s != 0; - } - }; + public static final F Short_Boolean = s -> s != 0; /** * A function that converts shorts to bytes. */ - public static final F Short_Byte = new F() { - public Byte f(final Short s) { - return (byte) (short) s; - } - }; + public static final F Short_Byte = s -> (byte) (short) s; /** * A function that converts shorts to characters. */ - public static final F Short_Character = new F() { - public Character f(final Short s) { - return (char) (short) s; - } - }; + public static final F Short_Character = s -> (char) (short) s; /** * A function that converts shorts to doubles. */ - public static final F Short_Double = new F() { - public Double f(final Short s) { - return (double) (short) s; - } - }; + public static final F Short_Double = s -> (double) (short) s; /** * A function that converts shorts to floats. */ - public static final F Short_Float = new F() { - public Float f(final Short s) { - return (float) (short) s; - } - }; + public static final F Short_Float = s -> (float) (short) s; /** * A function that converts shorts to integers. */ - public static final F Short_Integer = new F() { - public Integer f(final Short s) { - return (int) (short) s; - } - }; + public static final F Short_Integer = s -> (int) (short) s; /** * A function that converts shorts to longs. */ - public static final F Short_Long = new F() { - public Long f(final Short s) { - return (long) (short) s; - } - }; + public static final F Short_Long = s -> (long) (short) s; // END Short } From c270d4acc28a33261459458586b2c9b1751e9c0f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 21:56:41 +1000 Subject: [PATCH 387/811] Converted fj.control to use lambdas --- core/src/main/java/fj/control/db/DB.java | 16 +------ .../java/fj/control/parallel/ParModule.java | 12 +---- .../java/fj/control/parallel/Promise.java | 46 +++---------------- 3 files changed, 11 insertions(+), 63 deletions(-) diff --git a/core/src/main/java/fj/control/db/DB.java b/core/src/main/java/fj/control/db/DB.java index 4c891254..8e8590b6 100644 --- a/core/src/main/java/fj/control/db/DB.java +++ b/core/src/main/java/fj/control/db/DB.java @@ -41,15 +41,7 @@ public A run(final Connection c) { * @return The callable-valued function which is isomorphic to this database action. */ public final F> asFunction() { - return new F>() { - public Callable f(final Connection c) { - return new Callable() { - public A call() throws Exception { - return run(c); - } - }; - } - }; + return c -> () -> run(c); } /** @@ -73,11 +65,7 @@ public B run(final Connection c) throws SQLException { * @return A function equivalent to the given one, which operates on values in the database. */ public static F, DB> liftM(final F f) { - return new F, DB>() { - public DB f(final DB a) { - return a.map(f); - } - }; + return a -> a.map(f); } /** diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index e6f37228..7d01139a 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -452,11 +452,7 @@ public Promise> parZipWith(final Stream as, final Stream< * @return A Promise of a new array with the results of applying the given function across the two arrays, stepwise. */ public Promise> parZipWith(final Array as, final Array bs, final F> f) { - return parZipWith(as.toStream(), bs.toStream(), f).fmap(new F, Array>() { - public Array f(final Stream stream) { - return stream.toArray(); - } - }); + return parZipWith(as.toStream(), bs.toStream(), f).fmap(stream -> stream.toArray()); } /** @@ -500,11 +496,7 @@ public Promise parFoldMap(final Stream as, final F map, final */ public Promise parFoldMap(final Stream as, final F map, final Monoid reduce, final F, P2, Stream>> chunking) { - return parMap(Stream.unfold(stream -> stream.isEmpty() ? Option., Stream>>none() : some(chunking.f(stream)), as), Stream.map_().f(map)).bind(new F>, Promise>() { - public Promise f(final Stream> stream) { - return parMap(stream, reduce.sumLeftS()).fmap(reduce.sumLeftS()); - } - }); + return parMap(Stream.unfold(stream -> stream.isEmpty() ? Option., Stream>>none() : some(chunking.f(stream)), as), Stream.map_().f(map)).bind(stream -> parMap(stream, reduce.sumLeftS()).fmap(reduce.sumLeftS())); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 2f93d5e7..20d9b68b 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -86,11 +86,7 @@ public static Promise promise(final Strategy s, final P1 a) { * @return A function that, given a 1-product, yields a promise of that product's value. */ public static F, Promise> promise(final Strategy s) { - return new F, Promise>() { - public Promise f(final P1 a) { - return promise(s, a); - } - }; + return a -> promise(s, a); } /** @@ -117,11 +113,7 @@ public Callable _1() { * @return The given function transformed into a function that returns a promise. */ public static F> promise(final Strategy s, final F f) { - return new F>() { - public Promise f(final A a) { - return promise(s, P1.curry(f).f(a)); - } - }; + return a -> promise(s, P1.curry(f).f(a)); } /** @@ -150,11 +142,7 @@ public Promise fmap(final F f) { * @return That function lifted to a function on Promises. */ public static F, Promise> fmap_(final F f) { - return new F, Promise>() { - public Promise f(final Promise a) { - return a.fmap(f); - } - }; + return a -> a.fmap(f); } /** @@ -206,11 +194,7 @@ public void f(final B b) { * @return A new promise after applying the given promised function to this promise. */ public Promise apply(final Promise> pf) { - return pf.bind(new F, Promise>() { - public Promise f(final F f) { - return fmap(f); - } - }); + return pf.bind(f -> fmap(f)); } /** @@ -267,11 +251,7 @@ public static Promise> sequence(final Strategy s, final List

F>, Promise>> sequence(final Strategy s) { - return new F>, Promise>>() { - public Promise> f(final List> as) { - return sequence(s, as); - } - }; + return as -> sequence(s, as); } /** @@ -282,15 +262,7 @@ public Promise> f(final List> as) { * @return A single promise for the given Stream. */ public static Promise> sequence(final Strategy s, final Stream> as) { - return join(foldRightS(s, curry(new F2, P1>>, Promise>>() { - public Promise> f(final Promise o, final P1>> p) { - return o.bind(new F>>() { - public Promise> f(final A a) { - return p._1().fmap(Stream.cons_().f(a)); - } - }); - } - }), promise(s, P.p(Stream.nil()))).f(as)); + return join(foldRightS(s, curry((Promise o, P1>> p) -> o.bind(a -> p._1().fmap(Stream.cons_().f(a)))), promise(s, P.p(Stream.nil()))).f(as)); } /** @@ -300,11 +272,7 @@ public Promise> f(final A a) { * @return A function that turns a list of promises into a single promise of a Stream.. */ public static F>, Promise>> sequenceS(final Strategy s) { - return new F>, Promise>>() { - public Promise> f(final List> as) { - return sequence(s, as); - } - }; + return as -> sequence(s, as); } /** From 7904bfa11a6e7d113dfb76cf0c1194ea24f9ee45 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 23:06:59 +1000 Subject: [PATCH 388/811] Converted root fj.data package to use lambdas --- core/src/main/java/fj/data/Array.java | 41 +- core/src/main/java/fj/data/Conversions.java | 442 ++++--------------- core/src/main/java/fj/data/Enumerator.java | 199 +++------ core/src/main/java/fj/data/HashMap.java | 12 +- core/src/main/java/fj/data/IOFunctions.java | 24 +- core/src/main/java/fj/data/IterableW.java | 21 +- core/src/main/java/fj/data/LazyString.java | 10 +- core/src/main/java/fj/data/NonEmptyList.java | 6 +- core/src/main/java/fj/data/Option.java | 22 +- core/src/main/java/fj/data/Tree.java | 7 +- core/src/main/java/fj/data/Validation.java | 36 +- 11 files changed, 182 insertions(+), 638 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 6d492212..d6700dc6 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -171,12 +171,9 @@ public List toList() { */ @SuppressWarnings("unchecked") public Stream toStream() { - return Stream.unfold(new F>>() { - public Option> f(final Integer o) { - return a.length > o ? some(p((A) a[o], o + 1)) - : Option.>none(); - } - }, 0); + return Stream.unfold(o -> + a.length > o ? some(p((A) a[o], o + 1)) : Option.>none(), 0 + ); } @Override @@ -515,15 +512,7 @@ public Array bind(final Array sb, final F2 f) { * @return A new array after applying the given array of functions through this array. */ public Array apply(final Array> lf) { - return lf.bind(new F, Array>() { - public Array f(final F f) { - return map(new F() { - public B f(final A a) { - return f.f(a); - } - }); - } - }); + return lf.bind(f -> map(a -> f.f(a))); } /** @@ -602,11 +591,7 @@ public static Array single(final A a) { * @return A function that wraps a given array. */ public static F> wrap() { - return new F>() { - public Array f(final A[] as) { - return array(as); - } - }; + return as -> array(as); } /** @@ -639,11 +624,7 @@ public static Array join(final Array> o) { * @return A function that joins a array of arrays using a bind operation. */ public static F>, Array> join() { - return new F>, Array>() { - public Array f(final Array> as) { - return join(as); - } - }; + return as -> join(as); } /** @@ -775,15 +756,7 @@ public Array> zip(final Array bs) { * @return A new array with the same length as this array. */ public Array> zipIndex() { - return zipWith(range(0, length()), new F>>() { - public F> f(final A a) { - return new F>() { - public P2 f(final Integer i) { - return p(a, i); - } - }; - } - }); + return zipWith(range(0, length()), a -> i -> p(a, i)); } /** diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 47db668f..7f74ce86 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -36,11 +36,7 @@ private Conversions() { * @return A function that converts lists to arrays. */ public static F, Array> List_Array() { - return new F, Array>() { - public Array f(final List as) { - return as.toArray(); - } - }; + return as -> as.toArray(); } /** @@ -49,11 +45,7 @@ public Array f(final List as) { * @return A function that converts lists to streams. */ public static F, Stream> List_Stream() { - return new F, Stream>() { - public Stream f(final List as) { - return as.toStream(); - } - }; + return as -> as.toStream(); } /** @@ -62,11 +54,7 @@ public Stream f(final List as) { * @return A function that converts lists to options. */ public static F, Option> List_Option() { - return new F, Option>() { - public Option f(final List as) { - return as.toOption(); - } - }; + return as -> as.toOption(); } /** @@ -75,43 +63,23 @@ public Option f(final List as) { * @return A function that converts lists to eithers. */ public static F, F, Either>> List_Either() { - return new F, F, Either>>() { - public F, Either> f(final P1 a) { - return new F, Either>() { - public Either f(final List bs) { - return bs.toEither(a); - } - }; - } - }; + return a -> bs -> bs.toEither(a); } /** * A function that converts lists to strings. */ - public static final F, String> List_String = new F, String>() { - public String f(final List cs) { - return asString(cs); - } - }; + public static final F, String> List_String = cs -> asString(cs); /** * A function that converts lists to string buffers. */ - public static final F, StringBuffer> List_StringBuffer = new F, StringBuffer>() { - public StringBuffer f(final List cs) { - return new StringBuffer(asString(cs)); - } - }; + public static final F, StringBuffer> List_StringBuffer = cs -> new StringBuffer(asString(cs)); /** * A function that converts lists to string builders. */ - public static final F, StringBuilder> List_StringBuilder = new F, StringBuilder>() { - public StringBuilder f(final List cs) { - return new StringBuilder(asString(cs)); - } - }; + public static final F, StringBuilder> List_StringBuilder = cs -> new StringBuilder(asString(cs)); // END List -> @@ -123,11 +91,7 @@ public StringBuilder f(final List cs) { * @return A function that converts arrays to lists. */ public static F, List> Array_List() { - return new F, List>() { - public List f(final Array as) { - return as.toList(); - } - }; + return as -> as.toList(); } /** @@ -136,11 +100,7 @@ public List f(final Array as) { * @return A function that converts arrays to streams. */ public static F, Stream> Array_Stream() { - return new F, Stream>() { - public Stream f(final Array as) { - return as.toStream(); - } - }; + return as -> as.toStream(); } /** @@ -149,11 +109,7 @@ public Stream f(final Array as) { * @return A function that converts arrays to options. */ public static F, Option> Array_Option() { - return new F, Option>() { - public Option f(final Array as) { - return as.toOption(); - } - }; + return as -> as.toOption(); } /** @@ -162,58 +118,35 @@ public Option f(final Array as) { * @return A function that converts arrays to eithers. */ public static F, F, Either>> Array_Either() { - return new F, F, Either>>() { - public F, Either> f(final P1 a) { - return new F, Either>() { - public Either f(final Array bs) { - return bs.toEither(a); - } - }; - } - }; + return a -> bs -> bs.toEither(a); } /** * A function that converts arrays to strings. */ - public static final F, String> Array_String = new F, String>() { - public String f(final Array cs) { + public static final F, String> Array_String = cs -> { final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect(new Effect1() { - public void f(final Character c) { - sb.append(c); - } - }); + cs.foreachDoEffect(c -> sb.append(c)); return sb.toString(); - } }; /** * A function that converts arrays to string buffers. */ - public static final F, StringBuffer> Array_StringBuffer = new F, StringBuffer>() { - public StringBuffer f(final Array cs) { + public static final F, StringBuffer> Array_StringBuffer = cs -> { final StringBuffer sb = new StringBuffer(); - cs.foreachDoEffect(new Effect1() { - public void f(final Character c) { - sb.append(c); - } - }); + cs.foreachDoEffect(c -> sb.append(c)); return sb; - } }; /** * A function that converts arrays to string builders. */ - public static final F, StringBuilder> Array_StringBuilder = - new F, StringBuilder>() { - public StringBuilder f(final Array cs) { - final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect((Character c) -> sb.append(c)); - return sb; - } - }; + public static final F, StringBuilder> Array_StringBuilder = cs -> { + final StringBuilder sb = new StringBuilder(); + cs.foreachDoEffect((Character c) -> sb.append(c)); + return sb; + }; // END Array -> @@ -225,11 +158,7 @@ public StringBuilder f(final Array cs) { * @return A function that converts streams to lists. */ public static F, List> Stream_List() { - return new F, List>() { - public List f(final Stream as) { - return as.toList(); - } - }; + return as -> as.toList(); } /** @@ -238,11 +167,7 @@ public List f(final Stream as) { * @return A function that converts streams to arrays. */ public static F, Array> Stream_Array() { - return new F, Array>() { - public Array f(final Stream as) { - return as.toArray(); - } - }; + return as -> as.toArray(); } /** @@ -251,11 +176,7 @@ public Array f(final Stream as) { * @return A function that converts streams to options. */ public static F, Option> Stream_Option() { - return new F, Option>() { - public Option f(final Stream as) { - return as.toOption(); - } - }; + return as -> as.toOption(); } /** @@ -264,51 +185,35 @@ public Option f(final Stream as) { * @return A function that converts streams to eithers. */ public static F, F, Either>> Stream_Either() { - return new F, F, Either>>() { - public F, Either> f(final P1 a) { - return new F, Either>() { - public Either f(final Stream bs) { - return bs.toEither(a); - } - }; - } - }; + return a -> bs -> bs.toEither(a); } /** * A function that converts streams to strings. */ - public static final F, String> Stream_String = new F, String>() { - public String f(final Stream cs) { + public static final F, String> Stream_String = cs -> { final StringBuilder sb = new StringBuilder(); cs.foreachDoEffect((Character c) -> sb.append(c)); return sb.toString(); - } - }; + }; /** * A function that converts streams to string buffers. */ - public static final F, StringBuffer> Stream_StringBuffer = - new F, StringBuffer>() { - public StringBuffer f(final Stream cs) { - final StringBuffer sb = new StringBuffer(); - cs.foreachDoEffect((Character c) -> sb.append(c)); - return sb; - } - }; + public static final F, StringBuffer> Stream_StringBuffer = cs -> { + final StringBuffer sb = new StringBuffer(); + cs.foreachDoEffect((Character c) -> sb.append(c)); + return sb; + }; /** * A function that converts streams to string builders. */ - public static final F, StringBuilder> Stream_StringBuilder = - new F, StringBuilder>() { - public StringBuilder f(final Stream cs) { - final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect((Character c) -> sb.append(c)); - return sb; - } - }; + public static final F, StringBuilder> Stream_StringBuilder = cs -> { + final StringBuilder sb = new StringBuilder(); + cs.foreachDoEffect((Character c) -> sb.append(c)); + return sb; + }; // END Stream -> @@ -320,11 +225,7 @@ public StringBuilder f(final Stream cs) { * @return A function that converts options to lists. */ public static F, List> Option_List() { - return new F, List>() { - public List f(final Option o) { - return o.toList(); - } - }; + return o -> o.toList(); } /** @@ -333,11 +234,7 @@ public List f(final Option o) { * @return A function that converts options to arrays. */ public static F, Array> Option_Array() { - return new F, Array>() { - public Array f(final Option o) { - return o.toArray(); - } - }; + return o -> o.toArray(); } /** @@ -346,11 +243,7 @@ public Array f(final Option o) { * @return A function that converts options to streams. */ public static F, Stream> Option_Stream() { - return new F, Stream>() { - public Stream f(final Option o) { - return o.toStream(); - } - }; + return o -> o.toStream(); } /** @@ -359,45 +252,23 @@ public Stream f(final Option o) { * @return A function that converts options to eithers. */ public static F, F, Either>> Option_Either() { - return new F, F, Either>>() { - public F, Either> f(final P1 a) { - return new F, Either>() { - public Either f(final Option o) { - return o.toEither(a); - } - }; - } - }; + return a -> o -> o.toEither(a); } /** * A function that converts options to strings. */ - public static final F, String> Option_String = new F, String>() { - public String f(final Option o) { - return asString(o.toList()); - } - }; + public static final F, String> Option_String = o -> asString(o.toList()); /** * A function that converts options to string buffers. */ - public static final F, StringBuffer> Option_StringBuffer = - new F, StringBuffer>() { - public StringBuffer f(final Option o) { - return new StringBuffer(asString(o.toList())); - } - }; + public static final F, StringBuffer> Option_StringBuffer = o -> new StringBuffer(asString(o.toList())); /** * A function that converts options to string builders. */ - public static final F, StringBuilder> Option_StringBuilder = - new F, StringBuilder>() { - public StringBuilder f(final Option o) { - return new StringBuilder(asString(o.toList())); - } - }; + public static final F, StringBuilder> Option_StringBuilder = o -> new StringBuilder(asString(o.toList())); // END Option -> @@ -451,11 +322,7 @@ public static F> Effect_SafeIO() { * @return A function that converts eithers to lists. */ public static F, List> Either_ListA() { - return new F, List>() { - public List f(final Either e) { - return e.left().toList(); - } - }; + return e -> e.left().toList(); } /** @@ -464,11 +331,7 @@ public List f(final Either e) { * @return A function that converts eithers to lists. */ public static F, List> Either_ListB() { - return new F, List>() { - public List f(final Either e) { - return e.right().toList(); - } - }; + return e -> e.right().toList(); } /** @@ -477,11 +340,7 @@ public List f(final Either e) { * @return A function that converts eithers to arrays. */ public static F, Array> Either_ArrayA() { - return new F, Array>() { - public Array f(final Either e) { - return e.left().toArray(); - } - }; + return e -> e.left().toArray(); } /** @@ -490,11 +349,7 @@ public Array f(final Either e) { * @return A function that converts eithers to arrays. */ public static F, Array> Either_ArrayB() { - return new F, Array>() { - public Array f(final Either e) { - return e.right().toArray(); - } - }; + return e -> e.right().toArray(); } /** @@ -503,11 +358,7 @@ public Array f(final Either e) { * @return A function that converts eithers to streams. */ public static F, Stream> Either_StreamA() { - return new F, Stream>() { - public Stream f(final Either e) { - return e.left().toStream(); - } - }; + return e -> e.left().toStream(); } /** @@ -516,11 +367,7 @@ public Stream f(final Either e) { * @return A function that converts eithers to streams. */ public static F, Stream> Either_StreamB() { - return new F, Stream>() { - public Stream f(final Either e) { - return e.right().toStream(); - } - }; + return e -> e.right().toStream(); } /** @@ -529,11 +376,7 @@ public Stream f(final Either e) { * @return A function that converts eithers to options. */ public static F, Option> Either_OptionA() { - return new F, Option>() { - public Option f(final Either e) { - return e.left().toOption(); - } - }; + return e -> e.left().toOption(); } /** @@ -542,11 +385,7 @@ public Option f(final Either e) { * @return A function that converts eithers to options. */ public static F, Option> Either_OptionB() { - return new F, Option>() { - public Option f(final Either e) { - return e.right().toOption(); - } - }; + return e -> e.right().toOption(); } /** @@ -555,11 +394,7 @@ public Option f(final Either e) { * @return A function that converts eithers to strings. */ public static F, String> Either_StringA() { - return new F, String>() { - public String f(final Either e) { - return asString(e.left().toList()); - } - }; + return e -> asString(e.left().toList()); } /** @@ -568,11 +403,7 @@ public String f(final Either e) { * @return A function that converts eithers to strings. */ public static F, String> Either_StringB() { - return new F, String>() { - public String f(final Either e) { - return asString(e.right().toList()); - } - }; + return e -> asString(e.right().toList()); } /** @@ -581,11 +412,7 @@ public String f(final Either e) { * @return A function that converts eithers to string buffers. */ public static F, StringBuffer> Either_StringBufferA() { - return new F, StringBuffer>() { - public StringBuffer f(final Either e) { - return new StringBuffer(asString(e.left().toList())); - } - }; + return e -> new StringBuffer(asString(e.left().toList())); } /** @@ -594,11 +421,7 @@ public StringBuffer f(final Either e) { * @return A function that converts eithers to string buffers. */ public static F, StringBuffer> Either_StringBufferB() { - return new F, StringBuffer>() { - public StringBuffer f(final Either e) { - return new StringBuffer(asString(e.right().toList())); - } - }; + return e -> new StringBuffer(asString(e.right().toList())); } /** @@ -607,11 +430,7 @@ public StringBuffer f(final Either e) { * @return A function that converts eithers to string builders. */ public static F, StringBuilder> Either_StringBuilderA() { - return new F, StringBuilder>() { - public StringBuilder f(final Either e) { - return new StringBuilder(asString(e.left().toList())); - } - }; + return e -> new StringBuilder(asString(e.left().toList())); } /** @@ -620,11 +439,7 @@ public StringBuilder f(final Either e) { * @return A function that converts eithers to string builders. */ public static F, StringBuilder> Either_StringBuilderB() { - return new F, StringBuilder>() { - public StringBuilder f(final Either e) { - return new StringBuilder(asString(e.right().toList())); - } - }; + return e -> new StringBuilder(asString(e.right().toList())); } // END Either -> @@ -646,29 +461,17 @@ public static F, SafeIO> F_SafeIO() { /** * A function that converts strings to lists. */ - public static final F> String_List = new F>() { - public List f(final String s) { - return fromString(s); - } - }; + public static final F> String_List = s -> fromString(s); /** * A function that converts strings to arrays. */ - public static final F> String_Array = new F>() { - public Array f(final String s) { - return fromString(s).toArray(); - } - }; + public static final F> String_Array = s -> fromString(s).toArray(); /** * A function that converts strings to options. */ - public static final F> String_Option = new F>() { - public Option f(final String s) { - return fromString(s).toOption(); - } - }; + public static final F> String_Option = s -> fromString(s).toOption(); /** * A function that converts string to eithers. @@ -676,43 +479,23 @@ public Option f(final String s) { * @return A function that converts string to eithers. */ public static F, F>> String_Either() { - return new F, F>>() { - public F> f(final P1 a) { - return new F>() { - public Either f(final String s) { - return fromString(s).toEither(a); - } - }; - } - }; + return a -> s -> fromString(s).toEither(a); } /** * A function that converts strings to streams. */ - public static final F> String_Stream = new F>() { - public Stream f(final String s) { - return fromString(s).toStream(); - } - }; + public static final F> String_Stream = s -> fromString(s).toStream(); /** * A function that converts strings to string buffers. */ - public static final F String_StringBuffer = new F() { - public StringBuffer f(final String s) { - return new StringBuffer(s); - } - }; + public static final F String_StringBuffer = s -> new StringBuffer(s); /** * A function that converts strings to string builders. */ - public static final F String_StringBuilder = new F() { - public StringBuilder f(final String s) { - return new StringBuilder(s); - } - }; + public static final F String_StringBuilder = s -> new StringBuilder(s); // END String -> @@ -721,40 +504,22 @@ public StringBuilder f(final String s) { /** * A function that converts string buffers to lists. */ - public static final F> StringBuffer_List = new F>() { - public List f(final StringBuffer s) { - return fromString(s.toString()); - } - }; + public static final F> StringBuffer_List = s -> fromString(s.toString()); /** * A function that converts string buffers to arrays. */ - public static final F> StringBuffer_Array = new F>() { - public Array f(final StringBuffer s) { - return fromString(s.toString()).toArray(); - } - }; + public static final F> StringBuffer_Array = s -> fromString(s.toString()).toArray(); /** * A function that converts string buffers to streams. */ - public static final F> StringBuffer_Stream = - new F>() { - public Stream f(final StringBuffer s) { - return fromString(s.toString()).toStream(); - } - }; + public static final F> StringBuffer_Stream = s -> fromString(s.toString()).toStream(); /** * A function that converts string buffers to options. */ - public static final F> StringBuffer_Option = - new F>() { - public Option f(final StringBuffer s) { - return fromString(s.toString()).toOption(); - } - }; + public static final F> StringBuffer_Option = s -> fromString(s.toString()).toOption(); /** * A function that converts string buffers to eithers. @@ -762,34 +527,18 @@ public Option f(final StringBuffer s) { * @return A function that converts string buffers to eithers. */ public static F, F>> StringBuffer_Either() { - return new F, F>>() { - public F> f(final P1 a) { - return new F>() { - public Either f(final StringBuffer s) { - return fromString(s.toString()).toEither(a); - } - }; - } - }; + return a -> s -> fromString(s.toString()).toEither(a); } /** * A function that converts string buffers to strings. */ - public static final F StringBuffer_String = new F() { - public String f(final StringBuffer s) { - return s.toString(); - } - }; + public static final F StringBuffer_String = s -> s.toString(); /** * A function that converts string buffers to string builders. */ - public static final F StringBuffer_StringBuilder = new F() { - public StringBuilder f(final StringBuffer s) { - return new StringBuilder(s); - } - }; + public static final F StringBuffer_StringBuilder = s -> new StringBuilder(s); // END StringBuffer -> @@ -798,41 +547,22 @@ public StringBuilder f(final StringBuffer s) { /** * A function that converts string builders to lists. */ - public static final F> StringBuilder_List = new F>() { - public List f(final StringBuilder s) { - return fromString(s.toString()); - } - }; + public static final F> StringBuilder_List = s -> fromString(s.toString()); /** * A function that converts string builders to arrays. */ - public static final F> StringBuilder_Array = - new F>() { - public Array f(final StringBuilder s) { - return fromString(s.toString()).toArray(); - } - }; + public static final F> StringBuilder_Array = s -> fromString(s.toString()).toArray(); /** * A function that converts string builders to streams. */ - public static final F> StringBuilder_Stream = - new F>() { - public Stream f(final StringBuilder s) { - return fromString(s.toString()).toStream(); - } - }; + public static final F> StringBuilder_Stream = s -> fromString(s.toString()).toStream(); /** * A function that converts string builders to options. */ - public static final F> StringBuilder_Option = - new F>() { - public Option f(final StringBuilder s) { - return fromString(s.toString()).toOption(); - } - }; + public static final F> StringBuilder_Option = s -> fromString(s.toString()).toOption(); /** * A function that converts string builders to eithers. @@ -840,34 +570,18 @@ public Option f(final StringBuilder s) { * @return A function that converts string builders to eithers. */ public static F, F>> StringBuilder_Either() { - return new F, F>>() { - public F> f(final P1 a) { - return new F>() { - public Either f(final StringBuilder s) { - return fromString(s.toString()).toEither(a); - } - }; - } - }; + return a -> s -> fromString(s.toString()).toEither(a); } /** * A function that converts string builders to strings. */ - public static final F StringBuilder_String = new F() { - public String f(final StringBuilder s) { - return s.toString(); - } - }; + public static final F StringBuilder_String = s -> s.toString(); /** * A function that converts string builders to string buffers. */ - public static final F StringBuilder_StringBuffer = new F() { - public StringBuffer f(final StringBuilder s) { - return new StringBuffer(s); - } - }; + public static final F StringBuilder_StringBuffer = s -> new StringBuffer(s); // END StringBuilder -> diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index a3067e06..c9088bfa 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -165,11 +165,7 @@ public Ord order() { * @return An enumerator after the given functions are applied. */ public Enumerator xmap(final F f, final F g) { - final F, Option> of = new F, Option>() { - public Option f(final Option o) { - return o.map(f); - } - }; + final F, Option> of = o -> o.map(f); return enumerator(compose(compose(of, successor), g), compose(compose(of, predecessor), g), max.map(f), @@ -272,175 +268,116 @@ else if (l < 0L) { /** * An enumerator for boolean. */ - public static final Enumerator booleanEnumerator = enumerator(new F>() { - public Option f(final Boolean b) { - return b ? Option.none() : some(true); - } - }, new F>() { - public Option f(final Boolean b) { - return b ? some(false) : Option.none(); - } - }, some(true), some(false), booleanOrd); + public static final Enumerator booleanEnumerator = enumerator( + b -> b ? Option.none() : some(true), + b -> b ? some(false) : Option.none(), + some(true), some(false), booleanOrd + ); /** * An enumerator for byte. */ - public static final Enumerator byteEnumerator = enumerator(new F>() { - public Option f(final Byte b) { - return b == Byte.MAX_VALUE ? Option.none() : some((byte) (b + 1)); - } - }, new F>() { - public Option f(final Byte b) { - return b == Byte.MIN_VALUE ? Option.none() : some((byte) (b - 1)); - } - }, some(Byte.MAX_VALUE), some(Byte.MIN_VALUE), byteOrd); + public static final Enumerator byteEnumerator = enumerator( + b -> b == Byte.MAX_VALUE ? Option.none() : some((byte) (b + 1)), + b -> b == Byte.MIN_VALUE ? Option.none() : some((byte) (b - 1)), + some(Byte.MAX_VALUE), some(Byte.MIN_VALUE), byteOrd + ); /** * An enumerator for char. */ - public static final Enumerator charEnumerator = enumerator(new F>() { - public Option f(final Character c) { - return c == Character.MAX_VALUE ? Option.none() : some((char) (c + 1)); - } - }, new F>() { - public Option f(final Character c) { - return c == Character.MIN_VALUE ? Option.none() : some((char) (c - 1)); - } - }, some(Character.MAX_VALUE), some(Character.MIN_VALUE), charOrd); + public static final Enumerator charEnumerator = enumerator( + c -> c == Character.MAX_VALUE ? Option.none() : some((char) (c + 1)), + c -> c == Character.MIN_VALUE ? Option.none() : some((char) (c - 1)), + some(Character.MAX_VALUE), some(Character.MIN_VALUE), charOrd + ); /** * An enumerator for double. */ - public static final Enumerator doubleEnumerator = enumerator(new F>() { - public Option f(final Double d) { - return d == Double.MAX_VALUE ? Option.none() : some(d + 1D); - } - }, new F>() { - public Option f(final Double d) { - return d == Double.MIN_VALUE ? Option.none() : some(d - 1D); - } - }, some(Double.MAX_VALUE), some(Double.MIN_VALUE), doubleOrd); + public static final Enumerator doubleEnumerator = enumerator( + d -> d == Double.MAX_VALUE ? Option.none() : some(d + 1D), + d -> d == Double.MIN_VALUE ? Option.none() : some(d - 1D), + some(Double.MAX_VALUE), some(Double.MIN_VALUE), doubleOrd + ); /** * An enumerator for float. */ - public static final Enumerator floatEnumerator = enumerator(new F>() { - public Option f(final Float f) { - return f == Float.MAX_VALUE ? Option.none() : some(f + 1F); - } - }, new F>() { - public Option f(final Float f) { - return f == Float.MIN_VALUE ? Option.none() : some(f - 1F); - } - }, some(Float.MAX_VALUE), some(Float.MIN_VALUE), floatOrd); + public static final Enumerator floatEnumerator = enumerator( + f -> f == Float.MAX_VALUE ? Option.none() : some(f + 1F), + f -> f == Float.MIN_VALUE ? Option.none() : some(f - 1F), + some(Float.MAX_VALUE), some(Float.MIN_VALUE), floatOrd + ); /** * An enumerator for int. */ - public static final Enumerator intEnumerator = enumerator(new F>() { - public Option f(final Integer i) { - return i == Integer.MAX_VALUE ? Option.none() : some(i + 1); - } - }, new F>() { - public Option f(final Integer i) { - return i == Integer.MIN_VALUE ? Option.none() : some(i - 1); - } - }, some(Integer.MAX_VALUE), some(Integer.MIN_VALUE), intOrd); + public static final Enumerator intEnumerator = enumerator( + i -> i == Integer.MAX_VALUE ? Option.none() : some(i + 1), + i -> i == Integer.MIN_VALUE ? Option.none() : some(i - 1), + some(Integer.MAX_VALUE), some(Integer.MIN_VALUE), intOrd + ); /** * An enumerator for BigInteger. */ - public static final Enumerator bigintEnumerator = enumerator(new F>() { - public Option f(final BigInteger i) { - return some(i.add(BigInteger.ONE)); - } - }, new F>() { - public Option f(final BigInteger i) { - return some(i.subtract(BigInteger.ONE)); - } - }, Option.none(), Option.none(), bigintOrd, curry( - new F2>() { - public Option f(final BigInteger i, final Long l) { - return some(i.add(BigInteger.valueOf(l))); - } - })); + public static final Enumerator bigintEnumerator = enumerator( + i -> some(i.add(BigInteger.ONE)), + i -> some(i.subtract(BigInteger.ONE)), + Option.none(), Option.none(), bigintOrd, + curry((i, l) -> some(i.add(BigInteger.valueOf(l)))) + ); /** * An enumerator for BigDecimal. */ - public static final Enumerator bigdecimalEnumerator = enumerator(new F>() { - public Option f(final BigDecimal i) { - return some(i.add(BigDecimal.ONE)); - } - }, new F>() { - public Option f(final BigDecimal i) { - return some(i.subtract(BigDecimal.ONE)); - } - }, Option.none(), Option.none(), bigdecimalOrd, curry( - new F2>() { - public Option f(final BigDecimal d, final Long l) { - return some(d.add(BigDecimal.valueOf(l))); - } - })); + public static final Enumerator bigdecimalEnumerator = enumerator( + i -> some(i.add(BigDecimal.ONE)), + i -> some(i.subtract(BigDecimal.ONE)), + Option.none(), Option.none(), bigdecimalOrd, + curry((d, l) -> some(d.add(BigDecimal.valueOf(l)))) + ); /** * An enumerator for long. */ - public static final Enumerator longEnumerator = enumerator(new F>() { - public Option f(final Long i) { - return i == Long.MAX_VALUE ? Option.none() : some(i + 1L); - } - }, new F>() { - public Option f(final Long i) { - return i == Long.MIN_VALUE ? Option.none() : some(i - 1L); - } - }, some(Long.MAX_VALUE), some(Long.MIN_VALUE), longOrd); + public static final Enumerator longEnumerator = enumerator( + i -> i == Long.MAX_VALUE ? Option.none() : some(i + 1L), + i -> i == Long.MIN_VALUE ? Option.none() : some(i - 1L), + some(Long.MAX_VALUE), some(Long.MIN_VALUE), longOrd + ); /** * An enumerator for short. */ - public static final Enumerator shortEnumerator = enumerator(new F>() { - public Option f(final Short i) { - return i == Short.MAX_VALUE ? Option.none() : some((short) (i + 1)); - } - }, new F>() { - public Option f(final Short i) { - return i == Short.MIN_VALUE ? Option.none() : some((short) (i - 1)); - } - }, some(Short.MAX_VALUE), some(Short.MIN_VALUE), shortOrd); + public static final Enumerator shortEnumerator = enumerator( + i -> i == Short.MAX_VALUE ? Option.none() : some((short) (i + 1)), + i -> i == Short.MIN_VALUE ? Option.none() : some((short) (i - 1)), + some(Short.MAX_VALUE), some(Short.MIN_VALUE), shortOrd + ); /** * An enumerator for Ordering. */ - public static final Enumerator orderingEnumerator = enumerator(new F>() { - public Option f(final Ordering o) { - return o == LT ? some(EQ) : o == EQ ? some(GT) : Option.none(); - } - }, new F>() { - public Option f(final Ordering o) { - return o == GT ? some(EQ) : o == EQ ? some(LT) : Option.none(); - } - }, some(GT), some(LT), orderingOrd); + public static final Enumerator orderingEnumerator = enumerator( + o -> o == LT ? some(EQ) : o == EQ ? some(GT) : Option.none(), + o -> o == GT ? some(EQ) : o == EQ ? some(LT) : Option.none(), + some(GT), some(LT), orderingOrd + ); /** * An enumerator for Natural */ - public static final Enumerator naturalEnumerator = enumerator(new F>() { - public Option f(final Natural n) { - return Option.some(n.succ()); - } - }, new F>() { - public Option f(final Natural n) { - return n.pred(); - } - }, Option.none(), some(Natural.ZERO), naturalOrd, curry(new F2>() { - public Option f(final Natural n, final Long l) { - return some(n).apply(Natural.natural(l).map(Function.curry(new F2() { - public Natural f(final Natural n1, final Natural n2) { - return n1.add(n2); - } - }))); - } - })); + public static final Enumerator naturalEnumerator = enumerator( + n -> Option.some(n.succ()), + n -> n.pred(), + Option.none(), some(Natural.ZERO), naturalOrd, + curry((n, l) -> + some(n).apply( + Natural.natural(l).map(Function.curry((n1, n2) -> n1.add(n2))) + ) + ) + ); } diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 0b2215c6..2687bfd6 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -153,11 +153,7 @@ public Option get(final K k) { * @return A curried version of {@link #get(Object)}. */ public F> get() { - return new F>() { - public Option f(final K k) { - return get(k); - } - }; + return k -> get(k); } /** @@ -198,11 +194,7 @@ public List keys() { * @return All values in this hash map. */ public List values() { - return keys().map(new F() { - public V f(final K k) { - return m.get(new Key(k, e, h)); - } - }); + return keys().map(k -> m.get(new Key(k, e, h))); } /** diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index d2d82883..04564115 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -46,13 +46,7 @@ public static IO fromTry(Try0 t) { return () -> t.f(); } - public static final F> closeReader = - new F>() { - @Override - public IO f(final Reader r) { - return closeReader(r); - } - }; + public static final F> closeReader = r -> closeReader(r); /** * Convert io to a SafeIO, throwing any IOException wrapped inside a RuntimeException @@ -129,21 +123,13 @@ public static IO> enumFileChars(final File f, final Opti } public static IO bufferedReader(final File f, final Option encoding) { - return IOFunctions.map(fileReader(f, encoding), new F() { - @Override - public BufferedReader f(final Reader a) { - return new BufferedReader(a); - } - }); + return IOFunctions.map(fileReader(f, encoding), a -> new BufferedReader(a)); } public static IO fileReader(final File f, final Option encoding) { - return new IO() { - @Override - public Reader run() throws IOException { - final FileInputStream fis = new FileInputStream(f); - return encoding.isNone() ? new InputStreamReader(fis) : new InputStreamReader(fis, encoding.some()); - } + return () -> { + final FileInputStream fis = new FileInputStream(f); + return encoding.isNone() ? new InputStreamReader(fis) : new InputStreamReader(fis, encoding.some()); }; } diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 2474d72b..52be7d6b 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -129,20 +129,13 @@ public static F, F, IterableW>> liftM2(fina */ public static > IterableW> sequence(final Iterable as) { final Stream ts = iterableStream(as); - return ts.isEmpty() ? iterable(wrap(Option.none())) : wrap(ts.head()).bind(new F>>() { - public Iterable> f(final A a) { - return sequence(ts.tail().map(IterableW.>wrap())._1()) - .bind(new F, Iterable>>() { - public Iterable> f(final IterableW as) { - return iterable(wrap(Stream.cons(a, new P1>() { - public Stream _1() { - return iterableStream(as); - } - }))); - } - }); - } - }); + return ts.isEmpty() ? + iterable(wrap(Option.none())) : + wrap(ts.head()).bind(a -> + sequence(ts.tail().map(IterableW.>wrap())._1()).bind(as2 -> + iterable(wrap(Stream.cons(a, () -> iterableStream(as2)))) + ) + ); } /** diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index 43a93b02..3f3d660d 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -32,14 +32,12 @@ private LazyString(final Stream s) { * @return A lazy string with the characters from the given string. */ public static LazyString str(final String s) { - return new LazyString(Stream.unfold(new F, Option>>>() { - public Option>> f(final P2 o) { - final String s = o._1(); + return new LazyString(Stream.unfold(o -> { + final String s2 = o._1(); final int n = o._2(); final Option>> none = none(); - return s.length() <= n ? none : some(p(s.charAt(n), p(s, n + 1))); - } - }, p(s, 0))); + return s2.length() <= n ? none : some(p(s2.charAt(n), p(s2, n + 1))); + }, p(s, 0))); } /** diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index f7953ab6..0ebffc11 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -137,11 +137,7 @@ public NonEmptyList> sublists() { * @return A NonEmptyList of the tails of this list. */ public NonEmptyList> tails() { - return fromList(somes(toList().tails().map(new F, Option>>() { - public Option> f(final List list) { - return fromList(list); - } - }))).some(); + return fromList(somes(toList().tails().map(list -> fromList(list)))).some(); } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index a56850d8..c40adbe3 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -91,11 +91,7 @@ public final boolean isNone() { * @return A function that returns true if a given optional value has a value, otherwise false. */ public static F, Boolean> isSome_() { - return new F, Boolean>() { - public Boolean f(final Option a) { - return a.isSome(); - } - }; + return a -> a.isSome(); } /** @@ -104,11 +100,7 @@ public Boolean f(final Option a) { * @return A function that returns false if a given optional value has a value, otherwise true. */ public static F, Boolean> isNone_() { - return new F, Boolean>() { - public Boolean f(final Option a) { - return a.isNone(); - } - }; + return a -> a.isNone(); } /** @@ -464,15 +456,7 @@ public Validation> traverseValidation(F> * optional value. */ public final Option apply(final Option> of) { - return of.bind(new F, Option>() { - public Option f(final F f) { - return map(new F() { - public B f(final A a) { - return f.f(a); - } - }); - } - }); + return of.bind(f -> map(a -> f.f(a))); } /** diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index c5422408..777d39e8 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -326,12 +326,7 @@ public Tree zipWith(final Tree bs, final F> f) { * @return The folded tree */ public static Tree bottomUp(Tree t, final F>, B> f) { - final F, Tree> recursiveCall = new F, Tree>() { - @Override public Tree f(Tree a) { - return bottomUp(a, f); - } - }; - + final F, Tree> recursiveCall = a -> bottomUp(a, f); final Stream> tbs = t.subForest()._1().map(recursiveCall); return Tree.node(f.f(P.p(t.root(), tbs.map(Tree. getRoot()))), tbs); } diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 034aa927..073488ee 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -1175,11 +1175,7 @@ public static Validation parseByte(final String s) /** * A function that parses a string into a byte. */ - public static final F> parseByte = new F>() { - public Validation f(final String s) { - return parseByte(s); - } - }; + public static final F> parseByte = s -> parseByte(s); /** * Parses the given string into a double. @@ -1198,11 +1194,7 @@ public static Validation parseDouble(final String /** * A function that parses a string into a double. */ - public static final F> parseDouble = new F>() { - public Validation f(final String s) { - return parseDouble(s); - } - }; + public static final F> parseDouble = s -> parseDouble(s); /** * Parses the given string into a float. @@ -1221,11 +1213,7 @@ public static Validation parseFloat(final String s /** * A function that parses a string into a float. */ - public static final F> parseFloat = new F>() { - public Validation f(final String s) { - return parseFloat(s); - } - }; + public static final F> parseFloat = s -> parseFloat(s); /** * Parses the given string into a integer. @@ -1244,11 +1232,7 @@ public static Validation parseInt(final String s /** * A function that parses a string into an integer. */ - public static final F> parseInt = new F>() { - public Validation f(final String s) { - return parseInt(s); - } - }; + public static final F> parseInt = s -> parseInt(s); /** * Parses the given string into a long. @@ -1267,11 +1251,7 @@ public static Validation parseLong(final String s) /** * A function that parses a string into a long. */ - public static final F> parseLong = new F>() { - public Validation f(final String s) { - return parseLong(s); - } - }; + public static final F> parseLong = s -> parseLong(s); /** * Parses the given string into a short. @@ -1290,11 +1270,7 @@ public static Validation parseShort(final String s /** * A function that parses a string into a short. */ - public static final F> parseShort = new F>() { - public Validation f(final String s) { - return parseShort(s); - } - }; + public static final F> parseShort = s -> parseShort(s); /** * Partitions the list into the list of fails and the list of successes From 2335817624a4ed0688c787b82ca816320e223180 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 25 Aug 2015 23:48:49 +1000 Subject: [PATCH 389/811] Partial replace of anonymous classes with lambdas in Deep --- .../main/java/fj/data/fingertrees/Deep.java | 179 ++++++++---------- 1 file changed, 77 insertions(+), 102 deletions(-) diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index f0754e62..33032743 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -195,108 +195,83 @@ private static final FingerTree deepR(final Measured measured } } - private static FingerTree> addDigits0(final Measured m, final FingerTree> m1, - final Digit s1, final Digit p2, - final FingerTree> m2) { - final MakeTree mk = mkTree(m); - return s1.match(new F, FingerTree>>() { - public FingerTree> f(final One one1) { - return p2.match(new F, FingerTree>>() { - public FingerTree> f(final One one2) { - return append1(m, m1, mk.node2(one1.value(), one2.value()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Two two2) { - final V2 vs = two2.values(); - return append1(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Three three) { - final V3 vs = three.values(); - return append2(m, m1, mk.node2(one1.value(), vs._1()), mk.node2(vs._2(), vs._3()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Four four) { - final V4 vs = four.values(); - return append2(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), mk.node2(vs._3(), vs._4()), m2); - } - }); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Two two1) { - final V2 v1 = two1.values(); - return p2.match(new F, FingerTree>>() { - public FingerTree> f(final One one) { - return append1(m, m1, mk.node3(v1._1(), v1._2(), one.value()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Two two2) { - final V2 v2 = two2.values(); - return append2(m, m1, mk.node2(v1._1(), v1._2()), mk.node2(v2._1(), v2._2()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Three three) { - final V3 v2 = three.values(); - return append2(m, m1, mk.node3(v1._1(), v1._2(), v2._1()), mk.node2(v2._2(), v2._3()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Four four) { - final V4 v2 = four.values(); - return append2(m, m1, mk.node3(v1._1(), v1._2(), v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Three three1) { - final V3 v1 = three1.values(); - return p2.match(new F, FingerTree>>() { - public FingerTree> f(final One one) { - return append2(m, m1, mk.node2(v1._1(), v1._2()), mk.node2(v1._3(), one.value()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Two two) { - final V2 v2 = two.values(); - return append2(m, m1, mk.node3(v1), mk.node2(v2), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Three three2) { - return append2(m, m1, mk.node3(v1), mk.node3(three2.values()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Four four) { - return append3(m, m1, mk.node3(v1), mk.node2(four.values()._1(), four.values()._2()), - mk.node2(four.values()._3(), four.values()._4()), m2); - } - }); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Four four1) { - final V4 v1 = four1.values(); - return p2.match(new F, FingerTree>>() { - public FingerTree> f(final One one) { - return append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), one.value()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Two two) { - final V2 v2 = two.values(); - return append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), v2._1(), v2._2()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Three three) { - final V3 v2 = three.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), v2._1()), - mk.node2(v2._2(), v2._3()), m2); - } - }, new F, FingerTree>>() { - public FingerTree> f(final Four four2) { - final V4 v2 = four2.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), v2._1(), v2._2()), - mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }); - } + private static FingerTree> addDigits0( + final Measured m, final FingerTree> m1, + final Digit s1, final Digit p2, + final FingerTree> m2) { + + final MakeTree mk = mkTree(m); + return s1.match( + one1 -> { + return p2.match( + one2 -> append1(m, m1, mk.node2(one1.value(), one2.value()), m2), + two2 -> { + final V2 vs = two2.values(); + return append1(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), m2); + }, + three -> { + final V3 vs = three.values(); + return append2(m, m1, mk.node2(one1.value(), vs._1()), mk.node2(vs._2(), vs._3()), m2); + }, + four -> { + final V4 vs = four.values(); + return append2(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), mk.node2(vs._3(), vs._4()), m2); + } + ); + }, + two1 -> { + final V2 v1 = two1.values(); + return p2.match( + one -> append1(m, m1, mk.node3(v1._1(), v1._2(), one.value()), m2), + two2 -> { + final V2 v2 = two2.values(); + return append2(m, m1, mk.node2(v1._1(), v1._2()), mk.node2(v2._1(), v2._2()), m2); + }, + three -> { + final V3 v2 = three.values(); + return append2(m, m1, mk.node3(v1._1(), v1._2(), v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, + four -> { + final V4 v2 = four.values(); + return append2(m, m1, mk.node3(v1._1(), v1._2(), v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); + } + ); + }, + three1 -> { + final V3 v1 = three1.values(); + return p2.match( + one -> append2(m, m1, mk.node2(v1._1(), v1._2()), mk.node2(v1._3(), one.value()), m2), + two -> { + final V2 v2 = two.values(); + return append2(m, m1, mk.node3(v1), mk.node2(v2), m2); + }, + three2 -> append2(m, m1, mk.node3(v1), mk.node3(three2.values()), m2), + four -> append3(m, m1, mk.node3(v1), + mk.node2(four.values()._1(), four.values()._2()), + mk.node2(four.values()._3(), four.values()._4()), m2 + ) + ); + }, + four1 -> { + final V4 v1 = four1.values(); + return p2.match( + one -> append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), one.value()), m2), + two -> { + final V2 v2 = two.values(); + return append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), v2._1(), v2._2()), m2); + }, + three -> { + final V3 v2 = three.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, + four2 -> { + final V4 v2 = four2.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); + } + ); + } + ); + } private static FingerTree> append1(final Measured m, final FingerTree> xs, final Node a, final FingerTree> ys) { From 9e77606e9773244a3a61f96b70723f65236eef8b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 00:01:51 +1000 Subject: [PATCH 390/811] Converted most of fj.data.fingertrees to use lambdas --- .../main/java/fj/data/fingertrees/Digit.java | 128 +++++++----------- .../java/fj/data/fingertrees/Measured.java | 12 +- .../main/java/fj/data/fingertrees/Node.java | 19 +-- 3 files changed, 54 insertions(+), 105 deletions(-) diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index cf0f1a36..8a25084b 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -36,28 +36,23 @@ public abstract class Digit { * @param f A function with which to fold this digit. * @return The right reduction of this digit with the given function. */ - public final A reduceRight(final F> f) { - return match(new F, A>() { - public A f(final One one) { - return one.value(); - } - }, new F, A>() { - public A f(final Two two) { - final V2 v = two.values(); - return f.f(v._1()).f(v._2()); - } - }, new F, A>() { - public A f(final Three three) { - final V3 v = three.values(); - return f.f(v._1()).f(f.f(v._2()).f(v._3())); - } - }, new F, A>() { - public A f(final Four four) { - final V4 v = four.values(); - return f.f(v._1()).f(f.f(v._2()).f(f.f(v._3()).f(v._4()))); - } - }); - } + public final A reduceRight(final F> f) { + return match( + one -> one.value(), + two -> { + final V2 v = two.values(); + return f.f(v._1()).f(v._2()); + }, + three -> { + final V3 v = three.values(); + return f.f(v._1()).f(f.f(v._2()).f(v._3())); + }, + four -> { + final V4 v = four.values(); + return f.f(v._1()).f(f.f(v._2()).f(f.f(v._3()).f(v._4()))); + } + ); + } /** * Folds this digit to the right using the given function. @@ -66,26 +61,21 @@ public A f(final Four four) { * @return The right reduction of this digit with the given function. */ public final A reduceLeft(final F> f) { - return match(new F, A>() { - public A f(final One one) { - return one.value(); - } - }, new F, A>() { - public A f(final Two two) { - final V2 v = two.values(); - return f.f(v._1()).f(v._2()); - } - }, new F, A>() { - public A f(final Three three) { - final V3 v = three.values(); - return f.f(f.f(v._1()).f(v._2())).f(v._3()); - } - }, new F, A>() { - public A f(final Four four) { - final V4 v = four.values(); - return f.f(f.f(f.f(v._1()).f(v._2())).f(v._3())).f(v._4()); - } - }); + return match( + one -> one.value(), + two -> { + final V2 v = two.values(); + return f.f(v._1()).f(v._2()); + }, + three -> { + final V3 v = three.values(); + return f.f(f.f(v._1()).f(v._2())).f(v._3()); + }, + four -> { + final V4 v = four.values(); + return f.f(f.f(f.f(v._1()).f(v._2())).f(v._3())).f(v._4()); + } + ); } /** @@ -97,23 +87,12 @@ public A f(final Four four) { * with the given function and measured with the given measuring. */ public final Digit map(final F f, final Measured m) { - return match(new F, Digit>() { - public Digit f(final One one) { - return new One(m, f.f(one.value())); - } - }, new F, Digit>() { - public Digit f(final Two two) { - return new Two(m, two.values().map(f)); - } - }, new F, Digit>() { - public Digit f(final Three three) { - return new Three(m, three.values().map(f)); - } - }, new F, Digit>() { - public Digit f(final Four four) { - return new Four(m, four.values().map(f)); - } - }); + return match( + one -> new One(m, f.f(one.value())), + two -> new Two(m, two.values().map(f)), + three -> new Three(m, three.values().map(f)), + four -> new Four(m, four.values().map(f)) + ); } /** @@ -153,28 +132,15 @@ public V f(final V v, final A a) { * Returns the tree representation of this digit. * @return the tree representation of this digit. */ - public final FingerTree toTree() { - final MakeTree mk = mkTree(m); - return match(new F, FingerTree>() { - public FingerTree f(final One one) { - return mk.single(one.value()); - } - }, new F, FingerTree>() { - public FingerTree f(final Two two) { - return mk.deep(mk.one(two.values()._1()), new Empty>(m.nodeMeasured()), mk.one(two.values()._2())); - } - }, new F, FingerTree>() { - public FingerTree f(final Three three) { - return mk.deep(mk.two(three.values()._1(), three.values()._2()), new Empty>(m.nodeMeasured()), - mk.one(three.values()._3())); - } - }, new F, FingerTree>() { - public FingerTree f(final Four four) { - return mk.deep(mk.two(four.values()._1(), four.values()._2()), new Empty>(m.nodeMeasured()), - mk.two(four.values()._3(), four.values()._4())); - } - }); - } + public final FingerTree toTree() { + final MakeTree mk = mkTree(m); + return match( + one -> mk.single(one.value()), + two -> mk.deep(mk.one(two.values()._1()), new Empty>(m.nodeMeasured()), mk.one(two.values()._2())), + three -> mk.deep(mk.two(three.values()._1(), three.values()._2()), new Empty>(m.nodeMeasured()), mk.one(three.values()._3())), + four -> mk.deep(mk.two(four.values()._1(), four.values()._2()), new Empty>(m.nodeMeasured()), mk.two(four.values()._3(), four.values()._4())) + ); + } Option> tail() { return match( diff --git a/core/src/main/java/fj/data/fingertrees/Measured.java b/core/src/main/java/fj/data/fingertrees/Measured.java index 8d21b310..777eb369 100644 --- a/core/src/main/java/fj/data/fingertrees/Measured.java +++ b/core/src/main/java/fj/data/fingertrees/Measured.java @@ -74,11 +74,7 @@ public V zero() { * @return A measured instance for nodes. */ public Measured> nodeMeasured() { - return new Measured>(m, new F, V>() { - public V f(final Node node) { - return node.measure(); - } - }); + return new Measured>(m, node -> node.measure()); } /** @@ -87,11 +83,7 @@ public V f(final Node node) { * @return A measured instance for digits. */ public Measured> digitMeasured() { - return new Measured>(m, new F, V>() { - public V f(final Digit d) { - return d.measure(); - } - }); + return new Measured>(m, d -> d.measure()); } } diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index e051c8f0..737ea63f 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -32,23 +32,14 @@ public static F, B>> foldRight_(final F> af } public final Node map(final F f, final Measured m) { - return match(new F, Node>() { - public Node f(final Node2 node2) { - return new Node2(m, node2.toVector().map(f)); - } - }, new F, Node>() { - public Node f(final Node3 node3) { - return new Node3(m, node3.toVector().map(f)); - } - }); + return match( + node2 -> new Node2(m, node2.toVector().map(f)), + node3 -> new Node3(m, node3.toVector().map(f)) + ); } public static F, Node> liftM(final F f, final Measured m) { - return new F, Node>() { - public Node f(final Node node) { - return node.map(f, m); - } - }; + return node -> node.map(f, m); } public abstract Digit toDigit(); From 902825b9199841c7302675dffce70fd1a1255c63 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 00:03:15 +1000 Subject: [PATCH 391/811] Converted fj.data.hlist to use lambdas --- core/src/main/java/fj/data/hlist/HPre.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/data/hlist/HPre.java b/core/src/main/java/fj/data/hlist/HPre.java index 07d5ffa4..a37c3b78 100644 --- a/core/src/main/java/fj/data/hlist/HPre.java +++ b/core/src/main/java/fj/data/hlist/HPre.java @@ -184,11 +184,7 @@ private HZero() { } public Show show() { - return Show.showS(new F() { - public String f(final HZero hZero) { - return "HZero"; - } - }); + return Show.showS(hZero -> "HZero"); } public Integer toInteger() { @@ -209,11 +205,7 @@ private HSucc(final N n) { private final N pred; public Show> show() { - return Show.showS(new F, String>() { - public String f(final HSucc s) { - return "HSucc (" + s.show().showS(s) + ')'; - } - }); + return Show.showS(s -> "HSucc (" + s.show().showS(s) + ')'); } public Integer toInteger() { From 22c87b6298a27bb3683aa523e9d63db9956ad2f4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 00:13:52 +1000 Subject: [PATCH 392/811] Converted fj.data.vector to use lambdas --- core/src/main/java/fj/data/vector/V2.java | 24 ++------- core/src/main/java/fj/data/vector/V3.java | 30 ++---------- core/src/main/java/fj/data/vector/V4.java | 30 ++---------- core/src/main/java/fj/data/vector/V5.java | 24 ++------- core/src/main/java/fj/data/vector/V6.java | 48 +++--------------- core/src/main/java/fj/data/vector/V7.java | 54 ++++---------------- core/src/main/java/fj/data/vector/V8.java | 60 ++++------------------- 7 files changed, 45 insertions(+), 225 deletions(-) diff --git a/core/src/main/java/fj/data/vector/V2.java b/core/src/main/java/fj/data/vector/V2.java index 8cd6ca81..84d2c9e4 100644 --- a/core/src/main/java/fj/data/vector/V2.java +++ b/core/src/main/java/fj/data/vector/V2.java @@ -58,11 +58,7 @@ public A _2() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V2 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -71,11 +67,7 @@ public A f(final V2 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V2 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -124,11 +116,7 @@ public Stream _1() { * @return a function that transforms a vector-2 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V2 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -137,11 +125,7 @@ public Stream f(final V2 v) { * @return a function that transforms a vector-2 to the equivalent product-2. */ public static F, P2> p_() { - return new F, P2>() { - public P2 f(final V2 v) { - return v.p(); - } - }; + return v -> v.p(); } /** diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index 5d7dcfed..34d752f1 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -227,11 +227,7 @@ public V3 map(final F f) { * @return a function that transforms a vector-3 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V3 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -240,11 +236,7 @@ public Stream f(final V3 v) { * @return a function that transforms a vector-3 to the equivalent product-3. */ public static F, P3> p_() { - return new F, P3>() { - public P3 f(final V3 v) { - return v.p(); - } - }; + return v -> v.p(); } /** @@ -253,11 +245,7 @@ public P3 f(final V3 v) { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V3 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -266,11 +254,7 @@ public A f(final V3 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V3 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -279,11 +263,7 @@ public A f(final V3 v) { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return new F, A>() { - public A f(final V3 v) { - return v._3(); - } - }; + return v -> v._3(); } } \ No newline at end of file diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 960c52e9..06afd0dc 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -244,11 +244,7 @@ public V4> vzip(final V4 bs) { * @return a function that transforms a vector-4 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V4 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -257,11 +253,7 @@ public Stream f(final V4 v) { * @return a function that transforms a vector-4 to the equivalent product-4. */ public static F, P4> p_() { - return new F, P4>() { - public P4 f(final V4 v) { - return v.p(); - } - }; + return v -> v.p(); } /** @@ -270,11 +262,7 @@ public P4 f(final V4 v) { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V4 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -283,11 +271,7 @@ public A f(final V4 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V4 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -296,11 +280,7 @@ public A f(final V4 v) { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return new F, A>() { - public A f(final V4 v) { - return v._3(); - } - }; + return v -> v._3(); } /** diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 22564862..093f9a3c 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -287,11 +287,7 @@ public P5 f(final V5 v) { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V5 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -300,11 +296,7 @@ public A f(final V5 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V5 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -326,11 +318,7 @@ public A f(final V5 v) { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return new F, A>() { - public A f(final V5 v) { - return v._4(); - } - }; + return v -> v._4(); } /** @@ -339,10 +327,6 @@ public A f(final V5 v) { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return new F, A>() { - public A f(final V5 v) { - return v._5(); - } - }; + return v -> v._5(); } } diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 031b5761..2b61a2b4 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -278,11 +278,7 @@ public V6> vzip(final V6 bs) { * @return a function that transforms a vector-6 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V6 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -291,11 +287,7 @@ public Stream f(final V6 v) { * @return a function that transforms a vector-6 to the equivalent product-6. */ public static F, P6> p_() { - return new F, P6>() { - public P6 f(final V6 v) { - return v.p(); - } - }; + return v -> v.p(); } /** @@ -304,11 +296,7 @@ public P6 f(final V6 v) { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V6 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -317,11 +305,7 @@ public A f(final V6 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V6 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -330,11 +314,7 @@ public A f(final V6 v) { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return new F, A>() { - public A f(final V6 v) { - return v._3(); - } - }; + return v -> v._3(); } /** @@ -343,11 +323,7 @@ public A f(final V6 v) { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return new F, A>() { - public A f(final V6 v) { - return v._4(); - } - }; + return v -> v._4(); } /** @@ -356,11 +332,7 @@ public A f(final V6 v) { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return new F, A>() { - public A f(final V6 v) { - return v._5(); - } - }; + return v -> v._5(); } /** @@ -369,11 +341,7 @@ public A f(final V6 v) { * @return a function that gets the sixth element of a given vector. */ public static F, A> __6() { - return new F, A>() { - public A f(final V6 v) { - return v._6(); - } - }; + return v -> v._6(); } } diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index 8db9db6d..90273010 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -295,11 +295,7 @@ public V7> vzip(final V7 bs) { * @return a function that transforms a vector-7 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V7 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -308,11 +304,7 @@ public Stream f(final V7 v) { * @return a function that transforms a vector-7 to the equivalent product-7. */ public static F, P7> p_() { - return new F, P7>() { - public P7 f(final V7 v) { - return v.p(); - } - }; + return v -> v.p(); } /** @@ -321,11 +313,7 @@ public P7 f(final V7 v) { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V7 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -334,11 +322,7 @@ public A f(final V7 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V7 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -347,11 +331,7 @@ public A f(final V7 v) { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return new F, A>() { - public A f(final V7 v) { - return v._3(); - } - }; + return v -> v._3(); } /** @@ -360,11 +340,7 @@ public A f(final V7 v) { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return new F, A>() { - public A f(final V7 v) { - return v._4(); - } - }; + return v -> v._4(); } /** @@ -373,11 +349,7 @@ public A f(final V7 v) { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return new F, A>() { - public A f(final V7 v) { - return v._5(); - } - }; + return v -> v._5(); } /** @@ -386,11 +358,7 @@ public A f(final V7 v) { * @return a function that gets the sixth element of a given vector. */ public static F, A> __6() { - return new F, A>() { - public A f(final V7 v) { - return v._6(); - } - }; + return v -> v._6(); } /** @@ -399,11 +367,7 @@ public A f(final V7 v) { * @return a function that gets the seventh element of a given vector. */ public static F, A> __7() { - return new F, A>() { - public A f(final V7 v) { - return v._7(); - } - }; + return v -> v._7(); } } diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index b29635d0..d4995914 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -312,11 +312,7 @@ public V8> vzip(final V8 bs) { * @return a function that transforms a vector-8 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V8 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -325,11 +321,7 @@ public Stream f(final V8 v) { * @return a function that transforms a vector-8 to the equivalent product-8. */ public static F, P8> p_() { - return new F, P8>() { - public P8 f(final V8 v) { - return v.p(); - } - }; + return v -> v.p(); } @@ -339,11 +331,7 @@ public P8 f(final V8 v) { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return new F, A>() { - public A f(final V8 v) { - return v._1(); - } - }; + return v -> v._1(); } /** @@ -352,11 +340,7 @@ public A f(final V8 v) { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return new F, A>() { - public A f(final V8 v) { - return v._2(); - } - }; + return v -> v._2(); } /** @@ -365,11 +349,7 @@ public A f(final V8 v) { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return new F, A>() { - public A f(final V8 v) { - return v._3(); - } - }; + return v -> v._3(); } /** @@ -378,11 +358,7 @@ public A f(final V8 v) { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return new F, A>() { - public A f(final V8 v) { - return v._4(); - } - }; + return v -> v._4(); } /** @@ -391,11 +367,7 @@ public A f(final V8 v) { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return new F, A>() { - public A f(final V8 v) { - return v._5(); - } - }; + return v -> v._5(); } /** @@ -404,11 +376,7 @@ public A f(final V8 v) { * @return a function that gets the sixth element of a given vector. */ public static F, A> __6() { - return new F, A>() { - public A f(final V8 v) { - return v._6(); - } - }; + return v -> v._6(); } /** @@ -417,11 +385,7 @@ public A f(final V8 v) { * @return a function that gets the seventh element of a given vector. */ public static F, A> __7() { - return new F, A>() { - public A f(final V8 v) { - return v._7(); - } - }; + return v -> v._7(); } /** @@ -430,11 +394,7 @@ public A f(final V8 v) { * @return a function that gets the eighth element of a given vector. */ public static F, A> __8() { - return new F, A>() { - public A f(final V8 v) { - return v._8(); - } - }; + return v -> v._8(); } } From 3ce11a91f3f09ae4682cdb59083f4c37c36c675a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 00:33:41 +1000 Subject: [PATCH 393/811] Converted fj.function to use lambdas --- .../main/java/fj/function/BigIntegers.java | 42 ++----- .../src/main/java/fj/function/Characters.java | 105 +++++------------- core/src/main/java/fj/function/Doubles.java | 65 ++--------- core/src/main/java/fj/function/Integers.java | 59 ++-------- core/src/main/java/fj/function/Longs.java | 25 +---- core/src/main/java/fj/function/Strings.java | 79 ++++--------- core/src/main/java/fj/function/Visitor.java | 6 +- 7 files changed, 84 insertions(+), 297 deletions(-) diff --git a/core/src/main/java/fj/function/BigIntegers.java b/core/src/main/java/fj/function/BigIntegers.java index 2fd04a76..b60d29f4 100644 --- a/core/src/main/java/fj/function/BigIntegers.java +++ b/core/src/main/java/fj/function/BigIntegers.java @@ -22,68 +22,40 @@ private BigIntegers() { * Curried Integer addition. */ public static final F> add = - curry(new F2() { - public BigInteger f(final BigInteger a1, final BigInteger a2) { - return a1.add(a2); - } - }); + curry((a1, a2) -> a1.add(a2)); /** * Curried Integer multiplication. */ public static final F> multiply = - curry(new F2() { - public BigInteger f(final BigInteger a1, final BigInteger a2) { - return a1.multiply(a2); - } - }); + curry((a1, a2) -> a1.multiply(a2)); /** * Curried Integer subtraction. */ public static final F> subtract = - curry(new F2() { - public BigInteger f(final BigInteger a1, final BigInteger a2) { - return a1.subtract(a2); - } - }); + curry((a1, a2) -> a1.subtract(a2)); /** * Negation. */ - public static final F negate = new F() { - public BigInteger f(final BigInteger i) { - return i.negate(); - } - }; + public static final F negate = i -> i.negate(); /** * Absolute value. */ - public static final F abs = new F() { - public BigInteger f(final BigInteger i) { - return i.abs(); - } - }; + public static final F abs = i -> i.abs(); /** * Remainder. */ public static final F> remainder = - curry(new F2() { - public BigInteger f(final BigInteger a1, final BigInteger a2) { - return a1.remainder(a2); - } - }); + curry((a1, a2) -> a1.remainder(a2)); /** * Power. */ - public static final F> power = curry(new F2() { - public BigInteger f(final BigInteger a1, final Integer a2) { - return a1.pow(a2); - } - }); + public static final F> power = curry((a1, a2) -> a1.pow(a2)); /** * Sums a list of big integers. diff --git a/core/src/main/java/fj/function/Characters.java b/core/src/main/java/fj/function/Characters.java index 3c5a57af..8aebde7b 100644 --- a/core/src/main/java/fj/function/Characters.java +++ b/core/src/main/java/fj/function/Characters.java @@ -12,82 +12,31 @@ public final class Characters { private Characters() { throw new UnsupportedOperationException(); } - public static final F toString = new F() { - public String f(final Character c) {return Character.toString(c);} - }; - public static final F isLowerCase = new F() { - public Boolean f(final Character ch) {return Character.isLowerCase(ch);} - }; - public static final F isUpperCase = new F() { - public Boolean f(final Character ch) {return Character.isUpperCase(ch);} - }; - public static final F isTitleCase = new F() { - public Boolean f(final Character ch) {return Character.isTitleCase(ch);} - }; - public static final F isDigit = new F() { - public Boolean f(final Character ch) {return Character.isDigit(ch);} - }; - public static final F isDefined = new F() { - public Boolean f(final Character ch) {return Character.isDefined(ch);} - }; - public static final F isLetter = new F() { - public Boolean f(final Character ch) {return Character.isLetter(ch);} - }; - public static final F isLetterOrDigit = new F() { - public Boolean f(final Character ch) {return Character.isLetterOrDigit(ch);} - }; - public static final F isJavaIdentifierStart = new F() { - public Boolean f(final Character ch) {return Character.isJavaIdentifierStart(ch);} - }; - public static final F isJavaIdentifierPart = new F() { - public Boolean f(final Character ch) {return Character.isJavaIdentifierPart(ch);} - }; - public static final F isUnicodeIdentifierStart = new F() { - public Boolean f(final Character ch) {return Character.isUnicodeIdentifierStart(ch);} - }; - public static final F isUnicodeIdentifierPart = new F() { - public Boolean f(final Character ch) {return Character.isUnicodeIdentifierPart(ch);} - }; - public static final F isIdentifierIgnorable = new F() { - public Boolean f(final Character ch) {return Character.isIdentifierIgnorable(ch);} - }; - public static final F toLowerCase = new F() { - public Character f(final Character ch) {return Character.toLowerCase(ch);} - }; - public static final F toUpperCase = new F() { - public Character f(final Character ch) {return Character.toUpperCase(ch);} - }; - public static final F toTitleCase = new F() { - public Character f(final Character ch) {return Character.toTitleCase(ch);} - }; - public static final F> digit = curry(new F2() { - public Integer f(final Character ch, final Integer radix) {return Character.digit(ch, radix);} - }); - public static final F getNumericValue = new F() { - public Integer f(final Character ch) {return Character.getNumericValue(ch);} - }; - public static final F isSpaceChar = new F() { - public Boolean f(final Character ch) {return Character.isSpaceChar(ch);} - }; - public static final F isWhitespace = new F() { - public Boolean f(final Character ch) {return Character.isWhitespace(ch);} - }; - public static final F isISOControl = new F() { - public Boolean f(final Character ch) {return Character.isISOControl(ch);} - }; - public static final F getType = new F() { - public Integer f(final Character ch) {return Character.getType(ch);} - }; - public static final F getDirectionality = new F() { - public Byte f(final Character ch) {return Character.getDirectionality(ch);} - }; - public static final F isMirrored = new F() { - public Boolean f(final Character ch) {return Character.isMirrored(ch);} - }; - public static final F reverseBytes = new F() { - public Character f(final Character ch) {return Character.reverseBytes(ch);} - }; - public static final F isNewLine = new F() { - public Boolean f(final Character c) { return c == '\n'; } - }; + public static final F toString = c -> Character.toString(c); + public static final F isLowerCase = ch -> Character.isLowerCase(ch); + public static final F isUpperCase = ch -> Character.isUpperCase(ch); + public static final F isTitleCase = ch -> Character.isTitleCase(ch); + public static final F isDigit = ch -> Character.isDigit(ch); + public static final F isDefined = ch -> Character.isDefined(ch); + public static final F isLetter = ch -> Character.isLetter(ch); + public static final F isLetterOrDigit = ch -> Character.isLetterOrDigit(ch); + public static final F isJavaIdentifierStart = ch -> Character.isJavaIdentifierStart(ch); + public static final F isJavaIdentifierPart = ch -> Character.isJavaIdentifierPart(ch); + public static final F isUnicodeIdentifierStart = ch -> Character.isUnicodeIdentifierStart(ch); + public static final F isUnicodeIdentifierPart = ch -> Character.isUnicodeIdentifierPart(ch); + public static final F isIdentifierIgnorable = ch -> Character.isIdentifierIgnorable(ch); + public static final F toLowerCase = ch -> Character.toLowerCase(ch); + public static final F toUpperCase = ch -> Character.toUpperCase(ch); + public static final F toTitleCase = ch -> Character.toTitleCase(ch); + public static final F> digit = curry((ch, radix) -> Character.digit(ch, radix)); + public static final F getNumericValue = ch -> Character.getNumericValue(ch); + public static final F isSpaceChar = ch -> Character.isSpaceChar(ch); + public static final F isWhitespace = ch -> Character.isWhitespace(ch); + public static final F isISOControl = ch -> Character.isISOControl(ch); + public static final F getType = ch -> Character.getType(ch); + public static final F getDirectionality = ch -> Character.getDirectionality(ch); + public static final F isMirrored = ch -> Character.isMirrored(ch); + public static final F reverseBytes = ch -> Character.reverseBytes(ch); + public static final F isNewLine = c -> c == '\n'; + } diff --git a/core/src/main/java/fj/function/Doubles.java b/core/src/main/java/fj/function/Doubles.java index 51f3981b..a15a4042 100644 --- a/core/src/main/java/fj/function/Doubles.java +++ b/core/src/main/java/fj/function/Doubles.java @@ -36,56 +36,32 @@ private Doubles() { /** * Curried Double subtraction. */ - public static final F> subtract = curry(new F2() { - public Double f(final Double x, final Double y) { - return x - y; - } - }); + public static final F> subtract = curry((x, y) -> x - y); /** * Negation. */ - public static final F negate = new F() { - public Double f(final Double x) { - return x * -1; - } - }; + public static final F negate = x -> x * -1; /** * Absolute value. */ - public static final F abs = new F() { - public Double f(final Double x) { - return abs(x); - } - }; + public static final F abs = x -> abs(x); /** * Remainder. */ - public static final F> remainder = curry(new F2() { - public Double f(final Double a, final Double b) { - return a % b; - } - }); + public static final F> remainder = curry((a, b) -> a % b); /** * Power. */ - public static final F> power = curry(new F2() { - public Double f(final Double a, final Double b) { - return StrictMath.pow(a, b); - } - }); + public static final F> power = curry((a, b) -> StrictMath.pow(a, b)); /** * Evenness. */ - public static final F even = new F() { - public Boolean f(final Double i) { - return i % 2 == 0; - } - }; + public static final F even = i -> i % 2 == 0; /** * Sums a list of doubles. @@ -113,49 +89,32 @@ public static double product(final List doubles) { * @return A function that converts strings to doubles. */ public static F> fromString() { - return new F>() { - public Option f(final String s) { + return s -> { try { return some(Double.valueOf(s)); } catch (final NumberFormatException ignored) { return none(); } - } }; } /** * A function that returns true if the given double is greater than zero. */ - public static final F gtZero = new F() { - public Boolean f(final Double i) { - return Double.compare(i, 0) > 0; - } - }; + public static final F gtZero = i -> Double.compare(i, 0) > 0; /** * A function that returns true if the given double is greater than or equal to zero. */ - public static final F gteZero = new F() { - public Boolean f(final Double i) { - return Double.compare(i, 0) >= 0; - } - }; + public static final F gteZero = i -> Double.compare(i, 0) >= 0; /** * A function that returns true if the given double is less than zero. */ - public static final F ltZero = new F() { - public Boolean f(final Double i) { - return Double.compare(i, 0) < 0; - } - }; + public static final F ltZero = i -> Double.compare(i, 0) < 0; /** * A function that returns true if the given double is less than or equal to zero. */ - public static final F lteZero = new F() { - public Boolean f(final Double i) { - return Double.compare(i, 0) <= 0; - } - }; + public static final F lteZero = i -> Double.compare(i, 0) <= 0; + } diff --git a/core/src/main/java/fj/function/Integers.java b/core/src/main/java/fj/function/Integers.java index a9434186..70bef76f 100644 --- a/core/src/main/java/fj/function/Integers.java +++ b/core/src/main/java/fj/function/Integers.java @@ -46,47 +46,27 @@ public Integer f(final Integer x, final Integer y) { /** * Negation. */ - public static final F negate = new F() { - public Integer f(final Integer x) { - return x * -1; - } - }; + public static final F negate = x -> x * -1; /** * Absolute value. */ - public static final F abs = new F() { - public Integer f(final Integer x) { - return abs(x); - } - }; + public static final F abs = x -> abs(x); /** * Remainder. */ - public static final F> remainder = curry(new F2() { - public Integer f(final Integer a, final Integer b) { - return a % b; - } - }); + public static final F> remainder = curry((a, b) -> a % b); /** * Power. */ - public static final F> power = curry(new F2() { - public Integer f(final Integer a, final Integer b) { - return (int) StrictMath.pow(a, b); - } - }); + public static final F> power = curry((a, b) -> (int) StrictMath.pow(a, b)); /** * Evenness. */ - public static final F even = new F() { - public Boolean f(final Integer i) { - return i % 2 == 0; - } - }; + public static final F even = i -> i % 2 == 0; /** * Sums a list of integers. @@ -114,49 +94,32 @@ public static int product(final List ints) { * @return A function that converts strings to integers. */ public static F> fromString() { - return new F>() { - public Option f(final String s) { + return s -> { try { return some(Integer.valueOf(s)); } catch (final NumberFormatException ignored) { return none(); } - } }; } /** * A function that returns true if the given integer is greater than zero. */ - public static final F gtZero = new F() { - public Boolean f(final Integer i) { - return i > 0; - } - }; + public static final F gtZero = i -> i > 0; /** * A function that returns true if the given integer is greater than or equal to zero. */ - public static final F gteZero = new F() { - public Boolean f(final Integer i) { - return i >= 0; - } - }; + public static final F gteZero = i -> i >= 0; /** * A function that returns true if the given integer is less than zero. */ - public static final F ltZero = new F() { - public Boolean f(final Integer i) { - return i < 0; - } - }; + public static final F ltZero = i -> i < 0; /** * A function that returns true if the given integer is less than or equal to zero. */ - public static final F lteZero = new F() { - public Boolean f(final Integer i) { - return i <= 0; - } - }; + public static final F lteZero = i -> i <= 0; + } diff --git a/core/src/main/java/fj/function/Longs.java b/core/src/main/java/fj/function/Longs.java index d2d765a1..89c2babd 100644 --- a/core/src/main/java/fj/function/Longs.java +++ b/core/src/main/java/fj/function/Longs.java @@ -31,36 +31,21 @@ private Longs() { /** * Curried Long subtraction. */ - public static final F> subtract = curry(new F2() { - public Long f(final Long x, final Long y) { - return x - y; - } - }); + public static final F> subtract = curry((x, y) -> x - y); /** * Negation. */ - public static final F negate = new F() { - public Long f(final Long x) { - return x * -1L; - } - }; + public static final F negate = x -> x * -1L; /** * Absolute value. */ - public static final F abs = new F() { - public Long f(final Long x) { - return abs(x); - } - }; + public static final F abs = x -> abs(x); /** * Remainder. */ - public static final F> remainder = curry(new F2() { - public Long f(final Long a, final Long b) { - return a % b; - } - }); + public static final F> remainder = curry((a, b) -> a % b); + } diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index 02558450..59562cfc 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -20,7 +20,21 @@ private Strings() { public static final String lineSeparator = System.getProperty("line.separator"); - /** + /** + * This function checks if a given String is neither null nor empty. + * + * @see #isNullOrEmpty + */ + public static final F isNotNullOrEmpty = a -> a != null && a.length() > 0; + + /** + * This function checks if a given String is null or empty ({@link String#isEmpty()}). + * + * @see #isNotNullOrEmpty + */ + public static final F isNullOrEmpty = a -> a == null || a.length() == 0; + + /** * This function checks if a given String contains any non-whitespace character * (according to {@link Character#isWhitespace(char)}) and if it's also not * null and not empty (""). @@ -29,13 +43,7 @@ private Strings() { * @see Character#isWhitespace(char) * @see Characters#isWhitespace */ - public static final F isNotNullOrBlank = new F() { - @Override - public Boolean f(final String a) { - return isNotNullOrEmpty.f(a) && Stream.fromString(a).find(not(isWhitespace)).isSome(); - } - }; - + public static final F isNotNullOrBlank = a -> isNotNullOrEmpty.f(a) && Stream.fromString(a).find(not(isWhitespace)).isSome(); /** * This function checks if a given String is whitespace (according to {@link Character#isWhitespace(char)}), * empty ("") or null. @@ -44,74 +52,29 @@ public Boolean f(final String a) { * @see Character#isWhitespace(char) * @see Characters#isWhitespace */ - public static final F isNullOrBlank = new F() { - @Override - public Boolean f(final String a) { - return isNullOrEmpty.f(a) || Stream.fromString(a).find(not(isWhitespace)).isNone(); - } - }; - - /** - * This function checks if a given String is neither null nor empty. - * - * @see #isNullOrEmpty - */ - public static final F isNotNullOrEmpty = new F() { - @Override - public Boolean f(final String a) { - return a != null && a.length() > 0; - } - }; - - /** - * This function checks if a given String is null or empty ({@link String#isEmpty()}). - * - * @see #isNotNullOrEmpty - */ - public static final F isNullOrEmpty = new F() { - @Override - public Boolean f(final String a) { - return a == null || a.length() == 0; - } - }; + public static final F isNullOrBlank = a -> isNullOrEmpty.f(a) || Stream.fromString(a).find(not(isWhitespace)).isNone(); /** * A curried version of {@link String#isEmpty()}. */ - public static final F isEmpty = new F() { - public Boolean f(final String s) { - return s.length() == 0; - } - }; + public static final F isEmpty = s -> s.length() == 0; /** * A curried version of {@link String#length()}. */ - public static final F length = new F() { - public Integer f(final String s) { - return s.length(); - } - }; + public static final F length = s -> s.length(); /** * A curried version of {@link String#contains(CharSequence)}. * The function returns true if the second argument contains the first. */ - public static final F> contains = curry(new F2() { - public Boolean f(final String s1, final String s2) { - return s2.contains(s1); - } - }); + public static final F> contains = curry((s1, s2) -> s2.contains(s1)); /** * A curried version of {@link String#matches(String)}. * The function returns true if the second argument matches the first. */ - public static final F> matches = curry(new F2() { - public Boolean f(final String s1, final String s2) { - return s2.matches(s1); - } - }); + public static final F> matches = curry((s1, s2) -> s2.matches(s1)); public static List lines(String s) { return List.list(s.split("\\r?\\n")); diff --git a/core/src/main/java/fj/function/Visitor.java b/core/src/main/java/fj/function/Visitor.java index 211c4e16..2e3a2187 100644 --- a/core/src/main/java/fj/function/Visitor.java +++ b/core/src/main/java/fj/function/Visitor.java @@ -71,11 +71,7 @@ public static B visitor(final List>> visitors, final F0 * given default. */ public static B nullableVisitor(final List> visitors, final F0 def, final A value) { - return visitor(visitors.map(new F, F>>() { - public F> f(final F k) { - return compose(Option.fromNull(), k); - } - }), def, value); + return visitor(visitors.map(k -> compose(Option.fromNull(), k)), def, value); } /** From d2449303f50776d7428469b35930d7b8a6b468b0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 00:35:28 +1000 Subject: [PATCH 394/811] Converted fj.parser to use lambdas --- core/src/main/java/fj/parser/Result.java | 25 +++++------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/fj/parser/Result.java b/core/src/main/java/fj/parser/Result.java index b088b4c6..bcec7d8b 100644 --- a/core/src/main/java/fj/parser/Result.java +++ b/core/src/main/java/fj/parser/Result.java @@ -55,11 +55,7 @@ public Result mapRest(final F f) { * @return A first-class function mapping across the remainder of the parse input. */ public F, Result> mapRest() { - return new F, Result>() { - public Result f(final F f) { - return mapRest(f); - } - }; + return f -> mapRest(f); } /** @@ -78,11 +74,7 @@ public Result mapValue(final F f) { * @return A first-class function mapping across the parse value. */ public F, Result> mapValue() { - return new F, Result>() { - public Result f(final F f) { - return mapValue(f); - } - }; + return f -> mapValue(f); } /** @@ -102,11 +94,7 @@ public Result bimap(final F f, final F g) { * @return A first-class bifunctor map. */ public F, F, Result>> bimap() { - return curry(new F2, F, Result>() { - public Result f(final F f, final F g) { - return bimap(f, g); - } - }); + return curry((f, g) -> bimap(f, g)); } /** @@ -154,10 +142,7 @@ public static Result result(final I i, final A a) { * @return A first-class function for construction of a result. */ public static F>> result() { - return curry(new F2>() { - public Result f(final I i, final A a) { - return result(i, a); - } - }); + return curry((i, a) -> result(i, a)); } + } From 96ace09cfb72aad9c5a4a6a98a59dd86347315dd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 01:13:16 +1000 Subject: [PATCH 395/811] Convert demo to use lambdas --- demo/src/main/java/fj/demo/Array_bind.java | 6 +- demo/src/main/java/fj/demo/ChequeWrite.java | 36 ++------ .../main/java/fj/demo/Comonad_example.java | 11 +-- demo/src/main/java/fj/demo/Option_bind.java | 18 +--- demo/src/main/java/fj/demo/Set_map.java | 6 +- .../java/fj/demo/concurrent/MapReduce.java | 12 +-- .../java/fj/demo/concurrent/WordCount.java | 92 +++---------------- .../src/main/java/fj/demo/euler/Problem1.java | 4 +- .../src/main/java/fj/demo/euler/Problem3.java | 9 +- .../src/main/java/fj/demo/euler/Problem4.java | 4 +- .../java/fj/demo/test/EqualsHashCode.java | 6 +- .../java/fj/demo/test/ListFunctorLaws.java | 10 +- demo/src/main/java/fj/demo/test/Reflect.java | 35 ++----- .../fj/demo/test/StringBuilderReverse.java | 16 +--- .../main/java/fj/demo/test/Triangulation.java | 6 +- 15 files changed, 55 insertions(+), 216 deletions(-) diff --git a/demo/src/main/java/fj/demo/Array_bind.java b/demo/src/main/java/fj/demo/Array_bind.java index bbbdcd95..a0182dd1 100644 --- a/demo/src/main/java/fj/demo/Array_bind.java +++ b/demo/src/main/java/fj/demo/Array_bind.java @@ -9,11 +9,7 @@ public final class Array_bind { public static void main(final String[] args) { final Array a = array(97, 44, 67, 3, 22, 90, 1, 77, 98, 1078, 6, 64, 6, 79, 42); - final Array b = a.bind(new F>() { - public Array f(final Integer i) { - return array(500, i); - } - }); + final Array b = a.bind(i -> array(500, i)); arrayShow(intShow).println(b); // {500,97,500,44,500,67,500,3,500,22,500,90,500,1,500,77,500,98,500,1078,500,6,500,64,500,6,500,79,500,42} } diff --git a/demo/src/main/java/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java index e95950f8..44ee2956 100644 --- a/demo/src/main/java/fj/demo/ChequeWrite.java +++ b/demo/src/main/java/fj/demo/ChequeWrite.java @@ -25,11 +25,7 @@ public final class ChequeWrite { private ChequeWrite() {} static List toZero(final int from) { - return unfold(new F>>() { - public Option> f(final Integer i) { - return i < 0 ? Option.>none() : some(p(i, i - 1)); - } - }, from); + return unfold(i -> i < 0 ? Option.>none() : some(p(i, i - 1)), from); } static int signum(final int i) { @@ -80,12 +76,9 @@ static List show(final List cs) { static List, Integer>> split(final List as) { final int len = as.length(); - final List> ds = as.zip(toZero(len - 1)).foldRight(new F2, List>, List>>() { - public List> f(final P2 ki, final List> z) { - return ki._2() % 3 == 0 ? z.conss(single(ki._1())) : z.tail().conss(z.head().cons(ki._1())); - } - }, List.>nil()); - + final List> ds = as.zip(toZero(len - 1)).foldRight((ki, z) -> + ki._2() % 3 == 0 ? z.conss(single(ki._1())) : z.tail().conss(z.head().cons(ki._1())), List.>nil() + ); return ds.zip(toZero(len / 3 + signum(len % 3) - 1)); } @@ -103,19 +96,14 @@ static boolean and(final List cs) { } static boolean existsNotZero(final List cs) { - return cs.exists(new F() { - public Boolean f(final Character c) { - return c != '0'; - } - }); + return cs.exists(c -> c != '0'); } static boolean eq(final List a, final List b) { return listEqual(charEqual).eq(a, b); } - static final F, List> dollars = new F, List>() { - public List f(final List cs) { + static final F, List> dollars = cs -> { if (cs.isEmpty()) return fromString("zero dollars"); else { @@ -144,25 +132,19 @@ public void f(final P2, Integer> z) { return fromString(" ").intercalate(x.toList()); } - } + }; - static final F, List> cents = new F, List>() { - public List f(final List a) { + static final F, List> cents = a -> { final int n = a.length(); return n == 0 ? fromString("zero cents") : show(list(a.head(), n == 1 ? '0' : a.tail().head())) .append(fromString(eq(a, list('0', '1')) ? " cent" : " cents")); - } }; public static List write(final List cs) { - final F, List> dropNonDigit = new F, List>() { - public List f(final List cs) { - return cs.filter(Characters.isDigit); - } - }; + final F, List> dropNonDigit = cs2 -> cs2.filter(Characters.isDigit); final P2, List> x = cs.dropWhile(charEqual.eq('0')).breakk(charEqual.eq('.')).map1(dropNonDigit).map1(dollars).map2(dropNonDigit) .map2(List.take().f(2)).map2(cents); diff --git a/demo/src/main/java/fj/demo/Comonad_example.java b/demo/src/main/java/fj/demo/Comonad_example.java index a52b8957..70230e1d 100644 --- a/demo/src/main/java/fj/demo/Comonad_example.java +++ b/demo/src/main/java/fj/demo/Comonad_example.java @@ -25,12 +25,11 @@ public static void main(final String[] args) { public static Stream> perms(final Stream s) { Stream> r = single(Stream.nil()); for (final Zipper z : fromStream(s)) - r = join(z.cobind(new F, Stream>>() { - public Stream> f(final Zipper zp) { - return perms(zp.lefts().reverse().append(zp.rights())) - .map(F1Functions.o(Stream.cons().f(zp.focus()), P.>p1())); - } - }).toStream()); + r = join(z.cobind(zp -> + perms(zp.lefts().reverse().append(zp.rights())).map( + F1Functions.o(Stream.cons().f(zp.focus()), P.>p1()) + ) + ).toStream()); return r; } } diff --git a/demo/src/main/java/fj/demo/Option_bind.java b/demo/src/main/java/fj/demo/Option_bind.java index 96ecf153..d02a1493 100644 --- a/demo/src/main/java/fj/demo/Option_bind.java +++ b/demo/src/main/java/fj/demo/Option_bind.java @@ -18,21 +18,9 @@ public static void main(final String[] args) { final Option o5 = o2.bind(f); final Option o6 = o3.bind(f); - final Option p1 = o1.bind(new F>() { - public Option f(final Integer i) { - return i % 2 == 0 ? some(i * 3) : Option.none(); - } - }); - final Option p2 = o2.bind(new F>() { - public Option f(final Integer i) { - return i % 2 == 0 ? some(i * 3) : Option.none(); - } - }); - final Option p3 = o3.bind(new F>() { - public Option f(final Integer i) { - return i % 2 == 0 ? some(i * 3) : Option.none(); - } - }); + final Option p1 = o1.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p2 = o2.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p3 = o3.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); optionShow(intShow).println(o4); // None optionShow(intShow).println(o5); // Some(24) diff --git a/demo/src/main/java/fj/demo/Set_map.java b/demo/src/main/java/fj/demo/Set_map.java index 592057ca..ff5428df 100644 --- a/demo/src/main/java/fj/demo/Set_map.java +++ b/demo/src/main/java/fj/demo/Set_map.java @@ -10,11 +10,7 @@ public final class Set_map { public static void main(final String[] args) { final Set a = empty(Ord.intOrd).insert(1).insert(2).insert(3).insert(4).insert(5).insert(6); - final Set b = a.map(Ord.intOrd, new F() { - public Integer f(final Integer i) { - return i / 2; // divide each integer by 2 - } - }); + final Set b = a.map(Ord.intOrd, i -> i / 2); listShow(intShow).println(b.toList()); // [3,2,1,0] } } diff --git a/demo/src/main/java/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java index fd8b5282..9bfee40d 100644 --- a/demo/src/main/java/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -28,24 +28,20 @@ public class MapReduce { // Count words of documents in parallel public static Promise countWords(final List> documents, final ParModule m) { - return m.parFoldMap(documents, new F, Long>() { - public Long f(final Stream document) { - return (long) fromStream(document).words().length(); - } - }, longAdditionMonoid); + return m.parFoldMap(documents, + document -> (long) fromStream(document).words().length(), longAdditionMonoid + ); } // Main program does the requisite IO gymnastics public static void main(final String[] args) { final List> documents = list(args).map( - F1Functions.andThen(new F() { - public BufferedReader f(final String fileName) { + F1Functions.andThen(fileName -> { try { return new BufferedReader(new FileReader(new File(fileName))); } catch (FileNotFoundException e) { throw new Error(e); } - } }, new F>() { public Stream f(final BufferedReader reader) { final Option s; diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 277ca9dc..4af1a818 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -43,12 +43,7 @@ public class WordCount { // Integers.add.f(1) caused an SOE... - private static final F addOne = new F() { - @Override - public Integer f(Integer a) { - return a.intValue() + 1; - } - }; + private static final F addOne = a -> a.intValue() + 1; private static Map update(Map map, K key, F valueFunction, V initialValue) { @@ -60,37 +55,28 @@ private static Map update(Map map, K key, F valueFuncti return map; } - private static final F> fileNameToWordsAndCountsWithCharChunkIteratee = new F>() { - @Override - public Map f(final String fileName) { + private static final F> fileNameToWordsAndCountsWithCharChunkIteratee = fileName -> { try { return IOFunctions.enumFileCharChunks(new File(fileName), Option.none(), wordCountsFromCharChunks()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } - } }; - private static final F> fileNameToWordsAndCountsWithCharChunk2Iteratee = new F>() { - @Override - public Map f(final String fileName) { + private static final F> fileNameToWordsAndCountsWithCharChunk2Iteratee = fileName -> { try { return IOFunctions.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } - } }; - private static final F> fileNameToWordsAndCountsWithCharIteratee = new F>() { - @Override - public Map f(final String fileName) { + private static final F> fileNameToWordsAndCountsWithCharIteratee = fileName -> { try { return IOFunctions.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } - } }; /** An iteratee that consumes char chunks and calculates word counts */ @@ -145,12 +131,7 @@ public IterV> _1() { return IterV.done(acc._2(), Input.eof()); } }; - return new F, IterV>>() { - @Override - public IterV> f(final Input s) { - return s.apply(empty, el, eof); - } - }; + return s -> s.apply(empty, el, eof); } }; return IterV.cont(step.f(P.p(new StringBuilder(), (Map)new HashMap()))); @@ -164,20 +145,10 @@ public static final IterV> wordCountsFromCha @Override public F, IterV>> f(final P2> acc) { - final P1>> empty = - new P1>>() { - @Override - public IterV> _1() { - return IterV.cont(step.f(acc)); - } - }; + final P1>> empty = P.lazy(() -> IterV.cont(step.f(acc))); final P1>>> el = - new P1>>>() { - @Override - public F>> _1() { - return new F>>() { - @Override - public IterV> f(final Character e) { + P.lazy(() -> { + return e -> { if(Character.isWhitespace(e.charValue())) { final StringBuilder sb = acc._1(); if(sb.length() > 0) { @@ -193,14 +164,9 @@ public IterV> f(final Character e) { acc._1().append(e); return IterV.cont(step.f(acc)); } - } }; - } - }; - final P1>> eof = - new P1>>() { - @Override - public IterV> _1() { + }); + final P1>> eof = P.lazy(() -> { final StringBuilder sb = acc._1(); if(sb.length() > 0) { final Map map = update(acc._2(), sb.toString(), addOne, Integer.valueOf(0)); @@ -208,13 +174,8 @@ public IterV> _1() { } return IterV.done(acc._2(), Input.eof()); } - }; - return new F, IterV>>() { - @Override - public IterV> f(final Input s) { - return s.apply(empty, el, eof); - } - }; + ); + return s -> s.apply(empty, el, eof); } }; return IterV.cont(step.f(P.p(new StringBuilder(), (Map)new HashMap()))); @@ -229,11 +190,7 @@ public static void main(String[] args) throws IOException { final P2, Map> result = writeSampleFiles(numFiles, numSharedWords); final List fileNames = result._1(); final Map expectedWordsAndCounts = result._2(); - long avgSize = fileNames.foldLeft(new F2() { - @Override - public Long f(Long a, String file) { - return a.longValue() + new File(file).length(); - }}, 0l) / fileNames.length(); + long avgSize = fileNames.foldLeft((a, file) -> a.longValue() + new File(file).length(), 0l) / fileNames.length(); System.out.println("Processing " + numFiles + " files with ~"+numSharedWords+" words and an avg size of " + avgSize + " bytes."); // warmup @@ -349,12 +306,7 @@ private static P2, Map> writeSampleFiles( public static Map getWordsAndCountsFromFilesWithIteratee(final List fileNames, final F> fileNameToWordsAndCountsWithIteratee) { final List> maps = fileNames.map(fileNameToWordsAndCountsWithIteratee); - return maps.foldLeft(new F2, Map, Map>() { - @Override - public Map f(Map a, Map b) { - return plus(a, b); - } - }, new HashMap()); + return maps.foldLeft((Map a, Map b) -> plus(a, b), new HashMap()); } public static Map getWordsAndCountsFromFilesInParallel( @@ -374,21 +326,7 @@ public static Map getWordsAndCountsFromFilesInParallel( public static Promise> getWordsAndCountsFromFiles( final List fileNames, final F> fileNameToWordsAndCounts, final ParModule m) { final F, F, Map>> MapSum = - new F, F, Map>>() { - @Override - public F, Map> f( - final Map a) { - return new F, Map>() { - - @Override - public Map f(final Map b) { - return plus(a, b); - } - - }; - } - - }; + a -> b -> plus(a, b); final Monoid> monoid = monoid(MapSum, new HashMap()); return m.parFoldMap(fileNames, fileNameToWordsAndCounts, monoid); diff --git a/demo/src/main/java/fj/demo/euler/Problem1.java b/demo/src/main/java/fj/demo/euler/Problem1.java index cebdf9fa..82dc53c0 100644 --- a/demo/src/main/java/fj/demo/euler/Problem1.java +++ b/demo/src/main/java/fj/demo/euler/Problem1.java @@ -18,9 +18,7 @@ public static void main(final String[] args) { } public static void java7() { - out.println(sum(range(0, 1000).filter(new F() { - public Boolean f(final Integer a) { return a % 3 == 0 || a % 5 == 0;} - }))); + out.println(sum(range(0, 1000).filter(a -> a % 3 == 0 || a % 5 == 0))); } public static void java8() { diff --git a/demo/src/main/java/fj/demo/euler/Problem3.java b/demo/src/main/java/fj/demo/euler/Problem3.java index c3c6dde1..8276239d 100644 --- a/demo/src/main/java/fj/demo/euler/Problem3.java +++ b/demo/src/main/java/fj/demo/euler/Problem3.java @@ -1,6 +1,7 @@ package fj.demo.euler; import fj.F; +import fj.P; import fj.P1; import static fj.data.Enumerator.naturalEnumerator; import fj.data.Natural; @@ -17,13 +18,7 @@ */ public class Problem3 { // An infinite stream of all the primes. - public static final Stream primes = cons(natural(2).some(), new P1>() { - public Stream _1() { - return forever(naturalEnumerator, natural(3).some(), 2).filter(new F() { - public Boolean f(final Natural n) {return primeFactors(n).length() == 1;} - }); - } - }); + public static final Stream primes = cons(natural(2).some(), P.lazy(() -> forever(naturalEnumerator, natural(3).some(), 2).filter(n -> primeFactors(n).length() == 1))); //Finds factors of a given number. public static Stream factor(final Natural n, final Natural p, final P1> ps) { diff --git a/demo/src/main/java/fj/demo/euler/Problem4.java b/demo/src/main/java/fj/demo/euler/Problem4.java index c021d920..f1947057 100644 --- a/demo/src/main/java/fj/demo/euler/Problem4.java +++ b/demo/src/main/java/fj/demo/euler/Problem4.java @@ -17,11 +17,9 @@ public class Problem4 { public static void main(final String[] a) { final Stream tdl = iterate(flip(subtract).f(1), 999).takeWhile(intOrd.isGreaterThan(99)); - intShow.println(tdl.tails().bind(tdl.zipWith(multiply)).filter(new F() { - public Boolean f(final Integer i) { + intShow.println(tdl.tails().bind(tdl.zipWith(multiply)).filter(i -> { final Stream s = intShow.show(i); return streamEqual(charEqual).eq(s.reverse().take(3), s.take(3)); - } }).foldLeft1(intOrd.max)); } } diff --git a/demo/src/main/java/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java index 3b0d8fbf..bc150fa7 100644 --- a/demo/src/main/java/fj/demo/test/EqualsHashCode.java +++ b/demo/src/main/java/fj/demo/test/EqualsHashCode.java @@ -58,11 +58,7 @@ public int hashCode() { public static void main(final String[] args) { // Restrictive arbitrary for Byte, produces from three possible values. - final Arbitrary arbByteR = arbitrary(arbByte.gen.map(new F() { - public Byte f(final Byte b) { - return (byte)(b % 3); - } - })); + final Arbitrary arbByteR = arbitrary(arbByte.gen.map(b -> (byte)(b % 3))); // Restrictive arbitrary for String, produces from twelve (2 * 3 * 2) possible values. final Arbitrary arbStringR = arbitrary(arbCharacter.gen.bind(arbCharacter.gen, arbCharacter.gen, curry(new F3() { diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index edf94ed8..b2c230a5 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -42,18 +42,12 @@ For any list, mapping the identity function (\x -> x) produces the same list. @SuppressWarnings({"PackageVisibleField"}) @CheckParams(minSuccessful = 1000) public final class ListFunctorLaws { - final Property identity = property(arbList(arbString), new F, Property>() { - public Property f(final List x) { - return prop(listEqual(stringEqual).eq(x, x.map(Function.identity()))); - } - }); + final Property identity = property(arbList(arbString), x -> prop(listEqual(stringEqual).eq(x, x.map(Function.identity())))); - final Property composition = property(arbF(coarbInteger, arbString), arbF(coarbLong, arbInteger), arbList(arbLong), new F3, F, List, Property>() { - public Property f(final F f, final F g, final List x) { + final Property composition = property(arbF(coarbInteger, arbString), arbF(coarbLong, arbInteger), arbList(arbLong), (f, g, x) -> { final List s1 = x.map(compose(f, g)); final List s2 = x.map(g).map(f); return prop(listEqual(stringEqual).eq(s1, s2)); - } }); // identity: OK, passed 1000 tests. diff --git a/demo/src/main/java/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java index f83b8ce8..8831314e 100644 --- a/demo/src/main/java/fj/demo/test/Reflect.java +++ b/demo/src/main/java/fj/demo/test/Reflect.java @@ -52,53 +52,30 @@ public final class Reflect { @Name("Integer Addition Commutes") @Category("Passes for demo") @CheckParams(minSuccessful = 20) - final Property p1 = property(arbInteger, arbInteger, new F2() { - public Property f(final Integer a, final Integer b) { - return prop(a + b == b + a); - } - }); + final Property p1 = property(arbInteger, arbInteger, (a, b) -> prop(a + b == b + a)); @Name("Natural Integer Addition yields Natural Integer") @Category("Fails for demo") - final Property p2 = property(arbIntegerBoundaries, arbIntegerBoundaries, shrinkInteger, shrinkInteger, - new F2() { - public Property f(final Integer a, final Integer b) { - return bool(a > 0 && b > 0).implies(a + b > 0); - } - }); + final Property p2 = property(arbIntegerBoundaries, arbIntegerBoundaries, shrinkInteger, shrinkInteger, (a, b) -> bool(a > 0 && b > 0).implies(a + b > 0)); @Category("Passes for demo") - final Property p3 = property(arbStringBuilder, new F() { - public Property f(final StringBuilder sb) { - return prop(stringBuilderEqual.eq(sb, sb.reverse().reverse())); - } - }); + final Property p3 = property(arbStringBuilder, sb -> prop(stringBuilderEqual.eq(sb, sb.reverse().reverse()))); @Category("Passes for demo") - final Property p4 = property(arbCharacter, new F() { - public Property f(final Character c) { - return prop(stringBuilderEqual.eq(new StringBuilder().append(c), new StringBuilder().append(c).reverse())); - } - }); + final Property p4 = property(arbCharacter, c -> prop(stringBuilderEqual.eq(new StringBuilder().append(c), new StringBuilder().append(c).reverse()))); @Category("Passes for demo") @CheckParams(minSuccessful = 750, maxSize = 40) - final Property p5 = property(arbStringBuilder, arbStringBuilder, new F2() { - public Property f(final StringBuilder x, final StringBuilder y) { + final Property p5 = property(arbStringBuilder, arbStringBuilder, (x, y) -> { // copy the string builders before performing updates on x and y. final StringBuilder xx = new StringBuilder(x); final StringBuilder yy = new StringBuilder(y); return prop(stringBuilderEqual.eq(x.append(y).reverse(), yy.reverse().append(xx.reverse()))); - } }); @Name("Triangulation") @Category("Fails for demo") - final Property p6 = property(arbInteger, new F() { - public Property f(final Integer a) { - return prop(Triangulation.isPositive(a) == (a != 0 && !Triangulation.isNegative(a))); - } - }); + final Property p6 = property(arbInteger, a -> prop(Triangulation.isPositive(a) == (a != 0 && !Triangulation.isNegative(a)))); @NoCheck Property leave() { diff --git a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java index b5155739..9338065b 100644 --- a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java +++ b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java @@ -22,25 +22,15 @@ */ public final class StringBuilderReverse { public static void main(final String[] args) { - final Property p1 = property(arbStringBuilder, new F() { - public Property f(final StringBuilder sb) { - return prop(stringBuilderEqual.eq(new StringBuilder(sb), sb.reverse().reverse())); - } - }); + final Property p1 = property(arbStringBuilder, sb -> prop(stringBuilderEqual.eq(new StringBuilder(sb), sb.reverse().reverse()))); - final Property p2 = property(arbCharacter, new F() { - public Property f(final Character c) { - return prop(stringBuilderEqual.eq(new StringBuilder().append(c), new StringBuilder().append(c).reverse())); - } - }); + final Property p2 = property(arbCharacter, c -> prop(stringBuilderEqual.eq(new StringBuilder().append(c), new StringBuilder().append(c).reverse()))); - final Property p3 = property(arbStringBuilder, arbStringBuilder, new F2() { - public Property f(final StringBuilder x, final StringBuilder y) { + final Property p3 = property(arbStringBuilder, arbStringBuilder, (x, y) -> { // copy the string builders before performing updates on x and y. final StringBuilder xx = new StringBuilder(x); final StringBuilder yy = new StringBuilder(y); return prop(stringBuilderEqual.eq(x.append(y).reverse(), yy.reverse().append(xx.reverse()))); - } }); //OK, passed 100 tests. diff --git a/demo/src/main/java/fj/demo/test/Triangulation.java b/demo/src/main/java/fj/demo/test/Triangulation.java index cc460c95..56d110f2 100644 --- a/demo/src/main/java/fj/demo/test/Triangulation.java +++ b/demo/src/main/java/fj/demo/test/Triangulation.java @@ -23,11 +23,7 @@ static boolean isPositive(final int i) { } public static void main(final String[] args) { - final Property p = property(arbInteger, new F() { - public Property f(final Integer a) { - return prop(isPositive(a) == (a != 0 && !isNegative(a))); - } - }); + final Property p = property(arbInteger, a -> prop(isPositive(a) == (a != 0 && !isNegative(a)))); summary.println(p.check()); // Falsified after 0 passed tests with argument: 0 } } From 8ddc11546badbeafb0b16bc1e0fb922b06f23079 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 08:25:28 +1000 Subject: [PATCH 396/811] Use latest Java 8 available on Travis --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1d62c9c3..943d82f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,11 @@ sudo: false jdk: - oraclejdk8 +addons: + apt: + packages: + - oracle-java8-installer + script: - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME From 0b0df0f0c85f29b03e697de5398f552bf9374f39 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 21:40:40 +1000 Subject: [PATCH 397/811] Initial jacoco test coverage --- core/build.gradle | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/build.gradle b/core/build.gradle index 1a1763e7..f526e289 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,4 +1,6 @@ +apply plugin: "jacoco" + ext { signModule = true } @@ -15,3 +17,19 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true configureAllRetroLambda() + +jacoco { + toolVersion = "0.7.1.201405082137" +} + +jacocoTestReport { + reports { + xml.enabled false + csv.enabled false + html.destination "${buildDir}/jacocoHtml" + } +} + +task coverage(dependsOn: ["test", "jacocoTestReport"]) << { + +} From 3d6779125dcf9a5ecd2794311f8f6f8791c62e12 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 26 Aug 2015 23:31:53 +1000 Subject: [PATCH 398/811] Comverted P1 to lambdas for fj root --- core/src/main/java/fj/Bottom.java | 6 ++---- core/src/main/java/fj/F2Functions.java | 12 ++---------- core/src/main/java/fj/P2.java | 6 +----- core/src/main/java/fj/Primitive.java | 12 ++---------- core/src/main/java/fj/Semigroup.java | 6 +----- .../java/fj/control/parallel/Callables.java | 18 +++++++----------- .../main/java/fj/control/parallel/Promise.java | 18 +++--------------- core/src/main/java/fj/data/vector/V4.java | 6 +----- core/src/main/java/fj/data/vector/V5.java | 18 +++--------------- core/src/test/java/fj/P1Test.java | 16 ++-------------- 10 files changed, 24 insertions(+), 94 deletions(-) diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index 6c6588fd..a9951928 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -38,11 +38,9 @@ public static Error error(final String s) { * @return A thunk that throws an error using the given message when evaluated. */ public static P1 error_(final String s) { - return new P1() { - @Override public A _1() { + return P.lazy(() -> { throw new Error(s); - } - }; + }); } /** diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index e9de58b9..3508bd70 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -142,11 +142,7 @@ static public F2, Tree, Tree> treeM(final F2 f) return new F2, Tree, Tree>() { public Tree f(final Tree as, final Tree bs) { final F2, Tree, Tree> self = this; - return node(f.f(as.root(), bs.root()), new P1>>() { - public Stream> _1() { - return streamM(self).f(as.subForest()._1(), bs.subForest()._1()); - } - }); + return node(f.f(as.root(), bs.root()), P.lazy(() -> streamM(self).f(as.subForest()._1(), bs.subForest()._1()))); } }; } @@ -217,11 +213,7 @@ static public F2, Tree, Tree> zipTreeM(final F2 return new F2, Tree, Tree>() { public Tree f(final Tree ta, final Tree tb) { final F2, Tree, Tree> self = this; - return node(f.f(ta.root(), tb.root()), new P1>>() { - public Stream> _1() { - return zipStreamM(self).f(ta.subForest()._1(), tb.subForest()._1()); - } - }); + return node(f.f(ta.root(), tb.root()), P.lazy(() -> zipStreamM(self).f(ta.subForest()._1(), tb.subForest()._1()))); } }; } diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index c3ebe8cd..58707bfb 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -187,11 +187,7 @@ public final Either> traverseEither(final F> public final Stream sequenceW(final Stream, C>> fs) { return fs.isEmpty() ? Stream.nil() - : Stream.cons(fs.head().f(this), new P1>() { - public Stream _1() { - return sequenceW(fs.tail()._1()); - } - }); + : Stream.cons(fs.head().f(this), P.lazy(() -> sequenceW(fs.tail()._1()))); } /** diff --git a/core/src/main/java/fj/Primitive.java b/core/src/main/java/fj/Primitive.java index baf2bae7..2007c03c 100644 --- a/core/src/main/java/fj/Primitive.java +++ b/core/src/main/java/fj/Primitive.java @@ -113,11 +113,7 @@ private Primitive() { /** * A function that converts characters to integers. */ - public static final F Character_Integer = new F() { - public Integer f(final Character c) { - return (int) (char) c; - } - }; + public static final F Character_Integer = c -> (int) (char) c; /** * A function that converts characters to longs. @@ -141,11 +137,7 @@ public Integer f(final Character c) { /** * A function that converts doubles to bytes. */ - public static final F Double_Byte = new F() { - public Byte f(final Double d) { - return (byte) (double) d; - } - }; + public static final F Double_Byte = d -> (byte) (double) d; /** * A function that converts doubles to characters. diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 4637ac2f..5d5db1a2 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -305,11 +305,7 @@ public static Semigroup> arraySemigroup() { * @return A semigroup for unary products. */ public static Semigroup> p1Semigroup(final Semigroup sa) { - return semigroup((a1, a2) -> new P1() { - public A _1() { - return sa.sum(a1._1(), a2._1()); - } - }); + return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()))); } /** diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index 3b4fbbee..2403adb8 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -1,11 +1,9 @@ package fj.control.parallel; -import fj.F; -import fj.F0; -import fj.F2; -import fj.Function; +import fj.*; + import static fj.Function.curry; -import fj.P1; + import fj.data.Either; import static fj.data.Either.left; import static fj.data.Either.right; @@ -196,15 +194,13 @@ public static F, P1>> option() { * @return Either the value in the given Callable, or the Exception with which the Callable fails. */ public static P1> either(final Callable a) { - return new P1>() { - public Either _1() { + return P.lazy(() -> { try { - return right(a.call()); + return right(a.call()); } catch (Exception e) { - return left(e); + return left(e); } - } - }; + }); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 20d9b68b..9f9d2431 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -97,11 +97,7 @@ public static F, Promise> promise(final Strategy s) { * @return A promise of a new Callable that will return the result of calling the given Callable. */ public static Promise> promise(final Strategy s, final Callable a) { - return promise(s, new P1>() { - public Callable _1() { - return normalise(a); - } - }); + return promise(s, P.lazy(() -> normalise(a))); } /** @@ -368,11 +364,7 @@ public boolean isFulfilled() { * @return A new promise of the result of applying the given function to this promise. */ public Promise cobind(final F, B> f) { - return promise(s, new P1() { - public B _1() { - return f.f(Promise.this); - } - }); + return promise(s, P.lazy(() -> f.f(Promise.this))); } /** @@ -394,11 +386,7 @@ public Promise> cojoin() { public Stream sequenceW(final Stream, B>> fs) { return fs.isEmpty() ? Stream.nil() - : Stream.cons(fs.head().f(this), new P1>() { - public Stream _1() { - return sequenceW(fs.tail()._1()); - } - }); + : Stream.cons(fs.head().f(this), P.lazy(() -> sequenceW(fs.tail()._1()))); } } diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 06afd0dc..c56976cd 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -289,10 +289,6 @@ public static F, A> __3() { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return new F, A>() { - public A f(final V4 v) { - return v._4(); - } - }; + return v -> v._4(); } } diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 093f9a3c..3ecdd341 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -261,11 +261,7 @@ public V5> vzip(final V5 bs) { * @return a function that transforms a vector-5 to a stream of its elements. */ public static F, Stream> toStream_() { - return new F, Stream>() { - public Stream f(final V5 v) { - return v.toStream(); - } - }; + return v -> v.toStream(); } /** @@ -274,11 +270,7 @@ public Stream f(final V5 v) { * @return a function that transforms a vector-5 to the equivalent product-5. */ public static F, P5> p_() { - return new F, P5>() { - public P5 f(final V5 v) { - return v.p(); - } - }; + return v -> v.p(); } /** @@ -305,11 +297,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return new F, A>() { - public A f(final V5 v) { - return v._3(); - } - }; + return v -> v._3(); } /** diff --git a/core/src/test/java/fj/P1Test.java b/core/src/test/java/fj/P1Test.java index 16309aae..a866e0c2 100644 --- a/core/src/test/java/fj/P1Test.java +++ b/core/src/test/java/fj/P1Test.java @@ -31,20 +31,8 @@ public void bug105() throws Exception { @Test public void bug122() throws Exception { - final P1 p1a = new P1() { - - @Override - public Integer _1() { - return 1; - } - }; - final P1 p1b = new P1() { - - @Override - public Integer _1() { - return 1; - } - }; + final P1 p1a = P.lazy(() -> 1); + final P1 p1b = P.lazy(() -> 1); org.junit.Assert.assertTrue(p1a + " and " + p1b + " should be equal by Object.equals", p1a.equals(p1b)); } From 37c4943192737b86177af1252221a20ab1c20893 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 00:43:10 +1000 Subject: [PATCH 399/811] Convert P1 to use lambdas in core fj/data --- core/src/main/java/fj/data/LazyString.java | 6 +- core/src/main/java/fj/data/List.java | 6 +- core/src/main/java/fj/data/Stream.java | 187 ++++----------------- core/src/main/java/fj/data/vector/V2.java | 19 +-- core/src/main/java/fj/data/vector/V3.java | 33 ++-- core/src/main/java/fj/data/vector/V4.java | 15 +- core/src/main/java/fj/data/vector/V5.java | 15 +- core/src/main/java/fj/data/vector/V6.java | 15 +- core/src/main/java/fj/data/vector/V7.java | 15 +- core/src/main/java/fj/data/vector/V8.java | 15 +- 10 files changed, 75 insertions(+), 251 deletions(-) diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index 3f3d660d..b13bca44 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -257,11 +257,7 @@ public Stream split(final F p) { final Stream findIt = s.dropWhile(p); final P2, Stream> ws = findIt.split(p); return findIt.isEmpty() ? Stream.nil() - : Stream.cons(fromStream(ws._1()), new P1>() { - public Stream _1() { - return fromStream(ws._2()).split(p); - } - }); + : Stream.cons(fromStream(ws._1()), P.lazy(() -> fromStream(ws._2()).split(p))); } public LazyString map(F f) { diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index b9a11bef..7adc4a07 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -704,11 +704,7 @@ public final B foldRight(final F2 f, final B b) { * @return A Trampoline containing the final result after the right-fold reduction. */ public final Trampoline foldRightC(final F2 f, final B b) { - return Trampoline.suspend(new P1>() { - public Trampoline _1() { - return isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head())); - } - }); + return Trampoline.suspend(P.lazy(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head())))); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 8e8b3f7f..3d978be8 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -111,11 +111,7 @@ public final B stream(final B nil, final F>, B>> cons) { * @return The final result after the right-fold reduction. */ public final B foldRight(final F, B>> f, final B b) { - return isEmpty() ? b : f.f(head()).f(new P1() { - public B _1() { - return tail()._1().foldRight(f, b); - } - }); + return isEmpty() ? b : f.f(head()).f(P.lazy(() -> tail()._1().foldRight(f, b))); } /** @@ -235,12 +231,8 @@ public Stream _1() { } public Stream prefix(final A x, final Stream xs) { - return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), new P1>() { - public Stream _1() { - return prefix(a, xs.tail()._1()); - } - }))); - } + return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), P.lazy(() -> prefix(a, xs.tail()._1()))))); + } }); } @@ -251,11 +243,7 @@ public Stream _1() { * @return A new stream after the given function has been applied to each element. */ public final Stream map(final F f) { - return isEmpty() ? Stream.nil() : cons(f.f(head()), new P1>() { - public Stream _1() { - return tail()._1().map(f); - } - }); + return isEmpty() ? Stream.nil() : cons(f.f(head()), () -> tail()._1().map(f)); } /** @@ -299,11 +287,7 @@ public final void foreachDoEffect(final Effect1 f) { */ public final Stream filter(final F f) { final Stream as = dropWhile(not(f)); - return as.isNotEmpty() ? cons(as.head(), new P1>() { - public Stream _1() { - return as.tail()._1().filter(f); - } - }) : as; + return as.isNotEmpty() ? cons(as.head(), P.lazy(() -> as.tail()._1().filter(f))) : as; } /** @@ -313,11 +297,7 @@ public Stream _1() { * @return A new stream that has appended the given stream. */ public final Stream append(final Stream as) { - return isEmpty() ? as : cons(head(), new P1>() { - public Stream _1() { - return tail()._1().append(as); - } - }); + return isEmpty() ? as : cons(head(), P.lazy(() -> tail()._1().append(as))); } /** @@ -327,11 +307,7 @@ public Stream _1() { * @return A new stream that has appended the given stream. */ public final Stream append(final F0> as) { - return isEmpty() ? as.f() : cons(head(), new P1>() { - public Stream _1() { - return tail()._1().append(as); - } - }); + return isEmpty() ? as.f() : cons(head(), P.lazy(() -> tail()._1().append(as))); } /** @@ -574,11 +550,7 @@ public final Stream apply(final Stream> sf) { * @return A new stream with elements interleaved from this stream and the given stream. */ public final Stream interleave(final Stream as) { - return isEmpty() ? as : as.isEmpty() ? this : cons(head(), new P1>() { - @Override public Stream _1() { - return as.interleave(tail()._1()); - } - }); + return isEmpty() ? as : as.isEmpty() ? this : cons(head(), P.lazy(() -> as.interleave(tail()._1()))); } /** @@ -606,11 +578,7 @@ private static Stream> mergePairs(final Ord o, final Stream> t = s.tail()._1(); - return cons(merge(o, s.head(), t.head()), new P1>>() { - public Stream> _1() { - return mergePairs(o, t.tail()._1()); - } - }); + return cons(merge(o, s.head(), t.head()), () -> mergePairs(o, t.tail()._1())); } // Merges two individually sorted streams. @@ -622,16 +590,8 @@ private static Stream merge(final Ord o, final Stream xs, final Str final A x = xs.head(); final A y = ys.head(); if (o.isGreaterThan(x, y)) - return cons(y, new P1>() { - public Stream _1() { - return merge(o, xs, ys.tail()._1()); - } - }); - return cons(x, new P1>() { - public Stream _1() { - return merge(o, xs.tail()._1(), ys); - } - }); + return cons(y, () -> merge(o, xs, ys.tail()._1())); + return cons(x, () -> merge(o, xs.tail()._1(), ys)); } /** @@ -720,11 +680,7 @@ public int size() { * to value (exclusive). */ public static Stream range(final int from, final long to) { - return from >= to ? Stream.nil() : cons(from, new P1>() { - public Stream _1() { - return range(from + 1, to); - } - }); + return from >= to ? Stream.nil() : cons(from, () -> range(from + 1, to)); } /** @@ -773,11 +729,7 @@ public static Stream forever(final Enumerator e, final A from) { * given value and stepping at the given increment. */ public static Stream forever(final Enumerator e, final A from, final long step) { - return cons(from, new P1>() { - public Stream _1() { - return e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil()); - } - }); + return cons(from, P.lazy(() -> e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil()))); } /** @@ -807,15 +759,10 @@ public static Stream range(final Enumerator e, final A from, final A t */ public static Stream range(final Enumerator e, final A from, final A to, final long step) { final Ordering o = e.order().compare(from, to); - return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, new P1>() { - public Stream _1() { - return Stream.join(e.plus(from, step).filter(a -> !(o == LT + return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, () -> Stream.join(e.plus(from, step).filter(a -> !(o == LT ? e.order().isLessThan(to, a) - : e.order().isGreaterThan(to, a))).map(a1 -> range(e, a1, to, step)).toStream()); - } - }); + : e.order().isGreaterThan(to, a))).map(a1 -> range(e, a1, to, step)).toStream())); } - /** * Returns an infinite stream of integers from the given from value (inclusive). * @@ -823,11 +770,7 @@ public Stream _1() { * @return A stream of integers from the given from value (inclusive). */ public static Stream range(final int from) { - return cons(from, new P1>() { - public Stream _1() { - return range(from + 1); - } - }); + return cons(from, () -> range(from + 1)); } /** @@ -849,11 +792,7 @@ public static F, F, Stream>> filter() { */ public final Stream zapp(final Stream> fs) { return fs.isEmpty() || isEmpty() ? Stream.nil() : - cons(fs.head().f(head()), new P1>() { - public Stream _1() { - return tail()._1().zapp(fs.tail()._1()); - } - }); + cons(fs.head().f(head()), () -> tail()._1().zapp(fs.tail()._1())); } /** @@ -1005,11 +944,7 @@ public final A[] array(final Class c) { * @return A new stream with the given element at the head. */ public final Stream cons(final A a) { - return new Cons(a, new P1>() { - public Stream _1() { - return Stream.this; - } - }); + return new Cons(a, P.lazy(() -> Stream.this)); } /** @@ -1065,11 +1000,7 @@ public final Stream snoc(final F0 a) { public final Stream take(final int n) { return n <= 0 || isEmpty() ? Stream.nil() : - cons(head(), new P1>() { - public Stream _1() { - return n <= 1 ? Stream.nil() : tail()._1().take(n - 1); - } - }); + cons(head(), () -> n <= 1 ? Stream.nil() : tail()._1().take(n - 1)); } /** @@ -1100,11 +1031,7 @@ public final Stream takeWhile(final F f) { return isEmpty() ? this : f.f(head()) ? - cons(head(), new P1>() { - public Stream _1() { - return tail()._1().takeWhile(f); - } - }) : + cons(head(), () -> tail()._1().takeWhile(f)) : Stream.nil(); } @@ -1157,11 +1084,7 @@ public final P2, Stream> span(final F p) { if (isEmpty()) return p(this, this); else if (p.f(head())) { - final P1, Stream>> yszs = new P1, Stream>>() { - @Override public P2, Stream> _1() { - return tail()._1().span(p); - } - }; + final P1, Stream>> yszs = P.lazy(() -> tail()._1().span(p)); return new P2, Stream>() { @Override public Stream _1() { return cons(head(), yszs.map(P2., Stream>__1())); @@ -1187,11 +1110,7 @@ public final Stream replace(final F p, final A a) { return nil(); else { final P2, Stream> s = span(p); - return s._1().append(cons(a, new P1>() { - @Override public Stream _1() { - return s._2().tail()._1().replace(p, a); - } - })); + return s._1().append(cons(a, () -> s._2().tail()._1().replace(p, a))); } } @@ -1213,13 +1132,7 @@ public final P2, Stream> split(final F p) { * @return A new stream that is the reverse of this one. */ public final Stream reverse() { - return foldLeft(as -> { - return a -> cons(a, new P1>() { - public Stream _1() { - return as; - } - }); - }, Stream.nil()); + return foldLeft(as -> a -> cons(a, () -> as), Stream.nil()); } /** @@ -1357,11 +1270,7 @@ public final Stream cobind(final F, B> k) { * @return a stream of the suffixes of this stream, starting with the stream itself. */ public final Stream> tails() { - return isEmpty() ? Stream.>nil() : cons(this, new P1>>() { - public Stream> _1() { - return tail()._1().tails(); - } - }); + return isEmpty() ? Stream.>nil() : cons(this, () -> tail()._1().tails()); } /** @@ -1370,11 +1279,7 @@ public Stream> _1() { * @return a stream of the prefixes of this stream, starting with the stream itself. */ public final Stream> inits() { - final Stream> nil = Stream.cons(Stream.nil(), new P1>>() { - public Stream> _1() { - return nil(); - } - }); + final Stream> nil = Stream.cons(Stream.nil(), P.lazy(() -> nil())); return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.cons_().f(head()))); } @@ -1406,11 +1311,7 @@ public final Option indexOf(final F p) { public final Stream sequenceW(final Stream, B>> fs) { return fs.isEmpty() ? Stream.nil() - : cons(fs.head().f(this), new P1>() { - public Stream _1() { - return sequenceW(fs.tail()._1()); - } - }); + : cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } /** @@ -1443,14 +1344,12 @@ public static Stream fromFunction(final F f) { * starting at the given value. */ public static Stream fromFunction(final Enumerator e, final F f, final B i) { - return cons(f.f(i), new P1>() { - public Stream _1() { + return cons(f.f(i), P.lazy(() -> { final Option s = e.successor(i); return s.isSome() ? fromFunction(e, f, s.some()) : Stream.nil(); - } - }); + })); } /** @@ -1537,11 +1436,7 @@ public static Stream nil() { * @return An empty stream. */ public static P1> nil_() { - return new P1>() { - public Stream _1() { - return new Nil(); - } - }; + return P.lazy(() -> new Nil()); } /** @@ -1569,11 +1464,7 @@ public static F, Boolean> isNotEmpty_() { * @return A stream of one element containing the given value. */ public static Stream single(final A a) { - return cons(a, new P1>() { - public Stream _1() { - return nil(); - } - }); + return cons(a, () -> nil()); } /** @@ -1627,11 +1518,7 @@ public static Stream unfold(final F>> f, final B b) return nil(); else { final P2 p = o.some(); - return cons(p._1(), new P1>() { - public Stream _1() { - return unfold(f, p._2()); - } - }); + return cons(p._1(), () -> unfold(f, p._2())); } } @@ -1682,11 +1569,7 @@ public static Stream iteratorStream(final Iterator i) { * @return An infinite-length stream of the given element. */ public static Stream repeat(final A a) { - return cons(a, new P1>() { - public Stream _1() { - return repeat(a); - } - }); + return cons(a, () -> repeat(a)); } /** @@ -1710,11 +1593,7 @@ public static Stream cycle(final Stream as) { * @return A stream constructed by applying the given iteration function starting at the given value. */ public static Stream iterate(final F f, final A a) { - return cons(a, new P1>() { - public Stream _1() { - return iterate(f, f.f(a)); - } - }); + return cons(a, () -> iterate(f, f.f(a))); } /** diff --git a/core/src/main/java/fj/data/vector/V2.java b/core/src/main/java/fj/data/vector/V2.java index 84d2c9e4..e5bf7bc1 100644 --- a/core/src/main/java/fj/data/vector/V2.java +++ b/core/src/main/java/fj/data/vector/V2.java @@ -1,11 +1,10 @@ package fj.data.vector; -import fj.F; -import fj.F2; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; -import fj.P1; -import fj.P2; + import fj.data.Array; import fj.data.List; import fj.data.NonEmptyList; @@ -103,11 +102,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(_1(), new P1>() { - public Stream _1() { - return Stream.single(_2()); - } - }); + return Stream.cons(_1(), () -> Stream.single(_2())); } /** @@ -198,11 +193,7 @@ public V2> vzip(final V2 bs) { * @return the first element of this vector as a product-1. */ public P1 head() { - return new P1() { - public A _1() { - return V2.this._1(); - } - }; + return P.lazy(() -> V2.this._1()); } } diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index 34d752f1..f45ec3b6 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -1,10 +1,7 @@ package fj.data.vector; -import fj.F; -import fj.F2; -import fj.P1; -import fj.P2; -import fj.P3; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; import fj.data.Array; @@ -33,19 +30,19 @@ private V3(final P1 head, final V2 tail) { * @return A new vector-3. */ public static V3 p(final P3 p) { - return new V3(new P1() { - public A _1() { - return p._1(); - } - }, V2.p(new P2() { - public A _1() { - return p._2(); - } - - public A _2() { - return p._3(); - } - })); + return new V3( + P.lazy(() -> p._1()), + V2.p(new P2() { + public A _1() { + return p._2(); + } + + public A _2() { + return p._3(); + } + } + ) + ); } /** diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index c56976cd..4d537864 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -1,11 +1,7 @@ package fj.data.vector; -import fj.F; -import fj.F2; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.P4; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; import fj.data.Array; @@ -34,11 +30,8 @@ private V4(final P1 head, final V3 tail) { * @return A new vector-4. */ public static V4 p(final P4 p) { - return new V4(new P1() { - public A _1() { - return p._1(); - } - }, V3.p(new P3() { + return new V4(P.lazy(() -> p._1()), + V3.p(new P3() { public A _1() { return p._2(); } diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 3ecdd341..9375c7b1 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -1,11 +1,7 @@ package fj.data.vector; -import fj.F; -import fj.F2; -import fj.P1; -import fj.P2; -import fj.P4; -import fj.P5; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; import fj.data.Array; @@ -34,11 +30,8 @@ private V5(final P1 head, final V4 tail) { * @return A new vector-5. */ public static V5 p(final P5 p) { - return new V5(new P1() { - public A _1() { - return p._1(); - } - }, V4.p(new P4() { + return new V5(P.lazy(() -> p._1()), + V4.p(new P4() { public A _1() { return p._2(); } diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 2b61a2b4..259fae5d 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -1,11 +1,7 @@ package fj.data.vector; -import fj.F; -import fj.F2; -import fj.P1; -import fj.P2; -import fj.P5; -import fj.P6; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; import fj.data.Array; @@ -34,11 +30,8 @@ private V6(final P1 head, final V5 tail) { * @return A new vector-6. */ public static V6 p(final P6 p) { - return new V6(new P1() { - public A _1() { - return p._1(); - } - }, V5.p(new P5() { + return new V6(P.lazy(() -> p._1()), + V5.p(new P5() { public A _1() { return p._2(); } diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index 90273010..0a5069df 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -1,11 +1,7 @@ package fj.data.vector; -import fj.F; -import fj.F2; -import fj.P1; -import fj.P2; -import fj.P6; -import fj.P7; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; import fj.data.Array; @@ -34,11 +30,8 @@ private V7(final P1 head, final V6 tail) { * @return A new vector-7. */ public static V7 p(final P7 p) { - return new V7(new P1() { - public A _1() { - return p._1(); - } - }, V6.p(new P6() { + return new V7(P.lazy(() -> p._1()), + V6.p(new P6() { public A _1() { return p._2(); } diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index d4995914..c076ef83 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -1,11 +1,7 @@ package fj.data.vector; -import fj.F; -import fj.F2; -import fj.P1; -import fj.P2; -import fj.P7; -import fj.P8; +import fj.*; + import static fj.Function.curry; import static fj.P.p2; import fj.data.Array; @@ -34,11 +30,8 @@ private V8(final P1 head, final V7 tail) { * @return A new vector-8. */ public static V8 p(final P8 p) { - return new V8(new P1() { - public A _1() { - return p._1(); - } - }, V7.p(new P7() { + return new V8(P.lazy(() -> p._1()), + V7.p(new P7() { public A _1() { return p._2(); } From cceb3d5058c6d599f87ca2723614ab719838f741 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 00:57:40 +1000 Subject: [PATCH 400/811] Converted demo and quickcheck to use lambdas --- demo/src/main/java/fj/demo/Primes2.java | 6 +----- .../main/java/fj/demo/concurrent/WordCount.java | 15 ++++----------- demo/src/main/java/fj/demo/euler/Problem3.java | 4 +--- .../fj/demo/test/AdditionCommutesParallel.java | 7 ++----- quickcheck/src/main/java/fj/test/Bool.java | 12 ++---------- quickcheck/src/main/java/fj/test/Shrink.java | 6 +----- 6 files changed, 11 insertions(+), 39 deletions(-) diff --git a/demo/src/main/java/fj/demo/Primes2.java b/demo/src/main/java/fj/demo/Primes2.java index 0a79dd75..4a5b9dbd 100644 --- a/demo/src/main/java/fj/demo/Primes2.java +++ b/demo/src/main/java/fj/demo/Primes2.java @@ -21,11 +21,7 @@ public class Primes2 { // Finds primes in a given stream. public static Stream sieve(final Stream xs) { - return cons(xs.head(), new P1>() { - public Stream _1() { - return sieve(xs.tail()._1().removeAll(F1Functions.o(naturalOrd.equal().eq(ZERO), mod.f(xs.head())))); - } - }); + return cons(xs.head(), () -> sieve(xs.tail()._1().removeAll(F1Functions.o(naturalOrd.equal().eq(ZERO), mod.f(xs.head()))))); } // A stream of all primes less than n. diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 4af1a818..67fef136 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -88,12 +88,7 @@ public static final IterV> wordCountsFromCharCh @Override public F, IterV>> f(final P2> acc) { final P1>> empty = - new P1>>() { - @Override - public IterV> _1() { - return IterV.cont(step.f(acc)); - } - }; + P.lazy(() -> IterV.cont(step.f(acc))); final P1>>> el = new P1>>>() { @Override @@ -120,17 +115,15 @@ public IterV> f(final char[] e) { } }; final P1>> eof = - new P1>>() { - @Override - public IterV> _1() { + P.lazy(() -> { final StringBuilder sb = acc._1(); if(sb.length() > 0) { final Map map = update(acc._2(), sb.toString(), addOne, Integer.valueOf(0)); return IterV.done(map, Input.eof()); } return IterV.done(acc._2(), Input.eof()); - } - }; + }); + return s -> s.apply(empty, el, eof); } }; diff --git a/demo/src/main/java/fj/demo/euler/Problem3.java b/demo/src/main/java/fj/demo/euler/Problem3.java index 8276239d..6b4ab795 100644 --- a/demo/src/main/java/fj/demo/euler/Problem3.java +++ b/demo/src/main/java/fj/demo/euler/Problem3.java @@ -32,9 +32,7 @@ public static Stream factor(final Natural n, final Natural p, final P1< else { final V2 dm = n.divmod(h); if (naturalOrd.eq(dm._2(), ZERO)) - ret = cons(h, new P1>() { - public Stream _1() {return factor(dm._1(), h, t);} - }); + ret = cons(h, () -> factor(dm._1(), h, t)); else ns = ns.tail()._1(); } } diff --git a/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java index c254b67b..ca9f6934 100644 --- a/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java +++ b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java @@ -1,6 +1,7 @@ package fj.demo.test; import fj.F2; +import fj.P; import fj.P1; import fj.control.parallel.Strategy; import static fj.test.Arbitrary.arbInteger; @@ -21,11 +22,7 @@ public static void main(final String[] args) { final Strategy s = Strategy.executorStrategy(pool); final Property p = propertyP(arbInteger, arbInteger, new F2>() { public P1 f(final Integer a, final Integer b) { - return s.par(new P1() { - public Property _1() { - return prop(a + b == b + a); - } - }); + return s.par(P.lazy(() -> prop(a + b == b + a))); } }); summary.println(p.check(1000000, 5000000, 0, 100)); // OK, passed 1000000 tests. diff --git a/quickcheck/src/main/java/fj/test/Bool.java b/quickcheck/src/main/java/fj/test/Bool.java index aff8b295..deb072cf 100644 --- a/quickcheck/src/main/java/fj/test/Bool.java +++ b/quickcheck/src/main/java/fj/test/Bool.java @@ -56,11 +56,7 @@ public Property implies(final F0 p) { * @return a property that produces a result only if this value is true. */ public Property implies(final Property p) { - return Property.implies(b, new P1() { - public Property _1() { - return p; - } - }); + return Property.implies(b, () -> p); } /** @@ -80,11 +76,7 @@ public Property implies(final Bool c) { * @return a property that produces a result only if this value is true. */ public Property implies(final boolean c) { - return Property.implies(b, new P1() { - public Property _1() { - return prop(c); - } - }); + return Property.implies(b, () -> prop(c)); } /** diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 687c6549..e2ef9cca 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -190,11 +190,7 @@ public static Shrink empty() { public static Shrink> shrinkOption(final Shrink sa) { return shrink(o -> o.isNone() ? Stream.>nil() : - cons(Option.none(), new P1>>() { - public Stream> _1() { - return sa.shrink(o.some()).map(Option.some_()); - } - })); + cons(Option.none(), () -> sa.shrink(o.some()).map(Option.some_()))); } /** From 0a76120b71a4844eba2f49611e437c50f65249cb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 01:22:39 +1000 Subject: [PATCH 401/811] Use lambdas in fj.data.vector --- core/src/main/java/fj/data/vector/V3.java | 6 +----- core/src/main/java/fj/data/vector/V4.java | 6 +----- core/src/main/java/fj/data/vector/V5.java | 6 +----- core/src/main/java/fj/data/vector/V6.java | 6 +----- core/src/main/java/fj/data/vector/V7.java | 6 +----- core/src/main/java/fj/data/vector/V8.java | 1 + 6 files changed, 6 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index f45ec3b6..65353f8b 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -201,11 +201,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head()._1(), new P1>() { - public Stream _1() { - return tail().toStream(); - } - }); + return Stream.cons(head()._1(), () -> tail().toStream()); } /** diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 4d537864..19ea2648 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -160,11 +160,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), new P1>() { - public Stream _1() { - return tail.toStream(); - } - }); + return Stream.cons(head._1(), () -> tail.toStream()); } /** diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 9375c7b1..3aab13e3 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -177,11 +177,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), new P1>() { - public Stream _1() { - return tail.toStream(); - } - }); + return Stream.cons(head._1(), () -> tail.toStream()); } /** diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 259fae5d..66a5afca 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -194,11 +194,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), new P1>() { - public Stream _1() { - return tail.toStream(); - } - }); + return Stream.cons(head._1(), () -> tail.toStream()); } /** diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index 0a5069df..c57e3551 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -211,11 +211,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), new P1>() { - public Stream _1() { - return tail.toStream(); - } - }); + return Stream.cons(head._1(), () -> tail.toStream()); } /** diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index c076ef83..4d015715 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -229,6 +229,7 @@ public NonEmptyList toNonEmptyList() { */ public Stream toStream() { return Stream.cons(head._1(), new P1>() { + F0> f = 100; public Stream _1() { return tail.toStream(); } From 2d6a8dd4412220a749331b6ffec45bd720ac7479 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 19:58:20 +1000 Subject: [PATCH 402/811] Reviewed use of new P1 to use P.lazy --- core/src/main/java/fj/control/parallel/Callables.java | 7 ++----- core/src/main/java/fj/data/vector/V8.java | 7 +------ 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index 2403adb8..1b6114fe 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -166,16 +166,13 @@ public static F>, Callable>> sequence_() { * @return An optional value that yields the value in the Callable, or None if the Callable fails. */ public static P1> option(final Callable a) { - return new P1>() { - @SuppressWarnings({"UnusedCatchParameter"}) - public Option _1() { + return P.lazy(() -> { try { return some(a.call()); } catch (Exception e) { return none(); } - } - }; + }); } /** diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index 4d015715..22526af0 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -228,12 +228,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), new P1>() { - F0> f = 100; - public Stream _1() { - return tail.toStream(); - } - }); + return Stream.cons(head._1(), P.lazy(() -> tail.toStream())); } /** From 5b8248c51445e92aa8c8ff241e717f909a5bdd63 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 20:19:11 +1000 Subject: [PATCH 403/811] Reviewed use of P.lazy and used () -> where applicable for core and demo --- core/src/main/java/fj/P1.java | 4 +-- core/src/main/java/fj/P2.java | 2 +- .../java/fj/control/parallel/Promise.java | 2 +- core/src/main/java/fj/data/IOFunctions.java | 4 +-- core/src/main/java/fj/data/LazyString.java | 2 +- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/Stream.java | 28 +++++++++---------- core/src/main/java/fj/data/vector/V8.java | 2 +- .../java/fj/demo/concurrent/MapReduce.java | 2 +- .../src/main/java/fj/demo/euler/Problem3.java | 2 +- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index d3183208..1995352e 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -259,11 +259,11 @@ public P1 memo() { */ public P1 softMemo() { return new SoftReferenceMemo<>(this); } - static P1 memo(F f) { + public static P1 memo(F f) { return P.lazy(f).memo(); } - static P1 memo(F0 f) { + public static P1 memo(F0 f) { return P.lazy(f).memo(); } diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 58707bfb..901fe478 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -187,7 +187,7 @@ public final Either> traverseEither(final F> public final Stream sequenceW(final Stream, C>> fs) { return fs.isEmpty() ? Stream.nil() - : Stream.cons(fs.head().f(this), P.lazy(() -> sequenceW(fs.tail()._1()))); + : Stream.cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 9f9d2431..c6b8ea1b 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -386,7 +386,7 @@ public Promise> cojoin() { public Stream sequenceW(final Stream, B>> fs) { return fs.isEmpty() ? Stream.nil() - : Stream.cons(fs.head().f(this), P.lazy(() -> sequenceW(fs.tail()._1()))); + : Stream.cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 04564115..bb2d7de1 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -360,7 +360,7 @@ public static IO> sequence(List> list) { public static IO> sequence(Stream> stream) { F2>, IO, IO>> f2 = (ioList, io) -> - IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, P.lazy(() -> xs)))); + IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, () -> xs))); return stream.foldLeft(f2, IOFunctions.unit(Stream.nil())); } @@ -443,7 +443,7 @@ public Stream run() throws IOException { } else { IO> io2 = sequenceWhile(stream.tail()._1(), f); SafeIO> s3 = toSafe(() -> io2.run()); - return Stream.cons(a, P.lazy(() -> s3.run())); + return Stream.cons(a, () -> s3.run()); } } } diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index b13bca44..95160de1 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -257,7 +257,7 @@ public Stream split(final F p) { final Stream findIt = s.dropWhile(p); final P2, Stream> ws = findIt.split(p); return findIt.isEmpty() ? Stream.nil() - : Stream.cons(fromStream(ws._1()), P.lazy(() -> fromStream(ws._2()).split(p))); + : Stream.cons(fromStream(ws._1()), () -> fromStream(ws._2()).split(p)); } public LazyString map(F f) { diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 7adc4a07..1570a259 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -167,7 +167,7 @@ public final Either toEither(final F0 x) { * @return A stream projection of this list. */ public final Stream toStream() { - return isEmpty() ? Stream.nil() : Stream.cons(head(), P.lazy(() -> tail().toStream())); + return isEmpty() ? Stream.nil() : Stream.cons(head(), () -> tail().toStream()); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 3d978be8..5fdcdc72 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -231,7 +231,7 @@ public Stream _1() { } public Stream prefix(final A x, final Stream xs) { - return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), P.lazy(() -> prefix(a, xs.tail()._1()))))); + return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), () -> prefix(a, xs.tail()._1())))); } }); } @@ -287,7 +287,7 @@ public final void foreachDoEffect(final Effect1 f) { */ public final Stream filter(final F f) { final Stream as = dropWhile(not(f)); - return as.isNotEmpty() ? cons(as.head(), P.lazy(() -> as.tail()._1().filter(f))) : as; + return as.isNotEmpty() ? cons(as.head(), () -> as.tail()._1().filter(f)) : as; } /** @@ -297,7 +297,7 @@ public final Stream filter(final F f) { * @return A new stream that has appended the given stream. */ public final Stream append(final Stream as) { - return isEmpty() ? as : cons(head(), P.lazy(() -> tail()._1().append(as))); + return isEmpty() ? as : cons(head(), () -> tail()._1().append(as)); } /** @@ -307,7 +307,7 @@ public final Stream append(final Stream as) { * @return A new stream that has appended the given stream. */ public final Stream append(final F0> as) { - return isEmpty() ? as.f() : cons(head(), P.lazy(() -> tail()._1().append(as))); + return isEmpty() ? as.f() : cons(head(), () -> tail()._1().append(as)); } /** @@ -550,7 +550,7 @@ public final Stream apply(final Stream> sf) { * @return A new stream with elements interleaved from this stream and the given stream. */ public final Stream interleave(final Stream as) { - return isEmpty() ? as : as.isEmpty() ? this : cons(head(), P.lazy(() -> as.interleave(tail()._1()))); + return isEmpty() ? as : as.isEmpty() ? this : cons(head(), () -> as.interleave(tail()._1())); } /** @@ -729,7 +729,7 @@ public static Stream forever(final Enumerator e, final A from) { * given value and stepping at the given increment. */ public static Stream forever(final Enumerator e, final A from, final long step) { - return cons(from, P.lazy(() -> e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil()))); + return cons(from, () -> e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil())); } /** @@ -944,7 +944,7 @@ public final A[] array(final Class c) { * @return A new stream with the given element at the head. */ public final Stream cons(final A a) { - return new Cons(a, P.lazy(() -> Stream.this)); + return new Cons(a, () -> Stream.this); } /** @@ -1279,7 +1279,7 @@ public final Stream> tails() { * @return a stream of the prefixes of this stream, starting with the stream itself. */ public final Stream> inits() { - final Stream> nil = Stream.cons(Stream.nil(), P.lazy(() -> nil())); + final Stream> nil = Stream.cons(Stream.nil(), () -> nil()); return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.cons_().f(head()))); } @@ -1344,12 +1344,12 @@ public static Stream fromFunction(final F f) { * starting at the given value. */ public static Stream fromFunction(final Enumerator e, final F f, final B i) { - return cons(f.f(i), P.lazy(() -> { + return cons(f.f(i), () -> { final Option s = e.successor(i); return s.isSome() ? fromFunction(e, f, s.some()) : Stream.nil(); - })); + }); } /** @@ -1388,9 +1388,9 @@ private static final class Cons extends Stream { private final A head; private final P1> tail; - Cons(final A head, final P1> tail) { + Cons(final A head, final F0> tail) { this.head = head; - this.tail = tail.memo(); + this.tail = P1.memo(tail); } public A head() { @@ -1484,7 +1484,7 @@ public static F> single() { * @return The stream with the given element prepended. */ public static Stream cons(final A head, final F0> tail) { - return new Cons(head, P.lazy(tail)); + return new Cons(head, tail); } /** @@ -1557,7 +1557,7 @@ public static Stream iterableStream(final Iterable i) { public static Stream iteratorStream(final Iterator i) { if (i.hasNext()) { final A a = i.next(); - return cons(a, P.lazy(() -> iteratorStream(i))); + return cons(a, () -> iteratorStream(i)); } else return nil(); } diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index 22526af0..72af03f1 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -228,7 +228,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), P.lazy(() -> tail.toStream())); + return Stream.cons(head._1(), () -> tail.toStream()); } /** diff --git a/demo/src/main/java/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java index 9bfee40d..57a59d9e 100644 --- a/demo/src/main/java/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -51,7 +51,7 @@ public Stream f(final BufferedReader reader) { throw new Error(e); } if (s.isSome()) - return fromString(s.some()).append(P.lazy(sc -> f(reader))); + return fromString(s.some()).append(() -> f(reader)); else { try { reader.close(); diff --git a/demo/src/main/java/fj/demo/euler/Problem3.java b/demo/src/main/java/fj/demo/euler/Problem3.java index 6b4ab795..bde87126 100644 --- a/demo/src/main/java/fj/demo/euler/Problem3.java +++ b/demo/src/main/java/fj/demo/euler/Problem3.java @@ -18,7 +18,7 @@ */ public class Problem3 { // An infinite stream of all the primes. - public static final Stream primes = cons(natural(2).some(), P.lazy(() -> forever(naturalEnumerator, natural(3).some(), 2).filter(n -> primeFactors(n).length() == 1))); + public static final Stream primes = cons(natural(2).some(), () -> forever(naturalEnumerator, natural(3).some(), 2).filter(n -> primeFactors(n).length() == 1)); //Finds factors of a given number. public static Stream factor(final Natural n, final Natural p, final P1> ps) { From 0ca5248a3016209c9e62df509a79ed9432421322 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 20:21:01 +1000 Subject: [PATCH 404/811] Reviewed use of P.lazy and used () -> where applicable for quickcheck --- quickcheck/src/main/java/fj/test/Shrink.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index e2ef9cca..d1403ee7 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -138,9 +138,9 @@ public static Shrink empty() { if (i == 0L) return nil(); else { - final Stream is = cons(0L, P.lazy(() -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1))); + final Stream is = cons(0L, () -> iterate(x -> x / 2L, i).takeWhile(x2 -> x2 != 0L).map(x1 -> i - x1)); - return i < 0L ? cons(-i, P.lazy(() -> is)) : is; + return i < 0L ? cons(-i, () -> is) : is; } }); From b438b1b89705f6d0bfd5e7c31bd217d173c43dfc Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 20:55:02 +1000 Subject: [PATCH 405/811] Converted anonymous F2 classes to use lambdas --- core/src/main/java/fj/Monoid.java | 6 +----- .../main/java/fj/control/parallel/Promise.java | 6 +----- core/src/main/java/fj/data/Array.java | 6 +----- core/src/main/java/fj/data/Enumerator.java | 4 +--- core/src/main/java/fj/data/Option.java | 6 +----- .../src/main/java/fj/data/fingertrees/Digit.java | 6 +----- core/src/main/java/fj/data/fingertrees/Node.java | 8 ++------ core/src/main/java/fj/data/hlist/HList.java | 12 ++---------- core/src/main/java/fj/function/Integers.java | 6 +----- core/src/main/java/fj/function/Visitor.java | 12 ++---------- .../main/java/fj/demo/test/AdditionCommutes.java | 6 +----- .../fj/demo/test/AdditionCommutesParallel.java | 6 +----- .../main/java/fj/demo/test/EqualsHashCode.java | 12 ++---------- .../main/java/fj/demo/test/IntegerOverflow.java | 6 +----- .../main/java/fj/demo/test/JavaLinkedList.java | 4 +--- .../java/fj/demo/test/OptionMonadFunctorLaw.java | 6 +----- quickcheck/src/main/java/fj/test/Gen.java | 16 +++------------- 17 files changed, 23 insertions(+), 105 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index ac10b79f..e1192682 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -118,11 +118,7 @@ public A sumRight(final List as) { * @return The sum of the given values. */ public A sumRight(final Stream as) { - return as.foldRight(new F2, A>() { - public A f(final A a, final P1 ap1) { - return sum(a, ap1._1()); - } - }, zero); + return as.foldRight((a, ap1) -> sum(a, ap1._1()), zero); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index c6b8ea1b..100b50f6 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -222,11 +222,7 @@ public Promise bind(final P1> p, final F> f) { * @return A function of arity-2 promoted to map over promises. */ public static F, F, Promise>> liftM2(final F> f) { - return curry(new F2, Promise, Promise>() { - public Promise f(final Promise ca, final Promise cb) { - return ca.bind(cb, f); - } - }); + return curry((ca, cb) -> ca.bind(cb, f)); } /** diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index d6700dc6..bb3b24a4 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -600,11 +600,7 @@ public static F> wrap() { * @return A function that maps a given function across a given array. */ public static F, F, Array>> map() { - return curry(new F2, Array, Array>() { - public Array f(final F abf, final Array array) { - return array.map(abf); - } - }); + return curry((abf, array) -> array.map(abf)); } /** diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index c9088bfa..fe57a643 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -236,8 +236,7 @@ public static Enumerator enumerator(final F> successor, fina */ public static Enumerator enumerator(final F> successor, final F> predecessor, final Option max, final Option min, final Ord order) { - return new Enumerator(successor, predecessor, max, min, order, curry(new F2>() { - public Option f(final A a, final Long l) { + return new Enumerator(successor, predecessor, max, min, order, curry((a, l) -> { if (l == 0L) return some(a); else if (l < 0L) { @@ -261,7 +260,6 @@ else if (l < 0L) { } return some(aa); } - } })); } diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index c40adbe3..c9f9f9f2 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -512,11 +512,7 @@ public final Validation toValidation(final X x) { * return in left. */ public static F, F>> toEither() { - return curry(new F2, X, Either>() { - public Either f(final Option a, final X x) { - return a.toEither(x); - } - }); + return curry((a, x) -> a.toEither(x)); } /** diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index 8a25084b..002f9b77 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -121,11 +121,7 @@ public abstract B match(final F, B> one, final F, B> two * @return the sum of the measurements of this digit according to the monoid. */ public final V measure() { - return foldLeft(Function.curry(new F2() { - public V f(final V v, final A a) { - return m.sum(v, m.measure(a)); - } - }), m.zero()); + return foldLeft(Function.curry((v, a) -> m.sum(v, m.measure(a))), m.zero()); } /** diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index 737ea63f..dca76b62 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -20,15 +20,11 @@ public abstract class Node { public abstract B foldLeft(final F> f, final B z); public static F, B>> foldLeft_(final F> bff) { - return curry(new F2, B>() { - public B f(final B b, final Node node) { return node.foldLeft(bff, b); } - }); + return curry((b, node) -> node.foldLeft(bff, b)); } public static F, B>> foldRight_(final F> aff) { - return curry(new F2, B>() { - public B f(final B b, final Node node) { return node.foldRight(aff, b); } - }); + return curry((b, node) -> node.foldRight(aff, b)); } public final Node map(final F f, final Measured m) { diff --git a/core/src/main/java/fj/data/hlist/HList.java b/core/src/main/java/fj/data/hlist/HList.java index 2d9be568..9cbc492e 100644 --- a/core/src/main/java/fj/data/hlist/HList.java +++ b/core/src/main/java/fj/data/hlist/HList.java @@ -91,11 +91,7 @@ public C append(final A a, final B b) { * @return a method for concatenating lists to the empty list. */ public static > HAppend append() { - return new HAppend(new F2() { - public L f(final HNil hNil, final L l) { - return l; - } - }); + return new HAppend((hNil, l) -> l); } /** @@ -106,11 +102,7 @@ public L f(final HNil hNil, final L l) { */ public static , B, C extends HList, H extends HAppend> HAppend, B, HCons> append(final H h) { - return new HAppend, B, HCons>(new F2, B, HCons>() { - public HCons f(final HCons c, final B l) { - return cons(c.head(), h.append(c.tail(), l)); - } - }); + return new HAppend, B, HCons>((c, l) -> cons(c.head(), h.append(c.tail(), l))); } } diff --git a/core/src/main/java/fj/function/Integers.java b/core/src/main/java/fj/function/Integers.java index 70bef76f..10fd3b15 100644 --- a/core/src/main/java/fj/function/Integers.java +++ b/core/src/main/java/fj/function/Integers.java @@ -37,11 +37,7 @@ private Integers() { /** * Curried Integer subtraction. */ - public static final F> subtract = curry(new F2() { - public Integer f(final Integer x, final Integer y) { - return x - y; - } - }); + public static final F> subtract = curry((x, y) -> x - y); /** * Negation. diff --git a/core/src/main/java/fj/function/Visitor.java b/core/src/main/java/fj/function/Visitor.java index 2e3a2187..ebd18c03 100644 --- a/core/src/main/java/fj/function/Visitor.java +++ b/core/src/main/java/fj/function/Visitor.java @@ -83,11 +83,7 @@ public static B nullableVisitor(final List> visitors, final F0 * @return A function that can be applied to a default value (there is no association) and an associated key. */ public static F> association(final List> x, final Equal eq) { - return curry(new F2() { - public B f(final B def, final A a) { - return lookup(eq, x, a).orSome(def); - } - }); + return curry((def, a) -> lookup(eq, x, a).orSome(def)); } /** @@ -99,10 +95,6 @@ public B f(final B def, final A a) { * @return A function that can be applied to a default value (there is no association) and an associated key. */ public static F, F> associationLazy(final List> x, final Equal eq) { - return curry(new F2, A, B>() { - public B f(final P1 def, final A a) { - return lookup(eq, x, a).orSome(def); - } - }); + return curry((def, a) -> lookup(eq, x, a).orSome(def)); } } diff --git a/demo/src/main/java/fj/demo/test/AdditionCommutes.java b/demo/src/main/java/fj/demo/test/AdditionCommutes.java index e1770034..8aea4f03 100644 --- a/demo/src/main/java/fj/demo/test/AdditionCommutes.java +++ b/demo/src/main/java/fj/demo/test/AdditionCommutes.java @@ -13,11 +13,7 @@ */ public final class AdditionCommutes { public static void main(final String[] args) { - final Property p = property(arbInteger, arbInteger, new F2() { - public Property f(final Integer a, final Integer b) { - return prop(a + b == b + a); - } - }); + final Property p = property(arbInteger, arbInteger, (a, b) -> prop(a + b == b + a)); summary.println(p.check()); // OK, passed 100 tests. } } diff --git a/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java index ca9f6934..b1629c21 100644 --- a/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java +++ b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java @@ -20,11 +20,7 @@ public final class AdditionCommutesParallel { public static void main(final String[] args) { final ExecutorService pool = Executors.newFixedThreadPool(8); final Strategy s = Strategy.executorStrategy(pool); - final Property p = propertyP(arbInteger, arbInteger, new F2>() { - public P1 f(final Integer a, final Integer b) { - return s.par(P.lazy(() -> prop(a + b == b + a))); - } - }); + final Property p = propertyP(arbInteger, arbInteger, (a, b) -> s.par(P.lazy(() -> prop(a + b == b + a)))); summary.println(p.check(1000000, 5000000, 0, 100)); // OK, passed 1000000 tests. pool.shutdown(); } diff --git a/demo/src/main/java/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java index bc150fa7..86891242 100644 --- a/demo/src/main/java/fj/demo/test/EqualsHashCode.java +++ b/demo/src/main/java/fj/demo/test/EqualsHashCode.java @@ -69,19 +69,11 @@ public String f(final Character c1, final Character c2, final Character c3) { // Arbitrary for MyClass that uses the restrictive arbitraries above. // We are using the monad pattern (bind) to make this a trivial exercise. - final Arbitrary arbMyClass = arbitrary(arbByteR.gen.bind(arbStringR.gen, curry(new F2() { - public MyClass f(final Byte b, final String s) { - return new MyClass(b, s); - } - }))); + final Arbitrary arbMyClass = arbitrary(arbByteR.gen.bind(arbStringR.gen, curry((b, s) -> new MyClass(b, s)))); // Finally the property. // if m1 equals m2, then this implies that m1's hashCode is equal to m2's hashCode. - final Property p = property(arbMyClass, arbMyClass, new F2() { - public Property f(final MyClass m1, final MyClass m2) { - return bool(m1.equals(m2)).implies(m1.hashCode() == m2.hashCode()); - } - }); + final Property p = property(arbMyClass, arbMyClass, (m1, m2) -> bool(m1.equals(m2)).implies(m1.hashCode() == m2.hashCode())); // at least 100 from 10,000 should satisfy the premise (m1.equals(m2)) summary.println(p.check(100, 10000, 0, 100)); // OK, passed 100 tests (4776 discarded). } diff --git a/demo/src/main/java/fj/demo/test/IntegerOverflow.java b/demo/src/main/java/fj/demo/test/IntegerOverflow.java index c82a2102..155f8495 100644 --- a/demo/src/main/java/fj/demo/test/IntegerOverflow.java +++ b/demo/src/main/java/fj/demo/test/IntegerOverflow.java @@ -16,11 +16,7 @@ public final class IntegerOverflow { public static void main(final String[] args) { final Property p = property(arbIntegerBoundaries, arbIntegerBoundaries, shrinkInteger, shrinkInteger, - new F2() { - public Property f(final Integer a, final Integer b) { - return bool(a > 0 && b > 0).implies(a + b > 0); - } - }); + (a, b) -> bool(a > 0 && b > 0).implies(a + b > 0)); summary.println(p.check()); // Falsified after 4 passed tests with arguments: [8,2147483647] } } diff --git a/demo/src/main/java/fj/demo/test/JavaLinkedList.java b/demo/src/main/java/fj/demo/test/JavaLinkedList.java index eb8b2bd8..0954c705 100644 --- a/demo/src/main/java/fj/demo/test/JavaLinkedList.java +++ b/demo/src/main/java/fj/demo/test/JavaLinkedList.java @@ -17,12 +17,10 @@ public final class JavaLinkedList { public static void main(final String[] args) { final Property p = property(arbLinkedList(arbInteger), arbLinkedList(arbInteger), - new F2, LinkedList, Property>() { - public Property f(final LinkedList x, final LinkedList y) { + (x, y) -> { final LinkedList xy = new LinkedList(x); xy.addAll(y); return prop(xy.size() == x.size() + y.size()); - } }); summary.println(p.check()); // OK, passed 100 tests. } diff --git a/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java index f5cf0e40..675c8eff 100644 --- a/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java +++ b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java @@ -21,11 +21,7 @@ For any Option (o) and any function (f), then calling flatMap on o with a */ public final class OptionMonadFunctorLaw { public static void main(final String[] args) { - final Property unitMap = property(arbOption(arbInteger), Arbitrary.arbFInvariant(arbString), new F2, F, Property>() { - public Property f(final Option o, final F f) { - return prop(optionEqual(stringEqual).eq(o.bind(andThen(f, Option.some_())), o.map(f))); - } - }); + final Property unitMap = property(arbOption(arbInteger), Arbitrary.arbFInvariant(arbString), (o, f) -> prop(optionEqual(stringEqual).eq(o.bind(andThen(f, Option.some_())), o.map(f)))); summary.println(unitMap.minSuccessful(500)); // OK, passed 500 tests. } } diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 556e10ca..9ff45dfe 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -125,8 +125,7 @@ public B f(final Rand r) { * @return A generator that produces values that meet the given predicate. */ public Gen filter(final F f) { - return gen(curry(new F2() { - public A f(final Integer i, final Rand r) { + return gen(curry((i, r) -> { A a; do { @@ -134,7 +133,6 @@ public A f(final Integer i, final Rand r) { } while(!f.f(a)); return a; - } })); } @@ -359,11 +357,7 @@ public static Gen> sequenceN(final int n, final Gen g) { * @return A new generator. */ public static Gen parameterised(final F>> f) { - return new Gen(curry(new F2() { - public A f(final Integer i, final Rand r) { - return f.f(i).f(r).gen(i, r); - } - })); + return new Gen(curry((i, r) -> f.f(i).f(r).gen(i, r))); } /** @@ -404,11 +398,7 @@ public A f(final Rand r) { public static Gen choose(final int from, final int to) { final int f = min(from, to); final int t = max(from, to); - return parameterised(curry(new F2>() { - public Gen f(final Integer i, final Rand r) { - return value(r.choose(f, t)); - } - })); + return parameterised(curry((i, r) -> value(r.choose(f, t)))); } /** From 721118902a5af76665df347b073534debf384f69 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 27 Aug 2015 21:03:33 +1000 Subject: [PATCH 406/811] Replaced anonymous F3s with lambdas --- core/src/main/java/fj/data/hlist/HList.java | 12 ++---------- demo/src/main/java/fj/demo/test/EqualsHashCode.java | 6 +----- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/fj/data/hlist/HList.java b/core/src/main/java/fj/data/hlist/HList.java index 9cbc492e..b02d9504 100644 --- a/core/src/main/java/fj/data/hlist/HList.java +++ b/core/src/main/java/fj/data/hlist/HList.java @@ -212,11 +212,7 @@ private HFoldr(final F3 foldRight) { * @return a fold instance for the empty list. */ public static HFoldr hFoldr() { - return new HFoldr(new F3() { - public V f(final G f, final V v, final HNil hNil) { - return v; - } - }); + return new HFoldr((f, v, hNil) -> v); } /** @@ -238,11 +234,7 @@ public V f(final G f, final V v, final HNil hNil) { H extends HFoldr, PP extends Apply, RR>> HFoldr, RR> hFoldr(final PP p, final H h) { - return new HFoldr, RR>(new F3, RR>() { - public RR f(final G f, final V v, final HCons c) { - return p.apply(f, P.p(c.head(), h.foldRight(f, v, c.tail()))); - } - }); + return new HFoldr, RR>((f, v, c) -> p.apply(f, P.p(c.head(), h.foldRight(f, v, c.tail())))); } /** diff --git a/demo/src/main/java/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java index 86891242..20a732a2 100644 --- a/demo/src/main/java/fj/demo/test/EqualsHashCode.java +++ b/demo/src/main/java/fj/demo/test/EqualsHashCode.java @@ -61,11 +61,7 @@ public static void main(final String[] args) { final Arbitrary arbByteR = arbitrary(arbByte.gen.map(b -> (byte)(b % 3))); // Restrictive arbitrary for String, produces from twelve (2 * 3 * 2) possible values. - final Arbitrary arbStringR = arbitrary(arbCharacter.gen.bind(arbCharacter.gen, arbCharacter.gen, curry(new F3() { - public String f(final Character c1, final Character c2, final Character c3) { - return new String(new char[]{(char)(c1 % 2 + 'a'), (char)(c2 % 3 + 'a'), (char)(c3 % 2 + 'a')}); - } - }))); + final Arbitrary arbStringR = arbitrary(arbCharacter.gen.bind(arbCharacter.gen, arbCharacter.gen, curry((c1, c2, c3) -> new String(new char[]{(char)(c1 % 2 + 'a'), (char)(c2 % 3 + 'a'), (char)(c3 % 2 + 'a')})))); // Arbitrary for MyClass that uses the restrictive arbitraries above. // We are using the monad pattern (bind) to make this a trivial exercise. From 13ebd6f22db7a8bf8247f0f4ea4ac3cd8afef4b9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 28 Aug 2015 00:57:16 +1000 Subject: [PATCH 407/811] Added java core module --- java-core/build.gradle | 16 ++++++++++++++++ .../src/main/java/fj/java/util/ListUtil.java | 14 ++++++++++++++ settings.gradle | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 java-core/build.gradle create mode 100644 java-core/src/main/java/fj/java/util/ListUtil.java diff --git a/java-core/build.gradle b/java-core/build.gradle new file mode 100644 index 00000000..88e9a25f --- /dev/null +++ b/java-core/build.gradle @@ -0,0 +1,16 @@ + +archivesBaseName = "${project.projectName}-${project.name}" + +ext { + signModule = true +} + +dependencies { + compile project(":core") + testCompile dependencyJunit +} + +performSigning(signingEnabled, signModule) +configureUpload(signingEnabled, signModule) + +uploadArchives.enabled = true diff --git a/java-core/src/main/java/fj/java/util/ListUtil.java b/java-core/src/main/java/fj/java/util/ListUtil.java new file mode 100644 index 00000000..9df37601 --- /dev/null +++ b/java-core/src/main/java/fj/java/util/ListUtil.java @@ -0,0 +1,14 @@ +package fj.java.util; + +import fj.F; +import java.util.List; + +/** + * Created by MarkPerry on 28/08/2015. + */ +public class ListUtil { + + public static List map(List list, F f) { + return fj.data.List.list(list).map(f).toJavaList(); + } +} diff --git a/settings.gradle b/settings.gradle index cd29326d..e936f374 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = "functionaljava" -include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck" +include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck", "java-core" From 8eb43cec7b48344dbb95604ce9a09a9cd9bc8f3d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 28 Aug 2015 00:57:54 +1000 Subject: [PATCH 408/811] Updated all sub component names --- consume/build.gradle | 2 ++ demo/build.gradle | 2 ++ props-core/build.gradle | 2 ++ 3 files changed, 6 insertions(+) diff --git a/consume/build.gradle b/consume/build.gradle index 57c82333..7cc58a0c 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -1,4 +1,6 @@ +archivesBaseName = "${project.projectName}-${project.name}" + dependencies { compile("$group:$projectName:$fjConsumeVersion") } diff --git a/demo/build.gradle b/demo/build.gradle index 851ff614..0b83f4f8 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -3,6 +3,8 @@ apply plugin: 'application' mainClassName = "fj.demo.euler.Problem2" +archivesBaseName = "${project.projectName}-${project.name}" + configureAllRetroLambda() dependencies { diff --git a/props-core/build.gradle b/props-core/build.gradle index c146bc36..d697cff5 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -1,4 +1,6 @@ +archivesBaseName = "${project.projectName}-${project.name}" + configureAllRetroLambda() dependencies { From 4611c3524eca1786c112fcae0a727f2243b2d492 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 28 Aug 2015 01:50:18 +1000 Subject: [PATCH 409/811] Implement filter, fold, bind for java.util.List --- .../src/main/java/fj/java/util/ListUtil.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/java-core/src/main/java/fj/java/util/ListUtil.java b/java-core/src/main/java/fj/java/util/ListUtil.java index 9df37601..343ce7ae 100644 --- a/java-core/src/main/java/fj/java/util/ListUtil.java +++ b/java-core/src/main/java/fj/java/util/ListUtil.java @@ -1,6 +1,8 @@ package fj.java.util; import fj.F; +import fj.F2; + import java.util.List; /** @@ -11,4 +13,21 @@ public class ListUtil { public static List map(List list, F f) { return fj.data.List.list(list).map(f).toJavaList(); } + + public static List filter(List list, F f) { + return fj.data.List.list(list).filter(f).toJavaList(); + } + + public static B fold(List list, F2 f, B b) { + return fj.data.List.list(list).foldLeft(f, b); + } + + public static List flatMap(List list, F> f) { + return fj.data.List.list(list).bind(a -> fj.data.List.list(f.f(a))).toJavaList(); + } + + public static List bind(List list, F> f) { + return flatMap(list, f); + } + } From d04b616d3c75ead5f688f7abb21c862c6532b9c3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 29 Aug 2015 17:26:53 +1000 Subject: [PATCH 410/811] #185: Added tree isLeaf and isEmpty --- core/src/main/java/fj/data/Tree.java | 8 ++++ core/src/test/java/fj/data/TreeTest.java | 52 ++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 core/src/test/java/fj/data/TreeTest.java diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 777d39e8..f02a6e73 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -338,4 +338,12 @@ private static F, A> getRoot() { return a -> a.root(); } + public boolean isLeaf() { + return subForest._1().isEmpty(); + } + + public int length() { + return 1 + subForest._1().map(t -> t.length()).foldLeft((acc, i) -> acc + i, 0); + } + } \ No newline at end of file diff --git a/core/src/test/java/fj/data/TreeTest.java b/core/src/test/java/fj/data/TreeTest.java new file mode 100644 index 00000000..811826fb --- /dev/null +++ b/core/src/test/java/fj/data/TreeTest.java @@ -0,0 +1,52 @@ +package fj.data; + +import org.junit.Assert; +import org.junit.Test; + +import static fj.data.Tree.leaf; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.*; + +/** + * Created by MarkPerry on 29/08/2015. + */ +public class TreeTest { + + @Test + public void emptyLength() { + Tree t = leaf(1); + assertThat(t.length(), equalTo(1)); + } + + @Test + public void shallowStreamLength() { + Tree t2 = Tree.node(3, Stream.stream(leaf(4), leaf(5))); + assertThat(t2.length(), equalTo(3)); + } + + @Test + public void deepStreamLength() { + Tree t3 = Tree.node(4, Stream.stream(leaf(5), Tree.node(6, Stream.stream(leaf(7), leaf(8))))); + assertThat(t3.length(), equalTo(5)); + } + + + @Test + public void singleIsLeft() { + Tree t = leaf(1); + assertThat(t.isLeaf(), equalTo(true)); + } + + @Test + public void shallowStreamIsLeaf() { + Tree t2 = Tree.node(3, Stream.stream(leaf(4), leaf(5))); + assertThat(t2.isLeaf(), equalTo(false)); + } + + @Test + public void deepStreamIsLeaf() { + Tree t3 = Tree.node(4, Stream.stream(leaf(5), Tree.node(6, Stream.stream(leaf(7), leaf(8))))); + assertThat(t3.isLeaf(), equalTo(false)); + } + +} From 63c87b8526fff5559285a5d6efbd1de866757a62 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 29 Aug 2015 17:57:27 +1000 Subject: [PATCH 411/811] #176: Added min and max to Set --- core/src/main/java/fj/data/Set.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 21723185..14e07a9e 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -4,6 +4,7 @@ import static fj.Function.*; import static fj.data.Either.right; +import static fj.data.Option.none; import static fj.data.Option.some; import static fj.function.Booleans.not; @@ -387,6 +388,14 @@ public static F, F, Set>> minus() { return curry((s1, s2) -> s1.minus(s2)); } + public Option min() { + return isEmpty() ? none() : l().min().orElse(some(head())); + } + + public Option max() { + return isEmpty() ? none() : r().max().orElse(some(head())); + } + /** * Returns the size of this set. * From 2ac9d5222842e83c93dcd169fb63180a009c9a4f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 29 Aug 2015 23:55:36 +1000 Subject: [PATCH 412/811] #176: Implemented min, minKey, max and maxKey for tree maps. Added arbitrary tree maps. --- core/src/main/java/fj/data/TreeMap.java | 28 ++++++++ core/src/test/java/fj/data/TreeMapTest.java | 10 +++ .../main/scala/fj/data/ArbitraryTreeMap.scala | 16 ----- .../src/test/scala/fj/Tests.scala | 1 - .../src/test/scala/fj/data/CheckTreeMap.scala | 21 ------ .../fj/data/properties/TreeMapProperties.java | 69 +++++++++++++++++++ .../src/main/java/fj/test/Arbitrary.java | 49 +++++++++++-- .../src/main/java/fj/test/Property.java | 16 +++++ .../fj/test/runner/PropertyTestRunner.java | 7 +- 9 files changed, 173 insertions(+), 44 deletions(-) delete mode 100644 props-core-scalacheck/src/main/scala/fj/data/ArbitraryTreeMap.scala delete mode 100644 props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala create mode 100644 props-core/src/test/java/fj/data/properties/TreeMapProperties.java diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 01c5bc6f..2346572f 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -308,6 +308,34 @@ public TreeMap map(final F f) { return new TreeMap(tree.map(TreeMap.>ord(o), g)); } + /** + * Returns the minimum (key, value) pair in the tree if the tree is not empty. + */ + public Option> min() { + return tree.min().map(p -> p(p._1(), p._2().some())); + } + + /** + * Returns the minimum key in the tree if the tree is not empty. + */ + public Option minKey() { + return tree.min().map(p -> p._1()); + } + + /** + * Returns the maximum (key, value) pair in the tree if the tree is not empty. + */ + public Option> max() { + return tree.max().map(p -> p(p._1(), p._2().some())); + } + + /** + * Returns the maximum key in the tree if the tree is not empty. + */ + public Option maxKey() { + return tree.max().map(p -> p._1()); + } + /** * The expression t1.union(t2) takes the left-biased union of t1 * and t2. It prefers t1 when duplicate keys are encountered. diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index cbfec54e..4c847343 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -11,6 +11,7 @@ import org.junit.Test; import static fj.P.p; +import static fj.data.Option.none; import static fj.data.Option.some; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; @@ -112,4 +113,13 @@ public void testString() { assertThat(t2.toStream(), equalTo(s)); } + @Test + public void minKey() { + TreeMap t1 = TreeMap.empty(Ord.intOrd); + assertThat(t1.minKey(), equalTo(none())); + TreeMap t2 = t1.set(1, 2).set(2, 4).set(10, 20).set(5, 10).set(0, 100); + assertThat(t2.minKey(), equalTo(some(0))); + assertThat(t2.delete(0).minKey(), equalTo(some(1))); + } + } diff --git a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryTreeMap.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryTreeMap.scala deleted file mode 100644 index 5eed461c..00000000 --- a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryTreeMap.scala +++ /dev/null @@ -1,16 +0,0 @@ -package fj -package data - -import org.scalacheck.{Arbitrary, Gen} -import TreeMap.empty; -import org.scalacheck.Arbitrary.arbitrary - -object ArbitraryTreeMap { - implicit def arbitraryTreeMap[K, V](implicit ak: Arbitrary[K], - av: Arbitrary[V], - o: Ord[K]): Arbitrary[TreeMap[K, V]] = - Arbitrary(treeOf(arbitrary[(K, V)], o)) - - def treeOf[K, V](g : => Gen[(K, V)], o : Ord[K]) : Gen[TreeMap[K, V]] = - Gen.listOf(g).map(_.foldLeft(empty(o):TreeMap[K, V])((m:TreeMap[K, V], p:(K, V)) => m.set(p._1, p._2))) -} diff --git a/props-core-scalacheck/src/test/scala/fj/Tests.scala b/props-core-scalacheck/src/test/scala/fj/Tests.scala index 3f353e52..60c2f009 100644 --- a/props-core-scalacheck/src/test/scala/fj/Tests.scala +++ b/props-core-scalacheck/src/test/scala/fj/Tests.scala @@ -13,7 +13,6 @@ object Tests { fj.data.CheckHashMap.properties, fj.data.CheckHashSet.properties, fj.data.CheckSet.properties, - fj.data.CheckTreeMap.properties, fj.control.parallel.CheckStrategy.properties, fj.control.parallel.CheckParModule.properties ).flatten diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala deleted file mode 100644 index 25a7719a..00000000 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckTreeMap.scala +++ /dev/null @@ -1,21 +0,0 @@ -package fj -package data - -import Ord.{intOrd, stringOrd} -import org.scalacheck.Prop._ -import ArbitraryTreeMap._ -import org.scalacheck.Properties - -object CheckTreeMap extends Properties("TreeMap") { - def idInt(n: Int) = n:java.lang.Integer - implicit def oi : Ord[Int] = intOrd.contramap(idInt _) - implicit def os : Ord[String] = stringOrd - - property("set") = forAll((m: TreeMap[Int, String], k: Int, v: String) => m.set(k, v).get(k).some == v) - - property("updateId") = forAll((m: TreeMap[Int, String], k: Int, v: String) => - m.set(k, v).update(k, (x: String) => x)._2.get(k).some == v) - - property("update") = forAll((m: TreeMap[Int, String], k: Int, v: String, c: Char) => - m.set(k, v).update(k, (x: String) => c + x)._2.get(k).some.equals(c + v)) -} diff --git a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java new file mode 100644 index 00000000..f4440d79 --- /dev/null +++ b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java @@ -0,0 +1,69 @@ +package fj.data.properties; + +import fj.Equal; +import fj.data.TreeMap; +import fj.test.Arbitrary; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import java.util.concurrent.atomic.AtomicInteger; + +import static fj.Equal.stringEqual; +import static fj.Ord.intOrd; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbString; +import static fj.test.Arbitrary.arbTreeMap; +import static fj.test.Property.*; + +/** + * Created by MarkPerry on 29/08/2015. + */ +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class TreeMapProperties { + + private static final int smallMax = 5; + private static final int midMax = 20; + public static final Arbitrary> smallArbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, smallMax); + public static final Arbitrary> arbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, midMax); + + public Property empty() { + return property(smallArbTreeMapIS, tm -> impliesBoolean(tm.isEmpty(), tm.size() == 0)); + } + + public Property set() { + return property(arbTreeMapIS, arbInteger, arbString, (tm, k, v) -> + prop(stringEqual.eq(tm.set(k, v).get(k).some(), v)) + ); + } + + public Property updateId() { + return property(arbTreeMapIS, arbInteger, arbString, (tm, k, v) -> + prop(stringEqual.eq(tm.set(k, v).update(k, x -> x)._2().get(k).some(), v)) + ); + } + + public Property update() { + return property(arbTreeMapIS, arbInteger, arbString, arbString, (tm, k, v, v2) -> + prop(stringEqual.eq(tm.set(k, v).update(k, x -> x + v2)._2().get(k).some(), v + v2)) + ); + } + + public Property minKey() { + return property(arbTreeMapIS, tm -> + impliesBoolean(!tm.isEmpty(), () -> Equal.intEqual.eq(tm.minKey().some(), tm.toStream().head()._1())) + ); + } + + public Property maxKey() { + return property(arbTreeMapIS, tm -> + impliesBoolean(!tm.isEmpty(), + () -> Equal.intEqual.eq(tm.maxKey().some(), tm.toStream().reverse().head()._1()) + ) + ); + } + +} diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 571aa149..e12f3d6d 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -9,6 +9,8 @@ import fj.F7; import fj.F8; import fj.Function; +import fj.Bottom; + import static fj.Function.compose; import static fj.P.p; import fj.P1; @@ -1115,22 +1117,59 @@ public Stack f(final Array a) { } /** - * Returns an arbitrary implementation for tree maps. + * Returns an arbitrary implementation for java.util tree maps. * * @param ak An arbitrary implementation for the type over which the tree map's keys are defined. * @param av An arbitrary implementation for the type over which the tree map's values are * defined. * @return An arbitrary implementation for tree maps. */ - public static Arbitrary> arbTreeMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, TreeMap>() { + public static Arbitrary> arbJavaTreeMap(final Arbitrary ak, final Arbitrary av) { + return arbitrary(arbHashtable(ak, av).gen.map(new F, java.util.TreeMap>() { @SuppressWarnings({"UseOfObsoleteCollectionType"}) - public TreeMap f(final Hashtable ht) { - return new TreeMap(ht); + public java.util.TreeMap f(final Hashtable ht) { + return new java.util.TreeMap(ht); } })); } + /** + * Returns an arbitrary implementation for tree maps. + */ + public static Arbitrary> arbTreeMap(Ord ord, Arbitrary>> al) { + return arbitrary(al.gen.map(list -> fj.data.TreeMap.treeMap(ord, list))); + } + + /** + * Returns an arbitrary implementation for tree maps. + */ + public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av) { + return arbTreeMap(ord, arbList(arbP2(ak, av))); + } + + /** + * Returns an arbitrary implementation for tree maps where the map size is the given arbitrary integer. + */ + public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av, Arbitrary ai) { + Gen>> gl2 = ai.gen.bind(i -> { + if (i < 0) { + Bottom.error("Undefined: arbitrary natural is negative (" + i + ")"); + } + return Gen.sequenceN(Math.max(i, 0), Arbitrary.arbP2(ak, av).gen); + }); + return arbTreeMap(ord, arbitrary(gl2)); + } + + /** + * Returns an arbitrary implementation for tree maps where the size is less than or equal to the max size. + */ + public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av, int maxSize) { + if (maxSize < 0) { + Bottom.error("Undefined: arbitrary natural is negative (" + maxSize + ")"); + } + return arbTreeMap(ord, ak, av, arbitrary(Gen.choose(0, maxSize))); + } + /** * Returns an arbitrary implementation for tree sets. * diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 04b9d93c..232911bd 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -362,6 +362,22 @@ public Result f(final Rand r) { }); } + /** + * Returns a property that produces a result only if the given condition satisfies. The result + * will be taken from the given boolean b. + */ + public static Property impliesBoolean(final boolean a, final boolean b) { + return implies(a, () -> Property.prop(b)); + } + + /** + * Returns a property that produces a result only if the given condition satisfies. The result + * will be taken from the given lazy boolean b. + */ + public static Property impliesBoolean(final boolean a, final F0 b) { + return implies(a, () -> Property.prop(b.f())); + } + /** * Returns a property from the given function. * diff --git a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java index 3537fe92..7f2b04ce 100644 --- a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java +++ b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java @@ -43,7 +43,8 @@ public void run(RunNotifier notifier) { CheckResult result = checkProperty(p._1(), p._2()); try { - CheckResult.summaryEx.showS(result); + String s = CheckResult.summaryEx.showS(result); + System.out.println(getLabel(desc) + ": " + s); } catch (Throwable t) { notifier.fireTestFailure(new Failure(desc, t)); } @@ -52,6 +53,10 @@ public void run(RunNotifier notifier) { }); } + private static String getLabel(Description d) { + return d.getDisplayName(); + } + private static CheckResult checkProperty(Property prop, Option params) { for (CheckParams ps : params) { return prop.check(ps.minSuccessful(), ps.maxDiscarded(), ps.minSize(), ps.maxSize()); From c7f1c4105a49d1f394af7951f36541e5ad0e88b2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 30 Aug 2015 01:46:05 +1000 Subject: [PATCH 413/811] #175: Added Set toStream and TreeMap toList and toStream --- core/src/main/java/fj/Ord.java | 8 +++++++ core/src/main/java/fj/data/Set.java | 14 +++++++++---- core/src/main/java/fj/data/TreeMap.java | 11 +++++++--- .../fj/data/properties/SetProperties.java | 17 +++++++++++++-- .../fj/data/properties/TreeMapProperties.java | 21 +++++++++++++++++++ .../src/main/java/fj/test/Arbitrary.java | 8 ++++++- 6 files changed, 69 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 0d24a768..a7a39cac 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -458,6 +458,14 @@ public static Ord> p2Ord(final Ord oa, final Ord ob) { return ord(curry((P2 a, P2 b) -> oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1()))); } + public static Ord> p2Ord1(Ord oa) { + return ord(p1 -> p2 -> oa.compare(p1._1(), p2._1())); + } + + public static Ord> p2Ord2(Ord ob) { + return ord(p1 -> p2 -> ob.compare(p1._2(), p2._2())); + } + /** * An order instance for a product-3, with the first factor considered most significant. * diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 14e07a9e..f4bbb208 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -283,11 +283,17 @@ public final List toList() { * * @return a stream representation of this set. */ - public final Stream toStream() { - return foldMap(Stream.single(), Monoid.streamMonoid()); - } + public final Stream toStream() { + if (isEmpty()) { + return Stream.nil(); + } else if (l().isEmpty()) { + return Stream.cons(head(), () -> r().toStream()); + } else { + return l().toStream().append(Stream.cons(head(), () -> r().toStream())); + } + } - /** + /** * Binds the given function across this set. * * @param o An order for the elements of the target set. diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 2346572f..cbe47522 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -182,9 +182,14 @@ public Map toMutableMap() { return m; } - public Stream> toStream() { - return Stream.iteratorStream(iterator()); - } + public Stream> toStream() { + return tree.toStream().map(p -> p.map2(o -> o.some())); + } + + public List> toList() { + return tree.toList().map(p -> p.map2(o -> o.some())); + } + /** * An immutable projection of the given mutable map. * diff --git a/props-core/src/test/java/fj/data/properties/SetProperties.java b/props-core/src/test/java/fj/data/properties/SetProperties.java index ba807936..11fc7af5 100644 --- a/props-core/src/test/java/fj/data/properties/SetProperties.java +++ b/props-core/src/test/java/fj/data/properties/SetProperties.java @@ -2,13 +2,16 @@ import fj.Equal; import fj.Ord; +import fj.data.List; import fj.data.Set; +import fj.data.Stream; import fj.test.Arbitrary; import fj.test.Property; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; import org.junit.runner.RunWith; +import static fj.test.Property.prop; import static fj.test.Property.property; /** @@ -18,9 +21,19 @@ @CheckParams(maxSize = 10000) public class SetProperties { + public final static Arbitrary> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger, 5); + Property setToListIsSorted() { - Arbitrary> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger); - return property(as, s -> Property.prop(s.toList().equals(s.toList().sort(Ord.intOrd)))); + return property(as, s -> prop(s.toList().equals(s.toList().sort(Ord.intOrd)))); } + Property stream() { + return property(as, s -> { + Equal> eq = Equal.listEqual(Equal.intEqual); + List l1 = s.toList(); + List l2 = s.toStream().toList(); + return prop(eq.eq(l1, l2)); + }); + } + } diff --git a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java index f4440d79..8dd718ee 100644 --- a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java +++ b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java @@ -1,6 +1,10 @@ package fj.data.properties; import fj.Equal; +import fj.Ord; +import fj.P2; +import fj.data.List; +import fj.data.Stream; import fj.data.TreeMap; import fj.test.Arbitrary; import fj.test.Gen; @@ -11,6 +15,8 @@ import java.util.concurrent.atomic.AtomicInteger; +import static fj.Equal.intEqual; +import static fj.Equal.p2Equal; import static fj.Equal.stringEqual; import static fj.Ord.intOrd; import static fj.test.Arbitrary.arbInteger; @@ -29,6 +35,9 @@ public class TreeMapProperties { private static final int midMax = 20; public static final Arbitrary> smallArbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, smallMax); public static final Arbitrary> arbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, midMax); + public static final Ord> p2Ord = Ord.p2Ord1(Ord.intOrd); + Equal>> listEq = Equal.listEqual(p2Equal(intEqual, stringEqual)); + public Property empty() { return property(smallArbTreeMapIS, tm -> impliesBoolean(tm.isEmpty(), tm.size() == 0)); @@ -66,4 +75,16 @@ public Property maxKey() { ); } + Property listSize() { + return property(arbTreeMapIS, tm -> prop(tm.size() == tm.toList().length())); + } + + Property listSorted() { + return property(arbTreeMapIS, tm -> prop(listEq.eq(tm.toList(), tm.toList().sort(p2Ord)))); + } + + Property listStreamEq() { + return property(arbTreeMapIS, tm -> prop(listEq.eq(tm.toList(), tm.toStream().toList()))); + } + } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index e12f3d6d..479e3d0d 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -818,7 +818,13 @@ public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { return arbitrary(arbList(aa).gen.map(list -> Set.set(ord, list))); } - /** + public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, int max) { + Gen> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.set(ord, list)); + return arbitrary(g); + } + + + /** * Returns an arbitrary implementation for throwables. * * @param as An arbitrary used for the throwable message. From 87db1bd86d9439382e6d2b1dadecf4110147bc56 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 30 Aug 2015 20:55:52 +1000 Subject: [PATCH 414/811] #177: Implemented toListReverse and toStreamReverse for Set and TreeMap --- core/src/main/java/fj/data/Set.java | 37 +++++++++++++++++++ core/src/main/java/fj/data/TreeMap.java | 8 ++++ .../fj/data/properties/SetProperties.java | 15 +++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index f4bbb208..0b7f4a0f 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -269,6 +269,19 @@ public final B foldMap(final F f, final Monoid m) { m.sum(m.sum(l().foldMap(f, m), f.f(head())), r().foldMap(f, m)); } + /** + * Folds this Set from the right using the given monoid. + * + * @param f A transformation from this Set's elements, to the monoid. + * @param m The monoid to fold this Set with. + * @return The result of folding the Set from the right with the given monoid. + */ + public final B foldMapRight(final F f, final Monoid m) { + return isEmpty() ? + m.zero() : + m.sum(m.sum(r().foldMapRight(f, m), f.f(head())), l().foldMapRight(f, m)); + } + /** * Returns a list representation of this set. * @@ -278,6 +291,15 @@ public final List toList() { return foldMap(List.cons(List.nil()), Monoid.listMonoid()); } + /** + * Returns a list representation of this set in reverse order. + * + * @return a list representation of this set in reverse order. + */ + public final List toListReverse() { + return foldMapRight(List.cons(List.nil()), Monoid.listMonoid()); + } + /** * Returns a stream representation of this set. * @@ -293,6 +315,21 @@ public final Stream toStream() { } } + /** + * Returns a stream representation of this set in reverse order. + * + * @return a stream representation of this set in reverse order. + */ + public final Stream toStreamReverse() { + if (isEmpty()) { + return Stream.nil(); + } else if (r().isEmpty()) { + return Stream.cons(head(), () -> l().toStreamReverse()); + } else { + return r().toStreamReverse().append(Stream.cons(head(), () -> l().toStreamReverse())); + } + } + /** * Binds the given function across this set. * diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index cbe47522..698fe697 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -186,10 +186,18 @@ public Stream> toStream() { return tree.toStream().map(p -> p.map2(o -> o.some())); } + public Stream> toStreamReverse() { + return tree.toStreamReverse().map(p -> p.map2(o -> o.some())); + } + public List> toList() { return tree.toList().map(p -> p.map2(o -> o.some())); } + public List> toListReverse() { + return tree.toListReverse().map(p -> p.map2(o -> o.some())); + } + /** * An immutable projection of the given mutable map. * diff --git a/props-core/src/test/java/fj/data/properties/SetProperties.java b/props-core/src/test/java/fj/data/properties/SetProperties.java index 11fc7af5..84c7e40c 100644 --- a/props-core/src/test/java/fj/data/properties/SetProperties.java +++ b/props-core/src/test/java/fj/data/properties/SetProperties.java @@ -21,7 +21,9 @@ @CheckParams(maxSize = 10000) public class SetProperties { - public final static Arbitrary> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger, 5); + public final static int maxSize = 20; + public final static Arbitrary> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger, maxSize); + public final static Equal> eq = Equal.listEqual(Equal.intEqual); Property setToListIsSorted() { return property(as, s -> prop(s.toList().equals(s.toList().sort(Ord.intOrd)))); @@ -29,11 +31,20 @@ Property setToListIsSorted() { Property stream() { return property(as, s -> { - Equal> eq = Equal.listEqual(Equal.intEqual); List l1 = s.toList(); List l2 = s.toStream().toList(); return prop(eq.eq(l1, l2)); }); } + Property listReverse() { + return property(as, s -> { + return prop(eq.eq(s.toList().reverse(), s.toListReverse())); + }); + } + + Property streamReverse() { + return property(as, s -> prop(eq.eq(s.toStream().toList().reverse(), s.toStreamReverse().toList()))); + } + } From cf074892be69f27bc0aa29068a4ad8db66d25d6b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 30 Aug 2015 23:53:27 +1000 Subject: [PATCH 415/811] Added integrated view of test coverage. Turn retro lambda off temporarily --- build.gradle | 34 ++++++++++++++++++++++- consume/build.gradle | 2 ++ consume/src/test/java/fj/EmptyTest.java | 18 ++++++++++++ core/build.gradle | 14 ---------- demo/src/test/java/fj/EmptyTest.java | 18 ++++++++++++ java-core/src/test/java/fj/EmptyTest.java | 17 ++++++++++++ java8/src/test/java/fj/EmptyTest.java | 17 ++++++++++++ 7 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 consume/src/test/java/fj/EmptyTest.java create mode 100644 demo/src/test/java/fj/EmptyTest.java create mode 100644 java-core/src/test/java/fj/EmptyTest.java create mode 100644 java8/src/test/java/fj/EmptyTest.java diff --git a/build.gradle b/build.gradle index 81139aac..12b7fecb 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,12 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { + apply plugin: "jacoco" + + jacoco { + toolVersion = "0.7.1.201405082137" + } + defaultTasks "build" ext { @@ -43,7 +49,7 @@ allprojects { fjConsumeVersion = "4.4" signModule = false - useRetroLambda = true + useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" @@ -70,6 +76,10 @@ allprojects { retroLambdaTarget = JavaVersion.VERSION_1_7 } + repositories { + jcenter() + } + version = fjVersion group = "org.functionaljava" @@ -96,6 +106,28 @@ subprojects { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" } } + + jacocoTestReport { + reports { + html.enabled = true + xml.enabled = true + csv.enabled = false +// html.destination "${buildDir}/jacocoHtml" + } + } + +} + +task coverageRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) { + dependsOn = subprojects.test + sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) + classDirectories = files(subprojects.sourceSets.main.output) + executionData = files(subprojects.jacocoTestReport.executionData) + reports { + html.enabled = true + xml.enabled = true + csv.enabled = false + } } configure(subprojects.findAll { it.name != "props-core" }) { diff --git a/consume/build.gradle b/consume/build.gradle index 7cc58a0c..ff92a601 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -3,4 +3,6 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { compile("$group:$projectName:$fjConsumeVersion") + + testCompile dependencyJunit } diff --git a/consume/src/test/java/fj/EmptyTest.java b/consume/src/test/java/fj/EmptyTest.java new file mode 100644 index 00000000..e112a97a --- /dev/null +++ b/consume/src/test/java/fj/EmptyTest.java @@ -0,0 +1,18 @@ +package fj; + +import org.junit.Ignore; +import org.junit.Test; + +import org.junit.Assert; + +/** + * Created by MarkPerry on 30/08/2015. + */ +public class EmptyTest { + + @Ignore @Test + public void missing() { + Assert.fail("not implemented"); + + } +} diff --git a/core/build.gradle b/core/build.gradle index f526e289..6831569d 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,6 +1,4 @@ -apply plugin: "jacoco" - ext { signModule = true } @@ -18,18 +16,6 @@ uploadArchives.enabled = true configureAllRetroLambda() -jacoco { - toolVersion = "0.7.1.201405082137" -} - -jacocoTestReport { - reports { - xml.enabled false - csv.enabled false - html.destination "${buildDir}/jacocoHtml" - } -} - task coverage(dependsOn: ["test", "jacocoTestReport"]) << { } diff --git a/demo/src/test/java/fj/EmptyTest.java b/demo/src/test/java/fj/EmptyTest.java new file mode 100644 index 00000000..e112a97a --- /dev/null +++ b/demo/src/test/java/fj/EmptyTest.java @@ -0,0 +1,18 @@ +package fj; + +import org.junit.Ignore; +import org.junit.Test; + +import org.junit.Assert; + +/** + * Created by MarkPerry on 30/08/2015. + */ +public class EmptyTest { + + @Ignore @Test + public void missing() { + Assert.fail("not implemented"); + + } +} diff --git a/java-core/src/test/java/fj/EmptyTest.java b/java-core/src/test/java/fj/EmptyTest.java new file mode 100644 index 00000000..d1088c03 --- /dev/null +++ b/java-core/src/test/java/fj/EmptyTest.java @@ -0,0 +1,17 @@ +package fj; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.Assert; + +/** + * Created by MarkPerry on 30/08/2015. + */ +public class EmptyTest { + + @Ignore @Test + public void missing() { + Assert.fail("not implemented"); + + } +} diff --git a/java8/src/test/java/fj/EmptyTest.java b/java8/src/test/java/fj/EmptyTest.java new file mode 100644 index 00000000..e187cccb --- /dev/null +++ b/java8/src/test/java/fj/EmptyTest.java @@ -0,0 +1,17 @@ +package fj; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Created by MarkPerry on 30/08/2015. + */ +public class EmptyTest { + + @Ignore @Test + public void missing() { + Assert.fail("not implemented"); + + } +} From 647bc57d96051bcc03cba5f89b8f59ca6941e445 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 31 Aug 2015 00:54:05 +1000 Subject: [PATCH 416/811] Added overall coveralls for test coverage on CI --- .travis.yml | 5 ++++- build.gradle | 33 ++++++++++++++++++++++++++++++--- core/build.gradle | 4 ---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 943d82f0..1bd5c803 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,7 @@ addons: script: - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME - - ./gradlew build --stacktrace --info + - ./gradlew build coverage -s -i + +after_success: + - ./gradlew coverageRoot coveralls -s -i diff --git a/build.gradle b/build.gradle index 12b7fecb..86080a58 100644 --- a/build.gradle +++ b/build.gradle @@ -19,9 +19,15 @@ buildscript { dependencies { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" classpath "me.tatarka:gradle-retrolambda:$retrolambdaVersion" + classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1' } } + +apply plugin: "jacoco" +apply plugin: 'com.github.kt3k.coveralls' + + if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { @@ -32,7 +38,7 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { - apply plugin: "jacoco" + jacoco { toolVersion = "0.7.1.201405082137" @@ -78,6 +84,8 @@ allprojects { repositories { jcenter() + mavenCentral() + mavenLocal() } version = fjVersion @@ -87,7 +95,21 @@ allprojects { subprojects { - apply from: "$rootDir/lib.gradle" + + buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1' + } + } + + apply plugin: "jacoco" + apply plugin: 'com.github.kt3k.coveralls' + + apply from: "$rootDir/lib.gradle" apply plugin: "java" apply plugin: "eclipse" apply plugin: "com.ofg.uptodate" @@ -116,9 +138,14 @@ subprojects { } } + + task coverage(dependsOn: ["test", "jacocoTestReport"]) << { + + } + } -task coverageRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) { +task coverageRoot(type: org.gradle.testing.jacoco.tasks.JacocoReport) { dependsOn = subprojects.test sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) classDirectories = files(subprojects.sourceSets.main.output) diff --git a/core/build.gradle b/core/build.gradle index 6831569d..1a1763e7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -15,7 +15,3 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true configureAllRetroLambda() - -task coverage(dependsOn: ["test", "jacocoTestReport"]) << { - -} From 5e2374bd95594f53802ae5253b7812b2bbaea5ce Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 31 Aug 2015 22:22:45 +1000 Subject: [PATCH 417/811] Tidy up coveralls --- .travis.yml | 2 +- build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1bd5c803..eb3778d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,4 +16,4 @@ script: - ./gradlew build coverage -s -i after_success: - - ./gradlew coverageRoot coveralls -s -i + - ./gradlew coverage coveralls -s -i diff --git a/build.gradle b/build.gradle index 86080a58..7445558f 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ buildscript { dependencies { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" classpath "me.tatarka:gradle-retrolambda:$retrolambdaVersion" - classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1' + classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0' } } @@ -145,7 +145,7 @@ subprojects { } -task coverageRoot(type: org.gradle.testing.jacoco.tasks.JacocoReport) { +task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { dependsOn = subprojects.test sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) classDirectories = files(subprojects.sourceSets.main.output) From 67e69b3dcc6f1a53166d4d7ab395b2be81baf75d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 4 Sep 2015 08:13:48 +1000 Subject: [PATCH 418/811] Test empty TreeMap hashCode --- core/src/test/java/fj/data/TreeMapTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 4c847343..e6b66ba2 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -122,4 +122,11 @@ public void minKey() { assertThat(t2.delete(0).minKey(), equalTo(some(1))); } + public void emptyHashCode() { + // Hash code of tree map should not throw NullPointerException + // see https://github.com/functionaljava/functionaljava/issues/187 + int i = TreeMap.empty(Ord.stringOrd).hashCode(); + assertTrue(true); + } + } From b8a8d7d72b330c94b5783d55c90acf43a919a1b1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 4 Sep 2015 08:27:20 +1000 Subject: [PATCH 419/811] Added test annotation to TreeMapTest hashCode --- core/src/test/java/fj/data/TreeMapTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index e6b66ba2..d476d308 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -122,6 +122,7 @@ public void minKey() { assertThat(t2.delete(0).minKey(), equalTo(some(1))); } + @Test public void emptyHashCode() { // Hash code of tree map should not throw NullPointerException // see https://github.com/functionaljava/functionaljava/issues/187 From b95c232f78a9f76ce90311c1d90ffa62b334ee27 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 4 Sep 2015 08:51:39 +1000 Subject: [PATCH 420/811] #188: Made List.intersperse use heap, not stack --- core/src/main/java/fj/data/List.java | 2 +- core/src/test/java/fj/data/ListTest.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 1570a259..403902e1 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1069,7 +1069,7 @@ public final Option find(final F f) { public final List intersperse(final A a) { return isEmpty() || tail().isEmpty() ? this : - cons(head(), cons(a, tail().intersperse(a))); + cons(head(), tail().bind(a2 -> List.list(a, a2))); } /** diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 3639dddb..04c37d2b 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -64,4 +64,12 @@ public void partition() { assertTrue(e.eq(p._2(), List.list(1, 3))); } + @Test + public void intersperseOverflow() { + // should not overflow + int n = 100000; + List list = List.replicate(n, 1).intersperse(2); + String s = list.toString(); + } + } From 92f663384541dfbea013c14b7f60951d925bcd26 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 4 Sep 2015 16:23:26 +1000 Subject: [PATCH 421/811] #189: Replace anonymous P2 with static constructor --- core/src/main/java/fj/P.java | 15 +++----- core/src/main/java/fj/P2.java | 43 ++++------------------- core/src/main/java/fj/Semigroup.java | 10 +----- core/src/main/java/fj/data/Stream.java | 13 +++---- core/src/main/java/fj/data/vector/V.java | 10 +----- core/src/main/java/fj/data/vector/V3.java | 11 +----- 6 files changed, 18 insertions(+), 84 deletions(-) diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 4a203bba..073de4f6 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -233,6 +233,10 @@ public H _8() { }; } + public static P2 lazyProduct(F0> f) { + return P.lazy(() -> f.f()._1(), () -> f.f()._2()); + } + /** * A function that puts an element in a product-2. * @@ -548,16 +552,7 @@ public static P1 lazy(F f) { } public static P2 lazy(F fa, F fb) { - return new P2() { - @Override - public A _1() { - return fa.f(unit()); - } - @Override - public B _2() { - return fb.f(unit()); - } - }; + return P.lazy(() -> fa.f(unit()), () -> fb.f(unit())); } public static P3 lazy(F fa, F fb, F fc) { diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 901fe478..3283f344 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -42,15 +42,7 @@ public int hashCode() { * @return A new product-2 with the elements swapped. */ public final P2 swap() { - return new P2() { - public B _1() { - return P2.this._2(); - } - - public A _2() { - return P2.this._1(); - } - }; + return P.lazy(() -> P2.this._2(), () -> P2.this._1()); } /** @@ -60,15 +52,8 @@ public A _2() { * @return A product with the given function applied. */ public final P2 map1(final F f) { - return new P2() { - public X _1() { - return f.f(P2.this._1()); - } - - public B _2() { - return P2.this._2(); - } - }; + P2 self = this; + return P.lazy(() -> f.f(self._1()), () -> self._2()); } /** @@ -78,15 +63,7 @@ public B _2() { * @return A product with the given function applied. */ public final P2 map2(final F f) { - return new P2() { - public A _1() { - return P2.this._1(); - } - - public X _2() { - return f.f(P2.this._2()); - } - }; + return P.lazy(() -> P2.this._1(), () -> f.f(P2.this._2())); } @@ -112,16 +89,8 @@ public final P2 split(final F f, final F g) { * and with the second element intact. */ public final P2 cobind(final F, C> k) { - return new P2() { - - public C _1() { - return k.f(P2.this); - } - - public B _2() { - return P2.this._2(); - } - }; + P2 self = this; + return P.lazy(() -> k.f(self), () -> self._2()); } /** diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 5d5db1a2..02a0d647 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -316,15 +316,7 @@ public static Semigroup> p1Semigroup(final Semigroup sa) { * @return A semigroup for binary products. */ public static Semigroup> p2Semigroup(final Semigroup sa, final Semigroup sb) { - return semigroup((a1, a2) -> new P2() { - public A _1() { - return sa.sum(a1._1(), a2._1()); - } - - public B _2() { - return sb.sum(a1._2(), a2._2()); - } - }); + return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 5fdcdc72..a3f2cf9c 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1085,15 +1085,10 @@ public final P2, Stream> span(final F p) { return p(this, this); else if (p.f(head())) { final P1, Stream>> yszs = P.lazy(() -> tail()._1().span(p)); - return new P2, Stream>() { - @Override public Stream _1() { - return cons(head(), yszs.map(P2., Stream>__1())); - } - - @Override public Stream _2() { - return yszs._1()._2(); - } - }; + return P.lazy( + () -> cons(head(), yszs.map(P2., Stream>__1())), + () -> yszs._1()._2() + ); } else return p(Stream.nil(), this); } diff --git a/core/src/main/java/fj/data/vector/V.java b/core/src/main/java/fj/data/vector/V.java index 80e1c0f9..84481d96 100644 --- a/core/src/main/java/fj/data/vector/V.java +++ b/core/src/main/java/fj/data/vector/V.java @@ -36,15 +36,7 @@ public static V2 v(final A a1, final A a2) { * @return The vector-2. */ public static V2 v(final F0 a1, final F0 a2) { - return V2.p(new P2() { - public A _1() { - return a1.f(); - } - - public A _2() { - return a2.f(); - } - }); + return V2.p(P.lazy(() -> a1.f(), () -> a2.f())); } /** diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index 65353f8b..22e11946 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -32,16 +32,7 @@ private V3(final P1 head, final V2 tail) { public static V3 p(final P3 p) { return new V3( P.lazy(() -> p._1()), - V2.p(new P2() { - public A _1() { - return p._2(); - } - - public A _2() { - return p._3(); - } - } - ) + V2.p(P.lazy(() -> p._2(), () -> p._3())) ); } From ffeb05b2cf3de0cc576037a8f5306860bb2c254b Mon Sep 17 00:00:00 2001 From: Shintaro Murakami Date: Fri, 4 Sep 2015 22:22:31 +0900 Subject: [PATCH 422/811] Fix bug in Validation.accumulate corresponding to ap4 --- core/src/main/java/fj/data/Validation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 073488ee..60e01b40 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -763,7 +763,7 @@ public Validation, D> accumulate(Validation v2, Validati } } - public Validation, E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { + public Validation, $E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { List list = fails(list(this, v2, v3, v4)); if (!list.isEmpty()) { return Validation.fail(list); From 7e1d3a9300af84b3c4c5204e4b7a5a0e89c44303 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 10 Oct 2015 21:22:08 +1000 Subject: [PATCH 423/811] Added headOption to Sqq and FingerTree. Added length to FingerTree. Added length property test to Seq and FingerTree --- core/src/main/java/fj/data/Seq.java | 4 +++ .../main/java/fj/data/fingertrees/Deep.java | 6 ++++ .../main/java/fj/data/fingertrees/Digit.java | 3 ++ .../main/java/fj/data/fingertrees/Empty.java | 7 ++++- .../java/fj/data/fingertrees/FingerTree.java | 13 ++++++++ .../main/java/fj/data/fingertrees/Four.java | 5 ++++ .../main/java/fj/data/fingertrees/Node.java | 2 ++ .../main/java/fj/data/fingertrees/Node2.java | 7 ++++- .../main/java/fj/data/fingertrees/Node3.java | 7 ++++- .../main/java/fj/data/fingertrees/One.java | 5 ++++ .../main/java/fj/data/fingertrees/Single.java | 7 ++++- .../main/java/fj/data/fingertrees/Three.java | 5 ++++ .../main/java/fj/data/fingertrees/Two.java | 6 ++++ .../fingertrees/FingerTreeProperties.java | 26 ++++++++++++++++ .../fj/data/fingertrees/FingerTreeTest.java | 30 +++++++++++++++++++ .../fj/data/properties/SeqProperties.java | 11 +++++-- 16 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java create mode 100644 props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index a1026e34..6e4c393b 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -100,6 +100,10 @@ public Seq snoc(final A a) { */ public A head() { return ftree.head(); } + public Option headOption() { + return ftree.headOption(); + } + /** * The last element of this sequence. This is an O(1) operation. * diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index 33032743..e42bde4d 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -195,6 +195,12 @@ private static final FingerTree deepR(final Measured measured } } + @Override + public int length() { + int midSize = middle.foldLeft((acc, n) -> acc + n.length(), 0); + return prefix.length() + midSize + suffix.length(); + } + private static FingerTree> addDigits0( final Measured m, final FingerTree> m1, final Digit s1, final Digit p2, diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index 002f9b77..debf2635 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -159,4 +159,7 @@ Option> init() { abstract P3>, A, Option>> split1(final F predicate, final V acc); public abstract P2 lookup(final F o, final int i); + + public abstract int length(); + } diff --git a/core/src/main/java/fj/data/fingertrees/Empty.java b/core/src/main/java/fj/data/fingertrees/Empty.java index 5d034192..17ea5927 100644 --- a/core/src/main/java/fj/data/fingertrees/Empty.java +++ b/core/src/main/java/fj/data/fingertrees/Empty.java @@ -37,7 +37,12 @@ public final class Empty extends FingerTree { @Override public P2 lookup(final F o, final int i) { throw error("Lookup of empty tree."); } - @Override public B foldRight(final F> aff, final B z) { + @Override + public int length() { + return 0; + } + + @Override public B foldRight(final F> aff, final B z) { return z; } diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index a7449fb1..9f86db45 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -4,6 +4,8 @@ import fj.data.Option; import fj.data.Seq; +import static fj.Monoid.intAdditionMonoid; + /** * Provides 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in * amortized O(1) time. Concatenation and splitting time is O(log n) in the size of the smaller piece. @@ -158,6 +160,10 @@ public static MakeTree mkTree(final Measured m) { */ public abstract A head(); + public Option headOption() { + return isEmpty() ? Option.none() : Option.some(head()); + } + /** * The last element of this tree. This is an O(1) operation. * @@ -215,4 +221,11 @@ public final P3, A, FingerTree> split1(final F, A, FingerTree> split1(final F predicate, final V acc); public abstract P2 lookup(final F o, final int i); + + public abstract int length(); + + public static FingerTree emptyIntAddition() { + return FingerTree.mkTree(FingerTree.measured(intAdditionMonoid, Function.constant(1))).empty(); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Four.java b/core/src/main/java/fj/data/fingertrees/Four.java index 1cdf8355..c66ddeca 100644 --- a/core/src/main/java/fj/data/fingertrees/Four.java +++ b/core/src/main/java/fj/data/fingertrees/Four.java @@ -83,4 +83,9 @@ public V4 values() { } } } + + @Override + public int length() { + return 4; + } } diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index dca76b62..3e451766 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -58,4 +58,6 @@ Measured measured() { public abstract P2 lookup(final F o, final int i); public abstract B match(final F, B> n2, final F, B> n3); + + public abstract int length(); } diff --git a/core/src/main/java/fj/data/fingertrees/Node2.java b/core/src/main/java/fj/data/fingertrees/Node2.java index 81b6738d..5fc979be 100644 --- a/core/src/main/java/fj/data/fingertrees/Node2.java +++ b/core/src/main/java/fj/data/fingertrees/Node2.java @@ -58,7 +58,12 @@ public B match(final F, B> n2, final F, B> n3) { return n2.f(this); } - public V2 toVector() { + @Override + public int length() { + return 2; + } + + public V2 toVector() { return as; } } diff --git a/core/src/main/java/fj/data/fingertrees/Node3.java b/core/src/main/java/fj/data/fingertrees/Node3.java index ae83a6f9..233fcda7 100644 --- a/core/src/main/java/fj/data/fingertrees/Node3.java +++ b/core/src/main/java/fj/data/fingertrees/Node3.java @@ -34,7 +34,12 @@ public B match(final F, B> n2, final F, B> n3) { return n3.f(this); } - public Digit toDigit() { + @Override + public int length() { + return 3; + } + + public Digit toDigit() { return new Three(measured(), as); } diff --git a/core/src/main/java/fj/data/fingertrees/One.java b/core/src/main/java/fj/data/fingertrees/One.java index 953cf60c..d07cab60 100644 --- a/core/src/main/java/fj/data/fingertrees/One.java +++ b/core/src/main/java/fj/data/fingertrees/One.java @@ -49,4 +49,9 @@ public A value() { @Override public P2 lookup(final F o, final int i) { return P.p(i, a); } + + @Override + public int length() { + return 1; + } } diff --git a/core/src/main/java/fj/data/fingertrees/Single.java b/core/src/main/java/fj/data/fingertrees/Single.java index c42f79e4..410378f1 100644 --- a/core/src/main/java/fj/data/fingertrees/Single.java +++ b/core/src/main/java/fj/data/fingertrees/Single.java @@ -86,7 +86,12 @@ public V measure() { @Override public P2 lookup(final F o, final int i) { return p(i, a); } - /** + @Override + public int length() { + return 1; + } + + /** * Returns the single element of this tree. * * @return the single element of this tree. diff --git a/core/src/main/java/fj/data/fingertrees/Three.java b/core/src/main/java/fj/data/fingertrees/Three.java index 6f7c8e93..da9f6a9e 100644 --- a/core/src/main/java/fj/data/fingertrees/Three.java +++ b/core/src/main/java/fj/data/fingertrees/Three.java @@ -73,4 +73,9 @@ public V3 values() { } } } + + @Override + public int length() { + return 3; + } } diff --git a/core/src/main/java/fj/data/fingertrees/Two.java b/core/src/main/java/fj/data/fingertrees/Two.java index 7b2e35fd..3029fd9d 100644 --- a/core/src/main/java/fj/data/fingertrees/Two.java +++ b/core/src/main/java/fj/data/fingertrees/Two.java @@ -64,4 +64,10 @@ public V2 values() { return P.p(i - s1, as._2()); } } + + @Override + public int length() { + return 2; + } + } diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java new file mode 100644 index 00000000..a4265be6 --- /dev/null +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java @@ -0,0 +1,26 @@ +package fj.data.fingertrees; + +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbList; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by MarkPerry on 10/10/2015. + */ +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class FingerTreeProperties { + + public Property size() { + return property(arbList(arbInteger), list -> + prop(list.foldLeft((acc, i) -> acc.snoc(i), FingerTree.emptyIntAddition()).length() == list.length()) + ); + } + +} diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java new file mode 100644 index 00000000..3d95d182 --- /dev/null +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -0,0 +1,30 @@ +package fj.data.fingertrees; + +import fj.data.List; +import org.junit.Test; + +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by MarkPerry on 10/10/2015. + */ +public class FingerTreeTest { + + @Test + public void size() { + validateSize(List.list(-92, 68, 54, -77, -18, 67)); + validateSize(List.list(-92, 68, 54, -77, -18, 67, -60, 23, -70, 99, 66, -79, -5)); + } + + void validateSize(List list) { + FingerTree ft = list.foldLeft( + (acc, i) -> acc.snoc(i), FingerTree.emptyIntAddition() + ); + assertThat(ft.measure(), equalTo(list.length())); + assertThat(ft.length(), equalTo(list.length())); + } + +} diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 4e4a8144..6f472b3b 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -16,9 +16,7 @@ import static fj.Function.identity; import static fj.data.Option.none; import static fj.data.Option.some; -import static fj.test.Arbitrary.arbInteger; -import static fj.test.Arbitrary.arbSeq; -import static fj.test.Arbitrary.arbitrary; +import static fj.test.Arbitrary.*; import static fj.test.Property.implies; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -121,4 +119,11 @@ public Property foldRight() { return property(arbSeq(arbitrary(Gen.value(1))), seq -> prop(seq.foldRight((i, acc) -> acc + i, 0) == seq.length())); } + + public Property length() { + return property(arbList(arbInteger), list -> + prop(Seq.seq(list).length() == list.length()) + ); + } + } From adb381dab965bf8ccaad66246d3ae74e150c95d3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 10 Oct 2015 21:41:07 +1000 Subject: [PATCH 424/811] Update gradle to 2.7 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e60d0819..18eac0ae 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-bin.zip From 0ca0e13a4106e7dad676b9c389e7ea3b79854c62 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Nov 2015 11:52:06 +1000 Subject: [PATCH 425/811] Avoid stackoverflow with List.splitAt --- core/src/main/java/fj/data/List.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 403902e1..499f85ce 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -823,16 +823,19 @@ public final List drop(final int i) { * @return A pair of lists split at the given index of this list. */ public final P2, List> splitAt(final int i) { - P2, List> s = p(List.nil(), List.nil()); - int c = 0; + List first = List.nil(); + List second = List.nil(); for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) { final A h = xs.head(); - s = c < i ? s.map1(as -> as.snoc(h)) : s.map2(as1 -> as1.snoc(h)); + if (c < i) { + first = first.cons(h); + } else { + second = second.cons(h); + } c++; } - - return s; + return P.p(first.reverse(), second.reverse()); } /** From 0028ef0f8e6a36b77cbd75b29e92d77eacc167bd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 3 Nov 2015 11:53:05 +1000 Subject: [PATCH 426/811] Added Stream.enumerationStream --- core/src/main/java/fj/data/Stream.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index a3f2cf9c..4a53971f 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -18,10 +18,7 @@ import fj.Ordering; import fj.function.Effect1; -import java.util.AbstractCollection; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; +import java.util.*; import static fj.Bottom.error; import static fj.Function.compose; @@ -232,7 +229,7 @@ public Stream _1() { public Stream prefix(final A x, final Stream xs) { return xs.isEmpty() ? xs : cons(x, p(cons(xs.head(), () -> prefix(a, xs.tail()._1())))); - } + } }); } @@ -553,6 +550,14 @@ public final Stream interleave(final Stream as) { return isEmpty() ? as : as.isEmpty() ? this : cons(head(), () -> as.interleave(tail()._1())); } + public static Stream enumerationStream(Enumeration e) { + if (e.hasMoreElements()) { + return Stream.cons(e.nextElement(), () -> enumerationStream(e)); + } else { + return Stream.nil(); + } + } + /** * Sort this stream according to the given ordering. * From aec491c84c7c7761f8a1ddddd67b4678b485c1af Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 11 Nov 2015 08:13:35 +1000 Subject: [PATCH 427/811] Made List.take avoid stack overflow by using an internal buffer --- core/src/main/java/fj/data/List.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 499f85ce..e9a624e7 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -795,7 +795,15 @@ public final A index(final int i) { * @return A new list with a length the same, or less than, this list. */ public final List take(final int i) { - return i <= 0 || isEmpty() ? List.nil() : cons(head(), tail().take(i - 1)); + Buffer result = Buffer.empty(); + List list = this; + int index = i; + while (index > 0 && list.isNotEmpty()) { + result.snoc(list.head()); + list = list.tail(); + index--; + } + return result.toList(); } /** From d3e99ced4ec5f3ae4c4066a02a50da55ffc981b2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 26 Nov 2015 01:47:40 +1000 Subject: [PATCH 428/811] Resolved overloaded List methods. Marked numerous list methods as deprecated --- core/src/main/java/fj/data/Array.java | 24 +++--- core/src/main/java/fj/data/Conversions.java | 8 +- core/src/main/java/fj/data/HashMap.java | 2 +- core/src/main/java/fj/data/Java.java | 2 +- core/src/main/java/fj/data/List.java | 79 +++++++++++++------ core/src/main/java/fj/data/TreeMap.java | 13 ++- core/src/main/java/fj/data/Validation.java | 2 +- core/src/test/java/fj/data/ListTest.java | 11 ++- core/src/test/java/fj/data/TreeMapTest.java | 2 +- .../src/main/java/fj/java/util/ListUtil.java | 8 +- .../scala/fj/data/optic/TraversalLaws.scala | 2 +- .../test/scala/fj/data/CheckIteratee.scala | 2 +- .../src/test/scala/fj/data/CheckList.scala | 2 +- .../fj/data/properties/ListProperties.java | 2 +- 14 files changed, 105 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index bb3b24a4..bc570198 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -1,31 +1,33 @@ package fj.data; +import fj.Equal; import fj.F; import fj.F0; import fj.F2; +import fj.Hash; import fj.P; -import fj.P1; import fj.P2; -import fj.Equal; import fj.Show; -import fj.Hash; import fj.Unit; import fj.function.Effect1; -import static fj.Function.*; + +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import static fj.Function.constant; +import static fj.Function.curry; +import static fj.Function.identity; import static fj.P.p; import static fj.P.p2; import static fj.Unit.unit; -import static fj.data.List.iterableList; +import static fj.data.List.fromIterable; import static fj.data.Option.none; import static fj.data.Option.some; import static java.lang.Math.min; import static java.lang.System.arraycopy; -import java.util.AbstractCollection; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; - /** * Provides an interface to arrays. * @@ -800,7 +802,7 @@ public int size() { * @return An array from the given iterable. */ public static Array iterableArray(final Iterable i) { - return iterableList(i).toArray(); + return fromIterable(i).toArray(); } /** diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 7f74ce86..5405f70a 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -54,7 +54,7 @@ public static F, Stream> List_Stream() { * @return A function that converts lists to options. */ public static F, Option> List_Option() { - return as -> as.toOption(); + return as -> as.headOption(); } /** @@ -471,7 +471,7 @@ public static F, SafeIO> F_SafeIO() { /** * A function that converts strings to options. */ - public static final F> String_Option = s -> fromString(s).toOption(); + public static final F> String_Option = s -> fromString(s).headOption(); /** * A function that converts string to eithers. @@ -519,7 +519,7 @@ public static F, F>> String_Either() { /** * A function that converts string buffers to options. */ - public static final F> StringBuffer_Option = s -> fromString(s.toString()).toOption(); + public static final F> StringBuffer_Option = s -> fromString(s.toString()).headOption(); /** * A function that converts string buffers to eithers. @@ -562,7 +562,7 @@ public static F, F>> StringBuffer_E /** * A function that converts string builders to options. */ - public static final F> StringBuilder_Option = s -> fromString(s.toString()).toOption(); + public static final F> StringBuilder_Option = s -> fromString(s.toString()).headOption(); /** * A function that converts string builders to eithers. diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 2687bfd6..1d934db4 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -309,7 +309,7 @@ public Stream> toStream() { } public Option> toOption() { - return toList().toOption(); + return toList().headOption(); } public Array> toArray() { diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 14ba97d6..80a2757d 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1458,7 +1458,7 @@ public static F, List> JavaList_List() { } public static List JavaList_List(java.util.List list) { - return List.list(list); + return List.fromIterable(list); } // BEGIN BitSet -> diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index e9a624e7..fce14dc8 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1,20 +1,22 @@ package fj.data; import static fj.Bottom.error; -import fj.F0; -import fj.F2Functions; + import fj.Equal; -import fj.F; -import fj.F2; -import fj.Function; +import fj.F2Functions; import fj.Hash; import fj.Monoid; import fj.Ord; +import fj.Ordering; import fj.P; import fj.P1; -import fj.P2; import fj.Show; import fj.Unit; +import fj.P2; +import fj.F0; +import fj.F; +import fj.F2; +import fj.Function; import static fj.Function.*; import static fj.P.p; @@ -30,7 +32,8 @@ import static fj.function.Booleans.not; import static fj.Ordering.GT; import static fj.Ord.intOrd; -import fj.Ordering; + + import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; @@ -111,13 +114,19 @@ public final boolean isNotEmpty() { /** * Performs a reduction on this list using the given arguments. + * @deprecated As of release 4.5, use {@link #reduce} * * @param nil The value to return if this list is empty. * @param cons The function to apply to the head and tail of this list if it is not empty. * @return A reduction on this list. */ + @Deprecated public final B list(final B nil, final F, B>> cons) { - return isEmpty() ? nil : cons.f(head()).f(tail()); + return reduce(Function.uncurryF2(cons), nil); + } + + public final B reduce(final F2, B> cons, final B nil) { + return isEmpty() ? nil : cons.f(head(), tail()); } /** @@ -143,10 +152,21 @@ public final List orTail(final F0> as) { /** * Returns an option projection of this list; None if empty, or the first element in * Some. Equivalent to {@link #headOption()}. - * + * @deprecated As of release 4.5, use {@link #headOption()} * @return An option projection of this list. */ + @Deprecated public final Option toOption() { + return headOption(); + + } + + /** + * Returns the head of the list, if any. Equivalent to {@link #toOption()} . + * + * @return The optional head of the list. + */ + public Option headOption() { return isEmpty() ? Option.none() : some(head()); } @@ -1134,14 +1154,6 @@ public static F, A> head_() { return list -> list.head(); } - /** - * Returns the head of the list, if any. Equivalent to {@link #toOption()} . - * - * @return The optional head of the list. - */ - public Option headOption() { - return toOption(); - } /** * Reutrns the tail of the list, if any. @@ -1529,13 +1541,24 @@ private void tail(final List tail) { return Array.array(as).toList(); } - + /** + * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} + */ + @Deprecated public static List list(final Iterable i) { - return iterableList(i); + return fromIterable(i); } + /** + * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} + */ + @Deprecated public static List list(final Iterator it) { - return iterableList(() -> it); + return fromIterable(() -> it); + } + + public static List fromIterator(final Iterator it) { + return fromIterable(() -> it); } /** @@ -1840,20 +1863,24 @@ public static F, List>> take() { /** * Takes the given iterable to a list. + * @deprecated From release 4.5 use {@link #fromIterable(Iterable)} * * @param i The iterable to take to a list. * @return A list from the given iterable. */ + @Deprecated public static List iterableList(final Iterable i) { - final Buffer bs = empty(); + return fromIterable(i); + } - for (final A a : i) + public static List fromIterable(final Iterable i) { + final Buffer bs = empty(); + for (final A a : i) { bs.snoc(a); - + } return bs.toList(); } - /** * A mutable, singly linked list. This structure should be used very sparingly, in favour * of the {@link List immutable singly linked list structure}. @@ -2159,4 +2186,8 @@ public static Prism, P2>> cons() { } + public static final class Unsafe { + + } + } diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 698fe697..e38bc0a7 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -1,6 +1,14 @@ package fj.data; -import fj.*; +import fj.Equal; +import fj.F; +import fj.F1Functions; +import fj.Hash; +import fj.Ord; +import fj.P; +import fj.P2; +import fj.P3; +import fj.Show; import java.util.Comparator; import java.util.Iterator; @@ -10,6 +18,7 @@ import static fj.Function.flip; import static fj.P.p; import static fj.data.IterableW.join; +import static fj.data.List.fromIterable; import static fj.data.List.iterableList; /** @@ -134,7 +143,7 @@ public boolean isEmpty() { * @return All values in this tree map. */ public List values() { - return iterableList(join(tree.toList().map(compose(IterableW.>wrap(), P2.>__2())))); + return fromIterable(join(tree.toList().map(compose(IterableW.>wrap(), P2.>__2())))); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 60e01b40..e9107ff0 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -828,7 +828,7 @@ public static Validation, List> sequenceNonCumulative(List List> traverseList(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : - list(fail(e.left().value())); + List.fromIterable(fail(e.left().value())); } public Stream> traverseStream(F> f){ diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 04c37d2b..b63836e6 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -6,8 +6,10 @@ import java.util.Arrays; +import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** @@ -37,7 +39,7 @@ public void objectMethods() { @Test public void integration() { java.util.List ul = Arrays.asList(1, 2, 3); - List dl = List.list(ul); + List dl = List.fromIterable(ul); assertTrue(ul.equals(dl.toJavaList())); } @@ -72,4 +74,11 @@ public void intersperseOverflow() { String s = list.toString(); } + @Test + public void listReduce() { + String list = List.range(1, 11).reduce((a, la) -> List.cons(a, la).toString(), ""); + String expected = List.range(1, 11).toString(); + assertThat(expected, equalTo(list)); + } + } diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index d476d308..f3cf61b6 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -88,7 +88,7 @@ public void toMutableMap() { List> l = List.range(1, max + 1).map(n -> List.single(n)); TreeMap, String> m2 = TreeMap.treeMap(Ord.listOrd(Ord.intOrd), l.zip(l.map(i -> i.toString()))); Map, String> mm = m2.toMutableMap(); - assertEquals(m2.keys(), List.iterableList(mm.keySet())); + assertEquals(m2.keys(), List.fromIterable(mm.keySet())); } diff --git a/java-core/src/main/java/fj/java/util/ListUtil.java b/java-core/src/main/java/fj/java/util/ListUtil.java index 343ce7ae..4fcc1c07 100644 --- a/java-core/src/main/java/fj/java/util/ListUtil.java +++ b/java-core/src/main/java/fj/java/util/ListUtil.java @@ -11,19 +11,19 @@ public class ListUtil { public static List map(List list, F f) { - return fj.data.List.list(list).map(f).toJavaList(); + return fj.data.List.fromIterable(list).map(f).toJavaList(); } public static List filter(List list, F f) { - return fj.data.List.list(list).filter(f).toJavaList(); + return fj.data.List.fromIterable(list).filter(f).toJavaList(); } public static B fold(List list, F2 f, B b) { - return fj.data.List.list(list).foldLeft(f, b); + return fj.data.List.fromIterable(list).foldLeft(f, b); } public static List flatMap(List list, F> f) { - return fj.data.List.list(list).bind(a -> fj.data.List.list(f.f(a))).toJavaList(); + return fj.data.List.fromIterable(list).bind(a -> fj.data.List.fromIterable(f.f(a))).toJavaList(); } public static List bind(List list, F> f) { diff --git a/props-core-scalacheck/src/main/scala/fj/data/optic/TraversalLaws.scala b/props-core-scalacheck/src/main/scala/fj/data/optic/TraversalLaws.scala index 2172db2c..423dac6a 100644 --- a/props-core-scalacheck/src/main/scala/fj/data/optic/TraversalLaws.scala +++ b/props-core-scalacheck/src/main/scala/fj/data/optic/TraversalLaws.scala @@ -34,7 +34,7 @@ object TraversalLaws { } property("headMaybe returns the first element of getAll (if getAll is finite)") = forAll { s: S => - optionEqual(aEqual).eq(traversal.headOption(s), traversal.getAll(s).toOption()) + optionEqual(aEqual).eq(traversal.headOption(s), traversal.getAll(s).headOption()) } } diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala index d47c95f8..86feeb7a 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala @@ -25,7 +25,7 @@ object CheckIteratee extends Properties("Iteratee") { enumerate[Int, java.lang.Integer](a, IterV.length[Int]).run == a.length) property("head") = forAll((a: List[Int]) => - enumerate(a, IterV.head[Int]).run == a.toOption) + enumerate(a, IterV.head[Int]).run == a.headOption) property("drop") = forAll((a: List[String], x: Byte) => (a.length > 0) ==> { val n = math.abs(x) % a.length diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala index a3cfa2b5..36bd99f0 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala @@ -33,7 +33,7 @@ object CheckList extends Properties("List") { (listEqual(stringEqual).eq(a.orTail(n), a.tail))) property("toOption") = forAll((a: List[Int]) => - a.toOption.isNone || a.toOption.some == a.head) + a.headOption.isNone || a.headOption.some == a.head) // crashes the type checker for unknown reason // property("toEither") = property((a: List[Int], n: P1[Int]) => diff --git a/props-core/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java index f4ab1476..825a5f17 100644 --- a/props-core/src/test/java/fj/data/properties/ListProperties.java +++ b/props-core/src/test/java/fj/data/properties/ListProperties.java @@ -60,7 +60,7 @@ public Property orTail() { public Property toOption() { return property(arbList(arbInteger), list -> - prop(list.toOption().isNone() || intEqual.eq(list.toOption().some(), list.head()))); + prop(list.headOption().isNone() || intEqual.eq(list.headOption().some(), list.head()))); } public Property consHead() { From 67f1fc9f2c35479bf18d9ef948062e01ef740d5e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 7 Dec 2015 09:12:09 +1000 Subject: [PATCH 429/811] Backport to Java 6 --- build.gradle | 8 +++++--- core/build.gradle | 6 +++--- demo/build.gradle | 6 +++--- props-core/build.gradle | 6 +++--- quickcheck/build.gradle | 6 +++--- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/build.gradle b/build.gradle index a508b4e2..437bedf0 100644 --- a/build.gradle +++ b/build.gradle @@ -36,11 +36,11 @@ allprojects { ext { isSnapshot = false - fjBaseVersion = "4.4" + fjBaseVersion = "4.4.1" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.3" + fjConsumeVersion = "4.4" signModule = false useRetroLambda = true @@ -62,7 +62,9 @@ allprojects { primaryEmail = "functionaljava@googlegroups.com" dependencyJunit = "junit:junit:4.12" - + backportVersion = JavaVersion.VERSION_1_6 + backportJdk = System.getenv("JAVA8_HOME") + backportOldJdk = System.getenv("JAVA6_HOME") } version = fjVersion diff --git a/core/build.gradle b/core/build.gradle index 7bd8c184..87a97578 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -21,8 +21,8 @@ uploadArchives.enabled = true if (useRetroLambda) { retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk backportJdk + oldJdk backportOldJdk + javaVersion backportVersion } } diff --git a/demo/build.gradle b/demo/build.gradle index 7af49271..bffc8344 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -9,9 +9,9 @@ mainClassName = "fj.demo.euler.Problem2" if (useRetroLambda) { retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk backportJdk + oldJdk backportOldJdk + javaVersion backportVersion } } diff --git a/props-core/build.gradle b/props-core/build.gradle index f9f7fbb9..695788be 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -3,9 +3,9 @@ if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk backportJdk + oldJdk backportOldJdk + javaVersion backportVersion } } diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index d4543f38..a9f0b834 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -7,9 +7,9 @@ if (useRetroLambda) { apply plugin: 'me.tatarka.retrolambda' retrolambda { - jdk System.getenv("JAVA8_HOME") - oldJdk System.getenv("JAVA7_HOME") - javaVersion JavaVersion.VERSION_1_7 + jdk backportJdk + oldJdk backportOldJdk + javaVersion backportVersion } } From 267984dc6294a2235016fcaae2898de87febc883 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Dec 2015 20:41:07 +1000 Subject: [PATCH 430/811] Increased version to 4.4.2-SNAPSHOT --- build.gradle | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 437bedf0..818d5914 100644 --- a/build.gradle +++ b/build.gradle @@ -35,8 +35,8 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.4.1" + isSnapshot = true + fjBaseVersion = "4.4.2" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From f3a0d070b93973df91fcbb71aa34d20a510b4b2e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Dec 2015 20:54:56 +1000 Subject: [PATCH 431/811] Set JAVA6_HOME for Travis CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1d62c9c3..4fa41b23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ jdk: - oraclejdk8 script: + - jdk_switcher use oraclejdk6 && export JAVA6_HOME=$JAVA_HOME - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME - ./gradlew build --stacktrace --info From e0159facf9f9b90d45d5a940e115317de0d36174 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Dec 2015 22:14:23 +1000 Subject: [PATCH 432/811] Use openjdk6 for java 6 on Travis CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4fa41b23..5a9371f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ jdk: - oraclejdk8 script: - - jdk_switcher use oraclejdk6 && export JAVA6_HOME=$JAVA_HOME + - jdk_switcher use openjdk6 && export JAVA6_HOME=$JAVA_HOME - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME - ./gradlew build --stacktrace --info From f18edd48d4ffcf594941e0022c0a21a7e16a02f6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Dec 2015 22:52:36 +1000 Subject: [PATCH 433/811] Upgrade gradle to 2.9 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 18eac0ae..7761b5b4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-bin.zip From 4b9936c8f4178c4ac91c06fa2edd416167b24d84 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Dec 2015 01:09:41 +1000 Subject: [PATCH 434/811] Fully updated release notes --- etc/release-notes/release-notes-4.5.adoc | 56 +++++++++++++++++++++--- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/etc/release-notes/release-notes-4.5.adoc b/etc/release-notes/release-notes-4.5.adoc index 32118535..0e4fcb80 100644 --- a/etc/release-notes/release-notes-4.5.adoc +++ b/etc/release-notes/release-notes-4.5.adoc @@ -5,24 +5,68 @@ Proposed release: last quarter 2015 == Enhancements -* TODO. +* Added Seq toList and delete (#198). +* Added functions to P1: map_, liftM2, sequence (#200). +* Added liftM2 to Option (#201). +* Added headOption and tailOption to List (#202). +* Replaced usage of P1 with F0 in Stream orTail, sequence and cons (#203). +* Added Arbitrary.arbSet (48d4c8358f1257e2126726be0808b48568f372bf). +* Added to Arbitrary arbitrary lists for integer, string, boolean and double (#183). +* Updated Stream.toList using List.Buffer for performance (#180). +* Added java-core module for simple handling of core Java types, e.g. List map, bind, filter, fold (4611c3524eca1786c112fcae0a727f2243b2d492, 13ebd6f22db7a8bf8247f0f4ea4ac3cd8afef4b9). +* Added Tree isLeaf and length (#185). +* Added min and max to Set (#176). +* Added min, minKey, max and maxKey for TreeMap. Added arbitrary TreeMap's (#176). +* Added ordering a P2 by first or second element in the tuple (#175). +* Added Set.toStream (#175). +* Added TreeMap.toList (#175). +* Added toListReverse and toStreamReverse for Set and TreeMap (#177). +* Added headOption to Seq and FingerTree. Added length to FingerTree (7e1d3a9300af84b3c4c5204e4b7a5a0e89c44303). +* Added Stream.enumerationStream (0028ef0f8e6a36b77cbd75b29e92d77eacc167bd). +* Support use of FunctionalJava on Java 6 runtime (67f1fc9f2c35479bf18d9ef948062e01ef740d5e). == Fixes -* TODO. +* Fixed constructors of fixed length monomorphic traversal (#179). +* Fixed defect in Buffer.copy (#181). +* Fixed order of foldMap for Set which switch the left and right branches (#205). +* Fixed List.intersperse to use heap, not stack space (#188). +* Fixed Validation.accumulate for 4 validations (#190). +* Avoid stackoverflow for List.splitAt (0ca0e13a4106e7dad676b9c389e7ea3b79854c62). +* Avoid stackoverflow for List.take (aec491c84c7c7761f8a1ddddd67b4678b485c1af). +* Resolved overloaded List methods (d3e99ced4ec5f3ae4c4066a02a50da55ffc981b2). == Internal -* TODO. +* Added @SafeVargs to suppress various unchecked warnings (#174). +* Suppressed various unchecked compiler warnings (9853c6a26309cf9f4936d431a6bc65b4c37550b1). +* Added compiler warnings for unchecked and deprecation (#204). +* Simplified code to avoid function creation and inner static class (#179). +* Upgraded to Gradle 2.9. +* Added example of badly creating a Stream from an iterator (d38a694f9f1728417cb178c685850f627b10bf5b). +* Configure Retro Lambda using variables (6aa26bcb56dd43d36bede2e8c34cbb21f69c1c8a). +* Updated package fj, fj.control, fj.data, fj.data.fingertrees, fj.data.hlist, fj.data.vector, fj.function, fj.parser to use lambdas (#206). +* Added test coverage report, run "gradlew coverage", report is under root/build/reports/jacoco/coverage/html/index.html (#207). +* Updated Travis CI to use latest Java 8 (8ddc11546badbeafb0b16bc1e0fb922b06f23079). +* Replaced usage of new P1 with P.lazy (2d6a8dd4412220a749331b6ffec45bd720ac7479). +* Replaced P1 with F0 instances where possible (5b8248c51445e92aa8c8ff241e717f909a5bdd63, 0ca5248a3016209c9e62df509a79ed9432421322). +* Replace anonymous F2 instances with lambdas (b438b1b89705f6d0bfd5e7c31bd217d173c43dfc). +* Replace anonymous F3 instances with lambdas (721118902a5af76665df347b073534debf384f69). +* Added coverall integration, submodules not consolidated into single report. +* Replaced annonymous P2 with static constructor (92f663384541dfbea013c14b7f60951d925bcd26). == Breaking Changes -* TODO. +* None. == Documentation -* TODO. +* Added release process doc (#174). == Contributors -* TODO. +* Mark Perry +* Zheka Kozlov +* Jean-Baptiste Giraudeau +* Shintaro Murakami + From 71c637bd35aa182b66367c0afaf9a74a641fa817 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 10 Dec 2015 21:22:15 +0100 Subject: [PATCH 435/811] Add Void: a logically uninhabited data type. Fix #193 --- core/src/main/java/fj/Void.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 core/src/main/java/fj/Void.java diff --git a/core/src/main/java/fj/Void.java b/core/src/main/java/fj/Void.java new file mode 100644 index 00000000..6a9aaf07 --- /dev/null +++ b/core/src/main/java/fj/Void.java @@ -0,0 +1,16 @@ +package fj; + +/** + * A logically uninhabited data type. + */ +public abstract class Void { + + private Void() { + throw new IllegalStateException("Void cannot be instantiated"); + } + + /** + * Since Void values logically don't exist, this witnesses the logical reasoning tool of "ex falso quodlibet". + */ + public abstract X absurd(); +} From 61ec2b09e5acc629f334d7c4264a92b99dd9fd3b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 16 Oct 2015 08:02:49 +0200 Subject: [PATCH 436/811] log n multiply for Semigroup/Monoid --- core/src/main/java/fj/Monoid.java | 19 ++++++++---- core/src/main/java/fj/Semigroup.java | 44 +++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index e1192682..40d6e8e7 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -8,6 +8,8 @@ import fj.data.Option; import fj.data.Set; import fj.data.Stream; + +import static fj.Semigroup.multiply1p; import static fj.data.Stream.iterableStream; import java.math.BigInteger; @@ -90,15 +92,20 @@ public A zero() { } /** - * Returns a value summed n times (a + a + ... + a) + * Returns a value summed n times (a + a + ... + a). + * The default definition uses peasant multiplication, exploiting + * associativity to only require `O(log n)` uses of + * {@link #sum(Object, Object)}. + * * @param n multiplier - * @param a the value to multiply - * @return a summed n times. If n <= 0, returns zero() + * @param a the value to be reapeatly summed + * @return {@code a} summed {@code n} times. If {@code n <= 0}, returns + * {@code zero()} */ public A multiply(final int n, final A a) { - A m = zero(); - for (int i = 0; i < n; i++) { m = sum(m, a); } - return m; + return (n <= 0) + ? zero + : multiply1p(sum, n - 1, a); } /** diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 02a0d647..e1e4fdf7 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -1,7 +1,5 @@ package fj; -import static fj.Function.curry; - import fj.data.Array; import fj.data.List; import fj.data.Natural; @@ -10,8 +8,10 @@ import fj.data.Set; import fj.data.Stream; -import java.math.BigInteger; import java.math.BigDecimal; +import java.math.BigInteger; + +import static fj.Function.curry; /** * Implementations must satisfy the law of associativity: @@ -58,6 +58,42 @@ public F> sum() { return sum; } + /** + * Returns a value summed n + 1 times ( + * a + a + ... + a) The default definition uses peasant + * multiplication, exploiting associativity to only require `O(log n)` uses of + * {@link #sum(Object, Object)}. + * + * @param n multiplier + * @param a the value to be reapeatly summed n + 1 times + * @return {@code a} summed {@code n} times. If {@code n <= 0}, returns + * {@code zero()} + */ + public A multiply1p(int n, A a) { + return multiply1p(sum, n, a); + } + + // shared implementation between Semigroup and Monoid + static A multiply1p(F> sum, int n, A a) { + if (n <= 0) { + return a; + } + + A xTmp = a; + int yTmp = n; + A zTmp = a; + while (true) { + if ((yTmp & 1) == 1) { + zTmp = sum.f(xTmp).f(zTmp); + if (yTmp == 1) { + return zTmp; + } + } + xTmp = sum.f(xTmp).f(xTmp); + yTmp = (yTmp) >>> 1; + } + } + /** * Constructs a semigroup from the given function. * @@ -316,7 +352,7 @@ public static Semigroup> p1Semigroup(final Semigroup sa) { * @return A semigroup for binary products. */ public static Semigroup> p2Semigroup(final Semigroup sa, final Semigroup sb) { - return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); + return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); } /** From e24045cf1d4297d65b2dc4ff613943e5f48ced42 Mon Sep 17 00:00:00 2001 From: daneko <3a3k.web+github@gmail.com> Date: Thu, 17 Dec 2015 17:12:24 +0900 Subject: [PATCH 437/811] avoid forEach --- core/src/main/java/fj/function/Strings.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index 59562cfc..88e9cc2f 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -1,7 +1,6 @@ package fj.function; import fj.F; -import fj.F2; import fj.data.List; import fj.data.Stream; import static fj.Function.curry; @@ -86,7 +85,7 @@ public static F> lines() { public static String unlines(List list) { StringBuilder sb = new StringBuilder(); - list.intersperse(lineSeparator).forEach(s -> sb.append(s)); + list.intersperse(lineSeparator).foreachDoEffect(s -> sb.append(s)); return sb.toString(); } From dec583c87f9aabee3f9901c4925d343d53336fc3 Mon Sep 17 00:00:00 2001 From: Clinton Selke Date: Sat, 30 Jan 2016 18:35:09 +1000 Subject: [PATCH 438/811] DList --- .gitignore | 1 + core/src/main/java/fj/data/DList.java | 50 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 core/src/main/java/fj/data/DList.java diff --git a/.gitignore b/.gitignore index 6988acc1..d3f6bf89 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ build MANIFEST.MF */bin/** *~ +/.nb-gradle/ \ No newline at end of file diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java new file mode 100644 index 00000000..7e88f214 --- /dev/null +++ b/core/src/main/java/fj/data/DList.java @@ -0,0 +1,50 @@ +package fj.data; + +import fj.F; +import fj.P; +import fj.control.Trampoline; + +/** + * Difference List. It converts left associative appends into right associative ones to improve performance. + * + * @version %build.number% + */ +public class DList { + private final F,Trampoline>> appendFn; + + private DList(F,Trampoline>> appendFn) { + this.appendFn = appendFn; + } + + public static DList fromList(List a) { + return new DList<>((List tail) -> Trampoline.pure(a.append(tail))); + } + + public List run() { + return appendFn.f(List.nil()).run(); + } + + public static DList nil() { + return new DList<>(Trampoline.>pure()); + } + + public static DList single(A a) { + return new DList<>((List tail) -> Trampoline.pure(tail.cons(a))); + } + + public DList cons(A a) { + return DList.single(a).append(this); + } + + public DList snoc(A a) { + return this.append(DList.single(a)); + } + + public DList append(DList other) { + return new DList<>(kleisliTrampCompose(this.appendFn, other.appendFn)); + } + + private static F> kleisliTrampCompose(F> bc, F> ab) { + return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(P.lazy(() -> bc.f(b)))); + } +} From ba2601c2e7f0ccdfaba8a061f4d7a5573da8cd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 30 Jan 2016 18:55:31 -0500 Subject: [PATCH 439/811] Add coverage badge to README --- README.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.adoc b/README.adoc index aebe093a..508fdc37 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,7 @@ = Functional Java image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] +image:https://coveralls.io/repos/github/functionaljava/functionaljava/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/github/functionaljava/functionaljava?branch=master"] image::http://www.functionaljava.org/img/logo-600x144.png[] From 7ab6f63528904dfeecb78baeeb20525e468d8cf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 30 Jan 2016 20:12:50 -0500 Subject: [PATCH 440/811] Process coverage for all subprojects --- .travis.yml | 2 +- build.gradle | 28 +++++++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7cf9b2e7..edb97c8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,4 @@ script: - ./gradlew build coverage -s -i after_success: - - ./gradlew coverage coveralls -s -i + - ./gradlew jacocoRootReport coveralls diff --git a/build.gradle b/build.gradle index 6f8dd9ce..032ab43d 100644 --- a/build.gradle +++ b/build.gradle @@ -19,7 +19,7 @@ buildscript { dependencies { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" classpath "me.tatarka:gradle-retrolambda:$retrolambdaVersion" - classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.4.0' + classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.6.3' } } @@ -27,7 +27,6 @@ buildscript { apply plugin: "jacoco" apply plugin: 'com.github.kt3k.coveralls' - if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { @@ -100,14 +99,9 @@ subprojects { repositories { mavenCentral() } - - dependencies { - classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.0.1' - } } apply plugin: "jacoco" - apply plugin: 'com.github.kt3k.coveralls' apply from: "$rootDir/lib.gradle" apply plugin: "java" @@ -214,3 +208,23 @@ configure(subprojects.findAll { it.name != "props-core" }) { task env << { println System.getenv() } + +task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) { + dependsOn = subprojects.jacocoTestReport + sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) + classDirectories = files(subprojects.sourceSets.main.output) + executionData = files(subprojects.jacocoTestReport.executionData) + reports { + xml.enabled true + xml.destination ="${buildDir}/reports/jacoco/test/jacocoTestReport.xml" + } + // We could remove the following setOnlyIf line, but then + // jacocoRootReport would silently be SKIPPED if something with + // the projectsWithUnitTests is wrong (e.g. a project is missing + // in there). + setOnlyIf { true } +} + +coveralls { + sourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs).files.absolutePath +} From 8ceeb228fdd756748504fc3df6d800445cd27d55 Mon Sep 17 00:00:00 2001 From: Michal Samek Date: Sun, 31 Jan 2016 16:35:09 +0100 Subject: [PATCH 441/811] Update Option_filter.java Corrections for few small mistakes in the Java8 Option filter example. --- demo/src/main/java/fj/demo/Option_filter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/src/main/java/fj/demo/Option_filter.java b/demo/src/main/java/fj/demo/Option_filter.java index b572d315..44db69c9 100644 --- a/demo/src/main/java/fj/demo/Option_filter.java +++ b/demo/src/main/java/fj/demo/Option_filter.java @@ -19,12 +19,12 @@ public static void main(final String[] args) { final Option o6 = o3.filter(even); F f = i -> i % 2 == 0; - final Option o7 = o1.filter(f); - final Option o8 = o1.filter(f); - final Option o9 = o1.filter(i -> i % 2 == 0); + final Option o7 = o4.filter(f); + final Option o8 = o5.filter(f); + final Option o9 = o6.filter(i -> i % 2 == 0); optionShow(intShow).println(o4); // None optionShow(intShow).println(o5); // None - optionShow(intShow).println(o6); // Some(8) + optionShow(intShow).println(o6); // Some(4) } } From dfc58878ea23cc73917ed13072033519fe449d9b Mon Sep 17 00:00:00 2001 From: Michal Samek Date: Sun, 31 Jan 2016 17:01:20 +0100 Subject: [PATCH 442/811] Update Option_filter.java Corrected ouput typos --- demo/src/main/java/fj/demo/Option_filter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/src/main/java/fj/demo/Option_filter.java b/demo/src/main/java/fj/demo/Option_filter.java index 44db69c9..9f934c0e 100644 --- a/demo/src/main/java/fj/demo/Option_filter.java +++ b/demo/src/main/java/fj/demo/Option_filter.java @@ -23,8 +23,8 @@ public static void main(final String[] args) { final Option o8 = o5.filter(f); final Option o9 = o6.filter(i -> i % 2 == 0); - optionShow(intShow).println(o4); // None - optionShow(intShow).println(o5); // None - optionShow(intShow).println(o6); // Some(4) + optionShow(intShow).println(o7); // None + optionShow(intShow).println(o8); // None + optionShow(intShow).println(o9); // Some(4) } } From 7753f00d98154846536c16d9d831b3af74cedefa Mon Sep 17 00:00:00 2001 From: Clinton Selke Date: Thu, 4 Feb 2016 17:54:56 +1000 Subject: [PATCH 443/811] added some JavaDoc (not my strength) --- core/src/main/java/fj/data/DList.java | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 7e88f214..6c4ee773 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -16,30 +16,69 @@ private DList(F,Trampoline>> appendFn) { this.appendFn = appendFn; } + /** + * Wraps a list with a DList. + * @param + * @param a the regular List + * @return the DList + */ public static DList fromList(List a) { return new DList<>((List tail) -> Trampoline.pure(a.append(tail))); } + /** + * Concatenates all the internal Lists together that are held in + * the DList's lambda's state to produce a List. + * This is what converts the appending operation from left associative to right associative, + * giving DList it's speed. + * @return the final List + */ public List run() { return appendFn.f(List.nil()).run(); } + /** + * A empty DList. + * @param + * @return a empty DList. + */ public static DList nil() { return new DList<>(Trampoline.>pure()); } + /** + * Produces a DList with one element. + * @param + * @param a the element in the DList. + * @return a DList with one element. + */ public static DList single(A a) { return new DList<>((List tail) -> Trampoline.pure(tail.cons(a))); } + /** + * Prepends a single element on the DList to produce a new DList. + * @param a the element to append. + * @return the new DList. + */ public DList cons(A a) { return DList.single(a).append(this); } + /** + * Appends a single element on the end of the DList to produce a new DList. + * @param a the element to append. + * @return the new DList. + */ public DList snoc(A a) { return this.append(DList.single(a)); } + /** + * Appends two DLists together to produce a new DList. + * @param other the other DList to append on the end of this one. + * @return the new DList. + */ public DList append(DList other) { return new DList<>(kleisliTrampCompose(this.appendFn, other.appendFn)); } From e3350b195002f717860b8831f0da94748785b33e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 03:26:19 +1000 Subject: [PATCH 444/811] Attempt at solving high memory usage --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7cf9b2e7..41c7cc3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,19 @@ addons: packages: - oracle-java8-installer +before_script: + - sudo service postgresql stop || true + - sudo service mysql stop || true + - sudo service memcached stop || true + - sudo service bootlogd stop || true + - sudo service elasticsearch stop || true + - sudo service mongodb stop || true + - sudo service neo4j stop || true + - sudo service cassandra stop || true + - sudo service riak stop || true + - sudo service rsync stop || true + - sudo service x11-common stop || true + script: - jdk_switcher use openjdk6 && export JAVA6_HOME=$JAVA_HOME - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME From cbd63e305e4cf7e5a90664725509f5a4e37419e3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 03:36:15 +1000 Subject: [PATCH 445/811] Use sudo to stop services on Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 41c7cc3e..bd0b8919 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: java -sudo: false +sudo: required jdk: - oraclejdk8 From 6f66aa4aca90beb7c29be16013c012e193e860b6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 04:05:06 +1000 Subject: [PATCH 446/811] Added Stream.toJavaList --- core/src/main/java/fj/data/Stream.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 4a53971f..808e296a 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -894,6 +894,12 @@ public final List toList() { return buf.toList(); } + /** + * Returns a java.util.List projection of this stream. + */ + public final java.util.List toJavaList() { + return new java.util.LinkedList(toCollection()); + } /** * Returns a array projection of this stream. From 64fdac726d65c9dc1f6bd38a2537f16fa65e9e95 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 08:39:33 +1000 Subject: [PATCH 447/811] Made Stream consistent with List for constructing a Stream from an array, iterator and iterable --- core/src/main/java/fj/F1Functions.java | 23 ++++--- core/src/main/java/fj/Monoid.java | 3 +- core/src/main/java/fj/Show.java | 2 +- .../java/fj/control/parallel/ParModule.java | 11 +-- core/src/main/java/fj/data/IterableW.java | 35 +++++----- core/src/main/java/fj/data/List.java | 10 ++- core/src/main/java/fj/data/Stream.java | 67 ++++++++++++++++--- core/src/main/java/fj/data/Validation.java | 2 +- core/src/test/java/fj/data/StreamTest.java | 2 +- java8/src/main/java/fj/data/Collectors.java | 2 +- 10 files changed, 107 insertions(+), 50 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 2d3c56d4..e5f4bba8 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -12,6 +12,7 @@ import java.util.concurrent.*; import static fj.data.Option.some; +import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; import static fj.data.Zipper.fromStream; @@ -558,7 +559,7 @@ static public F, P2> mapBoth(final F f) { */ static public SynchronousQueue mapJ(final F f, final SynchronousQueue as) { final SynchronousQueue bs = new SynchronousQueue(); - bs.addAll(iterableStream(as).map(f).toCollection()); + bs.addAll(fromIterable(as).map(f).toCollection()); return bs; } @@ -570,7 +571,7 @@ static public SynchronousQueue mapJ(final F f, final Synchronous * @return A new PriorityBlockingQueue with this function applied to each element. */ static public PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { - return new PriorityBlockingQueue(iterableStream(as).map(f).toCollection()); + return new PriorityBlockingQueue(fromIterable(as).map(f).toCollection()); } /** @@ -580,7 +581,7 @@ static public PriorityBlockingQueue mapJ(final F f, final Priori * @return A new LinkedBlockingQueue with this function applied to each element. */ static public LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { - return new LinkedBlockingQueue(iterableStream(as).map(f).toCollection()); + return new LinkedBlockingQueue(fromIterable(as).map(f).toCollection()); } /** @@ -590,7 +591,7 @@ static public LinkedBlockingQueue mapJ(final F f, final LinkedBl * @return A new CopyOnWriteArraySet with this function applied to each element. */ static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { - return new CopyOnWriteArraySet(iterableStream(as).map(f).toCollection()); + return new CopyOnWriteArraySet(fromIterable(as).map(f).toCollection()); } /** @@ -600,7 +601,7 @@ static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWr * @return A new CopyOnWriteArrayList with this function applied to each element. */ static public CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { - return new CopyOnWriteArrayList(iterableStream(as).map(f).toCollection()); + return new CopyOnWriteArrayList(fromIterable(as).map(f).toCollection()); } /** @@ -610,7 +611,7 @@ static public CopyOnWriteArrayList mapJ(final F f, final CopyOnW * @return A new ConcurrentLinkedQueue with this function applied to each element. */ static public ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { - return new ConcurrentLinkedQueue(iterableStream(as).map(f).toCollection()); + return new ConcurrentLinkedQueue(fromIterable(as).map(f).toCollection()); } /** @@ -621,7 +622,7 @@ static public ConcurrentLinkedQueue mapJ(final F f, final Concur */ static public ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); - bs.addAll(iterableStream(as).map(f).toCollection()); + bs.addAll(fromIterable(as).map(f).toCollection()); return bs; } @@ -633,7 +634,7 @@ static public ArrayBlockingQueue mapJ(final F f, final ArrayBloc * @return A new TreeSet with this function applied to each element. */ static public TreeSet mapJ(final F f, final TreeSet as) { - return new TreeSet(iterableStream(as).map(f).toCollection()); + return new TreeSet(fromIterable(as).map(f).toCollection()); } /** @@ -643,7 +644,7 @@ static public TreeSet mapJ(final F f, final TreeSet as) { * @return A new PriorityQueue with this function applied to each element. */ static public PriorityQueue mapJ(final F f, final PriorityQueue as) { - return new PriorityQueue(iterableStream(as).map(f).toCollection()); + return new PriorityQueue(fromIterable(as).map(f).toCollection()); } /** @@ -653,7 +654,7 @@ static public PriorityQueue mapJ(final F f, final PriorityQueue< * @return A new LinkedList with this function applied to each element. */ static public LinkedList mapJ(final F f, final LinkedList as) { - return new LinkedList(iterableStream(as).map(f).toCollection()); + return new LinkedList(fromIterable(as).map(f).toCollection()); } /** @@ -663,7 +664,7 @@ static public LinkedList mapJ(final F f, final LinkedList as) * @return A new ArrayList with this function applied to each element. */ static public ArrayList mapJ(final F f, final ArrayList as) { - return new ArrayList(iterableStream(as).map(f).toCollection()); + return new ArrayList(fromIterable(as).map(f).toCollection()); } static public F map(F target, F f) { diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 40d6e8e7..5929c7c6 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -10,6 +10,7 @@ import fj.data.Stream; import static fj.Semigroup.multiply1p; +import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; import java.math.BigInteger; @@ -183,7 +184,7 @@ public F, A> sumLeftS() { * @return The sum of the given values and the interspersed value. */ public A join(final Iterable as, final A a) { - final Stream s = iterableStream(as); + final Stream s = fromIterable(as); return s.isEmpty() ? zero : s.foldLeft1(Function.compose(sum, flip(sum).f(a))); diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index b67f662a..a1635314 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -324,7 +324,7 @@ public static Show> setShow(final Show sa) { */ public static Show> treeMapShow(final Show sk, final Show sv) { return show(tm -> { - Stream> stream = Stream.iteratorStream(tm.iterator()); + Stream> stream = Stream.fromIterator(tm.iterator()); return streamShow(Show.p2MapShow(sk, sv), "TreeMap(", ",", ")").show(stream); }); } diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 7d01139a..589b0e93 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -18,6 +18,7 @@ import fj.function.Effect1; import static fj.data.Option.some; +import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; /** @@ -292,7 +293,7 @@ public F, F, Promise>>> parMapStream() { * @return A Promise of a new Iterable with the given function applied to each element. */ public Promise> parMap(final Iterable as, final F f) { - return parMap(iterableStream(as), f) + return parMap(fromIterable(as), f) .fmap(Function., Iterable>vary(Function.>identity())); } @@ -464,7 +465,7 @@ public Promise> parZipWith(final Array as, final Array * @return A Promise of a new iterable with the results of applying the given function across the two iterables, stepwise. */ public Promise> parZipWith(final Iterable as, final Iterable bs, final F> f) { - return parZipWith(iterableStream(as), iterableStream(bs), f).fmap( + return parZipWith(fromIterable(as), fromIterable(bs), f).fmap( Function., Iterable>vary(Function.>identity())); } @@ -514,8 +515,8 @@ public Promise parFoldMap(final Stream as, final F map, final */ public Promise parFoldMap(final Iterable as, final F map, final Monoid reduce, final F, P2, Iterable>> chunking) { - return parFoldMap(iterableStream(as), map, reduce, (Stream stream) -> { - final F, Stream> is = iterable -> iterableStream(iterable); + return parFoldMap(fromIterable(as), map, reduce, (Stream stream) -> { + final F, Stream> is = iterable -> fromIterable(iterable); return chunking.f(stream).map1(is).map2(is); }); } @@ -530,7 +531,7 @@ public Promise parFoldMap(final Iterable as, final F map, fin * @return A promise of a result of mapping and folding in parallel. */ public Promise parFoldMap(final Iterable as, final F map, final Monoid reduce) { - return parFoldMap(iterableStream(as), map, reduce); + return parFoldMap(fromIterable(as), map, reduce); } diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 52be7d6b..9da85ce0 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -1,6 +1,7 @@ package fj.data; import static fj.data.Option.some; +import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; import fj.Equal; import fj.F; @@ -85,7 +86,7 @@ public static F, F>> arrow() { * @return an iterable result of binding the given function over the wrapped Iterable. */ public > IterableW bind(final F f) { - return wrap(iterableStream(this).bind(a -> iterableStream(f.f(a)))); + return wrap(fromIterable(this).bind(a -> fromIterable(f.f(a)))); } /** @@ -128,12 +129,12 @@ public static F, F, IterableW>> liftM2(fina * @return A iterable of iterables containing the results of the bind operations across all given iterables. */ public static > IterableW> sequence(final Iterable as) { - final Stream ts = iterableStream(as); + final Stream ts = fromIterable(as); return ts.isEmpty() ? iterable(wrap(Option.none())) : wrap(ts.head()).bind(a -> sequence(ts.tail().map(IterableW.>wrap())._1()).bind(as2 -> - iterable(wrap(Stream.cons(a, () -> iterableStream(as2)))) + iterable(wrap(Stream.cons(a, () -> fromIterable(as2)))) ) ); } @@ -221,7 +222,7 @@ public A foldLeft1(final F2 f) { * @return The final result after the left-fold reduction. */ public A foldLeft1(final F> f) { - return iterableStream(this).foldLeft1(f); + return fromIterable(this).foldLeft1(f); } /** @@ -254,7 +255,7 @@ public Iterator iterator() { * @return A new iterable with the results of applying the functions to this iterable. */ public IterableW zapp(final Iterable> fs) { - return wrap(iterableStream(this).zapp(iterableStream(fs))); + return wrap(fromIterable(this).zapp(fromIterable(fs))); } /** @@ -268,7 +269,7 @@ public IterableW zapp(final Iterable> fs) { * iterable. */ public Iterable zipWith(final Iterable bs, final F> f) { - return wrap(iterableStream(this).zipWith(iterableStream(bs), f)); + return wrap(fromIterable(this).zipWith(fromIterable(bs), f)); } /** @@ -295,7 +296,7 @@ public Iterable zipWith(final Iterable bs, final F2 f) { * iterable. */ public Iterable> zip(final Iterable bs) { - return wrap(iterableStream(this).zip(iterableStream(bs))); + return wrap(fromIterable(this).zip(fromIterable(bs))); } /** @@ -304,7 +305,7 @@ public Iterable> zip(final Iterable bs) { * @return A new iterable with the same length as this iterable. */ public Iterable> zipIndex() { - return wrap(iterableStream(this).zipIndex()); + return wrap(fromIterable(this).zipIndex()); } /** @@ -317,16 +318,16 @@ public List toStandardList() { return new List() { public int size() { - return iterableStream(IterableW.this).length(); + return fromIterable(IterableW.this).length(); } public boolean isEmpty() { - return iterableStream(IterableW.this).isEmpty(); + return fromIterable(IterableW.this).isEmpty(); } @SuppressWarnings({"unchecked"}) public boolean contains(final Object o) { - return iterableStream(IterableW.this).exists(Equal.anyEqual().eq((A) o)); + return fromIterable(IterableW.this).exists(Equal.anyEqual().eq((A) o)); } public Iterator iterator() { @@ -334,12 +335,12 @@ public Iterator iterator() { } public Object[] toArray() { - return Array.iterableArray(iterableStream(IterableW.this)).array(); + return Array.iterableArray(fromIterable(IterableW.this)).array(); } @SuppressWarnings({"SuspiciousToArrayCall"}) public T[] toArray(final T[] a) { - return iterableStream(IterableW.this).toCollection().toArray(a); + return fromIterable(IterableW.this).toCollection().toArray(a); } public boolean add(final A a) { @@ -351,7 +352,7 @@ public boolean remove(final Object o) { } public boolean containsAll(final Collection c) { - return iterableStream(IterableW.this).toCollection().containsAll(c); + return fromIterable(IterableW.this).toCollection().containsAll(c); } public boolean addAll(final Collection c) { @@ -375,7 +376,7 @@ public void clear() { } public A get(final int index) { - return iterableStream(IterableW.this).index(index); + return fromIterable(IterableW.this).index(index); } public A set(final int index, final A element) { @@ -420,7 +421,7 @@ public ListIterator listIterator(final int index) { } public List subList(final int fromIndex, final int toIndex) { - return wrap(Stream.iterableStream(IterableW.this).drop(fromIndex).take(toIndex - fromIndex)).toStandardList(); + return wrap(Stream.fromIterable(IterableW.this).drop(fromIndex).take(toIndex - fromIndex)).toStandardList(); } private ListIterator toListIterator(final Option> z) { @@ -476,6 +477,6 @@ public void add(final A a) { } public Option> toZipper() { - return Zipper.fromStream(iterableStream(this)); + return Zipper.fromStream(fromIterable(this)); } } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fce14dc8..29acc536 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1542,14 +1542,16 @@ private void tail(final List tail) { } /** + * Constructs a list from the given Iterable. * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} - */ + */ @Deprecated public static List list(final Iterable i) { return fromIterable(i); } /** + * Constructs a list from the given Iterator. * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} */ @Deprecated @@ -1557,6 +1559,9 @@ public static List list(final Iterator it) { return fromIterable(() -> it); } + /** + * Constructs a list from the given Iterator. + */ public static List fromIterator(final Iterator it) { return fromIterable(() -> it); } @@ -1873,6 +1878,9 @@ public static List iterableList(final Iterable i) { return fromIterable(i); } + /** + * Constructs a list from the Iterable. + */ public static List fromIterable(final Iterable i) { final Buffer bs = empty(); for (final A a : i) { diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 808e296a..0ccde672 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -90,13 +90,27 @@ public final boolean isNotEmpty() { } /** - * Performs a reduction on this stream using the given arguments. + * Performs a reduction on this stream using the given arguments. Equivalent to {@link #reduce}. + * + * @deprecated As of release 4.5, use {@link #reduce} * * @param nil The value to return if this stream is empty. * @param cons The function to apply to the head and tail of this stream if it is not empty. * @return A reduction on this stream. */ + @Deprecated public final B stream(final B nil, final F>, B>> cons) { + return reduce(nil, cons); + } + + /** + * Performs a reduction on this stream using the given arguments. + * + * @param nil The value to return if this stream is empty. + * @param cons The function to apply to the head and tail of this stream if it is not empty. + * @return A reduction on this stream. + */ + public final B reduce(final B nil, final F>, B>> cons) { return isEmpty() ? nil : cons.f(head()).f(tail()); } @@ -701,14 +715,43 @@ public static Stream range(final int from, final long to) { } + /** + * Constructs a stream with the given elements in the Iterable. Equivalent to {@link #fromIterable(Iterable)} . + * + * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} + */ + @Deprecated public static Stream stream(Iterable it) { - return iterableStream(it); + return fromIterable(it); + } + + /** + * Constructs a stream with the given elements in the Iterable. + */ + public static Stream fromIterable(Iterable it) { + return fromIterator(it.iterator()); } + /** + * Constructs a stream with the given elements in the Iterator. Equivalent to {@link #fromIterator(Iterator)} . + * + * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} + */ + @Deprecated public static Stream stream(Iterator it) { - return iteratorStream(it); + return fromIterator(it); } + /** + * Constructs a stream with the given elements in the Iterator. + */ + public static Stream fromIterator(Iterator it) { + if (it.hasNext()) { + final A a = it.next(); + return cons(a, () -> fromIterator(it)); + } else + return nil(); + } /** * Returns a stream that is either infinite or bounded up to the maximum value of the given iterator starting at the @@ -1545,27 +1588,29 @@ public static Stream iterateWhile(final F f, final F p, } /** - * Takes the given iterable to a stream. + * Takes the given iterable to a stream. Equivalent to {@link #fromIterable(Iterable)}. + * + * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} * * @param i The iterable to take to a stream. * @return A stream from the given iterable. */ + @Deprecated public static Stream iterableStream(final Iterable i) { - return iteratorStream(i.iterator()); + return fromIterable(i); } /** - * Takes the given iterator to a stream. + * Takes the given iterator to a stream. Equivalent to {@link #fromIterator(Iterator)}. + * + * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} * * @param i The iterator to take to a stream. * @return A stream from the given iterator. */ + @Deprecated public static Stream iteratorStream(final Iterator i) { - if (i.hasNext()) { - final A a = i.next(); - return cons(a, () -> iteratorStream(i)); - } else - return nil(); + return fromIterator(i); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index e9107ff0..11513c7d 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -834,7 +834,7 @@ public List> traverseList(F> f){ public Stream> traverseStream(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : - Stream.stream(fail(e.left().value())); + Stream.fromIterable(fail(e.left().value())); } public Option> traverseOption(F> f){ diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index a37764c2..a583edd0 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -41,7 +41,7 @@ public void testToString() { @Test(expected = ConcurrentModificationException.class) public void iterableStreamWithStructureUpdate() { java.util.List list = List.list(1, 2, 3).toJavaList(); - Stream s1 = Stream.iterableStream(list); + Stream s1 = Stream.fromIterable(list); int x = s1.head(); list.remove(1); Stream s2 = s1.tail()._1(); diff --git a/java8/src/main/java/fj/data/Collectors.java b/java8/src/main/java/fj/data/Collectors.java index 3f3d7e40..738c7c43 100644 --- a/java8/src/main/java/fj/data/Collectors.java +++ b/java8/src/main/java/fj/data/Collectors.java @@ -30,7 +30,7 @@ public static Collector, Stream> toStream() { List.Buffer::new, List.Buffer::snoc, (acc1, acc2) -> acc1.append(acc2.toList()), - (buf) -> Stream.iterableStream(buf.toList()) + (buf) -> Stream.fromIterable(buf.toList()) ); } } From 99f38a16a676899ea0a62f23439f7c9e4c41a236 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 08:53:22 +1000 Subject: [PATCH 448/811] Upgrade to Gradle 2.10 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7761b5b4..be138e88 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip From f649a68b9b4839195d64cedc4ec11887aefae164 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 09:42:06 +1000 Subject: [PATCH 449/811] Added support to create sets from iterable, iterator, set and list. Deprecated overloaded methods. Added methods to convert to standard java.util classes --- core/src/main/java/fj/F2Functions.java | 3 +- core/src/main/java/fj/data/Set.java | 91 +++++++++++++++++-- core/src/test/java/fj/data/TreeMapTest.java | 2 +- .../src/test/scala/fj/data/CheckSet.scala | 6 +- .../src/main/java/fj/test/Arbitrary.java | 4 +- 5 files changed, 93 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index 3508bd70..a9d17364 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -6,6 +6,7 @@ import static fj.P.p; import static fj.data.IterableW.wrap; +import static fj.data.Set.fromIterable; import static fj.data.Set.iterableSet; import static fj.data.Tree.node; import static fj.data.TreeZipper.treeZipper; @@ -200,7 +201,7 @@ static public F2, NonEmptyList, NonEmptyList> zi * @return A function that zips two sets with this function. */ static public F2, Set, Set> zipSetM(final F2 f, final Ord o) { - return (as, bs) -> iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); + return (as, bs) -> fromIterable(o, as.toStream().zipWith(bs.toStream(), f)); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 0b7f4a0f..fa00c48b 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -291,7 +291,43 @@ public final List toList() { return foldMap(List.cons(List.nil()), Monoid.listMonoid()); } - /** + /** + * Returns a java.util.Set representation of this set. + * + * @return a java.util.Set representation of this set. + */ + public final java.util.Set toJavaSet() { + return toJavaHashSet(); + } + + /** + * Returns a java.util.HashSet representation of this set. + * + * @return a java.util.HashSet representation of this set. + */ + public final java.util.HashSet toJavaHashSet() { + return new java.util.HashSet(toStream().toCollection()); + } + + /** + * Returns a java.util.TreeSet representation of this set. + * + * @return a java.util.TreeSet representation of this set. + */ + public final java.util.TreeSet toJavaTreeSet() { + return new java.util.TreeSet(toStream().toCollection()); + } + + /** + * Returns a java.util.List representation of this set. + * + * @return a java.util.List representation of this set. + */ + public final java.util.List toJavaList() { + return new java.util.ArrayList(toStream().toCollection()); + } + + /** * Returns a list representation of this set in reverse order. * * @return a list representation of this set in reverse order. @@ -509,17 +545,53 @@ public static Set join(final Ord o, final Set> s) { /** * Return the elements of the given iterable as a set. * + * @deprecated As of release 4.5, use {@link #fromIterable} + * * @param o An order for the elements of the new set. * @param as An iterable of elements to add to a set. * @return A new set containing the elements of the given iterable. */ + @Deprecated public static Set iterableSet(final Ord o, final Iterable as) { + return fromIterable(o, as); + } + + /** + * Return the elements of the given iterable as a set. + * + * @param o An order for the elements of the new set. + * @param as An iterable of elements to add to a set. + * @return A new set containing the elements of the given iterable. + */ + public static Set fromIterable(final Ord o, final Iterable as) { Set s = empty(o); for (final A a : as) s = s.insert(a); return s; } + /** + * Return the elements of the given java.util.Set as a set. + * + * @param o An order for the elements of the new set. + * @param as A set of elements to create the set. + * @return A new set containing the elements of the given set. + */ + public static Set fromJavaSet(final Ord o, final java.util.Set as) { + return fromIterable(o, as); + } + + /** + * Return the elements of the given iterator as a set. + * + * @param o An order for the elements of the new set. + * @param as An iterator of elements to add to a set. + * @return A new set containing the elements of the given iterator. + */ + public static Set fromIterator(final Ord o, final Iterator as) { + return fromIterable(o, () -> as); + } + /** * Constructs a set from the given elements. * @@ -535,17 +607,24 @@ public static Set iterableSet(final Ord o, final Iterable as) { } /** - * Constructs a set from the given elements. + * Constructs a set from the list. + * + * @deprecated As of release 4.5, use {@link #fromList} * * @param o An order for the elements of the new set. * @param list The elements to add to a set. * @return A new set containing the elements of the given list. */ + @Deprecated public static Set set(final Ord o, List list) { - Set s = empty(o); - for (final A a : list) - s = s.insert(a); - return s; + return fromList(o, list); + } + + /** + * Constructs a set from the list. + */ + public static Set fromList(final Ord o, List list) { + return fromIterable(o, list); } } diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index f3cf61b6..0fda57e1 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -51,7 +51,7 @@ public void split() { } private static Set toSetString(List list) { - return Set.set(Ord.stringOrd, list.map(i -> i.toString())); + return Set.fromList(Ord.stringOrd, list.map(i -> i.toString())); } @Test diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala index 96bce311..3c006631 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala @@ -10,7 +10,7 @@ import Ord.intOrd import Ord.stringOrd import P.p import Unit.unit -import Set.{empty, single, join, iterableSet} +import Set.{empty, single, join, iterableSet, fromIterable} import org.scalacheck.Properties object CheckSet extends Properties("Set") { @@ -38,10 +38,10 @@ object CheckSet extends Properties("Set") { single(oi, n).member(n)) property("noDupesFromList") = forAll((a: List[String]) => - setEqual(stringEqual).eq(iterableSet(os, a.nub(stringEqual)), iterableSet(os, a))) + setEqual(stringEqual).eq(fromIterable(os, a.nub(stringEqual)), fromIterable(os, a))) property("noDupesToList") = forAll((a: List[String]) => - iterableSet(os, a).toList().length() == a.nub(stringEqual).length()) + fromIterable(os, a).toList().length() == a.nub(stringEqual).length()) property("subsetEmpty") = forAll((a: Set[Int]) => empty(oi).subsetOf(a)) diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 479e3d0d..1abc5699 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -815,11 +815,11 @@ public static Arbitrary> arbSeq(final Arbitrary aa) { } public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(list -> Set.set(ord, list))); + return arbitrary(arbList(aa).gen.map(list -> Set.fromList(ord, list))); } public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, int max) { - Gen> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.set(ord, list)); + Gen> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.fromList(ord, list)); return arbitrary(g); } From f24d04387b889b3a34ea0e81d93cd0c86d56160b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 10:16:39 +1000 Subject: [PATCH 450/811] Added methods to create a Seq. Deprecated overloaded seq method. --- core/src/main/java/fj/data/Seq.java | 61 ++++++++++++++++++- .../fj/data/properties/SeqProperties.java | 2 +- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 6e4c393b..40966778 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -65,12 +65,66 @@ public static Seq single(final A a) { return new Seq(Seq.mkTree().single(a)); } + /** + * Constructs a sequence from the given elements. + * @param as The elements to create the sequence from. + * @return A sequence with the given elements. + */ @SafeVarargs public static Seq seq(final A... as) { - return seq(List.list(as)); + return fromList(List.list(as)); } + /** + * Constructs a sequence from the given list. + * + * @deprecated As of release 4.5, use {@link #fromList(List)} + * + * @param list The list to create the sequence from. + * @return A sequence with the given elements in the list. + */ + @Deprecated public static Seq seq(final List list) { - return list.foldLeft((b, a) -> b.snoc(a), Seq.empty()); + return fromList(list); + } + + /** + * Constructs a sequence from the given list. + * @param list The list to create the sequence from. + * @return A sequence with the elements of the list. + */ + public static Seq fromList(final List list) { + return fromIterable(list); + } + + /** + * Constructs a sequence from the iterable. + * @param i The iterable to create the sequence from. + * @return A sequence with the elements of the iterable. + */ + public static Seq fromIterable(final Iterable i) { + Seq s = Seq.empty(); + for (final A a: i) { + s = s.snoc(a); + } + return s; + } + + /** + * Constructs a sequence from the iterator. + * @param i The iterator to create the sequence from. + * @return A sequence with the elements of the iterator. + */ + public static Seq fromIterator(final Iterator i) { + return fromIterable(() -> i); + } + + /** + * Constructs a sequence from the given list. + * @param list The list to create the sequence from. + * @return A sequence with the elements of the list. + */ + public static Seq fromJavaList(final java.util.List list) { + return fromIterable(list); } /** @@ -145,6 +199,9 @@ public List toList() { return buf.toList(); } + /** + * Converts the sequence to a java.util.List + */ public final java.util.List toJavaList() { return new AbstractList() { @Override public A get(int i) { return index(i); } diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 6f472b3b..1a21189d 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -122,7 +122,7 @@ public Property foldRight() { public Property length() { return property(arbList(arbInteger), list -> - prop(Seq.seq(list).length() == list.length()) + prop(Seq.fromList(list).length() == list.length()) ); } From 077832d1e34669f6829a0f38765973700fa8c642 Mon Sep 17 00:00:00 2001 From: Michal Samek Date: Fri, 5 Feb 2016 10:32:12 +0100 Subject: [PATCH 451/811] Correction of comment --- demo/src/main/java/fj/demo/Option_filter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/src/main/java/fj/demo/Option_filter.java b/demo/src/main/java/fj/demo/Option_filter.java index 9f934c0e..aac3538f 100644 --- a/demo/src/main/java/fj/demo/Option_filter.java +++ b/demo/src/main/java/fj/demo/Option_filter.java @@ -25,6 +25,6 @@ public static void main(final String[] args) { optionShow(intShow).println(o7); // None optionShow(intShow).println(o8); // None - optionShow(intShow).println(o9); // Some(4) + optionShow(intShow).println(o9); // Some(8) } } From 4eb7e9e4f3f5c8d1dcb905fe23c92f96300af325 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 5 Feb 2016 23:02:50 +1000 Subject: [PATCH 452/811] Setup benchmarks module --- benchmarks/build.gradle | 6 ++++++ .../src/main/java/fj/data/dummy/DummyClass.java | 8 ++++++++ .../src/test/java/fj/data/dummy/DummyTest.java | 17 +++++++++++++++++ settings.gradle | 2 +- 4 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 benchmarks/build.gradle create mode 100644 benchmarks/src/main/java/fj/data/dummy/DummyClass.java create mode 100644 benchmarks/src/test/java/fj/data/dummy/DummyTest.java diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle new file mode 100644 index 00000000..e1e42422 --- /dev/null +++ b/benchmarks/build.gradle @@ -0,0 +1,6 @@ + +configureAllRetroLambda() + +dependencies { + testCompile dependencyJunit +} diff --git a/benchmarks/src/main/java/fj/data/dummy/DummyClass.java b/benchmarks/src/main/java/fj/data/dummy/DummyClass.java new file mode 100644 index 00000000..72cc5c34 --- /dev/null +++ b/benchmarks/src/main/java/fj/data/dummy/DummyClass.java @@ -0,0 +1,8 @@ +package fj.data.dummy; + +/** + * Created by MarkPerry on 5 Feb 16. + */ +public class DummyClass { + +} diff --git a/benchmarks/src/test/java/fj/data/dummy/DummyTest.java b/benchmarks/src/test/java/fj/data/dummy/DummyTest.java new file mode 100644 index 00000000..d3865433 --- /dev/null +++ b/benchmarks/src/test/java/fj/data/dummy/DummyTest.java @@ -0,0 +1,17 @@ +package fj.data.dummy; + +import org.junit.Ignore; +import org.junit.Test; + +/** + * Created by MarkPerry on 5 Feb 16. + */ +public class DummyTest { + + @Test + @Ignore + public void test1() { + + } + +} diff --git a/settings.gradle b/settings.gradle index e936f374..a5fab06a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = "functionaljava" -include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck", "java-core" +include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck", "java-core", "benchmarks" From 3cd3a4b7a3f0f4df3086373575e5abab767789d3 Mon Sep 17 00:00:00 2001 From: mrbackend Date: Fri, 5 Feb 2016 23:10:14 +0100 Subject: [PATCH 453/811] #210 Make Array.ImmutableProjection static --- core/src/main/java/fj/data/Array.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index bc570198..9cbd6e9c 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -348,7 +348,7 @@ public Array scanLeft(final F2 f, final B b) { public Array scanLeft1(final F> f) { final Object[] bs = new Object[a.length]; A x = get(0); - bs[0] = x; + bs[0] = x; for (int i = 1; i < a.length; i++) { x = f.f(x).f((A) a[i]); @@ -417,7 +417,7 @@ public Array scanRight(final F2 f, final B b) { public Array scanRight1(final F>f) { final Object[] bs = new Object[a.length]; A x = get(length() - 1); - bs[length() - 1] = x; + bs[length() - 1] = x; for (int i = a.length - 2; i >= 0; i--) { x = f.f((A) a[i]).f(x); @@ -827,7 +827,7 @@ public static P2, Array> unzip(final Array> xs) { /** * Projects an array by providing only operations which do not mutate. */ - public final class ImmutableProjection implements Iterable { + public static final class ImmutableProjection implements Iterable { private final Array a; private ImmutableProjection(final Array a) { From 99db71ef72050d58864a607d9c5b1afc114a9012 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 6 Feb 2016 09:11:09 +1000 Subject: [PATCH 454/811] Added dlist performance class --- benchmarks/build.gradle | 1 + benchmarks/src/main/java/main/Main.java | 99 +++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 benchmarks/src/main/java/main/Main.java diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index e1e42422..b5bc2916 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -2,5 +2,6 @@ configureAllRetroLambda() dependencies { + compile project(":core") testCompile dependencyJunit } diff --git a/benchmarks/src/main/java/main/Main.java b/benchmarks/src/main/java/main/Main.java new file mode 100644 index 00000000..90b742a1 --- /dev/null +++ b/benchmarks/src/main/java/main/Main.java @@ -0,0 +1,99 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package main; + +import fj.data.DList; +import fj.data.List; +import fj.data.Seq; +import fj.data.Stream; + +/** + * + * @author clintonselke + */ +public class Main { + + private interface BenchmarkMethods { + C range(int from, int to); + C append(C a, C b); + List unbox(C a); + } + + private static final BenchmarkMethods> listMethods = new BenchmarkMethods>() { + @Override + public List range(int from, int to) { + return List.range(from, to); + } + @Override + public List append(List a, List b) { + return a.append(b); + } + @Override + public List unbox(List a) { + return a; + } + }; + + private static final BenchmarkMethods> seqMethods = new BenchmarkMethods>() { + @Override + public Seq range(int from, int to) { + return Seq.seq(List.range(from, to)); + } + @Override + public Seq append(Seq a, Seq b) { + return a.append(b); + } + @Override + public List unbox(Seq a) { + return a.toList(); + } + }; + + private static final BenchmarkMethods> dListMethods = new BenchmarkMethods>() { + @Override + public DList range(int from, int to) { + return DList.fromList(List.range(from, to)); + } + @Override + public DList append(DList a, DList b) { + return a.append(b); + } + @Override + public List unbox(DList a) { + return a.run(); + } + }; + + private static double benchmark(BenchmarkMethods methods) { + long msStart = System.currentTimeMillis(); + for (int n = 0; n < 10; ++n) { + final C xs = methods.range(0, 100); + C r = xs; + for (int i = 1; i < 2000; ++i) { + r = methods.append(r, xs); + } + List r2 = methods.unbox(r); + for (Integer x : r2) {} + } + long msEnd = System.currentTimeMillis(); + return (msEnd - msStart) / 10.0; + } + + public static void main(String[] params) { + // warm up + benchmark(listMethods); + benchmark(seqMethods); + benchmark(dListMethods); + // actual run + double listTime = benchmark(listMethods); + double seqTime = benchmark(seqMethods); + double dListTime = benchmark(dListMethods); + System.out.println("Average over 10 runs..."); + System.out.println("List: " + listTime + "ms"); + System.out.println("Seq: " + seqTime + "ms"); + System.out.println("DList: " + dListTime + "ms"); + } +} From 6bd39673c83fd4ae53808c15c50de090e9e368d9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 6 Feb 2016 09:19:33 +1000 Subject: [PATCH 455/811] Renamed benchmarks to performance --- {benchmarks => performance}/build.gradle | 0 .../src/main/java/fj/data/dummy/DummyClass.java | 0 {benchmarks => performance}/src/main/java/main/Main.java | 0 .../src/test/java/fj/data/dummy/DummyTest.java | 0 settings.gradle | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) rename {benchmarks => performance}/build.gradle (100%) rename {benchmarks => performance}/src/main/java/fj/data/dummy/DummyClass.java (100%) rename {benchmarks => performance}/src/main/java/main/Main.java (100%) rename {benchmarks => performance}/src/test/java/fj/data/dummy/DummyTest.java (100%) diff --git a/benchmarks/build.gradle b/performance/build.gradle similarity index 100% rename from benchmarks/build.gradle rename to performance/build.gradle diff --git a/benchmarks/src/main/java/fj/data/dummy/DummyClass.java b/performance/src/main/java/fj/data/dummy/DummyClass.java similarity index 100% rename from benchmarks/src/main/java/fj/data/dummy/DummyClass.java rename to performance/src/main/java/fj/data/dummy/DummyClass.java diff --git a/benchmarks/src/main/java/main/Main.java b/performance/src/main/java/main/Main.java similarity index 100% rename from benchmarks/src/main/java/main/Main.java rename to performance/src/main/java/main/Main.java diff --git a/benchmarks/src/test/java/fj/data/dummy/DummyTest.java b/performance/src/test/java/fj/data/dummy/DummyTest.java similarity index 100% rename from benchmarks/src/test/java/fj/data/dummy/DummyTest.java rename to performance/src/test/java/fj/data/dummy/DummyTest.java diff --git a/settings.gradle b/settings.gradle index a5fab06a..d231d998 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = "functionaljava" -include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck", "java-core", "benchmarks" +include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck", "java-core", "performance" From e7ad3c9ffd3c09528ca7bedd5d8acee5b2a0e0d9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 6 Feb 2016 09:31:51 +1000 Subject: [PATCH 456/811] Renamed class to DListPerformance --- .../java/{main/Main.java => fj/data/DListPerformance.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename performance/src/main/java/{main/Main.java => fj/data/DListPerformance.java} (98%) diff --git a/performance/src/main/java/main/Main.java b/performance/src/main/java/fj/data/DListPerformance.java similarity index 98% rename from performance/src/main/java/main/Main.java rename to performance/src/main/java/fj/data/DListPerformance.java index 90b742a1..56e5748b 100644 --- a/performance/src/main/java/main/Main.java +++ b/performance/src/main/java/fj/data/DListPerformance.java @@ -3,7 +3,7 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package main; +package fj.data; import fj.data.DList; import fj.data.List; @@ -14,7 +14,7 @@ * * @author clintonselke */ -public class Main { +public class DListPerformance { private interface BenchmarkMethods { C range(int from, int to); From 3ce9d0ece1eea2f2ea9487050a5772a0df509c30 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 6 Feb 2016 09:45:56 +1000 Subject: [PATCH 457/811] Small output changes to dlist peformance test --- .../main/java/fj/data/DListPerformance.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/performance/src/main/java/fj/data/DListPerformance.java b/performance/src/main/java/fj/data/DListPerformance.java index 56e5748b..fbcfafa7 100644 --- a/performance/src/main/java/fj/data/DListPerformance.java +++ b/performance/src/main/java/fj/data/DListPerformance.java @@ -5,17 +5,14 @@ */ package fj.data; -import fj.data.DList; -import fj.data.List; -import fj.data.Seq; -import fj.data.Stream; - /** * * @author clintonselke */ public class DListPerformance { + static final int TOTAL_RUNS = 10; + private interface BenchmarkMethods { C range(int from, int to); C append(C a, C b); @@ -40,7 +37,7 @@ public List unbox(List a) { private static final BenchmarkMethods> seqMethods = new BenchmarkMethods>() { @Override public Seq range(int from, int to) { - return Seq.seq(List.range(from, to)); + return Seq.fromList(List.range(from, to)); } @Override public Seq append(Seq a, Seq b) { @@ -69,7 +66,8 @@ public List unbox(DList a) { private static double benchmark(BenchmarkMethods methods) { long msStart = System.currentTimeMillis(); - for (int n = 0; n < 10; ++n) { + + for (int runNumber = 0; runNumber < TOTAL_RUNS; ++runNumber) { final C xs = methods.range(0, 100); C r = xs; for (int i = 1; i < 2000; ++i) { @@ -79,19 +77,22 @@ private static double benchmark(BenchmarkMethods methods) { for (Integer x : r2) {} } long msEnd = System.currentTimeMillis(); - return (msEnd - msStart) / 10.0; + return (msEnd - msStart) / ((double) TOTAL_RUNS); } public static void main(String[] params) { + System.out.println("Starting difference list (DList) performance benchmark..."); // warm up + System.out.println("warm up..."); benchmark(listMethods); benchmark(seqMethods); benchmark(dListMethods); // actual run + System.out.println("running benchmark..."); double listTime = benchmark(listMethods); double seqTime = benchmark(seqMethods); double dListTime = benchmark(dListMethods); - System.out.println("Average over 10 runs..."); + System.out.println("Average over " + TOTAL_RUNS + " runs..."); System.out.println("List: " + listTime + "ms"); System.out.println("Seq: " + seqTime + "ms"); System.out.println("DList: " + dListTime + "ms"); From b8fa5252fa27db0366084e378737e103baf84b89 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 6 Feb 2016 09:49:40 +1000 Subject: [PATCH 458/811] Added DList performance javadoc on class --- performance/src/main/java/fj/data/DListPerformance.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/performance/src/main/java/fj/data/DListPerformance.java b/performance/src/main/java/fj/data/DListPerformance.java index fbcfafa7..bc4b9d2a 100644 --- a/performance/src/main/java/fj/data/DListPerformance.java +++ b/performance/src/main/java/fj/data/DListPerformance.java @@ -1,12 +1,9 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package fj.data; /** - * + * Difference List performance benchmarks comparing DList to Seq and List + * over 10 runs for the methods range, append and unbox. + * * @author clintonselke */ public class DListPerformance { From 7d0d1031ff211a062196d44648a71938d8360f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Fri, 5 Feb 2016 19:49:55 -0500 Subject: [PATCH 459/811] Add JUnit for Doubles --- .../test/java/fj/function/DoublesTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 core/src/test/java/fj/function/DoublesTest.java diff --git a/core/src/test/java/fj/function/DoublesTest.java b/core/src/test/java/fj/function/DoublesTest.java new file mode 100644 index 00000000..6ba98fa2 --- /dev/null +++ b/core/src/test/java/fj/function/DoublesTest.java @@ -0,0 +1,61 @@ +package fj.function; + +import static org.junit.Assert.*; + +import fj.F; +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static org.hamcrest.core.Is.is; + +import static fj.data.List.list; + +public class DoublesTest { + + @Test + public void testSum() { + assertThat(Doubles.sum(list(3.0, 4.0, 5.0)), is(12.0)); + } + + @Test + public void testProduct() { + assertThat(Doubles.product(list(3.0, 4.0, 5.0)), is(60.0)); + } + + @Test + public void testAdd() { + assertThat(Doubles.add.f(10.0).f(20.0), is(30.0)); + } + + @Test + public void testMultiply() { + assertThat(Doubles.multiply.f(3.0).f(5.0), is(15.0)); + } + + @Test + public void testAbs() { + assertThat(Doubles.abs.f(-5.0), is(5.0)); + } + + @Test + public void testFromString() { + assertThat(Doubles.fromString().f("-123.45").some(), is(-123.45)); + } + + @Test + public void testCannotInstantiate() throws NoSuchMethodException, InvocationTargetException, + IllegalAccessException, InstantiationException { + Constructor constructor = Doubles.class.getDeclaredConstructor(new Class[0]); + constructor.setAccessible(true); + try { + constructor.newInstance(new Object[0]); + fail("expected InvocationTargetException"); + } catch (InvocationTargetException ite) { + assertTrue(ite.getCause() instanceof UnsupportedOperationException); + } + } + +} From e59516c1eb0e4b16cbe5c0cd6ea3c136c4c62ec3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Feb 2016 11:12:33 +1000 Subject: [PATCH 460/811] Add gitter badge to Github main page --- README.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.adoc b/README.adoc index 508fdc37..bf3b350e 100644 --- a/README.adoc +++ b/README.adoc @@ -2,6 +2,7 @@ image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] image:https://coveralls.io/repos/github/functionaljava/functionaljava/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/github/functionaljava/functionaljava?branch=master"] +image:https://badges.gitter.im/functionaljava.svg[link="https://gitter.im/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image::http://www.functionaljava.org/img/logo-600x144.png[] From 427180494d31f2eadb468f9cf2fe03e187b576c9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Feb 2016 11:35:42 +1000 Subject: [PATCH 461/811] Removed Cloudbees link --- README.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/README.adoc b/README.adoc index 508fdc37..e7fbd8a1 100644 --- a/README.adoc +++ b/README.adoc @@ -23,7 +23,6 @@ Important URLs for the project are: * Website repository, http://github.com/functionaljava/functionaljava.github.io * Travis continuous integration build, https://travis-ci.org/functionaljava/functionaljava * Sonatype Repository, https://oss.sonatype.org/content/groups/public/org/functionaljava/ -* Jenkins Cloudbees CI build, https://functionaljava.ci.cloudbees.com == Downloading From 030ae6fb9c9c97d275ab370fc9451f756eed29c1 Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Sat, 13 Feb 2016 09:48:10 +0000 Subject: [PATCH 462/811] Add Gitter badge --- README.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.adoc b/README.adoc index 5289f1f3..5b56ea2f 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,7 @@ = Functional Java +image:https://badges.gitter.im/functionaljava/functionaljava.svg[link="https://gitter.im/functionaljava/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] + image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] image:https://coveralls.io/repos/github/functionaljava/functionaljava/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/github/functionaljava/functionaljava?branch=master"] image:https://badges.gitter.im/functionaljava.svg[link="https://gitter.im/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] From 94a79d0d29e2adbd3ffa312d6b10b88e7af95665 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 00:57:35 +1000 Subject: [PATCH 463/811] Reviewed creating instances from iterable, iterator and varargs array for classes in core --- core/src/main/java/fj/F1Functions.java | 23 +++--- core/src/main/java/fj/F2Functions.java | 4 +- core/src/main/java/fj/Monoid.java | 3 +- core/src/main/java/fj/Show.java | 2 +- .../java/fj/control/parallel/ParModule.java | 11 ++- core/src/main/java/fj/data/Array.java | 25 ++++-- core/src/main/java/fj/data/DList.java | 53 ++++++++++--- core/src/main/java/fj/data/HashMap.java | 76 +++++++++++++++++-- core/src/main/java/fj/data/HashSet.java | 57 ++++++++++++++ core/src/main/java/fj/data/IterableW.java | 35 +++++---- core/src/main/java/fj/data/Java.java | 2 +- core/src/main/java/fj/data/List.java | 38 +++++----- core/src/main/java/fj/data/Seq.java | 23 +++--- core/src/main/java/fj/data/Set.java | 38 +++------- core/src/main/java/fj/data/Stream.java | 61 +++++---------- core/src/main/java/fj/data/TreeMap.java | 20 ++++- core/src/main/java/fj/data/Validation.java | 4 +- core/src/test/java/fj/data/ListTest.java | 4 +- core/src/test/java/fj/data/StreamTest.java | 2 +- core/src/test/java/fj/data/TreeMapTest.java | 2 +- .../src/main/java/fj/java/util/ListUtil.java | 8 +- java8/src/main/java/fj/data/Collectors.java | 2 +- .../main/java/fj/data/DListPerformance.java | 4 +- .../src/test/scala/fj/data/CheckHashMap.scala | 2 +- .../src/test/scala/fj/data/CheckSet.scala | 6 +- .../fj/data/properties/SeqProperties.java | 6 +- 26 files changed, 328 insertions(+), 183 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index e5f4bba8..2d3c56d4 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -12,7 +12,6 @@ import java.util.concurrent.*; import static fj.data.Option.some; -import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; import static fj.data.Zipper.fromStream; @@ -559,7 +558,7 @@ static public F, P2> mapBoth(final F f) { */ static public SynchronousQueue mapJ(final F f, final SynchronousQueue as) { final SynchronousQueue bs = new SynchronousQueue(); - bs.addAll(fromIterable(as).map(f).toCollection()); + bs.addAll(iterableStream(as).map(f).toCollection()); return bs; } @@ -571,7 +570,7 @@ static public SynchronousQueue mapJ(final F f, final Synchronous * @return A new PriorityBlockingQueue with this function applied to each element. */ static public PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { - return new PriorityBlockingQueue(fromIterable(as).map(f).toCollection()); + return new PriorityBlockingQueue(iterableStream(as).map(f).toCollection()); } /** @@ -581,7 +580,7 @@ static public PriorityBlockingQueue mapJ(final F f, final Priori * @return A new LinkedBlockingQueue with this function applied to each element. */ static public LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { - return new LinkedBlockingQueue(fromIterable(as).map(f).toCollection()); + return new LinkedBlockingQueue(iterableStream(as).map(f).toCollection()); } /** @@ -591,7 +590,7 @@ static public LinkedBlockingQueue mapJ(final F f, final LinkedBl * @return A new CopyOnWriteArraySet with this function applied to each element. */ static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { - return new CopyOnWriteArraySet(fromIterable(as).map(f).toCollection()); + return new CopyOnWriteArraySet(iterableStream(as).map(f).toCollection()); } /** @@ -601,7 +600,7 @@ static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWr * @return A new CopyOnWriteArrayList with this function applied to each element. */ static public CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { - return new CopyOnWriteArrayList(fromIterable(as).map(f).toCollection()); + return new CopyOnWriteArrayList(iterableStream(as).map(f).toCollection()); } /** @@ -611,7 +610,7 @@ static public CopyOnWriteArrayList mapJ(final F f, final CopyOnW * @return A new ConcurrentLinkedQueue with this function applied to each element. */ static public ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { - return new ConcurrentLinkedQueue(fromIterable(as).map(f).toCollection()); + return new ConcurrentLinkedQueue(iterableStream(as).map(f).toCollection()); } /** @@ -622,7 +621,7 @@ static public ConcurrentLinkedQueue mapJ(final F f, final Concur */ static public ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); - bs.addAll(fromIterable(as).map(f).toCollection()); + bs.addAll(iterableStream(as).map(f).toCollection()); return bs; } @@ -634,7 +633,7 @@ static public ArrayBlockingQueue mapJ(final F f, final ArrayBloc * @return A new TreeSet with this function applied to each element. */ static public TreeSet mapJ(final F f, final TreeSet as) { - return new TreeSet(fromIterable(as).map(f).toCollection()); + return new TreeSet(iterableStream(as).map(f).toCollection()); } /** @@ -644,7 +643,7 @@ static public TreeSet mapJ(final F f, final TreeSet as) { * @return A new PriorityQueue with this function applied to each element. */ static public PriorityQueue mapJ(final F f, final PriorityQueue as) { - return new PriorityQueue(fromIterable(as).map(f).toCollection()); + return new PriorityQueue(iterableStream(as).map(f).toCollection()); } /** @@ -654,7 +653,7 @@ static public PriorityQueue mapJ(final F f, final PriorityQueue< * @return A new LinkedList with this function applied to each element. */ static public LinkedList mapJ(final F f, final LinkedList as) { - return new LinkedList(fromIterable(as).map(f).toCollection()); + return new LinkedList(iterableStream(as).map(f).toCollection()); } /** @@ -664,7 +663,7 @@ static public LinkedList mapJ(final F f, final LinkedList as) * @return A new ArrayList with this function applied to each element. */ static public ArrayList mapJ(final F f, final ArrayList as) { - return new ArrayList(fromIterable(as).map(f).toCollection()); + return new ArrayList(iterableStream(as).map(f).toCollection()); } static public F map(F target, F f) { diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index a9d17364..c15a68cb 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -2,11 +2,9 @@ import fj.control.parallel.Promise; import fj.data.*; -import fj.function.Try2; import static fj.P.p; import static fj.data.IterableW.wrap; -import static fj.data.Set.fromIterable; import static fj.data.Set.iterableSet; import static fj.data.Tree.node; import static fj.data.TreeZipper.treeZipper; @@ -201,7 +199,7 @@ static public F2, NonEmptyList, NonEmptyList> zi * @return A function that zips two sets with this function. */ static public F2, Set, Set> zipSetM(final F2 f, final Ord o) { - return (as, bs) -> fromIterable(o, as.toStream().zipWith(bs.toStream(), f)); + return (as, bs) -> iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); } /** diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 5929c7c6..40d6e8e7 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -10,7 +10,6 @@ import fj.data.Stream; import static fj.Semigroup.multiply1p; -import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; import java.math.BigInteger; @@ -184,7 +183,7 @@ public F, A> sumLeftS() { * @return The sum of the given values and the interspersed value. */ public A join(final Iterable as, final A a) { - final Stream s = fromIterable(as); + final Stream s = iterableStream(as); return s.isEmpty() ? zero : s.foldLeft1(Function.compose(sum, flip(sum).f(a))); diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index a1635314..b67f662a 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -324,7 +324,7 @@ public static Show> setShow(final Show sa) { */ public static Show> treeMapShow(final Show sk, final Show sv) { return show(tm -> { - Stream> stream = Stream.fromIterator(tm.iterator()); + Stream> stream = Stream.iteratorStream(tm.iterator()); return streamShow(Show.p2MapShow(sk, sv), "TreeMap(", ",", ")").show(stream); }); } diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 589b0e93..7d01139a 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -18,7 +18,6 @@ import fj.function.Effect1; import static fj.data.Option.some; -import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; /** @@ -293,7 +292,7 @@ public F, F, Promise>>> parMapStream() { * @return A Promise of a new Iterable with the given function applied to each element. */ public Promise> parMap(final Iterable as, final F f) { - return parMap(fromIterable(as), f) + return parMap(iterableStream(as), f) .fmap(Function., Iterable>vary(Function.>identity())); } @@ -465,7 +464,7 @@ public Promise> parZipWith(final Array as, final Array * @return A Promise of a new iterable with the results of applying the given function across the two iterables, stepwise. */ public Promise> parZipWith(final Iterable as, final Iterable bs, final F> f) { - return parZipWith(fromIterable(as), fromIterable(bs), f).fmap( + return parZipWith(iterableStream(as), iterableStream(bs), f).fmap( Function., Iterable>vary(Function.>identity())); } @@ -515,8 +514,8 @@ public Promise parFoldMap(final Stream as, final F map, final */ public Promise parFoldMap(final Iterable as, final F map, final Monoid reduce, final F, P2, Iterable>> chunking) { - return parFoldMap(fromIterable(as), map, reduce, (Stream stream) -> { - final F, Stream> is = iterable -> fromIterable(iterable); + return parFoldMap(iterableStream(as), map, reduce, (Stream stream) -> { + final F, Stream> is = iterable -> iterableStream(iterable); return chunking.f(stream).map1(is).map2(is); }); } @@ -531,7 +530,7 @@ public Promise parFoldMap(final Iterable as, final F map, fin * @return A promise of a result of mapping and folding in parallel. */ public Promise parFoldMap(final Iterable as, final F map, final Monoid reduce) { - return parFoldMap(fromIterable(as), map, reduce); + return parFoldMap(iterableStream(as), map, reduce); } diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 9cbd6e9c..b16ae018 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -22,7 +22,7 @@ import static fj.P.p; import static fj.P.p2; import static fj.Unit.unit; -import static fj.data.List.fromIterable; +import static fj.data.List.iterableList; import static fj.data.Option.none; import static fj.data.Option.some; import static java.lang.Math.min; @@ -559,12 +559,12 @@ public static Array empty() { /** * Constructs an array from the given elements. * - * @param a The elements to construct the array with. + * @param as The elements to construct the array with. * @return A new array of the given elements. */ @SafeVarargs - public static Array array(final A... a) { - return new Array(a); + public static Array array(final A...as) { + return arrayArray(as); } /** @@ -802,7 +802,22 @@ public int size() { * @return An array from the given iterable. */ public static Array iterableArray(final Iterable i) { - return fromIterable(i).toArray(); + return iterableList(i).toArray(); + } + + public static Array iteratorArray(final Iterator i) { + return iterableArray(() -> i); + } + + /** + * Returns a copy of the underlying primitive array. + * Equivalent to array(A...) + * + * @return A copy of the underlying primitive array. + */ + @SafeVarargs + public static Array arrayArray(final A...as) { + return new Array(as); } /** diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 6c4ee773..6b7fc1b2 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -4,6 +4,10 @@ import fj.P; import fj.control.Trampoline; +import java.util.Iterator; + +import static fj.data.List.iterableList; + /** * Difference List. It converts left associative appends into right associative ones to improve performance. * @@ -12,20 +16,51 @@ public class DList { private final F,Trampoline>> appendFn; - private DList(F,Trampoline>> appendFn) { + private DList(final F,Trampoline>> appendFn) { this.appendFn = appendFn; } - + /** - * Wraps a list with a DList. - * @param - * @param a the regular List - * @return the DList + * Creates a DList from the function + * + * For alternatives functions to create a DList see: + * @see #iterableDList + * @see #iteratorDList + * @see #arrayDList */ - public static DList fromList(List a) { - return new DList<>((List tail) -> Trampoline.pure(a.append(tail))); + public static DList dlist(final F,Trampoline>> f) { + return new DList<>(f); } - + + /** + * Creates a DList from a List + */ + public static DList listDList(final List a) { + return dlist((List tail) -> Trampoline.pure(a.append(tail))); + } + + /** + * Creates a DList from an Iterable + */ + public static DList iterableDList(final Iterable it) { + return listDList(iterableList(it)); + } + + /** + * Creates a DList from an Iterator + */ + public static DList iteratorDList(final Iterator it) { + return iterableDList(() -> it); + } + + /** + * Creates a DList from an array + */ + @SafeVarargs + public static DList arrayDList(final A...as) { + return listDList(List.list(as)); + } + /** * Concatenates all the internal Lists together that are held in * the DList's lambda's state to produce a List. diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 1d934db4..3e3597d1 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -111,8 +111,15 @@ public HashMap(final Equal e, final Hash h, final int initialCapacity, fin * @return A new hash map that uses {@link Object#equals} and {@link Object#hashCode}. */ public static HashMap hashMap() { - final Equal e = Equal.anyEqual(); - final Hash h = Hash.anyHash(); + return hashMap(Equal.anyEqual(), Hash.anyHash()); + } + + /** + * Construct a hash map. + * + * @return A new hash map. + */ + public static HashMap hashMap(final Equal e, final Hash h) { return new HashMap(e, h); } @@ -324,15 +331,72 @@ public java.util.Map toMap() { return result; } - public static HashMap from(Iterable> entries) { - return from(entries, Equal.anyEqual(), Hash.anyHash()); + /** + * Converts the Iterable to a HashMap + * + * @deprecated As of release 4.5, use {@link #iterableHashMap(Iterable)} + */ + @Deprecated + public static HashMap from(final Iterable> entries) { + return iterableHashMap(Equal.anyEqual(), Hash.anyHash(), entries); + } + + /** + * Converts the Iterable to a HashMap + * + * @deprecated As of release 4.5, use {@link #iterableHashMap} + */ + @Deprecated + public static HashMap from(final Iterable> entries, final Equal equal, final Hash hash) { + return iterableHashMap(equal, hash, entries); } - public static HashMap from(Iterable> entries, Equal equal, Hash hash) { + /** + * Converts the Iterable to a HashMap + */ + public static HashMap iterableHashMap(final Equal equal, final Hash hash, final Iterable> entries) { final HashMap map = new HashMap(equal, hash); for (P2 entry : entries) { - map.set(entry._1(), entry._2()); + map.set(entry._1(), entry._2()); } return map; } + + /** + * Converts the Iterable to a HashMap + */ + public static HashMap iterableHashMap(final Iterable> entries) { + return iterableHashMap(Equal.anyEqual(), Hash.anyHash(), entries); + } + + /** + * Converts the array to a HashMap + */ + @SafeVarargs + public static HashMap arrayHashMap(final P2...entries) { + return iterableHashMap(Array.array(entries)); + } + + /** + * Converts the array to a HashMap + */ + @SafeVarargs + public static HashMap arrayHashMap(final Equal equal, final Hash hash, final P2...entries) { + return iterableHashMap(equal, hash, Array.array(entries)); + } + + /** + * Converts the Iterator to a HashMap + */ + public static HashMap iteratorHashMap(final Equal equal, final Hash hash, final Iterator> entries) { + return iterableHashMap(equal, hash, () -> entries); + } + + /** + * Converts the Iterator to a HashMap + */ + public static HashMap iteratorHashMap(final Iterator> entries) { + return iterableHashMap(() -> entries); + } + } diff --git a/core/src/main/java/fj/data/HashSet.java b/core/src/main/java/fj/data/HashSet.java index 8228eeab..555f8732 100644 --- a/core/src/main/java/fj/data/HashSet.java +++ b/core/src/main/java/fj/data/HashSet.java @@ -3,6 +3,9 @@ import fj.Equal; import fj.Hash; import fj.Unit; + +import static fj.Equal.anyEqual; +import static fj.Hash.anyHash; import static fj.Unit.unit; import java.util.Collection; @@ -80,6 +83,60 @@ public int hash(final A a) { return m.hash(a); } + /** + * Creates a new HashSet using the given Equal and Hash + */ + public static HashSet empty(final Equal e, final Hash h) { + return new HashSet(e, h); + } + + /** + * Creates an empty HashSet + */ + public static HashSet empty() { + return empty(anyEqual(), anyHash()); + } + + public static HashSet iterableHashSet(final Iterable it) { + return iterableHashSet(anyEqual(), anyHash(), it); + } + + public static HashSet iterableHashSet(final Equal e, final Hash h, final Iterable it) { + final HashSet hs = empty(e, h); + for (A a: it) { + hs.set(a); + } + return hs; + } + + public static HashSet iteratorHashSet(final Iterator it) { + return iterableHashSet(() -> it); + } + + public static HashSet iteratorHashSet(final Equal e, final Hash h, final Iterator it) { + return iterableHashSet(e, h, () -> it); + } + + @SafeVarargs + public static HashSet arrayHashSet(final A...as) { + return iterableHashSet(Array.array(as)); + } + + @SafeVarargs + public static HashSet arrayHashSet(final Equal e, final Hash h, final A...as) { + return iterableHashSet(e, h, Array.array(as)); + } + + @SafeVarargs + public static HashSet hashSet(final A...as) { + return arrayHashSet(as); + } + + @SafeVarargs + public static HashSet hashSet(final Equal e, final Hash h, final A...as) { + return arrayHashSet(e, h, as); + } + /** * Determines if this hash set contains the given element. * diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 9da85ce0..52be7d6b 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -1,7 +1,6 @@ package fj.data; import static fj.data.Option.some; -import static fj.data.Stream.fromIterable; import static fj.data.Stream.iterableStream; import fj.Equal; import fj.F; @@ -86,7 +85,7 @@ public static F, F>> arrow() { * @return an iterable result of binding the given function over the wrapped Iterable. */ public > IterableW bind(final F f) { - return wrap(fromIterable(this).bind(a -> fromIterable(f.f(a)))); + return wrap(iterableStream(this).bind(a -> iterableStream(f.f(a)))); } /** @@ -129,12 +128,12 @@ public static F, F, IterableW>> liftM2(fina * @return A iterable of iterables containing the results of the bind operations across all given iterables. */ public static > IterableW> sequence(final Iterable as) { - final Stream ts = fromIterable(as); + final Stream ts = iterableStream(as); return ts.isEmpty() ? iterable(wrap(Option.none())) : wrap(ts.head()).bind(a -> sequence(ts.tail().map(IterableW.>wrap())._1()).bind(as2 -> - iterable(wrap(Stream.cons(a, () -> fromIterable(as2)))) + iterable(wrap(Stream.cons(a, () -> iterableStream(as2)))) ) ); } @@ -222,7 +221,7 @@ public A foldLeft1(final F2 f) { * @return The final result after the left-fold reduction. */ public A foldLeft1(final F> f) { - return fromIterable(this).foldLeft1(f); + return iterableStream(this).foldLeft1(f); } /** @@ -255,7 +254,7 @@ public Iterator iterator() { * @return A new iterable with the results of applying the functions to this iterable. */ public IterableW zapp(final Iterable> fs) { - return wrap(fromIterable(this).zapp(fromIterable(fs))); + return wrap(iterableStream(this).zapp(iterableStream(fs))); } /** @@ -269,7 +268,7 @@ public IterableW zapp(final Iterable> fs) { * iterable. */ public Iterable zipWith(final Iterable bs, final F> f) { - return wrap(fromIterable(this).zipWith(fromIterable(bs), f)); + return wrap(iterableStream(this).zipWith(iterableStream(bs), f)); } /** @@ -296,7 +295,7 @@ public Iterable zipWith(final Iterable bs, final F2 f) { * iterable. */ public Iterable> zip(final Iterable bs) { - return wrap(fromIterable(this).zip(fromIterable(bs))); + return wrap(iterableStream(this).zip(iterableStream(bs))); } /** @@ -305,7 +304,7 @@ public Iterable> zip(final Iterable bs) { * @return A new iterable with the same length as this iterable. */ public Iterable> zipIndex() { - return wrap(fromIterable(this).zipIndex()); + return wrap(iterableStream(this).zipIndex()); } /** @@ -318,16 +317,16 @@ public List toStandardList() { return new List() { public int size() { - return fromIterable(IterableW.this).length(); + return iterableStream(IterableW.this).length(); } public boolean isEmpty() { - return fromIterable(IterableW.this).isEmpty(); + return iterableStream(IterableW.this).isEmpty(); } @SuppressWarnings({"unchecked"}) public boolean contains(final Object o) { - return fromIterable(IterableW.this).exists(Equal.anyEqual().eq((A) o)); + return iterableStream(IterableW.this).exists(Equal.anyEqual().eq((A) o)); } public Iterator iterator() { @@ -335,12 +334,12 @@ public Iterator iterator() { } public Object[] toArray() { - return Array.iterableArray(fromIterable(IterableW.this)).array(); + return Array.iterableArray(iterableStream(IterableW.this)).array(); } @SuppressWarnings({"SuspiciousToArrayCall"}) public T[] toArray(final T[] a) { - return fromIterable(IterableW.this).toCollection().toArray(a); + return iterableStream(IterableW.this).toCollection().toArray(a); } public boolean add(final A a) { @@ -352,7 +351,7 @@ public boolean remove(final Object o) { } public boolean containsAll(final Collection c) { - return fromIterable(IterableW.this).toCollection().containsAll(c); + return iterableStream(IterableW.this).toCollection().containsAll(c); } public boolean addAll(final Collection c) { @@ -376,7 +375,7 @@ public void clear() { } public A get(final int index) { - return fromIterable(IterableW.this).index(index); + return iterableStream(IterableW.this).index(index); } public A set(final int index, final A element) { @@ -421,7 +420,7 @@ public ListIterator listIterator(final int index) { } public List subList(final int fromIndex, final int toIndex) { - return wrap(Stream.fromIterable(IterableW.this).drop(fromIndex).take(toIndex - fromIndex)).toStandardList(); + return wrap(Stream.iterableStream(IterableW.this).drop(fromIndex).take(toIndex - fromIndex)).toStandardList(); } private ListIterator toListIterator(final Option> z) { @@ -477,6 +476,6 @@ public void add(final A a) { } public Option> toZipper() { - return Zipper.fromStream(fromIterable(this)); + return Zipper.fromStream(iterableStream(this)); } } diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 80a2757d..29c5714c 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1458,7 +1458,7 @@ public static F, List> JavaList_List() { } public static List JavaList_List(java.util.List list) { - return List.fromIterable(list); + return List.iterableList(list); } // BEGIN BitSet -> diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 29acc536..712d5001 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -114,7 +114,7 @@ public final boolean isNotEmpty() { /** * Performs a reduction on this list using the given arguments. - * @deprecated As of release 4.5, use {@link #reduce} + * @deprecated As of release 4.5, use {@link #uncons} * * @param nil The value to return if this list is empty. * @param cons The function to apply to the head and tail of this list if it is not empty. @@ -122,10 +122,10 @@ public final boolean isNotEmpty() { */ @Deprecated public final B list(final B nil, final F, B>> cons) { - return reduce(Function.uncurryF2(cons), nil); + return uncons(Function.uncurryF2(cons), nil); } - public final B reduce(final F2, B> cons, final B nil) { + public final B uncons(final F2, B> cons, final B nil) { return isEmpty() ? nil : cons.f(head(), tail()); } @@ -1538,32 +1538,36 @@ private void tail(final List tail) { * @return A list with the given elements. */ @SafeVarargs public static List list(final A... as) { - return Array.array(as).toList(); + return arrayList(as); } + @SafeVarargs + public static List arrayList(final A... as) { + return Array.array(as).toList(); + } /** * Constructs a list from the given Iterable. - * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} + * @deprecated As of release 4.5, use {@link #iterableList(Iterable)} */ @Deprecated public static List list(final Iterable i) { - return fromIterable(i); + return iterableList(i); } /** * Constructs a list from the given Iterator. - * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} + * @deprecated As of release 4.5, use {@link #iteratorList(Iterator)} */ @Deprecated public static List list(final Iterator it) { - return fromIterable(() -> it); + return iteratorList(it); } /** * Constructs a list from the given Iterator. */ public static List fromIterator(final Iterator it) { - return fromIterable(() -> it); + return iterableList(() -> it); } /** @@ -1868,20 +1872,11 @@ public static F, List>> take() { /** * Takes the given iterable to a list. - * @deprecated From release 4.5 use {@link #fromIterable(Iterable)} * * @param i The iterable to take to a list. * @return A list from the given iterable. */ - @Deprecated public static List iterableList(final Iterable i) { - return fromIterable(i); - } - - /** - * Constructs a list from the Iterable. - */ - public static List fromIterable(final Iterable i) { final Buffer bs = empty(); for (final A a : i) { bs.snoc(a); @@ -1889,6 +1884,13 @@ public static List fromIterable(final Iterable i) { return bs.toList(); } + /** + * Constructs a list from the given Iterator. + */ + public static List iteratorList(final Iterator it) { + return iterableList(() -> it); + } + /** * A mutable, singly linked list. This structure should be used very sparingly, in favour * of the {@link List immutable singly linked list structure}. diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 40966778..57a9d379 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -71,20 +71,20 @@ public static Seq single(final A a) { * @return A sequence with the given elements. */ @SafeVarargs public static Seq seq(final A... as) { - return fromList(List.list(as)); + return arraySeq(as); } /** * Constructs a sequence from the given list. * - * @deprecated As of release 4.5, use {@link #fromList(List)} + * @deprecated As of release 4.5, use {@link #listSeq(List)} * * @param list The list to create the sequence from. * @return A sequence with the given elements in the list. */ @Deprecated public static Seq seq(final List list) { - return fromList(list); + return listSeq(list); } /** @@ -92,8 +92,8 @@ public static Seq seq(final List list) { * @param list The list to create the sequence from. * @return A sequence with the elements of the list. */ - public static Seq fromList(final List list) { - return fromIterable(list); + public static Seq listSeq(final List list) { + return iterableSeq(list); } /** @@ -101,7 +101,7 @@ public static Seq fromList(final List list) { * @param i The iterable to create the sequence from. * @return A sequence with the elements of the iterable. */ - public static Seq fromIterable(final Iterable i) { + public static Seq iterableSeq(final Iterable i) { Seq s = Seq.empty(); for (final A a: i) { s = s.snoc(a); @@ -114,8 +114,13 @@ public static Seq fromIterable(final Iterable i) { * @param i The iterator to create the sequence from. * @return A sequence with the elements of the iterator. */ - public static Seq fromIterator(final Iterator i) { - return fromIterable(() -> i); + public static Seq iteratorSeq(final Iterator i) { + return iterableSeq(() -> i); + } + + @SafeVarargs + public static Seq arraySeq(A... as) { + return iterableSeq(Array.array(as)); } /** @@ -124,7 +129,7 @@ public static Seq fromIterator(final Iterator i) { * @return A sequence with the elements of the list. */ public static Seq fromJavaList(final java.util.List list) { - return fromIterable(list); + return iterableSeq(list); } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index fa00c48b..714955fb 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -545,25 +545,11 @@ public static Set join(final Ord o, final Set> s) { /** * Return the elements of the given iterable as a set. * - * @deprecated As of release 4.5, use {@link #fromIterable} - * * @param o An order for the elements of the new set. * @param as An iterable of elements to add to a set. * @return A new set containing the elements of the given iterable. */ - @Deprecated public static Set iterableSet(final Ord o, final Iterable as) { - return fromIterable(o, as); - } - - /** - * Return the elements of the given iterable as a set. - * - * @param o An order for the elements of the new set. - * @param as An iterable of elements to add to a set. - * @return A new set containing the elements of the given iterable. - */ - public static Set fromIterable(final Ord o, final Iterable as) { Set s = empty(o); for (final A a : as) s = s.insert(a); @@ -571,14 +557,14 @@ public static Set fromIterable(final Ord o, final Iterable as) { } /** - * Return the elements of the given java.util.Set as a set. + * Return the elements of the given iterator as a set. * * @param o An order for the elements of the new set. - * @param as A set of elements to create the set. - * @return A new set containing the elements of the given set. + * @param as An iterator of elements to add to a set. + * @return A new set containing the elements of the given iterator. */ - public static Set fromJavaSet(final Ord o, final java.util.Set as) { - return fromIterable(o, as); + public static Set iteratorSet(final Ord o, final Iterator as) { + return iterableSet(o, () -> as); } /** @@ -588,8 +574,9 @@ public static Set fromJavaSet(final Ord o, final java.util.Set as) * @param as An iterator of elements to add to a set. * @return A new set containing the elements of the given iterator. */ - public static Set fromIterator(final Ord o, final Iterator as) { - return fromIterable(o, () -> as); + @SafeVarargs + public static Set arraySet(final Ord o, final A...as) { + return iterableSet(o, Array.array(as)); } /** @@ -600,10 +587,7 @@ public static Set fromIterator(final Ord o, final Iterator as) { * @return A new set containing the elements of the given iterable. */ @SafeVarargs public static Set set(final Ord o, final A ... as) { - Set s = empty(o); - for (final A a : as) - s = s.insert(a); - return s; + return arraySet(o, as); } /** @@ -617,14 +601,14 @@ public static Set fromIterator(final Ord o, final Iterator as) { */ @Deprecated public static Set set(final Ord o, List list) { - return fromList(o, list); + return iterableSet(o, list); } /** * Constructs a set from the list. */ public static Set fromList(final Ord o, List list) { - return fromIterable(o, list); + return iterableSet(o, list); } } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 0ccde672..abff84cb 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -90,9 +90,9 @@ public final boolean isNotEmpty() { } /** - * Performs a reduction on this stream using the given arguments. Equivalent to {@link #reduce}. + * Performs a reduction on this stream using the given arguments. Equivalent to {@link #uncons}. * - * @deprecated As of release 4.5, use {@link #reduce} + * @deprecated As of release 4.5, use {@link #uncons} * * @param nil The value to return if this stream is empty. * @param cons The function to apply to the head and tail of this stream if it is not empty. @@ -100,7 +100,7 @@ public final boolean isNotEmpty() { */ @Deprecated public final B stream(final B nil, final F>, B>> cons) { - return reduce(nil, cons); + return uncons(nil, cons); } /** @@ -110,7 +110,7 @@ public final B stream(final B nil, final F>, B>> cons) { * @param cons The function to apply to the head and tail of this stream if it is not empty. * @return A reduction on this stream. */ - public final B reduce(final B nil, final F>, B>> cons) { + public final B uncons(final B nil, final F>, B>> cons) { return isEmpty() ? nil : cons.f(head()).f(tail()); } @@ -709,46 +709,36 @@ public static Stream range(final int from, final long to) { * @return a new stream with the given elements. */ @SafeVarargs public static Stream stream(final A... as) { - return as.length == 0 ? Stream.nil() - : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.>>none() - : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0)); + return arrayStream(as); } - /** - * Constructs a stream with the given elements in the Iterable. Equivalent to {@link #fromIterable(Iterable)} . + * Constructs a stream with the given elements in the Iterable. Equivalent to {@link #iterableStream(Iterable)} . * - * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} + * @deprecated As of release 4.5, use {@link #iterableStream(Iterable)} */ @Deprecated public static Stream stream(Iterable it) { - return fromIterable(it); + return iterableStream(it); } /** - * Constructs a stream with the given elements in the Iterable. - */ - public static Stream fromIterable(Iterable it) { - return fromIterator(it.iterator()); - } - - /** - * Constructs a stream with the given elements in the Iterator. Equivalent to {@link #fromIterator(Iterator)} . + * Constructs a stream with the given elements in the Iterator. Equivalent to {@link #iteratorStream(Iterator)} . * - * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} + * @deprecated As of release 4.5, use {@link #iteratorStream(Iterator)} */ @Deprecated - public static Stream stream(Iterator it) { - return fromIterator(it); + public static Stream stream(final Iterator it) { + return iteratorStream(it); } /** * Constructs a stream with the given elements in the Iterator. */ - public static Stream fromIterator(Iterator it) { + public static Stream iteratorStream(final Iterator it) { if (it.hasNext()) { final A a = it.next(); - return cons(a, () -> fromIterator(it)); + return cons(a, () -> iteratorStream(it)); } else return nil(); } @@ -1588,29 +1578,20 @@ public static Stream iterateWhile(final F f, final F p, } /** - * Takes the given iterable to a stream. Equivalent to {@link #fromIterable(Iterable)}. - * - * @deprecated As of release 4.5, use {@link #fromIterable(Iterable)} + * Takes the given iterable to a stream. * * @param i The iterable to take to a stream. * @return A stream from the given iterable. */ - @Deprecated public static Stream iterableStream(final Iterable i) { - return fromIterable(i); + return iteratorStream(i.iterator()); } - /** - * Takes the given iterator to a stream. Equivalent to {@link #fromIterator(Iterator)}. - * - * @deprecated As of release 4.5, use {@link #fromIterator(Iterator)} - * - * @param i The iterator to take to a stream. - * @return A stream from the given iterator. - */ - @Deprecated - public static Stream iteratorStream(final Iterator i) { - return fromIterator(i); + @SafeVarargs + public static Stream arrayStream(final A...as) { + return as.length == 0 ? Stream.nil() + : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.>>none() + : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0)); } /** diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index e38bc0a7..35883552 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -18,7 +18,6 @@ import static fj.Function.flip; import static fj.P.p; import static fj.data.IterableW.join; -import static fj.data.List.fromIterable; import static fj.data.List.iterableList; /** @@ -68,7 +67,7 @@ public String toString() { * @return a TreeMap with the given elements. */ @SafeVarargs public static TreeMap treeMap(final Ord keyOrd, final P2... p2s) { - return treeMap(keyOrd, List.list(p2s)); + return arrayTreeMap(keyOrd, p2s); } /** @@ -79,13 +78,26 @@ public String toString() { * @return a TreeMap with the given elements. */ public static TreeMap treeMap(final Ord keyOrd, final List> list) { + return iterableTreeMap(keyOrd, list); + } + + public static TreeMap iterableTreeMap(final Ord keyOrd, final Iterable> it) { TreeMap tm = empty(keyOrd); - for (final P2 p2 : list) { + for (final P2 p2 : it) { tm = tm.set(p2._1(), p2._2()); } return tm; } + public static TreeMap iteratorTreeMap(final Ord keyOrd, final Iterator> it) { + return iterableTreeMap(keyOrd, () -> it); + } + + @SafeVarargs + public static TreeMap arrayTreeMap(final Ord keyOrd, final P2...ps) { + return iterableTreeMap(keyOrd, Array.array(ps)); + } + /** * Returns a potential value that the given key maps to. * @@ -143,7 +155,7 @@ public boolean isEmpty() { * @return All values in this tree map. */ public List values() { - return fromIterable(join(tree.toList().map(compose(IterableW.>wrap(), P2.>__2())))); + return iterableList(join(tree.toList().map(compose(IterableW.>wrap(), P2.>__2())))); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 11513c7d..3a2cfa23 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -828,13 +828,13 @@ public static Validation, List> sequenceNonCumulative(List List> traverseList(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : - List.fromIterable(fail(e.left().value())); + List.iterableList(fail(e.left().value())); } public Stream> traverseStream(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : - Stream.fromIterable(fail(e.left().value())); + Stream.iterableStream(fail(e.left().value())); } public Option> traverseOption(F> f){ diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index b63836e6..5b69f597 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -39,7 +39,7 @@ public void objectMethods() { @Test public void integration() { java.util.List ul = Arrays.asList(1, 2, 3); - List dl = List.fromIterable(ul); + List dl = List.iterableList(ul); assertTrue(ul.equals(dl.toJavaList())); } @@ -76,7 +76,7 @@ public void intersperseOverflow() { @Test public void listReduce() { - String list = List.range(1, 11).reduce((a, la) -> List.cons(a, la).toString(), ""); + String list = List.range(1, 11).uncons((a, la) -> List.cons(a, la).toString(), ""); String expected = List.range(1, 11).toString(); assertThat(expected, equalTo(list)); } diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index a583edd0..a37764c2 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -41,7 +41,7 @@ public void testToString() { @Test(expected = ConcurrentModificationException.class) public void iterableStreamWithStructureUpdate() { java.util.List list = List.list(1, 2, 3).toJavaList(); - Stream s1 = Stream.fromIterable(list); + Stream s1 = Stream.iterableStream(list); int x = s1.head(); list.remove(1); Stream s2 = s1.tail()._1(); diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 0fda57e1..973e34bd 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -88,7 +88,7 @@ public void toMutableMap() { List> l = List.range(1, max + 1).map(n -> List.single(n)); TreeMap, String> m2 = TreeMap.treeMap(Ord.listOrd(Ord.intOrd), l.zip(l.map(i -> i.toString()))); Map, String> mm = m2.toMutableMap(); - assertEquals(m2.keys(), List.fromIterable(mm.keySet())); + assertEquals(m2.keys(), List.iterableList(mm.keySet())); } diff --git a/java-core/src/main/java/fj/java/util/ListUtil.java b/java-core/src/main/java/fj/java/util/ListUtil.java index 4fcc1c07..17fb5519 100644 --- a/java-core/src/main/java/fj/java/util/ListUtil.java +++ b/java-core/src/main/java/fj/java/util/ListUtil.java @@ -11,19 +11,19 @@ public class ListUtil { public static List map(List list, F f) { - return fj.data.List.fromIterable(list).map(f).toJavaList(); + return fj.data.List.iterableList(list).map(f).toJavaList(); } public static List filter(List list, F f) { - return fj.data.List.fromIterable(list).filter(f).toJavaList(); + return fj.data.List.iterableList(list).filter(f).toJavaList(); } public static B fold(List list, F2 f, B b) { - return fj.data.List.fromIterable(list).foldLeft(f, b); + return fj.data.List.iterableList(list).foldLeft(f, b); } public static List flatMap(List list, F> f) { - return fj.data.List.fromIterable(list).bind(a -> fj.data.List.fromIterable(f.f(a))).toJavaList(); + return fj.data.List.iterableList(list).bind(a -> fj.data.List.iterableList(f.f(a))).toJavaList(); } public static List bind(List list, F> f) { diff --git a/java8/src/main/java/fj/data/Collectors.java b/java8/src/main/java/fj/data/Collectors.java index 738c7c43..3f3d7e40 100644 --- a/java8/src/main/java/fj/data/Collectors.java +++ b/java8/src/main/java/fj/data/Collectors.java @@ -30,7 +30,7 @@ public static Collector, Stream> toStream() { List.Buffer::new, List.Buffer::snoc, (acc1, acc2) -> acc1.append(acc2.toList()), - (buf) -> Stream.fromIterable(buf.toList()) + (buf) -> Stream.iterableStream(buf.toList()) ); } } diff --git a/performance/src/main/java/fj/data/DListPerformance.java b/performance/src/main/java/fj/data/DListPerformance.java index bc4b9d2a..2508b2a5 100644 --- a/performance/src/main/java/fj/data/DListPerformance.java +++ b/performance/src/main/java/fj/data/DListPerformance.java @@ -34,7 +34,7 @@ public List unbox(List a) { private static final BenchmarkMethods> seqMethods = new BenchmarkMethods>() { @Override public Seq range(int from, int to) { - return Seq.fromList(List.range(from, to)); + return Seq.listSeq(List.range(from, to)); } @Override public Seq append(Seq a, Seq b) { @@ -49,7 +49,7 @@ public List unbox(Seq a) { private static final BenchmarkMethods> dListMethods = new BenchmarkMethods>() { @Override public DList range(int from, int to) { - return DList.fromList(List.range(from, to)); + return DList.listDList(List.range(from, to)); } @Override public DList append(DList a, DList b) { diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala index 58656779..dd95dabf 100755 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala @@ -67,7 +67,7 @@ object CheckHashMap extends Properties("HashMap") { }) property("from") = forAll((entries: java.lang.Iterable[P2[Int, String]]) => { - val map = HashMap.from[Int, String](entries, equalInt, hashInt) + val map = HashMap.iterableHashMap[Int, String](equalInt, hashInt, entries) entries.groupBy(_._1) .forall((e: (Int, Iterable[P2[Int, String]])) => e._2 .exists((elem: P2[Int, String]) => optionEqual(stringEqual).eq(map.get(e._1), Option.some(elem._2)))) diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala index 3c006631..96bce311 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckSet.scala @@ -10,7 +10,7 @@ import Ord.intOrd import Ord.stringOrd import P.p import Unit.unit -import Set.{empty, single, join, iterableSet, fromIterable} +import Set.{empty, single, join, iterableSet} import org.scalacheck.Properties object CheckSet extends Properties("Set") { @@ -38,10 +38,10 @@ object CheckSet extends Properties("Set") { single(oi, n).member(n)) property("noDupesFromList") = forAll((a: List[String]) => - setEqual(stringEqual).eq(fromIterable(os, a.nub(stringEqual)), fromIterable(os, a))) + setEqual(stringEqual).eq(iterableSet(os, a.nub(stringEqual)), iterableSet(os, a))) property("noDupesToList") = forAll((a: List[String]) => - fromIterable(os, a).toList().length() == a.nub(stringEqual).length()) + iterableSet(os, a).toList().length() == a.nub(stringEqual).length()) property("subsetEmpty") = forAll((a: Set[Int]) => empty(oi).subsetOf(a)) diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 1a21189d..13f2856b 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -3,8 +3,6 @@ import fj.P; import fj.P2; -import fj.data.Array; -import fj.data.Option; import fj.data.Seq; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; @@ -14,8 +12,6 @@ import org.junit.runner.RunWith; import static fj.Function.identity; -import static fj.data.Option.none; -import static fj.data.Option.some; import static fj.test.Arbitrary.*; import static fj.test.Property.implies; import static fj.test.Property.prop; @@ -122,7 +118,7 @@ public Property foldRight() { public Property length() { return property(arbList(arbInteger), list -> - prop(Seq.fromList(list).length() == list.length()) + prop(Seq.listSeq(list).length() == list.length()) ); } From 67a16a7154a2a7947a652821614290662c3d6e9f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 11:25:35 +1000 Subject: [PATCH 464/811] Added extra javadoc and deprecated warnings --- core/src/main/java/fj/data/Array.java | 3 +++ core/src/main/java/fj/data/DList.java | 2 +- core/src/main/java/fj/data/HashSet.java | 24 +++++++++++++++++++ core/src/main/java/fj/data/List.java | 4 ++++ core/src/main/java/fj/data/Seq.java | 9 ++++++- core/src/main/java/fj/data/Set.java | 5 +++- core/src/main/java/fj/data/TreeMap.java | 24 +++++++++++++++++++ core/src/test/java/fj/data/TreeMapTest.java | 13 +++++----- .../main/java/fj/data/DListPerformance.java | 2 +- .../fj/data/properties/SeqProperties.java | 2 +- .../src/main/java/fj/test/Arbitrary.java | 6 ++--- 11 files changed, 80 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index b16ae018..6000f28f 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -805,6 +805,9 @@ public static Array iterableArray(final Iterable i) { return iterableList(i).toArray(); } + /** + * Creates an Array from the iterator. + */ public static Array iteratorArray(final Iterator i) { return iterableArray(() -> i); } diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 6b7fc1b2..4293249c 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -23,7 +23,7 @@ private DList(final F,Trampoline>> appendFn) { /** * Creates a DList from the function * - * For alternatives functions to create a DList see: + * For alternatives functions to create a DList: * @see #iterableDList * @see #iteratorDList * @see #arrayDList diff --git a/core/src/main/java/fj/data/HashSet.java b/core/src/main/java/fj/data/HashSet.java index 555f8732..56410b4b 100644 --- a/core/src/main/java/fj/data/HashSet.java +++ b/core/src/main/java/fj/data/HashSet.java @@ -97,10 +97,16 @@ public static HashSet empty() { return empty(anyEqual(), anyHash()); } + /** + * Create a HashSet from the Iterable. + */ public static HashSet iterableHashSet(final Iterable it) { return iterableHashSet(anyEqual(), anyHash(), it); } + /** + * Create a HashSet from the Iterable. + */ public static HashSet iterableHashSet(final Equal e, final Hash h, final Iterable it) { final HashSet hs = empty(e, h); for (A a: it) { @@ -109,29 +115,47 @@ public static HashSet iterableHashSet(final Equal e, final Hash h, return hs; } + /** + * Create a HashSet from the Iterator. + */ public static HashSet iteratorHashSet(final Iterator it) { return iterableHashSet(() -> it); } + /** + * Create a HashSet from the Iterator. + */ public static HashSet iteratorHashSet(final Equal e, final Hash h, final Iterator it) { return iterableHashSet(e, h, () -> it); } + /** + * Create a HashSet from the array. + */ @SafeVarargs public static HashSet arrayHashSet(final A...as) { return iterableHashSet(Array.array(as)); } + /** + * Create a HashSet from the array. + */ @SafeVarargs public static HashSet arrayHashSet(final Equal e, final Hash h, final A...as) { return iterableHashSet(e, h, Array.array(as)); } + /** + * Create a HashSet from the array. + */ @SafeVarargs public static HashSet hashSet(final A...as) { return arrayHashSet(as); } + /** + * Create a HashSet from the array. + */ @SafeVarargs public static HashSet hashSet(final Equal e, final Hash h, final A...as) { return arrayHashSet(e, h, as); diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 712d5001..3213e041 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1541,10 +1541,14 @@ private void tail(final List tail) { return arrayList(as); } + /** + * Constructs a list from the given elements. + */ @SafeVarargs public static List arrayList(final A... as) { return Array.array(as).toList(); } + /** * Constructs a list from the given Iterable. * @deprecated As of release 4.5, use {@link #iterableList(Iterable)} diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 57a9d379..a29d97c0 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -84,14 +84,18 @@ public static Seq single(final A a) { */ @Deprecated public static Seq seq(final List list) { - return listSeq(list); + return iterableSeq(list); } /** * Constructs a sequence from the given list. + * + * @deprecated As of release 4.5, use {@link #iterableSeq} + * * @param list The list to create the sequence from. * @return A sequence with the elements of the list. */ + @Deprecated public static Seq listSeq(final List list) { return iterableSeq(list); } @@ -118,6 +122,9 @@ public static Seq iteratorSeq(final Iterator i) { return iterableSeq(() -> i); } + /** + * Constructs a sequence from the array. + */ @SafeVarargs public static Seq arraySeq(A... as) { return iterableSeq(Array.array(as)); diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 714955fb..6c23d6d5 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -593,7 +593,7 @@ public static Set arraySet(final Ord o, final A...as) { /** * Constructs a set from the list. * - * @deprecated As of release 4.5, use {@link #fromList} + * @deprecated As of release 4.5, use {@link #iterableSet} * * @param o An order for the elements of the new set. * @param list The elements to add to a set. @@ -606,7 +606,10 @@ public static Set set(final Ord o, List list) { /** * Constructs a set from the list. + * + * @deprecated As of release 4.5, use {@link #iterableSet} */ + @Deprecated public static Set fromList(final Ord o, List list) { return iterableSet(o, list); } diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 35883552..307c279e 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -73,14 +73,24 @@ public String toString() { /** * Constructs a tree map from the given elements. * + * @deprecated As of release 4.5, use {@link #iterableTreeMap(Ord, Iterable)} + * * @param keyOrd An order for the keys of the tree map. * @param list The elements to construct the tree map with. * @return a TreeMap with the given elements. */ + @Deprecated public static TreeMap treeMap(final Ord keyOrd, final List> list) { return iterableTreeMap(keyOrd, list); } + /** + * Constructs a tree map from the given elements. + * + * @param keyOrd An order for the keys of the tree map. + * @param it The elements to construct the tree map with. + * @return A TreeMap with the given elements. + */ public static TreeMap iterableTreeMap(final Ord keyOrd, final Iterable> it) { TreeMap tm = empty(keyOrd); for (final P2 p2 : it) { @@ -89,10 +99,24 @@ public static TreeMap iterableTreeMap(final Ord keyOrd, final It return tm; } + /** + * Constructs a tree map from the given elements. + * + * @param keyOrd An order for the keys of the tree map. + * @param it The elements to construct the tree map with. + * @return A TreeMap with the given elements. + */ public static TreeMap iteratorTreeMap(final Ord keyOrd, final Iterator> it) { return iterableTreeMap(keyOrd, () -> it); } + /** + * Constructs a tree map from the given elements. + * + * @param keyOrd An order for the keys of the tree map. + * @param ps The elements to construct the tree map with. + * @return A TreeMap with the given elements. + */ @SafeVarargs public static TreeMap arrayTreeMap(final Ord keyOrd, final P2...ps) { return iterableTreeMap(keyOrd, Array.array(ps)); diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 973e34bd..d3e60936 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -13,6 +13,7 @@ import static fj.P.p; import static fj.data.Option.none; import static fj.data.Option.some; +import static fj.data.TreeMap.iterableTreeMap; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -29,7 +30,7 @@ public void split() { int pivot = 4; int max = 5; List l = List.range(1, max + 1); - TreeMap m2 = TreeMap.treeMap(Ord.intOrd, l.zip(l.map(i -> i.toString()))); + TreeMap m2 = iterableTreeMap(Ord.intOrd, l.zip(l.map(i -> i.toString()))); P3, Option, Set> p = m2.split(Ord.stringOrd, pivot); // print debug info @@ -51,7 +52,7 @@ public void split() { } private static Set toSetString(List list) { - return Set.fromList(Ord.stringOrd, list.map(i -> i.toString())); + return Set.iterableSet(Ord.stringOrd, list.map(i -> i.toString())); } @Test @@ -60,14 +61,14 @@ public void splitLookup() { int pivot = 4; int max = 5; List l = List.range(1, max + 1); - TreeMap m2 = TreeMap.treeMap(Ord.intOrd, l.zip(l.map(i -> i.toString()))); + TreeMap m2 = iterableTreeMap(Ord.intOrd, l.zip(l.map(i -> i.toString()))); P3, Option, TreeMap> p3 = m2.splitLookup(pivot); // create expected output List leftList = List.range(1, pivot); - TreeMap leftMap = TreeMap.treeMap(Ord.intOrd, leftList.zip(leftList.map(i -> i.toString()))); + TreeMap leftMap = iterableTreeMap(Ord.intOrd, leftList.zip(leftList.map(i -> i.toString()))); List rightList = List.range(pivot + 1, max + 1); - TreeMap rightMap = TreeMap.treeMap(Ord.intOrd, rightList.zip(rightList.map(i -> i.toString()))); + TreeMap rightMap = iterableTreeMap(Ord.intOrd, rightList.zip(rightList.map(i -> i.toString()))); // debug info if (true) { @@ -86,7 +87,7 @@ public void splitLookup() { public void toMutableMap() { int max = 5; List> l = List.range(1, max + 1).map(n -> List.single(n)); - TreeMap, String> m2 = TreeMap.treeMap(Ord.listOrd(Ord.intOrd), l.zip(l.map(i -> i.toString()))); + TreeMap, String> m2 = iterableTreeMap(Ord.listOrd(Ord.intOrd), l.zip(l.map(i -> i.toString()))); Map, String> mm = m2.toMutableMap(); assertEquals(m2.keys(), List.iterableList(mm.keySet())); } diff --git a/performance/src/main/java/fj/data/DListPerformance.java b/performance/src/main/java/fj/data/DListPerformance.java index 2508b2a5..8294a884 100644 --- a/performance/src/main/java/fj/data/DListPerformance.java +++ b/performance/src/main/java/fj/data/DListPerformance.java @@ -34,7 +34,7 @@ public List unbox(List a) { private static final BenchmarkMethods> seqMethods = new BenchmarkMethods>() { @Override public Seq range(int from, int to) { - return Seq.listSeq(List.range(from, to)); + return Seq.iterableSeq(List.range(from, to)); } @Override public Seq append(Seq a, Seq b) { diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 13f2856b..8e8076aa 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -118,7 +118,7 @@ public Property foldRight() { public Property length() { return property(arbList(arbInteger), list -> - prop(Seq.listSeq(list).length() == list.length()) + prop(Seq.iterableSeq(list).length() == list.length()) ); } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 1abc5699..d46f4d4e 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -815,11 +815,11 @@ public static Arbitrary> arbSeq(final Arbitrary aa) { } public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(list -> Set.fromList(ord, list))); + return arbitrary(arbList(aa).gen.map(list -> Set.iterableSet(ord, list))); } public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, int max) { - Gen> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.fromList(ord, list)); + Gen> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.iterableSet(ord, list)); return arbitrary(g); } @@ -1143,7 +1143,7 @@ public java.util.TreeMap f(final Hashtable ht) { * Returns an arbitrary implementation for tree maps. */ public static Arbitrary> arbTreeMap(Ord ord, Arbitrary>> al) { - return arbitrary(al.gen.map(list -> fj.data.TreeMap.treeMap(ord, list))); + return arbitrary(al.gen.map(list -> fj.data.TreeMap.iterableTreeMap(ord, list))); } /** From fedea6bf31df996978d36c31fc7046b3a7c9d83a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 14:07:26 +1000 Subject: [PATCH 465/811] Added conversions for fj.data to standard java.util classes --- core/src/main/java/fj/data/Array.java | 11 +++++++++++ core/src/main/java/fj/data/DList.java | 7 +++++++ core/src/main/java/fj/data/HashMap.java | 13 +++++++++++++ core/src/main/java/fj/data/HashSet.java | 12 ++++++++++++ core/src/main/java/fj/data/List.java | 9 ++++++++- core/src/main/java/fj/data/Stream.java | 11 +++++++++++ core/src/test/java/fj/data/ArrayTest.java | 13 +++++++++++++ core/src/test/java/fj/data/ListTest.java | 10 ++++++++++ 8 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/fj/data/ArrayTest.java diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 6000f28f..ede5c9ca 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -127,6 +127,10 @@ public Object[] array() { return copyOf(a, a.length); } + public A[] toJavaArray() { + return (A[]) array(); + } + /** * Returns an option projection of this array; None if empty, or the first element in * Some. @@ -795,6 +799,13 @@ public int size() { }; } + /** + * Returns a standard java.util.List projection of this array. + */ + java.util.List toJavaList() { + return new ArrayList(toCollection()); + } + /** * Takes the given iterable to an array. * diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 4293249c..2c7856de 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -71,6 +71,13 @@ public static DList arrayDList(final A...as) { public List run() { return appendFn.f(List.nil()).run(); } + + /** + * Converts the DList to a standard java.util.List. + */ + public java.util.List toJavaList() { + return run().toJavaList(); + } /** * A empty DList. diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 3e3597d1..7cd9c8dd 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.Iterator; +import java.util.Map; import static fj.P.p; import static fj.data.Option.fromNull; @@ -341,6 +342,18 @@ public static HashMap from(final Iterable> entries) { return iterableHashMap(Equal.anyEqual(), Hash.anyHash(), entries); } + public static HashMap fromMap(java.util.Map map) { + return fromMap(Equal.anyEqual(), Hash.anyHash(), map); + } + + public static HashMap fromMap(Equal eq, Hash h, java.util.Map map) { + HashMap m = HashMap.hashMap(eq, h); + for (Map.Entry e: map.entrySet()) { + m.set(e.getKey(), e.getValue()); + } + return m; + } + /** * Converts the Iterable to a HashMap * diff --git a/core/src/main/java/fj/data/HashSet.java b/core/src/main/java/fj/data/HashSet.java index 56410b4b..1c6868e3 100644 --- a/core/src/main/java/fj/data/HashSet.java +++ b/core/src/main/java/fj/data/HashSet.java @@ -225,6 +225,18 @@ public List toList() { return m.keys(); } + public java.util.List toJavaList() { + return toList().toJavaList(); + } + + public java.util.Set toJavaSet() { + return new java.util.HashSet(toCollection()); + } + + public static HashSet fromSet(java.util.Set s) { + return iterableHashSet(s); + } + /** * Projects an immutable collection of this hash set. * diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 3213e041..47fa45b8 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -197,6 +197,10 @@ public final Stream toStream() { */ @SuppressWarnings({"unchecked"}) public final Array toArray() { + return mkArray(toArrayObject()); + } + + public final Object[] toArrayObject() { final int length = length(); final Object[] a = new Object[length]; List x = this; @@ -204,8 +208,11 @@ public final Array toArray() { a[i] = x.head(); x = x.tail(); } + return a; + } - return mkArray(a); + public final A[] toJavaArray() { + return (A[]) toArrayObject(); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index abff84cb..d21c2f15 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -916,6 +916,17 @@ public final Option toOption() { return isEmpty() ? Option.none() : some(head()); } + @SuppressWarnings({"unchecked", "UnnecessaryFullyQualifiedName"}) + public final A[] toJavaArray() { + final A[] array = (A[]) new Object[length()]; + int i = 0; + for (A a: this) { + array[i] = a; + i++; + } + return array; + } + /** * Returns a list projection of this stream. * diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java new file mode 100644 index 00000000..656b14c6 --- /dev/null +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -0,0 +1,13 @@ +package fj.data; + +/** + * Created by MarkPerry on 14 Feb 16. + */ +public class ArrayTest { + + + public void test1() { + + } + +} diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 5b69f597..8725ef05 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -81,4 +81,14 @@ public void listReduce() { assertThat(expected, equalTo(list)); } + @Test + public void toJavaArray() { + final int max = 3; + Integer[] ints = new Integer[max]; + for (int i = 0; i < max; i++) { + ints[i] = i + 1; + }; + assertThat(List.range(1, max + 1).toJavaArray(), equalTo(ints)); + } + } From 24766ba767f93365811673d36148c4173d2a5614 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 14:14:25 +1000 Subject: [PATCH 466/811] Test conversion from Array to array --- core/src/main/java/fj/data/Array.java | 1 + core/src/test/java/fj/data/ArrayTest.java | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index ede5c9ca..5ef630a6 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -12,6 +12,7 @@ import fj.function.Effect1; import java.util.AbstractCollection; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java index 656b14c6..e274a00a 100644 --- a/core/src/test/java/fj/data/ArrayTest.java +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -1,13 +1,20 @@ package fj.data; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + /** * Created by MarkPerry on 14 Feb 16. */ public class ArrayTest { - - public void test1() { - + @Test + public void toJavaArray() { + final int max = 3; + List list = List.range(1, max + 1); + assertThat(list.toArray().toJavaArray(), equalTo(list.toJavaArray())); } } From b5987617990af72f967bfdef2b4d5514d8c2dfff Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 14:23:49 +1000 Subject: [PATCH 467/811] Convert Array and List to array --- core/src/main/java/fj/data/Array.java | 1 + core/src/main/java/fj/data/List.java | 1 + 2 files changed, 2 insertions(+) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 5ef630a6..f24e529c 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -128,6 +128,7 @@ public Object[] array() { return copyOf(a, a.length); } + @SuppressWarnings("unchecked") public A[] toJavaArray() { return (A[]) array(); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 47fa45b8..2d6f7683 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -211,6 +211,7 @@ public final Object[] toArrayObject() { return a; } + @SuppressWarnings("unchecked") public final A[] toJavaArray() { return (A[]) toArrayObject(); } From 37732ac36165872d90f32dff93fb9ec7139b10b2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 14:42:08 +1000 Subject: [PATCH 468/811] Removed second gitter badge --- README.adoc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.adoc b/README.adoc index 5b56ea2f..12d6682a 100644 --- a/README.adoc +++ b/README.adoc @@ -1,10 +1,8 @@ = Functional Java -image:https://badges.gitter.im/functionaljava/functionaljava.svg[link="https://gitter.im/functionaljava/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] - image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] image:https://coveralls.io/repos/github/functionaljava/functionaljava/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/github/functionaljava/functionaljava?branch=master"] -image:https://badges.gitter.im/functionaljava.svg[link="https://gitter.im/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] +image:https://badges.gitter.im/functionaljava/functionaljava.svg[link="https://gitter.im/functionaljava/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image::http://www.functionaljava.org/img/logo-600x144.png[] From 1f4b826b2a2a52933dbc4172ab98168489b1c8d7 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 15:10:43 +1000 Subject: [PATCH 469/811] Update 4.5 release notes --- etc/release-notes/release-notes-4.5.adoc | 27 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/etc/release-notes/release-notes-4.5.adoc b/etc/release-notes/release-notes-4.5.adoc index 0e4fcb80..6a23fc0c 100644 --- a/etc/release-notes/release-notes-4.5.adoc +++ b/etc/release-notes/release-notes-4.5.adoc @@ -1,7 +1,7 @@ = Release 4.5 -Proposed release: last quarter 2015 +Proposed release: Feb 2016 == Enhancements @@ -24,6 +24,15 @@ Proposed release: last quarter 2015 * Added headOption to Seq and FingerTree. Added length to FingerTree (7e1d3a9300af84b3c4c5204e4b7a5a0e89c44303). * Added Stream.enumerationStream (0028ef0f8e6a36b77cbd75b29e92d77eacc167bd). * Support use of FunctionalJava on Java 6 runtime (67f1fc9f2c35479bf18d9ef948062e01ef740d5e). +* Added Void, a logically uninhabited type (#193). +* Log n multiply for Semigroup/Monoid (61ec2b09e5acc629f334d7c4264a92b99dd9fd3b). +* Added coverage badge. +* Added Stream.toJavaList +* Added support to create fj.data types from standard Java iterable, iterator and array types. +* Added support to convert to standard java.util.* classes for standard fj.data types where similar java.util class exists. +* Added difference list support (DList, #214). +* Made Array.ImmutableProjection static (#210). +* Added Gitter room and badge at the top of the main Github page. == Fixes @@ -42,22 +51,24 @@ Proposed release: last quarter 2015 * Suppressed various unchecked compiler warnings (9853c6a26309cf9f4936d431a6bc65b4c37550b1). * Added compiler warnings for unchecked and deprecation (#204). * Simplified code to avoid function creation and inner static class (#179). -* Upgraded to Gradle 2.9. +* Upgraded to Gradle 2.10. * Added example of badly creating a Stream from an iterator (d38a694f9f1728417cb178c685850f627b10bf5b). * Configure Retro Lambda using variables (6aa26bcb56dd43d36bede2e8c34cbb21f69c1c8a). * Updated package fj, fj.control, fj.data, fj.data.fingertrees, fj.data.hlist, fj.data.vector, fj.function, fj.parser to use lambdas (#206). -* Added test coverage report, run "gradlew coverage", report is under root/build/reports/jacoco/coverage/html/index.html (#207). +* Added test coverage report, run "gradlew jacocoRootReport coveralls", report is under root/build/reports/jacoco/coverage/html/index.html (#207). * Updated Travis CI to use latest Java 8 (8ddc11546badbeafb0b16bc1e0fb922b06f23079). * Replaced usage of new P1 with P.lazy (2d6a8dd4412220a749331b6ffec45bd720ac7479). * Replaced P1 with F0 instances where possible (5b8248c51445e92aa8c8ff241e717f909a5bdd63, 0ca5248a3016209c9e62df509a79ed9432421322). * Replace anonymous F2 instances with lambdas (b438b1b89705f6d0bfd5e7c31bd217d173c43dfc). * Replace anonymous F3 instances with lambdas (721118902a5af76665df347b073534debf384f69). * Added coverall integration, submodules not consolidated into single report. -* Replaced annonymous P2 with static constructor (92f663384541dfbea013c14b7f60951d925bcd26). +* Replaced annonymous P2 with static constructor (#189, 92f663384541dfbea013c14b7f60951d925bcd26). +* Created performance module to keep code demonstrating performance based reasoning. +* Added JUnit for Doubles (#226). == Breaking Changes -* None. +* Made Array.ImmutableProjection static (#210). This previously forced usage by `Array.ImmutableProjection` or `Array.ImmutableProjection`. == Documentation @@ -69,4 +80,10 @@ Proposed release: last quarter 2015 * Zheka Kozlov * Jean-Baptiste Giraudeau * Shintaro Murakami +* @daneko +* Gabor Liptak +* Michal Samek +* Clinton Selke +* Roy Brokvam + From da8215eeb62a3db3d124055b8b44abb756eecbf4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 14 Feb 2016 15:25:57 +1000 Subject: [PATCH 470/811] Updated release process to use retroLambda --- etc/release-process.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/etc/release-process.txt b/etc/release-process.txt index 5845037e..a7984c36 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -4,6 +4,7 @@ Current Release Process Update build.gradle: * set isSnapshot to false +* set useRetroLambda to true Update gradle.properties: * Set signingEnabled to true @@ -21,7 +22,7 @@ Login to Sonatype and verify the release: Commit changes Increase the version: -* Edit build.gradle: update isSnapshot to true, increase fjBaseVersion, update fjConsumeVersion +* Edit build.gradle: update isSnapshot to true, increase fjBaseVersion, update fjConsumeVersion, update useRetroLambda. * Edit gradle.properties: set signingEnabled to false Commit changes and push. Notes that CI builds using Travis and Jenkins will fail with the release due to lack of configured signing. From 7d33ffcfe30fb7a6c0d932090589254007fe4799 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 07:33:51 +1000 Subject: [PATCH 471/811] Changes to release 4.5 --- build.gradle | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 032ab43d..08db4884 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.5" snapshotAppendix = "-SNAPSHOT" @@ -54,7 +54,7 @@ allprojects { fjConsumeVersion = "4.4" signModule = false - useRetroLambda = false + useRetroLambda = true projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/gradle.properties b/gradle.properties index d4552a30..07c2b60c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false +signingEnabled = true From 9a4c1e4003c9cb50f83dff87701306cc4e455da1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 07:35:36 +1000 Subject: [PATCH 472/811] Increase version to 4.6-SNAPSHOT --- build.gradle | 8 ++++---- gradle.properties | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 08db4884..7a3b81cf 100644 --- a/build.gradle +++ b/build.gradle @@ -46,15 +46,15 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.5" + isSnapshot = true + fjBaseVersion = "4.6" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.4" + fjConsumeVersion = "4.5" signModule = false - useRetroLambda = true + useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From 4f3219dc5eb4df564b82a194fd2d12faca7ebe07 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 07:38:01 +1000 Subject: [PATCH 473/811] Added 4.6 release notes --- etc/release-notes/release-notes-4.6.adoc | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 etc/release-notes/release-notes-4.6.adoc diff --git a/etc/release-notes/release-notes-4.6.adoc b/etc/release-notes/release-notes-4.6.adoc new file mode 100644 index 00000000..d9bc2b3d --- /dev/null +++ b/etc/release-notes/release-notes-4.6.adoc @@ -0,0 +1,28 @@ + += Release 4.6 + +Proposed release: Jun 2016 + +== Enhancements + +* TODO. + +== Fixes + +* TODO. + +== Internal + +* TODO. + +== Breaking Changes + +* TODO. + +== Documentation + +* TODO. + +== Contributors + +* TODO. From 4f969768c36ea36607f0dc43adb60b489676a041 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 07:55:24 +1000 Subject: [PATCH 474/811] Updated readme for the 4.5 release --- README.adoc | 32 ++++++++++++++++++++------------ etc/release-process.txt | 4 ++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/README.adoc b/README.adoc index 12d6682a..40fec847 100644 --- a/README.adoc +++ b/README.adoc @@ -8,12 +8,12 @@ image::http://www.functionaljava.org/img/logo-600x144.png[] Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. -The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 5 to 8. +The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 6 to 8. Functional Java provides abstractions for the following types: -* Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation). -* Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list. +* Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation), void. +* Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list, difference list. * Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing (quickcheck), actors, optics (lens, prism, fold, traversal and others), concurrency and type conversion. == URLs @@ -35,11 +35,12 @@ The Functional Java artifact is published to Maven Central using the group `org. * Java 8 specific support (`functionaljava-java8`) * property based testing (`functionaljava-quickcheck`) -The latest stable version is `4.4`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.5`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.4" -compile "org.functionaljava:functionaljava-java8:4.4" -compile "org.functionaljava:functionaljava-quickcheck:4.4" +compile "org.functionaljava:functionaljava:4.5" +compile "org.functionaljava:functionaljava-java8:4.5" +compile "org.functionaljava:functionaljava-quickcheck:4.5" +compile "org.functionaljava:functionaljava-java-core:4.5" ---- and in Maven: @@ -47,25 +48,30 @@ and in Maven: org.functionaljava functionaljava - 4.4 + 4.5 org.functionaljava functionaljava-java8 - 4.4 + 4.5 org.functionaljava functionaljava-quickcheck - 4.4 + 4.5 + + + org.functionaljava + functionaljava-java-core + 4.5 ---- == Building -FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 7 bytecode. This requires access to both JDK 7 and 8. The build system requires the environment variables `JAVA7_HOME` and `JAVA8_HOME` to refer to the appropriate directories. +FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 6 bytecode. This requires access to both JDK 6 and 8. The build system requires the environment variables `JAVA6_HOME` and `JAVA8_HOME` to refer to the appropriate directories. -Building is done using Gradle 2.4. In the root directory run: +Building is done using Gradle 2.10. In the root directory run: ---- ./gradlew ---- @@ -94,6 +100,7 @@ A more complete description of the features mentioned above are: ** Immutable set implementation using a red/black tree (`fj.data.Set`). ** Immutable multi-way tree - aka rose tree (`fj.data.Tree`). ** Immutable tree-map using a red/black tree implementation (`fj.data.TreeMap`). +** Difference lists, a highly performant list. * Other Abstractions ** Monoid (`fj.Monoid`). ** Semigroup (`fj.Semigroup`). @@ -109,6 +116,7 @@ A more complete description of the features mentioned above are: ** Automated specification-based testing framework (`fj.test`). ** Fully operational Actors for parallel computations (`fj.control.parallel`) and layered abstractions such as parallel-map, map-reduce, parallel-zip. ** Optics for updating immutable data including lens, prism, iso, optional, traversal, getter, fold and setter. Inspired by the Scala Monocle library (https://github.com/julien-truffaut/Monocle) and the Haskell lens library (https://github.com/ekmett/lens). +** Void, a logically uninhabited type. == License diff --git a/etc/release-process.txt b/etc/release-process.txt index a7984c36..f62cb01f 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -33,9 +33,9 @@ Create tag: Create the next version of the release notes with empty fields using the template. -Update the website and Github README.adoc. This includes adding any features to the home page and features page. Updating the doc page with javadoc links. Update the download page with a link to the latest release notes. - Copy the generated javadoc for each component to the website repositories' master branch under /javadoc/. Commit the javadoc and push. +Update the website and Github README.adoc. This includes adding any features to the home page and features page. Updating the doc page with javadoc links. Update the download page with a link to the latest release notes. + Send a message to the group and social media about the release, TODO. From d53f429faa42c067de6a5d70038674a71056551d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 08:20:39 +1000 Subject: [PATCH 475/811] Added release date to 4.5 release notes --- etc/release-notes/release-notes-4.5.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.5.adoc b/etc/release-notes/release-notes-4.5.adoc index 6a23fc0c..3cbc7259 100644 --- a/etc/release-notes/release-notes-4.5.adoc +++ b/etc/release-notes/release-notes-4.5.adoc @@ -1,7 +1,7 @@ = Release 4.5 -Proposed release: Feb 2016 +Released: 15 February 2016 == Enhancements From 5c6a4d19c5bc74c4a5838dc643c3cc63a5560371 Mon Sep 17 00:00:00 2001 From: mrbackend Date: Sat, 27 Feb 2016 00:42:55 +0100 Subject: [PATCH 476/811] #235 fj.test.Gen.pick is broken --- quickcheck/src/main/java/fj/test/Gen.java | 237 +++++++++++++++--- quickcheck/src/test/java/fj/test/TestGen.java | 190 ++++++++++++++ 2 files changed, 396 insertions(+), 31 deletions(-) create mode 100644 quickcheck/src/test/java/fj/test/TestGen.java diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 9ff45dfe..2bac9cfc 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -1,25 +1,28 @@ package fj.test; -import static fj.Bottom.error; -import fj.Effect; import fj.F; import fj.Function; -import static fj.Function.flip; -import static fj.Function.curry; import fj.P2; -import static fj.P2.__1; import fj.Unit; -import fj.F2; -import static fj.data.Array.array; +import fj.control.Trampoline; +import fj.data.Array; import fj.data.List; -import static fj.data.List.nil; -import static fj.data.List.replicate; import fj.data.Option; import fj.function.Effect1; +import static fj.Bottom.error; +import static fj.Function.curry; +import static fj.Function.flip; import static fj.Monoid.intAdditionMonoid; import static fj.Ord.intOrd; - +import static fj.P.lazy; +import static fj.P2.__1; +import static fj.control.Trampoline.pure; +import static fj.control.Trampoline.suspend; +import static fj.data.Array.array; +import static fj.data.List.cons; +import static fj.data.List.nil; +import static fj.data.List.replicate; import static java.lang.Math.max; import static java.lang.Math.min; @@ -564,43 +567,215 @@ public static Gen> listOf1(final Gen g) { * Returns a generator of lists that picks the given number of elements from the given list. If * the given number is less than zero or greater than the length of the given list, then the * returned generator will never produce a value. + *

+ * Note: pick is synonymous with pickCombinationWithoutReplacement + * + * @param n The number of elements to pick from the given list. + * @param as The list from which to pick elements. + * @return A generator of lists that picks the given number of elements from the given list. + */ + @Deprecated + public static Gen> pick(int n, List as) { + return pickCombinationWithoutReplacement(n, as); + } + + /** + * Returns a generator of lists that picks the given number of elements from the given list. The selection is + * a combination without replacement of elements from the given list, i.e. + *

+ *

+ * If the given number is less than zero or greater than the length of the given list, then the + * returned generator will never produce a value. * * @param n The number of elements to pick from the given list. * @param as The list from which to pick elements. * @return A generator of lists that picks the given number of elements from the given list. */ - public static Gen> pick(final int n, final List as) { - return n < 0 || n > as.length() ? Gen.>fail() : sequenceN(n, choose(0, as.length() - 1)).map(new F, List>() { - public List f(final List is) { - List r = nil(); + public static Gen> pickCombinationWithoutReplacement(int n, List as) { + int aLength = as.length(); + return ((n >= 0) && (n <= aLength)) ? + parameterised(s -> r -> { + final class Tramp { + + // Picks elements in constant stack space + private Trampoline> tramp(List remainAs, int remainN, int remainALength) { + return suspend(lazy(() -> + (remainN == 0) ? + // We have picked N elements; stop + pure(nil()) : + // For M remaining elements of which N will be picked, pick remainAs.head() with probability N/M + (r.choose(0, remainALength - 1) < remainN) ? + tramp(remainAs.tail(), remainN - 1, remainALength - 1) + .map(pickedTail -> cons(remainAs.head(), pickedTail)) : + tramp(remainAs.tail(), remainN, remainALength - 1))); + } - List iis = is.sort(intOrd); - List> aas = as.zipIndex(); + } + return value(new Tramp().tramp(as, n, aLength).run()); + }) : + fail(); + } - //noinspection ForLoopWithMissingComponent - for(; iis.isNotEmpty() && aas.isNotEmpty(); aas = aas.tail()) - if(iis.head().equals(aas.head()._2())) - iis = iis.tail(); - else - r = r.snoc(aas.head()._1()); + /** + * Returns a generator of lists that picks the given number of elements from the given list. The selection is + * a combination with replacement of elements from the given list, i.e. + *

+ *

+ * If the given number is less than zero, then the returned generator will never produce a value. Note that, + * with replacement, the given number may be larger than the length of the given list. + * + * @param n The number of elements to pick from the given list. + * @param as The list from which to pick elements. + * @return A generator of lists that picks the given number of elements from the given list. + */ + public static Gen> pickCombinationWithReplacement(int n, List as) { + Array aArr = as.toArray(); + return (n >= 0) ? + pick(indexPermutation(n, aArr.length()).map(indexes -> indexes.sort(intOrd)), aArr) : + fail(); + } - return r; - } - }); + /** + * Returns a generator of lists that picks the given number of elements from the given list. The selection is + * a permutation without replacement of elements from the given list, i.e. + *

+ *

+ * If the given number is less than zero or greater than the length of the given list, then the + * returned generator will never produce a value. + * + * @param n The number of elements to pick from the given list. + * @param as The list from which to pick elements. + * @return A generator of lists that picks the given number of elements from the given list. + */ + public static Gen> pickPermutationWithoutReplacement(int n, List as) { + return parameterised(s -> r -> + pickCombinationWithoutReplacement(n, as).map(combination -> { + // Shuffle combination using the Fisher-Yates algorithm + Array aArr = combination.toArray(); + int length = aArr.length(); + for (int i = length - 1; i > 0; --i) { + int j = r.choose(0, i); + A tmp = aArr.get(i); + aArr.set(i, aArr.get(j)); + aArr.set(j, tmp); + } + return aArr.toList(); + })); + } + + /** + * Returns a generator of lists that picks the given number of elements from the given list. The selection is + * a permutation with replacement of elements from the given list, i.e. + *

+ *

+ * If the given number is less than zero, then the returned generator will never produce a value. Note that, + * with replacement, the given number may be larger than the length of the given list. + * + * @param n The number of elements to pick from the given list. + * @param as The list from which to pick elements. + * @return A generator of lists that picks the given number of elements from the given list. + */ + public static Gen> pickPermutationWithReplacement(int n, List as) { + Array aArr = as.toArray(); + return (n >= 0) ? + pick(indexPermutation(n, aArr.length()), aArr) : + fail(); + } + + private static Gen> indexPermutation(int n, int m) { + return sequenceN(n, choose(0, m - 1)); + } + + private static Gen> pick(Gen> indexesGen, Array as) { + return indexesGen.map(indexes -> + indexes.foldLeft((acc, index) -> cons(as.get(index), acc), List.nil()).reverse()); } /** * Returns a generator of lists that produces some of the values of the given list. + *

+ * Note: someOf is synonymous with someCombinationWithoutReplacementOf * * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ - public static Gen> someOf(final List as) { - return choose(0, as.length()).bind(new F>>() { - public Gen> f(final Integer i) { - return pick(i, as); - } - }); + @Deprecated + public static Gen> someOf(List as) { + return someCombinationWithoutReplacementOf(as); + } + + /** + * Returns a generator of lists that produces some of the values of the given list. The selection is + * a combination without replacement of elements from the given list, i.e. + *

+ * + * @param as The list from which to pick values. + * @return A generator of lists that produces some of the values of the given list. + */ + public static Gen> someCombinationWithoutReplacementOf(List as) { + return choose(0, as.length()).bind(n -> pickCombinationWithoutReplacement(n, as)); + } + + /** + * Returns a generator of lists that produces some of the values of the given list. The selection is + * a combination with replacement of elements from the given list, i.e. + *
    + *
  • For any given selection, a generated list will always contain its elements in the same order
  • + *
  • Each element may be picked more than once
  • + *
+ * + * @param maxLength The maximum length of a generated list + * @param as The list from which to pick values. + * @return A generator of lists that produces some of the values of the given list. + */ + public static
Gen> someCombinationWithReplacementOf(int maxLength, List as) { + return choose(0, maxLength).bind(n -> pickCombinationWithReplacement(n, as)); + } + + /** + * Returns a generator of lists that produces some of the values of the given list. The selection is + * a permutation without replacement of elements from the given list, i.e. + *
    + *
  • For any given selection, a generated list may contain its elements in any order
  • + *
  • An element will never be picked more than once
  • + *
+ * + * @param as The list from which to pick values. + * @return A generator of lists that produces some of the values of the given list. + */ + public static
Gen> somePermutationWithoutReplacementOf(List as) { + return choose(0, as.length()).bind(n -> pickPermutationWithoutReplacement(n, as)); + } + + /** + * Returns a generator of lists that produces some of the values of the given list. The selection is + * a permutation with replacement of elements from the given list, i.e. + *
    + *
  • For any given selection, a generated list may contain its elements in any order
  • + *
  • Each element may be picked more than once
  • + *
+ * + * @param maxLength The maximum length of a generated list + * @param as The list from which to pick values. + * @return A generator of lists that produces some of the values of the given list. + */ + public static
Gen> somePermutationWithReplacementOf(int maxLength, List as) { + return choose(0, maxLength).bind(n -> pickPermutationWithReplacement(n, as)); } /** diff --git a/quickcheck/src/test/java/fj/test/TestGen.java b/quickcheck/src/test/java/fj/test/TestGen.java new file mode 100644 index 00000000..5db6759c --- /dev/null +++ b/quickcheck/src/test/java/fj/test/TestGen.java @@ -0,0 +1,190 @@ +package fj.test; + +import fj.data.List; +import fj.function.Effect1; +import org.junit.Test; + +import static fj.Ord.charOrd; +import static fj.data.List.list; +import static fj.data.List.range; +import static fj.test.Gen.pickCombinationWithReplacement; +import static fj.test.Gen.pickCombinationWithoutReplacement; +import static fj.test.Gen.pickPermutationWithReplacement; +import static fj.test.Gen.pickPermutationWithoutReplacement; +import static fj.test.Rand.standard; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public final class TestGen { + + private static final List AS = list('A', 'B', 'C'); + + @Test + public void testPickCombinationWithoutReplacement_none() { + Gen> instance = pickCombinationWithoutReplacement(0, AS); + testPick(100, instance, actual -> { + assertTrue(actual.isEmpty()); + }); + } + + @Test + public void testPickCombinationWithoutReplacement_one() { + Gen> instance = pickCombinationWithoutReplacement(1, AS); + testPick(100, instance, actual -> { + assertEquals(1, actual.length()); + assertTrue(AS.exists(a -> a.equals(actual.head()))); + }); + } + + @Test + public void testPickCombinationWithoutReplacement_two() { + Gen> instance = pickCombinationWithoutReplacement(2, AS); + testPick(100, instance, actual -> { + assertEquals(2, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> charOrd.isGreaterThan(a, l.head())))); + }); + } + + @Test + public void testPickCombinationWithoutReplacement_three() { + Gen> instance = pickCombinationWithoutReplacement(3, AS); + testPick(100, instance, actual -> { + assertEquals(3, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> charOrd.isGreaterThan(a, l.head())))); + }); + } + + @Test + public void testPickCombinationWithReplacement_none() { + Gen> instance = pickCombinationWithReplacement(0, AS); + testPick(100, instance, actual -> { + assertTrue(actual.isEmpty()); + }); + } + + @Test + public void testPickCombinationWithReplacement_one() { + Gen> instance = pickCombinationWithReplacement(1, AS); + testPick(100, instance, actual -> { + assertEquals(1, actual.length()); + assertTrue(AS.exists(a -> a.equals(actual.head()))); + }); + } + + @Test + public void testPickCombinationWithReplacement_two() { + Gen> instance = pickCombinationWithReplacement(2, AS); + testPick(100, instance, actual -> { + assertEquals(2, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> !charOrd.isLessThan(a, l.head())))); + }); + } + + @Test + public void testPickCombinationWithReplacement_three() { + Gen> instance = pickCombinationWithReplacement(3, AS); + testPick(100, instance, actual -> { + assertEquals(3, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> !charOrd.isLessThan(a, l.head())))); + }); + } + + @Test + public void testPickCombinationWithReplacement_four() { + Gen> instance = pickCombinationWithReplacement(4, AS); + testPick(100, instance, actual -> { + assertEquals(4, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> !charOrd.isLessThan(a, l.head())))); + }); + } + + @Test + public void testPickPermutationWithoutReplacement_none() { + Gen> instance = pickPermutationWithoutReplacement(0, AS); + testPick(100, instance, actual -> { + assertTrue(actual.isEmpty()); + }); + } + + @Test + public void testPickPermutationWithoutReplacement_one() { + Gen> instance = pickPermutationWithoutReplacement(1, AS); + testPick(100, instance, actual -> { + assertEquals(1, actual.length()); + assertTrue(AS.exists(a -> a.equals(actual.head()))); + }); + } + + @Test + public void testPickPermutationWithoutReplacement_two() { + Gen> instance = pickCombinationWithoutReplacement(2, AS); + testPick(100, instance, actual -> { + assertEquals(2, actual.length()); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> !a.equals(l.head())))); + }); + } + + @Test + public void testPickPermutationWithoutReplacement_three() { + Gen> instance = pickPermutationWithoutReplacement(3, AS); + testPick(100, instance, actual -> { + assertEquals(3, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> !a.equals(l.head())))); + }); + } + + @Test + public void testPickPermutationWithReplacement_none() { + Gen> instance = pickPermutationWithReplacement(0, AS); + testPick(100, instance, actual -> { + assertTrue(actual.isEmpty()); + }); + } + + @Test + public void testPickPermutationWithReplacement_one() { + Gen> instance = pickPermutationWithReplacement(1, AS); + testPick(100, instance, actual -> { + assertEquals(1, actual.length()); + assertTrue(AS.exists(a -> a.equals(actual.head()))); + }); + } + + @Test + public void testPickPermutationWithReplacement_two() { + Gen> instance = pickPermutationWithReplacement(2, AS); + testPick(100, instance, actual -> { + assertEquals(2, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + }); + } + + @Test + public void testPickPermutationWithReplacement_three() { + Gen> instance = pickPermutationWithReplacement(3, AS); + testPick(100, instance, actual -> { + assertEquals(3, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + }); + } + + @Test + public void testPickPermutationWithReplacement_four() { + Gen> instance = pickPermutationWithReplacement(4, AS); + testPick(100, instance, actual -> { + assertEquals(4, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + }); + } + + private static void testPick(int n, Gen> instance, Effect1> test) { + range(0, n).map(i -> instance.gen(0, standard)).foreachDoEffect(test::f); + } + +} From 498e59b11dd9a9090c3b766bff3815645bd31ba2 Mon Sep 17 00:00:00 2001 From: mrbackend Date: Fri, 4 Mar 2016 03:23:34 +0100 Subject: [PATCH 477/811] fj.test.Rand.reseed() is broken (#237) --- .../src/main/java/fj/test/Property.java | 14 +- quickcheck/src/main/java/fj/test/Rand.java | 136 ++++++++++++------ .../src/test/java/fj/test/TestRand.java | 17 +++ 3 files changed, 113 insertions(+), 54 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 232911bd..18baccc3 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -184,7 +184,7 @@ else if (x.isFalsified()) { } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator} and the given + * Checks this property using a {@link Rand#standard standard random generator} and the given * arguments to produce a result. * * @param minSuccessful The minimum number of successful tests before a result is reached. @@ -226,7 +226,7 @@ public CheckResult check(final Rand r, final int minSize, final int maxSize) { } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator}, 100 minimum + * Checks this property using a {@link Rand#standard standard random generator}, 100 minimum * successful checks, 500 maximum discarded tests and the given arguments to produce a result. * * @param minSize The minimum size to use for checking. @@ -239,7 +239,7 @@ public CheckResult check(final int minSize, } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator}, 100 minimum + * Checks this property using a {@link Rand#standard standard random generator}, 100 minimum * successful checks, 500 maximum discarded tests, minimum size of 0, maximum size of 100. * * @return A result after checking this property. @@ -249,7 +249,7 @@ public CheckResult check() { } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator}, the given minimum + * Checks this property using a {@link Rand#standard standard random generator}, the given minimum * successful checks, 500 maximum discarded tests, minimum size of 0, maximum size of 100. * * @param minSuccessful The minimum number of successful tests before a result is reached. @@ -272,7 +272,7 @@ public CheckResult minSuccessful(final Rand r, final int minSuccessful) { } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator}, 100 minimum + * Checks this property using a {@link Rand#standard standard random generator}, 100 minimum * successful checks, the given maximum discarded tests, minimum size of 0, maximum size of 100. * * @param maxDiscarded The maximum number of tests discarded because they did not satisfy @@ -297,7 +297,7 @@ public CheckResult maxDiscarded(final Rand r, final int maxDiscarded) { } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator}, 100 minimum + * Checks this property using a {@link Rand#standard standard random generator}, 100 minimum * successful checks, 500 maximum discarded tests, the given minimum size, maximum size of 100. * * @param minSize The minimum size to use for checking. @@ -320,7 +320,7 @@ public CheckResult minSize(final Rand r, final int minSize) { } /** - * Checks this property using a {@link Rand#Rand(F, F) standard random generator}, 100 minimum + * Checks this property using a {@link Rand#standard standard random generator}, 100 minimum * successful checks, 500 maximum discarded tests, minimum size of 0, the given maximum size. * * @param maxSize The maximum size to use for checking. diff --git a/quickcheck/src/main/java/fj/test/Rand.java b/quickcheck/src/main/java/fj/test/Rand.java index 500d04eb..567dba77 100644 --- a/quickcheck/src/main/java/fj/test/Rand.java +++ b/quickcheck/src/main/java/fj/test/Rand.java @@ -2,11 +2,13 @@ import fj.F; import fj.data.Option; -import static fj.data.Option.some; +import java.util.Random; + +import static fj.data.Option.none; +import static fj.data.Option.some; import static java.lang.Math.max; import static java.lang.Math.min; -import java.util.Random; /** * A random number generator. @@ -17,9 +19,17 @@ public final class Rand { private final F, F>> f; private final F, F>> g; - private Rand(final F, F>> f, final F, F>> g) { + // TODO Change to F when rand(f,g) is removed + private final Option> optOnReseed; + + private Rand( + F, F>> f, + F, F>> g, + Option> optOnReseed) { + this.f = f; this.g = g; + this.optOnReseed = optOnReseed; } /** @@ -74,65 +84,97 @@ public double choose(final double from, final double to) { * @param seed The seed of the new random generator. * @return A random generator with the given seed. */ - public Rand reseed(final long seed) { - return new Rand(new F, F>>() { - public F> f(final Option old) { - return new F>() { - public F f(final Integer from) { - return new F() { - public Integer f(final Integer to) { - return f.f(some(seed)).f(from).f(to); - } - }; - } - }; - } - }, new F, F>>() { - public F> f(final Option old) { - return new F>() { - public F f(final Double from) { - return new F() { - public Double f(final Double to) { - return g.f(some(seed)).f(from).f(to); - } - }; - } - }; - } - }); + public Rand reseed(long seed) { + return optOnReseed.option( + () -> { + throw new IllegalStateException("reseed() called on a Rand created with deprecated rand() method"); + }, + onReseed -> onReseed.f(seed)); } /** * Constructs a random generator from the given functions that supply a range to produce a * result. + *

+ * Calling {@link #reseed(long)} on an instance returned from this method will + * result in an exception being thrown. Use {@link #rand(F, F, F)} instead. * * @param f The integer random generator. * @param g The floating-point random generator. * @return A random generator from the given functions that supply a range to produce a result. */ - public static Rand rand(final F, F>> f, final F, F>> g) { - return new Rand(f, g); + // TODO Change Option> optOnReseed to F onReseed when removing this method + @Deprecated + public static Rand rand( + F, F>> f, + F, F>> g) { + + return new Rand(f, g, none()); } + /** + * Constructs a reseedable random generator from the given functions that supply a range to produce a + * result. + * + * @param f The integer random generator. + * @param g The floating-point random generator. + * @param onReseed Function to create a reseeded Rand. + * @return A random generator from the given functions that supply a range to produce a result. + */ + public static Rand rand( + F, F>> f, + F, F>> g, + F onReseed) { - private static final F fr = new F() { - public Random f(final Long x) { - return new Random(x); - } - }; + return new Rand(f, g, some(onReseed)); + } /** * A standard random generator that uses {@link Random}. */ - public static final Rand standard = new Rand(seed -> from -> to -> { - final int min = min(from, to); - final int max = max(from, to); - final Random random = seed.map(fr).orSome(new Random()); - return (int) ((random.nextLong() & Long.MAX_VALUE) % (1L + max - min)) + min; - }, seed -> from -> to -> { - final double min = min(from, to); - final double max = max(from, to); - final Random random = seed.map(fr).orSome(new Random()); - return random.nextDouble() * (max - min) + min; - }); + public static final Rand standard = createStandard(new Random()); + + private static Rand createStandard(Random defaultRandom) { + return rand( + optSeed -> from -> to -> + standardChooseInt(optSeed.option(() -> defaultRandom, Random::new), from, to), + optSeed -> from -> to -> + standardChooseDbl(optSeed.option(() -> defaultRandom, Random::new), from, to), + newSeed -> createStandard(new Random(newSeed))); + } + + /* + * Returns a uniformly distributed value between min(from,to) (inclusive) and max(from,to) (inclusive). + */ + private static int standardChooseInt(Random random, int from, int to) { + int result; + if (from != to) { + int min = min(from, to); + int max = max(from, to); + long range = (1L + max) - min; + long bound = Long.MAX_VALUE - (Long.MAX_VALUE % range); + long r = random.nextLong() & Long.MAX_VALUE; + while (r >= bound) { + // Ensure uniformity + r = random.nextLong() & Long.MAX_VALUE; + } + result = (int) ((r % range) + min); + } else { + result = from; + } + return result; + } + + /* + * Returns a uniformly distributed value between min(from,to) (inclusive) and max(from,to) (exclusive) + * + * In theory, this differs from the choose() contract, which specifies a closed interval. + * In practice, the difference shouldn't matter. + */ + private static double standardChooseDbl(Random random, double from, double to) { + double min = min(from, to); + double max = max(from, to); + return ((max - min) * random.nextDouble()) + min; + } + } diff --git a/quickcheck/src/test/java/fj/test/TestRand.java b/quickcheck/src/test/java/fj/test/TestRand.java index 9df9639a..6c72b3b1 100644 --- a/quickcheck/src/test/java/fj/test/TestRand.java +++ b/quickcheck/src/test/java/fj/test/TestRand.java @@ -1,7 +1,10 @@ package fj.test; +import fj.Equal; import fj.Ord; +import fj.data.List; import fj.data.Stream; +import org.junit.Assert; import org.junit.Test; import static org.junit.Assert.assertTrue; @@ -21,4 +24,18 @@ public void testRandLowHighInclusive() { assertTrue(s.head() == min && s.last() == max); } + @Test + public void testReseed() { + Rand rand1 = Rand.standard.reseed(42); + List s1 = + List.range(0, 10).map(i -> rand1.choose(Integer.MIN_VALUE, Integer.MAX_VALUE)); + + Rand rand2 = rand1.reseed(42); + List s2 = + List.range(0, 10).map(i -> rand2.choose(Integer.MIN_VALUE, Integer.MAX_VALUE)); + + assertTrue(s1.zip(s2).forall(p -> p._1().equals(p._2()))); + Assert.assertFalse(s1.allEqual(Equal.intEqual)); + } + } From 3548db113244002b619dd406ab428964e0324f2e Mon Sep 17 00:00:00 2001 From: mrbackend Date: Mon, 7 Mar 2016 23:20:24 +0100 Subject: [PATCH 478/811] #235 Changes after Code Review + added Gen.pickOne() --- quickcheck/src/main/java/fj/test/Gen.java | 52 +++++++----- .../fj/test/{TestGen.java => GenTest.java} | 84 +++++++++---------- 2 files changed, 74 insertions(+), 62 deletions(-) rename quickcheck/src/test/java/fj/test/{TestGen.java => GenTest.java} (59%) diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 2bac9cfc..0aa11adb 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -563,12 +563,24 @@ public static Gen> listOf1(final Gen g) { return listOf(g, 1); } + /** + * Returns a generator that picks one element from the given list. If the given list is empty, then the + * returned generator will never produce a value. + * + * @param as The list from which to pick an element. + * @return A generator that picks an element from the given list. + */ + public static Gen pickOne(List as) { + // This is the fastest of the four; functionally, any of them would do + return wordOf(1, as).map(List::head); + } + /** * Returns a generator of lists that picks the given number of elements from the given list. If * the given number is less than zero or greater than the length of the given list, then the * returned generator will never produce a value. *

- * Note: pick is synonymous with pickCombinationWithoutReplacement + * Note: pick is synonymous with combinationOf * * @param n The number of elements to pick from the given list. * @param as The list from which to pick elements. @@ -576,7 +588,7 @@ public static Gen> listOf1(final Gen g) { */ @Deprecated public static Gen> pick(int n, List as) { - return pickCombinationWithoutReplacement(n, as); + return combinationOf(n, as); } /** @@ -594,7 +606,7 @@ public static Gen> pick(int n, List as) { * @param as The list from which to pick elements. * @return A generator of lists that picks the given number of elements from the given list. */ - public static Gen> pickCombinationWithoutReplacement(int n, List as) { + public static Gen> combinationOf(int n, List as) { int aLength = as.length(); return ((n >= 0) && (n <= aLength)) ? parameterised(s -> r -> { @@ -634,10 +646,10 @@ private Trampoline> tramp(List remainAs, int remainN, int remainALeng * @param as The list from which to pick elements. * @return A generator of lists that picks the given number of elements from the given list. */ - public static Gen> pickCombinationWithReplacement(int n, List as) { + public static Gen> selectionOf(int n, List as) { Array aArr = as.toArray(); return (n >= 0) ? - pick(indexPermutation(n, aArr.length()).map(indexes -> indexes.sort(intOrd)), aArr) : + pick(indexWord(n, aArr.length()).map(indexes -> indexes.sort(intOrd)), aArr) : fail(); } @@ -656,9 +668,9 @@ public static Gen> pickCombinationWithReplacement(int n, List as) * @param as The list from which to pick elements. * @return A generator of lists that picks the given number of elements from the given list. */ - public static Gen> pickPermutationWithoutReplacement(int n, List as) { + public static Gen> permutationOf(int n, List as) { return parameterised(s -> r -> - pickCombinationWithoutReplacement(n, as).map(combination -> { + combinationOf(n, as).map(combination -> { // Shuffle combination using the Fisher-Yates algorithm Array aArr = combination.toArray(); int length = aArr.length(); @@ -687,14 +699,14 @@ public static Gen> pickPermutationWithoutReplacement(int n, List * @param as The list from which to pick elements. * @return A generator of lists that picks the given number of elements from the given list. */ - public static Gen> pickPermutationWithReplacement(int n, List as) { + public static Gen> wordOf(int n, List as) { Array aArr = as.toArray(); return (n >= 0) ? - pick(indexPermutation(n, aArr.length()), aArr) : + pick(indexWord(n, aArr.length()), aArr) : fail(); } - private static Gen> indexPermutation(int n, int m) { + private static Gen> indexWord(int n, int m) { return sequenceN(n, choose(0, m - 1)); } @@ -706,14 +718,14 @@ private static Gen> pick(Gen> indexesGen, Array as) /** * Returns a generator of lists that produces some of the values of the given list. *

- * Note: someOf is synonymous with someCombinationWithoutReplacementOf + * Note: someOf is synonymous with someCombinationOf * * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ @Deprecated public static Gen> someOf(List as) { - return someCombinationWithoutReplacementOf(as); + return someCombinationOf(as); } /** @@ -727,8 +739,8 @@ public static Gen> someOf(List as) { * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ - public static Gen> someCombinationWithoutReplacementOf(List as) { - return choose(0, as.length()).bind(n -> pickCombinationWithoutReplacement(n, as)); + public static Gen> someCombinationOf(List as) { + return choose(0, as.length()).bind(n -> combinationOf(n, as)); } /** @@ -743,8 +755,8 @@ public static Gen> someCombinationWithoutReplacementOf(List as) { * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ - public static Gen> someCombinationWithReplacementOf(int maxLength, List as) { - return choose(0, maxLength).bind(n -> pickCombinationWithReplacement(n, as)); + public static Gen> someSelectionOf(int maxLength, List as) { + return choose(0, maxLength).bind(n -> selectionOf(n, as)); } /** @@ -758,8 +770,8 @@ public static Gen> someCombinationWithReplacementOf(int maxLength, L * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ - public static Gen> somePermutationWithoutReplacementOf(List as) { - return choose(0, as.length()).bind(n -> pickPermutationWithoutReplacement(n, as)); + public static Gen> somePermutationOf(List as) { + return choose(0, as.length()).bind(n -> permutationOf(n, as)); } /** @@ -774,8 +786,8 @@ public static Gen> somePermutationWithoutReplacementOf(List as) { * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ - public static Gen> somePermutationWithReplacementOf(int maxLength, List as) { - return choose(0, maxLength).bind(n -> pickPermutationWithReplacement(n, as)); + public static Gen> someWordOf(int maxLength, List as) { + return choose(0, maxLength).bind(n -> wordOf(n, as)); } /** diff --git a/quickcheck/src/test/java/fj/test/TestGen.java b/quickcheck/src/test/java/fj/test/GenTest.java similarity index 59% rename from quickcheck/src/test/java/fj/test/TestGen.java rename to quickcheck/src/test/java/fj/test/GenTest.java index 5db6759c..3bb723b8 100644 --- a/quickcheck/src/test/java/fj/test/TestGen.java +++ b/quickcheck/src/test/java/fj/test/GenTest.java @@ -7,29 +7,29 @@ import static fj.Ord.charOrd; import static fj.data.List.list; import static fj.data.List.range; -import static fj.test.Gen.pickCombinationWithReplacement; -import static fj.test.Gen.pickCombinationWithoutReplacement; -import static fj.test.Gen.pickPermutationWithReplacement; -import static fj.test.Gen.pickPermutationWithoutReplacement; +import static fj.test.Gen.selectionOf; +import static fj.test.Gen.combinationOf; +import static fj.test.Gen.wordOf; +import static fj.test.Gen.permutationOf; import static fj.test.Rand.standard; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -public final class TestGen { +public final class GenTest { private static final List AS = list('A', 'B', 'C'); @Test - public void testPickCombinationWithoutReplacement_none() { - Gen> instance = pickCombinationWithoutReplacement(0, AS); + public void testCombinationOf_none() { + Gen> instance = combinationOf(0, AS); testPick(100, instance, actual -> { assertTrue(actual.isEmpty()); }); } @Test - public void testPickCombinationWithoutReplacement_one() { - Gen> instance = pickCombinationWithoutReplacement(1, AS); + public void testCombinationOf_one() { + Gen> instance = combinationOf(1, AS); testPick(100, instance, actual -> { assertEquals(1, actual.length()); assertTrue(AS.exists(a -> a.equals(actual.head()))); @@ -37,8 +37,8 @@ public void testPickCombinationWithoutReplacement_one() { } @Test - public void testPickCombinationWithoutReplacement_two() { - Gen> instance = pickCombinationWithoutReplacement(2, AS); + public void testCombinationOf_two() { + Gen> instance = combinationOf(2, AS); testPick(100, instance, actual -> { assertEquals(2, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -47,8 +47,8 @@ public void testPickCombinationWithoutReplacement_two() { } @Test - public void testPickCombinationWithoutReplacement_three() { - Gen> instance = pickCombinationWithoutReplacement(3, AS); + public void testCombinationOf_three() { + Gen> instance = combinationOf(3, AS); testPick(100, instance, actual -> { assertEquals(3, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -57,16 +57,16 @@ public void testPickCombinationWithoutReplacement_three() { } @Test - public void testPickCombinationWithReplacement_none() { - Gen> instance = pickCombinationWithReplacement(0, AS); + public void testSelectionOf_none() { + Gen> instance = selectionOf(0, AS); testPick(100, instance, actual -> { assertTrue(actual.isEmpty()); }); } @Test - public void testPickCombinationWithReplacement_one() { - Gen> instance = pickCombinationWithReplacement(1, AS); + public void testSelectionOf_one() { + Gen> instance = selectionOf(1, AS); testPick(100, instance, actual -> { assertEquals(1, actual.length()); assertTrue(AS.exists(a -> a.equals(actual.head()))); @@ -74,8 +74,8 @@ public void testPickCombinationWithReplacement_one() { } @Test - public void testPickCombinationWithReplacement_two() { - Gen> instance = pickCombinationWithReplacement(2, AS); + public void testSelectionOf_two() { + Gen> instance = selectionOf(2, AS); testPick(100, instance, actual -> { assertEquals(2, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -84,8 +84,8 @@ public void testPickCombinationWithReplacement_two() { } @Test - public void testPickCombinationWithReplacement_three() { - Gen> instance = pickCombinationWithReplacement(3, AS); + public void testSelectionOf_three() { + Gen> instance = selectionOf(3, AS); testPick(100, instance, actual -> { assertEquals(3, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -94,8 +94,8 @@ public void testPickCombinationWithReplacement_three() { } @Test - public void testPickCombinationWithReplacement_four() { - Gen> instance = pickCombinationWithReplacement(4, AS); + public void testSelectionOf_four() { + Gen> instance = selectionOf(4, AS); testPick(100, instance, actual -> { assertEquals(4, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -104,16 +104,16 @@ public void testPickCombinationWithReplacement_four() { } @Test - public void testPickPermutationWithoutReplacement_none() { - Gen> instance = pickPermutationWithoutReplacement(0, AS); + public void testPermutationOf_none() { + Gen> instance = permutationOf(0, AS); testPick(100, instance, actual -> { assertTrue(actual.isEmpty()); }); } @Test - public void testPickPermutationWithoutReplacement_one() { - Gen> instance = pickPermutationWithoutReplacement(1, AS); + public void testPermutationOf_one() { + Gen> instance = permutationOf(1, AS); testPick(100, instance, actual -> { assertEquals(1, actual.length()); assertTrue(AS.exists(a -> a.equals(actual.head()))); @@ -121,8 +121,8 @@ public void testPickPermutationWithoutReplacement_one() { } @Test - public void testPickPermutationWithoutReplacement_two() { - Gen> instance = pickCombinationWithoutReplacement(2, AS); + public void testPermutationOf_two() { + Gen> instance = combinationOf(2, AS); testPick(100, instance, actual -> { assertEquals(2, actual.length()); assertTrue(actual.tails().forall(l -> l.isEmpty() || l.tail().forall(a -> !a.equals(l.head())))); @@ -130,8 +130,8 @@ public void testPickPermutationWithoutReplacement_two() { } @Test - public void testPickPermutationWithoutReplacement_three() { - Gen> instance = pickPermutationWithoutReplacement(3, AS); + public void testPermutationOf_three() { + Gen> instance = permutationOf(3, AS); testPick(100, instance, actual -> { assertEquals(3, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -140,16 +140,16 @@ public void testPickPermutationWithoutReplacement_three() { } @Test - public void testPickPermutationWithReplacement_none() { - Gen> instance = pickPermutationWithReplacement(0, AS); + public void testWordOf_none() { + Gen> instance = wordOf(0, AS); testPick(100, instance, actual -> { assertTrue(actual.isEmpty()); }); } @Test - public void testPickPermutationWithReplacement_one() { - Gen> instance = pickPermutationWithReplacement(1, AS); + public void testWordOf_one() { + Gen> instance = wordOf(1, AS); testPick(100, instance, actual -> { assertEquals(1, actual.length()); assertTrue(AS.exists(a -> a.equals(actual.head()))); @@ -157,8 +157,8 @@ public void testPickPermutationWithReplacement_one() { } @Test - public void testPickPermutationWithReplacement_two() { - Gen> instance = pickPermutationWithReplacement(2, AS); + public void testWordOf_two() { + Gen> instance = wordOf(2, AS); testPick(100, instance, actual -> { assertEquals(2, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -166,8 +166,8 @@ public void testPickPermutationWithReplacement_two() { } @Test - public void testPickPermutationWithReplacement_three() { - Gen> instance = pickPermutationWithReplacement(3, AS); + public void testWordOf_three() { + Gen> instance = wordOf(3, AS); testPick(100, instance, actual -> { assertEquals(3, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -175,8 +175,8 @@ public void testPickPermutationWithReplacement_three() { } @Test - public void testPickPermutationWithReplacement_four() { - Gen> instance = pickPermutationWithReplacement(4, AS); + public void testWordOf_four() { + Gen> instance = wordOf(4, AS); testPick(100, instance, actual -> { assertEquals(4, actual.length()); assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); @@ -184,7 +184,7 @@ public void testPickPermutationWithReplacement_four() { } private static void testPick(int n, Gen> instance, Effect1> test) { - range(0, n).map(i -> instance.gen(0, standard)).foreachDoEffect(test::f); + range(0, n).map(ignore -> instance.gen(0, standard)).foreachDoEffect(test::f); } } From a4695e352e115820e54551aa3d16b8ac50da22b9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 8 May 2016 22:45:00 +1000 Subject: [PATCH 479/811] Upgraded Gradle to 2.13 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be138e88..a54a2d93 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip From 5d45d6ac407d591c3404f88a27fbb4e46fed7dd5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 9 May 2016 00:39:43 +1000 Subject: [PATCH 480/811] Updated jacoco version --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 7a3b81cf..3bc75234 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,9 @@ allprojects { jacoco { - toolVersion = "0.7.1.201405082137" +// toolVersion = "0.7.1.201405082137" + toolVersion = "0.7.6.201602180812" + } defaultTasks "build" From acadf6afd4276ae33377648cd61fa6a6c1ed6206 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Wed, 11 May 2016 22:18:10 +1000 Subject: [PATCH 481/811] Add some optics for Option --- core/src/main/java/fj/data/Option.java | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index c9f9f9f2..476d38db 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -19,6 +19,8 @@ import fj.Equal; import fj.Ord; import fj.Hash; +import fj.data.optic.Prism; +import fj.data.optic.PPrism; import static fj.Function.*; import static fj.P.p; import static fj.Unit.unit; @@ -30,6 +32,8 @@ import static fj.data.Validation.parseInt; import static fj.data.Validation.parseLong; import static fj.data.Validation.parseShort; +import static fj.data.optic.Prism.prism; +import static fj.data.optic.PPrism.pPrism; import static fj.Show.optionShow; import java.util.Collection; @@ -883,4 +887,34 @@ public static F>, Option> join() { * A function that parses a string to a short. */ public static final F> parseShort = s -> parseShort(s).toOption(); + + public static final class Optic { + + private Optic() { + throw new UnsupportedOperationException(); + } + + /** + * None prism + */ + public static Prism, Unit> none() { + return prism(o -> o.option(Option.some(Unit.unit()), a -> Option.none()), u -> Option.none()); + } + + /** + * Polymorphic Some prism + */ + public static PPrism, Option, A, B> pSome() { + return pPrism(o -> o., A>>map(Either::right).orSome(Either.left(Option.none())), Option::some); + } + + /** + * Monomorphic Some prism + */ + public static Prism, A> some() { + return new Prism<>(pSome()); + } + + } + } From 5f1d7ad6660745784987d6e219747ca8d1d8e5e4 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Thu, 12 May 2016 11:52:29 +1000 Subject: [PATCH 482/811] Add property checks for Option optics --- props-core-scalacheck/src/main/scala/fj/package.scala | 8 +++++--- .../src/test/scala/fj/data/CheckOption.scala | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/props-core-scalacheck/src/main/scala/fj/package.scala b/props-core-scalacheck/src/main/scala/fj/package.scala index 5a3b9bfc..78afe491 100644 --- a/props-core-scalacheck/src/main/scala/fj/package.scala +++ b/props-core-scalacheck/src/main/scala/fj/package.scala @@ -1,5 +1,5 @@ import fj.Equal -import fj.data.List +import fj.data.{Option, List} package object fj { implicit def Function1F[A, B](g: A => B): F[A, B] = new F[A, B] { def f(a: A) = g(a) @@ -16,9 +16,11 @@ package object fj { implicit def intEqual: Equal[Int] = Equal.equal({(i1:Int, i2:Int) => Boolean.box((i1 == i2))}) implicit def unitEqual: Equal[Unit] = Equal.anyEqual() - + implicit def listEqual[A](implicit aEq: Equal[A]): Equal[List[A]] = Equal.listEqual(aEq) - + + implicit def optionEqual[A](implicit aEq: Equal[A]): Equal[Option[A]] = Equal.optionEqual(aEq) + implicit def p2Equal[A, B](implicit aEq: Equal[A], bEq: Equal[B]): Equal[P2[A, B]] = Equal.p2Equal(aEq, bEq) } \ No newline at end of file diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala index 18d2cdf2..13059d3f 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckOption.scala @@ -1,9 +1,11 @@ package fj package data +import fj.data.optic.PrismLaws import org.scalacheck.Prop._ import ArbitraryOption.arbitraryOption import ArbitraryP.arbitraryP1 +import ArbitraryUnit._ import Equal.{optionEqual, stringEqual} import Unit.unit import Option.{none, some, join} @@ -84,4 +86,10 @@ object CheckOption extends Properties("Option") { a.isNone || optionEqual(stringEqual).eq( join(a), a.some)) + + property("Optic.pSome") = PrismLaws[Option[String], String](Option.Optic.pSome()) + + property("Optic.some") = PrismLaws[Option[String], String](Option.Optic.some()) + + property("Optic.none") = PrismLaws[Option[Unit], Unit](Option.Optic.none()) } From 72f3e761d6c1afc209990d4fc9618e53af634cd1 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Thu, 12 May 2016 15:57:34 +1000 Subject: [PATCH 483/811] Add "as" and "voided" IO functions --- core/src/main/java/fj/data/IOFunctions.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index bb2d7de1..8d766d15 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -339,6 +339,14 @@ public B run() throws IOException { }; } + public static final IO as(final IO io, final B b) { + return map(io, ignored -> b); + } + + public static final IO voided(final IO io) { + return as(io, Unit.unit()); + } + public static final IO bind(final IO io, final F> f) { return new IO() { @Override From 8703a75974b9fa99127660bf70c653c180bb7dc7 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Thu, 12 May 2016 16:12:27 +1000 Subject: [PATCH 484/811] Add "when" and "unless" to IOFunctions --- core/src/main/java/fj/data/IOFunctions.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 8d766d15..9136311b 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -356,6 +356,14 @@ public B run() throws IOException { }; } + public static final IO when(final IO io, final Boolean b) { + return b ? io : ioUnit; + } + + public static final IO unless(final IO io, final Boolean b) { + return when(io, !b); + } + /** * Evaluate each action in the sequence from left to right, and collect the results. */ From 42ee23dca237d739036e5082f682285512da326e Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 13 May 2016 11:19:35 +1000 Subject: [PATCH 485/811] Swap arguments to "when" and "unless" --- core/src/main/java/fj/data/IOFunctions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 9136311b..dce5d0af 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -356,12 +356,12 @@ public B run() throws IOException { }; } - public static final IO when(final IO io, final Boolean b) { + public static final IO when(final Boolean b, final IO io) { return b ? io : ioUnit; } - public static final IO unless(final IO io, final Boolean b) { - return when(io, !b); + public static final IO unless(final Boolean b, final IO io) { + return when(!b, io); } /** From 6892c93a687b1df1f523f6e6f9e4ab431df72ac2 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 13 May 2016 11:20:15 +1000 Subject: [PATCH 486/811] Add a Semigroup for IO --- core/src/main/java/fj/Semigroup.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index e1e4fdf7..0da2cd77 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -2,6 +2,8 @@ import fj.data.Array; import fj.data.List; +import fj.data.IO; +import fj.data.IOFunctions; import fj.data.Natural; import fj.data.NonEmptyList; import fj.data.Option; @@ -355,6 +357,13 @@ public static Semigroup> p2Semigroup(final Semigroup sa, fina return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); } + /** + * A semigroup for IO values. + */ + public static Semigroup> ioSemigroup(final Semigroup sa) { + return semigroup((a1, a2) -> IOFunctions.liftM2(a1, a2, sa::sum)); + } + /** * A semigroup for the Unit value. */ From f89381d5aeed29ef553b8bb766999036ed2f465d Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 13 May 2016 11:31:56 +1000 Subject: [PATCH 487/811] Add "first" and "last" semigroups --- core/src/main/java/fj/Semigroup.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 0da2cd77..18172990 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -264,6 +264,20 @@ public static Semigroup semigroup(final F2 sum) { public static final Semigroup stringBuilderSemigroup = semigroup((s1, s2) -> new StringBuilder(s1).append(s2)); + /** + * A semigroup which always uses the "first" (left-hand side) value. + */ + public static Semigroup firstSemigroup() { + return semigroup((a1, a2) -> a1); + } + + /** + * A semigroup which always uses the "last" (right-hand side) value. + */ + public static Semigroup lastSemigroup() { + return semigroup((a1, a2) -> a2); + } + /** * A semigroup for functions. * From 637c18c9f7c819f6cd52486ecd7cdf07838048cb Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 13 May 2016 20:23:47 +1000 Subject: [PATCH 488/811] Add a Monoid for Unit --- core/src/main/java/fj/Monoid.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 40d6e8e7..0d70c481 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -384,6 +384,11 @@ public static Monoid> arrayMonoid() { return monoid(Semigroup.arraySemigroup(), Array.empty()); } + /** + * A monoid for the Unit value. + */ + public static final Monoid unitMonoid = monoid(Semigroup.unitSemigroup, Unit.unit()); + /** * A monoid for sets. * From 77f45b6005bcc2208311c629b86e49bbe8e0df71 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 13 May 2016 20:23:54 +1000 Subject: [PATCH 489/811] Add a Monoid for IO --- core/src/main/java/fj/Monoid.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 0d70c481..c2214748 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -4,6 +4,8 @@ import static fj.Function.flip; import fj.data.Array; import fj.data.List; +import fj.data.IO; +import fj.data.IOFunctions; import fj.data.Natural; import fj.data.Option; import fj.data.Set; @@ -384,6 +386,13 @@ public static Monoid> arrayMonoid() { return monoid(Semigroup.arraySemigroup(), Array.empty()); } + /** + * A monoid for IO values. + */ + public static Monoid> ioMonoid(final Monoid ma) { + return monoid(Semigroup.ioSemigroup(ma.semigroup()), IOFunctions.unit(ma.zero())); + } + /** * A monoid for the Unit value. */ From 36a0a784f03730191cf5970433a4e32a8d6c999d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 14 May 2016 00:08:41 +0200 Subject: [PATCH 490/811] Update to latest retrolambda release and gradle plugin. Retro lambda 2.3.0 reduce by ~5% the number of generated methods. --- build.gradle | 6 +++--- lib.gradle | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 3bc75234..2744cd00 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,8 @@ ext { buildscript { ext { uptodateVersion = "1.6.0" - retrolambdaVersion = "3.2.0" + retrolambdaPluginVersion = "3.2.5" + retrolambdaVersion = "2.3.0" } repositories { @@ -18,12 +19,11 @@ buildscript { dependencies { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" - classpath "me.tatarka:gradle-retrolambda:$retrolambdaVersion" + classpath "me.tatarka:gradle-retrolambda:$retrolambdaPluginVersion" classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.6.3' } } - apply plugin: "jacoco" apply plugin: 'com.github.kt3k.coveralls' diff --git a/lib.gradle b/lib.gradle index dbaebe4d..5b84e98b 100644 --- a/lib.gradle +++ b/lib.gradle @@ -90,6 +90,9 @@ void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String ol oldJdk System.getenv(oldJdkEnvVar) javaVersion retroLambdaTarget } + dependencies { + retrolambdaConfig "net.orfjackal.retrolambda:retrolambda:$retrolambdaVersion" + } } } From c7785406ed74b4f31eedb336acf7ab8334154dd7 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 16 May 2016 09:02:42 +1000 Subject: [PATCH 491/811] Fix backwards List#traverseIO Fixes #248 --- core/src/main/java/fj/data/List.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 2d6f7683..36b005f1 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -640,7 +640,7 @@ public P1> traverseP1(final F> f){ public IO> traverseIO(F> f) { return this.foldRight( - (a, acc) -> IOFunctions.bind(acc, (bs) -> IOFunctions.map(f.f(a), b -> bs.cons(b))), + (a, acc) -> IOFunctions.bind(f.f(a), b -> IOFunctions.map(acc, bs -> bs.cons(b))), IOFunctions.unit(List.nil()) ); } From c1565d7b986f5111fb73a412dab0ec4f02742543 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 16 May 2016 16:19:39 +1000 Subject: [PATCH 492/811] Add "ignored" Optional optic --- core/src/main/java/fj/data/optic/Optional.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index de63fc2d..ed737cf0 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -171,6 +171,10 @@ public static Optional id() { return new Optional<>(POptional.pId()); } + public static Optional ignored() { + return optional(s -> Option.none(), a -> s -> s); + } + public static final Optional optional(final F> getOption, final F> set) { return new Optional<>(new POptional() { From 77258ff71237f5d88aad1f833ab799f7021570f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=A4mer?= Date: Mon, 23 May 2016 18:44:00 +1000 Subject: [PATCH 493/811] Fix eager IOW.bind --- core/src/main/java/fj/data/IOW.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java index 5364f49e..8e8960d7 100644 --- a/core/src/main/java/fj/data/IOW.java +++ b/core/src/main/java/fj/data/IOW.java @@ -25,20 +25,11 @@ public A run() throws IOException { return io.run(); } - public IOW map(F f) { - return lift(() -> f.f(io.run())); - } + public IOW map(F f) { return lift(IOFunctions.map(io, f)); } - public IOW bind(F> f) throws IOException { - return lift(f.f(io.run())); - } + public IOW bind(F> f) { return lift(IOFunctions.bind(io, f)); } - public IOW append(IO iob) { - return lift(() -> { - io.run(); - return iob.run(); - }); - } + public IOW append(IO iob) { return lift(IOFunctions.append(io, iob)); } public IOW getContents() { return lift(() -> IOFunctions.getContents().run()); From 47b58b8f1c09ce2f9d875412c6f1c4213cd2dd90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=A4mer?= Date: Tue, 24 May 2016 11:43:41 +1000 Subject: [PATCH 494/811] Provide an IO walkthrough example demonstrating basic composition --- core/src/main/java/fj/data/IOFunctions.java | 7 ++ core/src/main/java/fj/data/IOW.java | 4 + demo/src/main/java/fj/demo/IOWalkthrough.java | 83 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 demo/src/main/java/fj/demo/IOWalkthrough.java diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index dce5d0af..d53caf9a 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -495,6 +495,13 @@ public static IO stdoutPrintln(final String s) { }; } + public static IO stdoutPrint(final String s) { + return () -> { + System.out.print(s); + return Unit.unit(); + }; + } + public static IO getContents() { Stream> s = Stream.>repeat(() -> (int) stdinBufferedReader.read()); return IOFunctions.map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> { diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java index 8e8960d7..4b146cde 100644 --- a/core/src/main/java/fj/data/IOW.java +++ b/core/src/main/java/fj/data/IOW.java @@ -25,6 +25,10 @@ public A run() throws IOException { return io.run(); } + public SafeIO> safe() { + return IOFunctions.toSafeValidation(io); + } + public IOW map(F f) { return lift(IOFunctions.map(io, f)); } public IOW bind(F> f) { return lift(IOFunctions.bind(io, f)); } diff --git a/demo/src/main/java/fj/demo/IOWalkthrough.java b/demo/src/main/java/fj/demo/IOWalkthrough.java new file mode 100644 index 00000000..85c9a7c9 --- /dev/null +++ b/demo/src/main/java/fj/demo/IOWalkthrough.java @@ -0,0 +1,83 @@ +package fj.demo; + +import fj.F; +import fj.F1Functions; +import fj.F1W; +import fj.Unit; +import fj.data.IO; +import fj.data.IOFunctions; +import fj.data.IOW; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import static fj.data.IOFunctions.stdinReadLine; +import static fj.data.IOFunctions.stdoutPrint; +import static fj.data.IOFunctions.stdoutPrintln; +import static fj.data.IOFunctions.toSafeValidation; + +/** + * Demonstrates how to use IO and basic function composition. + */ +public class IOWalkthrough { + public static void main(String[] args) { + + // IO is just a container to defer a computation (lazy), with the intention to encapsulate computations that either + // consume and/or produce side-effects + // the computation is not (yet) executed on creation hence it can be treated like a value + + final IO askName = () -> { + System.out.println("Hi, what's your name?"); + return Unit.unit(); + }; + + // fj.data.IOFunctions contains a lot of convenience functions regarding IO, the above example could be rewritten with IOFunctions.stdoutPrintln + // we now create an IO value to prompt for the name if executed + + IO promptName = IOFunctions.stdoutPrint("Name: "); + + // we can compose these two values with fj.data.IOFunctions.append, since they both are not interested in any runtime value + + IO askAndPromptName = IOFunctions.append(askName, promptName); + + // now we create an IO value to read a line from stdin + + final IO readName = () -> new BufferedReader(new InputStreamReader(System.in)).readLine(); + + // this is the same as IOFunctions.stdinReadLine() + + // now we create a function which takes a string, upper cases it and creates an IO value that would print the upper cased string if executed + + final F> upperCaseAndPrint = F1Functions., String>o(IOFunctions::stdoutPrintln).f(s -> s.toUpperCase()); + + // we now want to compose reading the name with printing it, for that we need to have access to the runtime value that is returned when the + // IO value for read is executed, hence we use fj.data.IOFunctions.bind instead of fj.data.IOFunctions.append + + final IO readAndPrintUpperCasedName = IOFunctions.bind(readName, upperCaseAndPrint); + + // so append is really just a specialised form of bind, ignoring the runtime value of the IO execution that was composed before us + + final IO program = IOFunctions.bind(askAndPromptName, ignored -> readAndPrintUpperCasedName); + + // this is the same as writing IOFunctions.append(askAndPromptName, readAndPrintUpperCasedName) + + // we have recorded the entire program, but have not run anything yet + // now we get to the small dirty part at the end of our program where we actually execute it + // we can either choose to just call program.run(), which allows the execution to escape + // or we use safe to receive an fj.data.Either with the potential exception on the left side + + toSafeValidation(program).run().on((IOException e) -> { e.printStackTrace(); return Unit.unit(); }); + + // doing function composition like this can be quite cumbersome, since you will end up nesting parenthesis unless you flatten it out by + // assigning the functions to variables like above, but you can use the fj.F1W syntax wrapper for composing single-argument functions and fj.data.IOW + // for composing IO values instead, the entire program can be written like so: + + IOW.lift(stdoutPrintln("What's your name again?")) + .append(stdoutPrint("Name: ")) + .append(stdinReadLine()) + .bind(F1W.lift((String s) -> s.toUpperCase()).andThen(IOFunctions::stdoutPrintln)) + .safe().run().on((IOException e) -> { e.printStackTrace(); return Unit.unit(); }); + } +} + From 369986e68bbcd9fa37f9a807e5b3b67dc02980b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Kr=C3=A4mer?= Date: Tue, 24 May 2016 15:24:53 +1000 Subject: [PATCH 495/811] Use instance method reference in IOWalkthrough --- demo/src/main/java/fj/demo/IOWalkthrough.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/src/main/java/fj/demo/IOWalkthrough.java b/demo/src/main/java/fj/demo/IOWalkthrough.java index 85c9a7c9..609d2502 100644 --- a/demo/src/main/java/fj/demo/IOWalkthrough.java +++ b/demo/src/main/java/fj/demo/IOWalkthrough.java @@ -49,7 +49,7 @@ public static void main(String[] args) { // now we create a function which takes a string, upper cases it and creates an IO value that would print the upper cased string if executed - final F> upperCaseAndPrint = F1Functions., String>o(IOFunctions::stdoutPrintln).f(s -> s.toUpperCase()); + final F> upperCaseAndPrint = F1Functions., String>o(IOFunctions::stdoutPrintln).f(String::toUpperCase); // we now want to compose reading the name with printing it, for that we need to have access to the runtime value that is returned when the // IO value for read is executed, hence we use fj.data.IOFunctions.bind instead of fj.data.IOFunctions.append From 74b0fe43f8acd42ad99aaeadd2cf9bd1192d5e8b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 07:33:51 +1000 Subject: [PATCH 496/811] Changes to release 4.5 --- build.gradle | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 2744cd00..e11b2274 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.6" snapshotAppendix = "-SNAPSHOT" @@ -56,7 +56,7 @@ allprojects { fjConsumeVersion = "4.5" signModule = false - useRetroLambda = false + useRetroLambda = true projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/gradle.properties b/gradle.properties index d4552a30..07c2b60c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false +signingEnabled = true From ff6c580256922884d41c867ef3888737cfe68308 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 15 Feb 2016 07:35:36 +1000 Subject: [PATCH 497/811] Increase version to 4.6-SNAPSHOT --- build.gradle | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index e11b2274..2744cd00 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false + isSnapshot = true fjBaseVersion = "4.6" snapshotAppendix = "-SNAPSHOT" @@ -56,7 +56,7 @@ allprojects { fjConsumeVersion = "4.5" signModule = false - useRetroLambda = true + useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From 61708ee4b0a079066271cee038ba5abbe4913470 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 4 Mar 2016 08:12:36 +0100 Subject: [PATCH 498/811] Remove deprecated shallowEqualsO --- core/src/main/java/fj/Equal.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 60fcb86d..23ceffd3 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -544,25 +544,6 @@ public static Equal> treeMapEqual(Equal k, Equal v) { public static Equal> writerEqual(Equal eq1, Equal eq2) { return equal(w1 -> w2 -> p2Equal(eq1, eq2).eq(w1.run(), w2.run())); } - - /** - * @return Returns none if no equality can be determined by checking the nullity and reference values, else the equality - * @deprecated see issue #122. - */ - @Deprecated - public static Option shallowEqualsO(Object o1, Object o2) { - if (o1 == null && o2 == null) { - return Option.some(true); - } else if (o1 == o2) { - return Option.some(true); - } else if (o1 != null && o2 != null) { - java.lang.Class c = o1.getClass(); - // WARNING: this may return some(false) for two instance of same type (and thus comparable) but of different class (typicaly anonymous class instance). - return c.isInstance(o2) ? Option.none() : Option.some(false); - } else { - return Option.some(false); - } - } /** * Helper method to implement {@link Object#equals(Object)} correctly. DO NOT USE it for any other purpose. From 5e6da6f8673ed97a2c99866662f757c2b5088e8c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 4 Mar 2016 22:01:00 +0100 Subject: [PATCH 499/811] Deprecate toJavaArray: unsafe --- core/src/main/java/fj/data/Array.java | 9 ++++++++- core/src/main/java/fj/data/List.java | 9 ++++++++- core/src/main/java/fj/data/Stream.java | 9 ++++++++- core/src/test/java/fj/data/ArrayTest.java | 9 +++++---- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index f24e529c..ea8c7312 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -128,7 +128,14 @@ public Object[] array() { return copyOf(a, a.length); } - @SuppressWarnings("unchecked") + /** + * To be removed in future release: + * affectation of the result of this method to a non generic array + * will result in runtime error (ClassCastException). + * + * @deprecated use {@link #array(Class)} + */ + @Deprecated public A[] toJavaArray() { return (A[]) array(); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 36b005f1..4920e021 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -211,7 +211,14 @@ public final Object[] toArrayObject() { return a; } - @SuppressWarnings("unchecked") + /** + * To be removed in future release: + * affectation of the result of this method to a non generic array + * will result in runtime error (ClassCastException). + * + * @deprecated use {@link #array(Class)} + */ + @Deprecated public final A[] toJavaArray() { return (A[]) toArrayObject(); } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index d21c2f15..2e7ca879 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -916,7 +916,14 @@ public final Option toOption() { return isEmpty() ? Option.none() : some(head()); } - @SuppressWarnings({"unchecked", "UnnecessaryFullyQualifiedName"}) + /** + * To be removed in future release: + * affectation of the result of this method to a non generic array + * will result in runtime error (ClassCastException). + * + * @deprecated use {@link #array(Class)} + */ + @Deprecated public final A[] toJavaArray() { final A[] array = (A[]) new Object[length()]; int i = 0; diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java index e274a00a..886031b3 100644 --- a/core/src/test/java/fj/data/ArrayTest.java +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertThat; /** @@ -11,10 +12,10 @@ public class ArrayTest { @Test - public void toJavaArray() { - final int max = 3; - List list = List.range(1, max + 1); - assertThat(list.toArray().toJavaArray(), equalTo(list.toJavaArray())); + public void array_is_safe() { + List list = List.range(1, 2); + + assertThat(list.toArray().array(Integer[].class), instanceOf(Integer[].class)); } } From 14b7f5c0174ecd0ff99ec224dee73daeef381a74 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 09:37:58 +0100 Subject: [PATCH 500/811] Make non-extendable classes final. --- core/src/main/java/fj/Effect.java | 2 +- core/src/main/java/fj/TryEffect.java | 2 +- core/src/main/java/fj/data/DList.java | 2 +- core/src/main/java/fj/data/IOW.java | 2 +- core/src/main/java/fj/data/State.java | 2 +- core/src/main/java/fj/data/Writer.java | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index aec3e442..387055f1 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -17,7 +17,7 @@ * * @version %build.number% */ -public class Effect { +public final class Effect { private Effect() {} diff --git a/core/src/main/java/fj/TryEffect.java b/core/src/main/java/fj/TryEffect.java index 02d4521f..90acaf06 100644 --- a/core/src/main/java/fj/TryEffect.java +++ b/core/src/main/java/fj/TryEffect.java @@ -10,7 +10,7 @@ /** * Created by mperry on 29/08/2014. */ -public class TryEffect { +public final class TryEffect { private TryEffect(){} diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 2c7856de..3f7b2fe3 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -13,7 +13,7 @@ * * @version %build.number% */ -public class DList { +public final class DList { private final F,Trampoline>> appendFn; private DList(final F,Trampoline>> appendFn) { diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java index 4b146cde..b508456c 100644 --- a/core/src/main/java/fj/data/IOW.java +++ b/core/src/main/java/fj/data/IOW.java @@ -8,7 +8,7 @@ /** * Created by MarkPerry on 9/06/2015. */ -public class IOW implements IO { +public final class IOW implements IO { private IO io; diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 46af5392..14620208 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -9,7 +9,7 @@ /** * Created by MarkPerry on 7/07/2014. */ -public class State { +public final class State { private F> run; diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index 96e449e3..ad55c3ae 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -5,7 +5,7 @@ /** * Created by MarkPerry on 7/07/2014. */ -public class Writer { +public final class Writer { private A val; private W logValue; From 9d2ca349043c673d468c76a4d8c8b3a0781cd12d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 14:17:47 +0100 Subject: [PATCH 501/811] Fix some final modifiers. Add private constructor on utility classes. --- core/src/main/java/fj/Effect.java | 4 +-- core/src/main/java/fj/F1Functions.java | 5 +++- core/src/main/java/fj/F2Functions.java | 7 +++-- core/src/main/java/fj/F3Functions.java | 7 +++-- core/src/main/java/fj/F4Functions.java | 7 +++-- core/src/main/java/fj/F5Functions.java | 5 +++- core/src/main/java/fj/F6Functions.java | 5 +++- core/src/main/java/fj/F7Functions.java | 5 +++- core/src/main/java/fj/F8Functions.java | 5 +++- core/src/main/java/fj/Ord.java | 2 +- core/src/main/java/fj/Try.java | 5 +++- .../main/java/fj/control/parallel/Actor.java | 4 +-- core/src/main/java/fj/data/IOFunctions.java | 29 ++++++++++--------- core/src/main/java/fj/data/Iteratee.java | 16 +++++----- core/src/main/java/fj/data/Seq.java | 4 +-- .../main/java/fj/data/fingertrees/Deep.java | 4 +-- core/src/main/java/fj/data/optic/Fold.java | 2 +- core/src/main/java/fj/data/optic/Getter.java | 4 +-- core/src/main/java/fj/data/optic/Iso.java | 22 +++++++------- core/src/main/java/fj/data/optic/Lens.java | 20 ++++++------- .../src/main/java/fj/data/optic/Optional.java | 22 +++++++------- core/src/main/java/fj/data/optic/PIso.java | 2 +- core/src/main/java/fj/data/optic/PLens.java | 2 +- .../main/java/fj/data/optic/POptional.java | 2 +- core/src/main/java/fj/data/optic/PSetter.java | 4 +-- core/src/main/java/fj/data/optic/Prism.java | 18 ++++++------ core/src/main/java/fj/data/optic/Setter.java | 12 ++++---- .../main/java/fj/data/optic/Traversal.java | 8 ++--- .../java/fj/data/test/PropertyAssert.java | 4 ++- 29 files changed, 134 insertions(+), 102 deletions(-) diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 387055f1..6e5e7b7f 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -33,7 +33,7 @@ public static P1 f(Effect0 e) { * * @return The function using the given effect. */ - public static final F f(Effect1 e1) { + public static F f(Effect1 e1) { return a -> { e1.f(a); return unit(); @@ -95,7 +95,7 @@ public static F5 f(Effect5 z * @param f The function to map over the effect. * @return An effect after a contra-variant map. */ - public static final Effect1 contramap(Effect1 e1, final F f) { + public static Effect1 contramap(Effect1 e1, final F f) { return b -> e1.f(f.f(b)); } diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 2d3c56d4..640b624c 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -18,9 +18,12 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F1Functions { +public final class F1Functions { + private F1Functions() { + } + /** * Function composition * diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index c15a68cb..9ce1cc0a 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -13,10 +13,13 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F2Functions { +public final class F2Functions { - /** + private F2Functions() { + } + + /** * Partial application. * * @param a The A to which to apply this function. diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 62d91aee..77a8fa74 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -9,10 +9,13 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F3Functions { +public final class F3Functions { - /** + private F3Functions() { + } + + /** * Partial application. * * @param a The A to which to apply this function. diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index 71ee56a3..ab57247b 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -6,9 +6,12 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F4Functions { +public final class F4Functions { - /** + private F4Functions() { + } + + /** * Partial application. * * @param a The A to which to apply this function. diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index 8cb26c6d..6345de01 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -6,7 +6,10 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F5Functions { +public final class F5Functions { + + private F5Functions() { + } /** * Partial application. diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 70458593..19269e40 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -6,7 +6,10 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F6Functions { +public final class F6Functions { + + private F6Functions() { + } /** * Partial application. diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index a6ceff9f..4abcb986 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -6,7 +6,10 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F7Functions { +public final class F7Functions { + + private F7Functions() { + } /** * Partial application. diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index 788f106d..5cb9bb3b 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -6,7 +6,10 @@ /** * Created by MarkPerry on 6/04/2014. */ -public class F8Functions { +public final class F8Functions { + + private F8Functions() { + } /** * Partial application. diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index a7a39cac..780f5edf 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -157,7 +157,7 @@ public A min(final A a1, final A a2) { */ public final F> min = curry((a, a1) -> min(a, a1)); - public final Ord reverse() { return ord(Function.flip(f)); } + public Ord reverse() { return ord(Function.flip(f)); } /** * Returns an order instance that uses the given equality test and ordering function. diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index 5ed2673f..c5829b01 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -13,7 +13,10 @@ /** * Created by mperry on 24/07/2014. */ -public class Try { +public final class Try { + + private Try() { + } /** * Promotes the Try0 to a Validation that returns an Exception on the failure side and its result on the success side. diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 77d4fe2d..301f057d 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -69,13 +69,13 @@ public static Actor queueActor(final Strategy s, final Effect1 e } // If there are pending messages, use the strategy to run the processor - protected void work() { + void work() { if (!mbox.isEmpty() && suspended.compareAndSet(true, false)) { s.par(processor); } } }); - }; + } private Actor(final Strategy s, final F> e) { this.s = s; diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index d53caf9a..1a3e93ff 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -26,10 +26,13 @@ * * @author Martin Grotzke */ -public class IOFunctions { +public final class IOFunctions { private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; + private IOFunctions() { + } + public static Try0 toTry(IO io) { return () -> io.run(); } @@ -133,7 +136,7 @@ public static IO fileReader(final File f, final Option encoding }; } - public static final IO bracket(final IO init, final F> fin, final F> body) { + public static IO bracket(final IO init, final F> fin, final F> body) { return new IO() { @Override public C run() throws IOException { @@ -149,7 +152,7 @@ public C run() throws IOException { }; } - public static final IO unit(final A a) { + public static IO unit(final A a) { return new IO() { @Override public A run() throws IOException { @@ -160,19 +163,19 @@ public A run() throws IOException { public static final IO ioUnit = unit(Unit.unit()); - public static final IO lazy(final F0 p) { + public static IO lazy(final F0 p) { return fromF(p); } - public static final IO lazy(final F f) { + public static IO lazy(final F f) { return () -> f.f(Unit.unit()); } - public static final SafeIO lazySafe(final F f) { + public static SafeIO lazySafe(final F f) { return () -> f.f(Unit.unit()); } - public static final SafeIO lazySafe(final F0 f) { + public static SafeIO lazySafe(final F0 f) { return f::f; } @@ -330,7 +333,7 @@ public IterV run() throws IOException { }; } - public static final IO map(final IO io, final F f) { + public static IO map(final IO io, final F f) { return new IO() { @Override public B run() throws IOException { @@ -339,15 +342,15 @@ public B run() throws IOException { }; } - public static final IO as(final IO io, final B b) { + public static IO as(final IO io, final B b) { return map(io, ignored -> b); } - public static final IO voided(final IO io) { + public static IO voided(final IO io) { return as(io, Unit.unit()); } - public static final IO bind(final IO io, final F> f) { + public static IO bind(final IO io, final F> f) { return new IO() { @Override public B run() throws IOException { @@ -356,11 +359,11 @@ public B run() throws IOException { }; } - public static final IO when(final Boolean b, final IO io) { + public static IO when(final Boolean b, final IO io) { return b ? io : ioUnit; } - public static final IO unless(final Boolean b, final IO io) { + public static IO unless(final Boolean b, final IO io) { return when(!b, io); } diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index 9eaeb95e..e4cd3530 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -22,7 +22,7 @@ public static abstract class Input { public abstract Z apply(final F0 empty, final F0> el, final F0 eof); /** Input that has no values available */ - public static final Input empty() { + public static Input empty() { return new Input() { @Override public Z apply(final F0 empty, final F0> el, final F0 eof) { @@ -32,7 +32,7 @@ public Z apply(final F0 empty, final F0> el, final F0 eof) { } /** Input that is exhausted */ - public static final Input eof() { + public static Input eof() { return new Input() { @Override public Z apply(final F0 empty, final F0> el, final F0 eof) { @@ -42,7 +42,7 @@ public Z apply(final F0 empty, final F0> el, final F0 eof) { } /** Input that has a value available */ - public static final Input el(final E element) { + public static Input el(final E element) { return new Input() { @Override public Z apply(final F0 empty, final F0> el, final F0 eof) { @@ -121,7 +121,7 @@ public IterV f(final P2> xe) { } /** An iteratee that counts and consumes the elements of the input */ - public static final IterV length() { + public static IterV length() { final F, IterV>> step = new F, IterV>>() { final F, IterV>> step = this; @@ -141,7 +141,7 @@ public F, IterV> f(final Integer acc) { } /** An iteratee that skips the first n elements of the input */ - public static final IterV drop(final int n) { + public static IterV drop(final int n) { final F, IterV> step = new F, IterV>() { final F, IterV> step = this; @@ -163,7 +163,7 @@ public IterV f(final Input s) { } /** An iteratee that consumes the head of the input */ - public static final IterV> head() { + public static IterV> head() { final F, IterV>> step = new F, IterV>>() { final F, IterV>> step = this; @@ -183,7 +183,7 @@ public IterV> f(final Input s) { } /** An iteratee that returns the first element of the input */ - public static final IterV> peek() { + public static IterV> peek() { final F, IterV>> step = new F, IterV>>() { final F, IterV>> step = this; @@ -204,7 +204,7 @@ public IterV> f(final Input s) { /** An iteratee that consumes the input elements and returns them as a list in reverse order, * so that the last line is the first element. This allows to build a list from 2 iteratees. */ - public static final IterV> list() { + public static IterV> list() { final F, F, IterV>>> step = new F, F, IterV>>>() { final F, F, IterV>>> step = this; diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index a29d97c0..00868ef3 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -214,7 +214,7 @@ public List toList() { /** * Converts the sequence to a java.util.List */ - public final java.util.List toJavaList() { + public java.util.List toJavaList() { return new AbstractList() { @Override public A get(int i) { return index(i); } @Override public Iterator iterator() { return Seq.this.iterator(); } @@ -227,7 +227,7 @@ public final java.util.List toJavaList() { * * @return A iterator for this seq. */ - public final Iterator iterator() { + public Iterator iterator() { return new Iterator() { private FingerTree ftree = Seq.this.ftree; diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index e42bde4d..a33637d8 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -134,14 +134,14 @@ public FingerTree snoc(final A a) { four -> four.values()._4()); } - private static final FingerTree deepL(final Measured measured, final Option> lOpt, final FingerTree> m, final Digit r) { + private static FingerTree deepL(final Measured measured, final Option> lOpt, final FingerTree> m, final Digit r) { return lOpt.option( P.lazy(() -> m.isEmpty() ? r.toTree() : mkTree(measured).deep(m.head().toDigit(), m.tail(), r)), (F, FingerTree>) l -> mkTree(measured).deep(l, m, r) ); } - private static final FingerTree deepR(final Measured measured, final Option> rOpt, final FingerTree> m, final Digit l) { + private static FingerTree deepR(final Measured measured, final Option> rOpt, final FingerTree> m, final Digit l) { return rOpt.option( P.lazy(() -> m.isEmpty() ? l.toTree() : mkTree(measured).deep(l, m.init(), m.last().toDigit())), (F, FingerTree>) r -> mkTree(measured).deep(l, m, r) diff --git a/core/src/main/java/fj/data/optic/Fold.java b/core/src/main/java/fj/data/optic/Fold.java index 94b8aaf6..21aca09f 100644 --- a/core/src/main/java/fj/data/optic/Fold.java +++ b/core/src/main/java/fj/data/optic/Fold.java @@ -110,7 +110,7 @@ public static Fold id() { return PIso. pId().asFold(); } - public static final Fold, A> codiagonal() { + public static Fold, A> codiagonal() { return new Fold, A>() { @Override public F, B> foldMap(final Monoid m, final F f) { diff --git a/core/src/main/java/fj/data/optic/Getter.java b/core/src/main/java/fj/data/optic/Getter.java index b5c60d50..a5c9fa99 100644 --- a/core/src/main/java/fj/data/optic/Getter.java +++ b/core/src/main/java/fj/data/optic/Getter.java @@ -94,11 +94,11 @@ public static Getter id() { return PIso. pId().asGetter(); } - public static final Getter, A> codiagonal() { + public static Getter, A> codiagonal() { return getter(e -> e.either(Function.identity(), Function.identity())); } - public static final Getter getter(final F get) { + public static Getter getter(final F get) { return new Getter() { @Override diff --git a/core/src/main/java/fj/data/optic/Iso.java b/core/src/main/java/fj/data/optic/Iso.java index 71ca7359..ea9babac 100644 --- a/core/src/main/java/fj/data/optic/Iso.java +++ b/core/src/main/java/fj/data/optic/Iso.java @@ -47,32 +47,32 @@ public Iso, P2> second() { /**********************************************************/ /** compose an {@link Iso} with a {@link Setter} */ - public final Setter composeSetter(final Setter other) { + public Setter composeSetter(final Setter other) { return new Setter<>(pIso.composeSetter(other.pSetter)); } /** compose an {@link Iso} with a {@link Traversal} */ - public final Traversal composeTraversal(final Traversal other) { + public Traversal composeTraversal(final Traversal other) { return new Traversal<>(pIso.composeTraversal(other.pTraversal)); } /** compose an {@link Iso} with a {@link Optional} */ - public final Optional composeOptional(final Optional other) { + public Optional composeOptional(final Optional other) { return new Optional<>(pIso.composeOptional(other.pOptional)); } /** compose an {@link Iso} with a {@link Prism} */ - public final Prism composePrism(final Prism other) { + public Prism composePrism(final Prism other) { return new Prism<>(pIso.composePrism(other.pPrism)); } /** compose an {@link Iso} with a {@link Lens} */ - public final Lens composeLens(final Lens other) { + public Lens composeLens(final Lens other) { return asLens().composeLens(other); } /** compose an {@link Iso} with an {@link Iso} */ - public final Iso composeIso(final Iso other) { + public Iso composeIso(final Iso other) { return new Iso<>(pIso.composeIso(other.pIso)); } @@ -82,31 +82,31 @@ public final Iso composeIso(final Iso other) { /** view an {@link Iso} as a {@link Setter} */ @Override - public final Setter asSetter() { + public Setter asSetter() { return new Setter<>(pIso.asSetter()); } /** view an {@link Iso} as a {@link Traversal} */ @Override - public final Traversal asTraversal() { + public Traversal asTraversal() { return new Traversal<>(pIso.asTraversal()); } /** view an {@link Iso} as a {@link Optional} */ @Override - public final Optional asOptional() { + public Optional asOptional() { return new Optional<>(pIso.asOptional()); } /** view an {@link Iso} as a {@link Prism} */ @Override - public final Prism asPrism() { + public Prism asPrism() { return new Prism<>(pIso.asPrism()); } /** view an {@link Iso} as a {@link Lens} */ @Override - public final Lens asLens() { + public Lens asLens() { return new Lens<>(pIso.asLens()); } diff --git a/core/src/main/java/fj/data/optic/Lens.java b/core/src/main/java/fj/data/optic/Lens.java index bb65952b..ceea42c9 100644 --- a/core/src/main/java/fj/data/optic/Lens.java +++ b/core/src/main/java/fj/data/optic/Lens.java @@ -94,7 +94,7 @@ public F modify(final F f) { } /** join two {@link Lens} with the same target */ - public final Lens, A> sum(final Lens other) { + public Lens, A> sum(final Lens other) { return new Lens<>(pLens.sum(other.pLens)); } @@ -105,34 +105,34 @@ public final Lens, A> sum(final Lens other) { /** * compose a {@link Lens} with a {@link Setter} */ - public final Setter composeSetter(final Setter other) { + public Setter composeSetter(final Setter other) { return new Setter<>(pLens.composeSetter(other.pSetter)); } /** * compose a {@link Lens} with a {@link Traversal} */ - public final Traversal composeTraversal(final Traversal other) { + public Traversal composeTraversal(final Traversal other) { return new Traversal<>(pLens.composeTraversal(other.pTraversal)); } /** compose a {@link Lens} with an {@link Optional} */ - public final Optional composeOptional(final Optional other) { + public Optional composeOptional(final Optional other) { return new Optional<>(pLens.composeOptional(other.pOptional)); } /** compose a {@link Lens} with a {@link Prism} */ - public final Optional composePrism(final Prism other) { + public Optional composePrism(final Prism other) { return new Optional<>(pLens.composePrism(other.pPrism)); } /** compose a {@link Lens} with a {@link Lens} */ - public final Lens composeLens(final Lens other) { + public Lens composeLens(final Lens other) { return new Lens<>(pLens.composeLens(other.pLens)); } /** compose a {@link Lens} with an {@link Iso} */ - public final Lens composeIso(final Iso other) { + public Lens composeIso(final Iso other) { return new Lens<>(pLens.composeIso(other.pIso)); } @@ -148,17 +148,17 @@ public Setter asSetter() { /** view a {@link Lens} as a {@link Traversal} */ @Override - public final Traversal asTraversal() { + public Traversal asTraversal() { return new Traversal<>(pLens.asTraversal()); } /** view a {@link Lens} as an {@link Optional} */ @Override - public final Optional asOptional() { + public Optional asOptional() { return new Optional<>(pLens.asOptional()); } - public static final Lens id() { + public static Lens id() { return new Lens<>(PLens.pId()); } diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index ed737cf0..200a952d 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -103,17 +103,17 @@ public Option getOption(final S s) { } /** join two {@link Optional} with the same target */ - public final Optional, A> sum(final Optional other) { + public Optional, A> sum(final Optional other) { return new Optional<>(pOptional.sum(other.pOptional)); } @Override - public final Optional, P2> first() { + public Optional, P2> first() { return new Optional<>(pOptional.first()); } @Override - public final Optional, P2> second() { + public Optional, P2> second() { return new Optional<>(pOptional.second()); } @@ -122,32 +122,32 @@ public final Optional, P2> second() { /**************************************************************/ /** compose a {@link Optional} with a {@link Setter} */ - public final Setter composeSetter(final Setter other) { + public Setter composeSetter(final Setter other) { return new Setter<>(pOptional.composeSetter(other.pSetter)); } /** compose a {@link Optional} with a {@link Traversal} */ - public final Traversal composeTraversal(final Traversal other) { + public Traversal composeTraversal(final Traversal other) { return new Traversal<>(pOptional.composeTraversal(other.pTraversal)); } /** compose a {@link Optional} with a {@link Optional} */ - public final Optional composeOptional(final Optional other) { + public Optional composeOptional(final Optional other) { return new Optional<>(pOptional.composeOptional(other.pOptional)); } /** compose a {@link Optional} with a {@link Prism} */ - public final Optional composePrism(final Prism other) { + public Optional composePrism(final Prism other) { return new Optional<>(pOptional.composePrism(other.pPrism)); } /** compose a {@link Optional} with a {@link Lens} */ - public final Optional composeLens(final Lens other) { + public Optional composeLens(final Lens other) { return new Optional<>(pOptional.composeLens(other.pLens)); } /** compose a {@link Optional} with an {@link Iso} */ - public final Optional composeIso(final Iso other) { + public Optional composeIso(final Iso other) { return new Optional<>(pOptional.composeIso(other.pIso)); } @@ -157,13 +157,13 @@ public final Optional composeIso(final Iso other) { /** view a {@link Optional} as a {@link Setter} */ @Override - public final Setter asSetter() { + public Setter asSetter() { return new Setter<>(pOptional.asSetter()); } /** view a {@link Optional} as a {@link Traversal} */ @Override - public final Traversal asTraversal() { + public Traversal asTraversal() { return new Traversal<>(pOptional.asTraversal()); } diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java index 850dedb6..4ed45ca0 100644 --- a/core/src/main/java/fj/data/optic/PIso.java +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -510,7 +510,7 @@ public F> modifyV2F(final F> f) { } /** create a {@link PIso} using a pair of functions: one to get the target and one to get the source. */ - public static final PIso pIso(final F get, final F reverseGet) { + public static PIso pIso(final F get, final F reverseGet) { return new PIso() { @Override diff --git a/core/src/main/java/fj/data/optic/PLens.java b/core/src/main/java/fj/data/optic/PLens.java index ade9b9e7..68de9079 100644 --- a/core/src/main/java/fj/data/optic/PLens.java +++ b/core/src/main/java/fj/data/optic/PLens.java @@ -418,7 +418,7 @@ public F modify(final F f) { }; } - public static final PLens pId() { + public static PLens pId() { return PIso. pId().asLens(); } diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java index b1b0fa6e..92e4edf0 100644 --- a/core/src/main/java/fj/data/optic/POptional.java +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -366,7 +366,7 @@ public static POptional pId() { } /** create a {@link POptional} using the canonical functions: getOrModify and set */ - public static final POptional pOptional(final F> getOrModify, final F> set) { + public static POptional pOptional(final F> getOrModify, final F> set) { return new POptional() { @Override public Either getOrModify(final S s) { diff --git a/core/src/main/java/fj/data/optic/PSetter.java b/core/src/main/java/fj/data/optic/PSetter.java index ad8e3ea8..012920cb 100644 --- a/core/src/main/java/fj/data/optic/PSetter.java +++ b/core/src/main/java/fj/data/optic/PSetter.java @@ -84,11 +84,11 @@ public static PSetter pId() { return PIso. pId().asSetter(); } - public static final PSetter, Either, S, T> pCodiagonal() { + public static PSetter, Either, S, T> pCodiagonal() { return pSetter(f -> e -> e.bimap(f, f)); } - public static final PSetter pSetter(final F, F> modify) { + public static PSetter pSetter(final F, F> modify) { return new PSetter() { @Override public F modify(final F f) { diff --git a/core/src/main/java/fj/data/optic/Prism.java b/core/src/main/java/fj/data/optic/Prism.java index 409bfc6d..42decaaf 100644 --- a/core/src/main/java/fj/data/optic/Prism.java +++ b/core/src/main/java/fj/data/optic/Prism.java @@ -35,32 +35,32 @@ public Option getOption(final S s) { /***********************************************************/ /** compose a {@link Prism} with a {@link Setter} */ - public final Setter composeSetter(final Setter other) { + public Setter composeSetter(final Setter other) { return new Setter<>(pPrism.composeSetter(other.pSetter)); } /** compose a {@link Prism} with a {@link Traversal} */ - public final Traversal composeTraversal(final Traversal other) { + public Traversal composeTraversal(final Traversal other) { return new Traversal<>(pPrism.composeTraversal(other.pTraversal)); } /** compose a {@link Prism} with a {@link Optional} */ - public final Optional composeOptional(final Optional other) { + public Optional composeOptional(final Optional other) { return new Optional<>(pPrism.composeOptional(other.pOptional)); } /** compose a {@link Prism} with a {@link Lens} */ - public final Optional composeLens(final Lens other) { + public Optional composeLens(final Lens other) { return new Optional<>(pPrism.composeLens(other.pLens)); } /** compose a {@link Prism} with a {@link Prism} */ - public final Prism composePrism(final Prism other) { + public Prism composePrism(final Prism other) { return new Prism<>(pPrism.composePrism(other.pPrism)); } /** compose a {@link Prism} with an {@link Iso} */ - public final Prism composeIso(final Iso other) { + public Prism composeIso(final Iso other) { return new Prism<>(pPrism.composeIso(other.pIso)); } @@ -70,19 +70,19 @@ public final Prism composeIso(final Iso other) { /** view a {@link Prism} as a {@link Setter} */ @Override - public final Setter asSetter() { + public Setter asSetter() { return new Setter<>(pPrism.asSetter()); } /** view a {@link Prism} as a {@link Traversal} */ @Override - public final Traversal asTraversal() { + public Traversal asTraversal() { return new Traversal<>(pPrism.asTraversal()); } /** view a {@link Prism} as a {@link Optional} */ @Override - public final Optional asOptional() { + public Optional asOptional() { return new Optional<>(pPrism.asOptional()); } diff --git a/core/src/main/java/fj/data/optic/Setter.java b/core/src/main/java/fj/data/optic/Setter.java index 40fc8473..95227f10 100644 --- a/core/src/main/java/fj/data/optic/Setter.java +++ b/core/src/main/java/fj/data/optic/Setter.java @@ -23,7 +23,7 @@ public F set(final A b) { } /** join two {@link Setter} with the same target */ - public final Setter, A> sum(final Setter other) { + public Setter, A> sum(final Setter other) { return new Setter<>(pSetter.sum(other.pSetter)); } @@ -32,17 +32,17 @@ public final Setter, A> sum(final Setter other) { /************************************************************/ /** compose a {@link Setter} with a {@link Setter} */ - public final Setter composeSetter(final Setter other) { + public Setter composeSetter(final Setter other) { return new Setter<>(pSetter.composeSetter(other.pSetter)); } /** compose a {@link Setter} with a {@link Traversal} */ - public final Setter composeTraversal(final Traversal other) { + public Setter composeTraversal(final Traversal other) { return new Setter<>(pSetter.composeTraversal(other.pTraversal)); } /** compose a {@link Setter} with an {@link Iso} */ - public final Setter composeIso(final Iso other) { + public Setter composeIso(final Iso other) { return new Setter<>(pSetter.composeIso(other.pIso)); } @@ -50,12 +50,12 @@ public static Setter id() { return new Setter<>(PSetter.pId()); } - public static final Setter, S> codiagonal() { + public static Setter, S> codiagonal() { return new Setter<>(PSetter.pCodiagonal()); } /** alias for {@link PSetter} constructor with a monomorphic modify function */ - public static final Setter setter(final F, F> modify) { + public static Setter setter(final F, F> modify) { return new Setter<>(PSetter.pSetter(modify)); } } diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java index 756a95ed..4064385e 100644 --- a/core/src/main/java/fj/data/optic/Traversal.java +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -87,7 +87,7 @@ public F foldMap(final Monoid monoid, final F f) { } /** join two {@link Traversal} with the same target */ - public final Traversal, A> sum(final Traversal other) { + public Traversal, A> sum(final Traversal other) { return new Traversal<>(pTraversal.sum(other.pTraversal)); } @@ -96,12 +96,12 @@ public final Traversal, A> sum(final Traversal other) /***************************************************************/ /** compose a {@link Traversal} with a {@link Setter} */ - public final Setter composeSetter(final Setter other) { + public Setter composeSetter(final Setter other) { return new Setter<>(pTraversal.composeSetter(other.pSetter)); } /** compose a {@link Traversal} with a {@link Traversal} */ - public final Traversal composeTraversal(final Traversal other) { + public Traversal composeTraversal(final Traversal other) { return new Traversal<>(pTraversal.composeTraversal(other.pTraversal)); } @@ -111,7 +111,7 @@ public final Traversal composeTraversal(final Traversal other) { /** view a {@link Traversal} as a {@link Setter} */ @Override - public final Setter asSetter() { + public Setter asSetter() { return new Setter<>(pTraversal.asSetter()); } diff --git a/quickcheck/src/main/java/fj/data/test/PropertyAssert.java b/quickcheck/src/main/java/fj/data/test/PropertyAssert.java index bec07f7f..00187b15 100644 --- a/quickcheck/src/main/java/fj/data/test/PropertyAssert.java +++ b/quickcheck/src/main/java/fj/data/test/PropertyAssert.java @@ -8,7 +8,9 @@ /** * Created by MarkPerry on 18/12/2014. */ -public class PropertyAssert { +public final class PropertyAssert { + + private PropertyAssert(){} public static Unit assertResult(Property p) { CheckResult cr = p.check(); From 9eaabfafa0588142555d5976e11b57d43cf3d0c2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 17:07:19 +0100 Subject: [PATCH 502/811] Make instance fields final when possible --- core/src/main/java/fj/control/parallel/Actor.java | 6 +++--- core/src/main/java/fj/data/IOW.java | 2 +- core/src/main/java/fj/data/Reader.java | 2 +- core/src/main/java/fj/data/State.java | 2 +- core/src/main/java/fj/data/Writer.java | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index 301f057d..bd1956bd 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -36,14 +36,14 @@ public static Actor queueActor(final Strategy s, final Effect1 e return actor(Strategy.seqStrategy(), new Effect1() { // Lock to ensure the actor only acts on one message at a time - AtomicBoolean suspended = new AtomicBoolean(true); + final AtomicBoolean suspended = new AtomicBoolean(true); // Queue to hold pending messages - ConcurrentLinkedQueue mbox = new ConcurrentLinkedQueue(); + final ConcurrentLinkedQueue mbox = new ConcurrentLinkedQueue(); // Product so the actor can use its strategy (to act on messages in other threads, // to handle exceptions, etc.) - P1 processor = new P1() { + final P1 processor = new P1() { @Override public Unit _1() { // get next item from queue T a = mbox.poll(); diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java index b508456c..8b1b2ac6 100644 --- a/core/src/main/java/fj/data/IOW.java +++ b/core/src/main/java/fj/data/IOW.java @@ -10,7 +10,7 @@ */ public final class IOW implements IO { - private IO io; + private final IO io; private IOW(IO in) { io = in; diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index 34a98c72..749f4c9b 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -9,7 +9,7 @@ */ public class Reader { - private F function; + private final F function; public Reader(F f) { function = f; diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 14620208..c54d6cb7 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -11,7 +11,7 @@ */ public final class State { - private F> run; + private final F> run; private State(F> f) { run = f; diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index ad55c3ae..7ff57d07 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -7,9 +7,9 @@ */ public final class Writer { - private A val; - private W logValue; - private Monoid monoid; + private final A val; + private final W logValue; + private final Monoid monoid; private Writer(A a, W w, Monoid m) { val = a; From 2b8c1af39c515beb79fd63e34cb66cbfe9913b7a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 17:08:38 +0100 Subject: [PATCH 503/811] Correct order of modifiers according to JLS --- core/src/main/java/fj/F1Functions.java | 136 +++++++++--------- core/src/main/java/fj/F2Functions.java | 52 +++---- core/src/main/java/fj/F3Functions.java | 2 +- core/src/main/java/fj/F4Functions.java | 2 +- core/src/main/java/fj/F5Functions.java | 2 +- core/src/main/java/fj/F6Functions.java | 2 +- core/src/main/java/fj/F7Functions.java | 2 +- core/src/main/java/fj/F8Functions.java | 2 +- core/src/main/java/fj/Try.java | 16 +-- core/src/main/java/fj/control/Trampoline.java | 2 +- core/src/main/java/fj/data/Conversions.java | 2 +- core/src/main/java/fj/data/Iteratee.java | 4 +- java8/src/main/java/fj/data/Java8.java | 36 ++--- 13 files changed, 130 insertions(+), 130 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 640b624c..5821a893 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -30,7 +30,7 @@ private F1Functions() { * @param g A function to compose with this one. * @return The composed function such that this function is applied last. */ - static public F o(final F f, final F g) { + public static F o(final F f, final F g) { return c -> f.f(g.f(c)); } @@ -39,7 +39,7 @@ static public F o(final F f, final F g) { * * @return A function that composes this function with another. */ - static public F, F> o(final F f) { + public static F, F> o(final F f) { return g -> o(f, g); } @@ -50,7 +50,7 @@ static public F, F> o(final F f) { * @return The composed function such that this function is applied first. */ @SuppressWarnings({"unchecked"}) - static public F andThen(final F f, final F g) { + public static F andThen(final F f, final F g) { return o(g, f); } @@ -59,7 +59,7 @@ static public F andThen(final F f, final F g) { * * @return A function that invokes this function and then a given function on the result. */ - static public F, F> andThen(final F f) { + public static F, F> andThen(final F f) { return g -> andThen(f, g); } @@ -69,7 +69,7 @@ static public F, F> andThen(final F f) { * @param g A function that takes the return value of this function as an argument, yielding a new function. * @return A function that invokes this function on its argument and then the given function on the result. */ - static public F bind(final F f, final F> g) { + public static F bind(final F f, final F> g) { return a -> g.f(f.f(a)).f(a); } @@ -78,7 +78,7 @@ static public F bind(final F f, final F> g) { * * @return A function that binds another function across this function. */ - static public F>, F> bind(final F f) { + public static F>, F> bind(final F f) { return g -> bind(f, g); } @@ -90,7 +90,7 @@ static public F>, F> bind(final F f) { * @return A new function that invokes the given function on its argument, yielding a new function that is then * applied to the result of applying this function to the argument. */ - static public F apply(final F f, final F> g) { + public static F apply(final F f, final F> g) { return a -> g.f(a).f(f.f(a)); } @@ -99,7 +99,7 @@ static public F apply(final F f, final F> g) { * * @return A function that applies a given function within the environment of this function. */ - static public F>, F> apply(final F f) { + public static F>, F> apply(final F f) { return g -> apply(f, g); } @@ -109,7 +109,7 @@ static public F>, F> apply(final F f) { * @param g The function over whose arguments to apply this function. * @return A new function that invokes this function on its arguments before invoking the given function. */ - static public F> on(final F f, final F> g) { + public static F> on(final F f, final F> g) { return a1 -> a2 -> g.f(f.f(a1)).f(f.f(a2)); } @@ -120,7 +120,7 @@ static public F> on(final F f, final F> g) * * @return A function that applies this function over the arguments of another function. */ - static public F>, F>> on(final F f) { + public static F>, F>> on(final F f) { return g -> on(f, g); } @@ -129,7 +129,7 @@ static public F>, F>> on(final F f) { * * @return This function promoted to return its result in a product-1. */ - static public F> lazy(final F f) { + public static F> lazy(final F f) { return a -> P.lazy(() -> f.f(a)); } @@ -139,7 +139,7 @@ static public F> lazy(final F f) { * @param a The A to which to apply this function. * @return The function partially applied to the given argument to return a lazy value. */ - static public P1 f(final F f, final A a) { + public static P1 f(final F f, final A a) { return P.lazy(() -> f.f(a)); } @@ -148,7 +148,7 @@ static public P1 f(final F f, final A a) { * * @return This function promoted to map over a product-1. */ - static public F, P1> mapP1(final F f) { + public static F, P1> mapP1(final F f) { return p -> p.map(f); } @@ -157,7 +157,7 @@ static public F, P1> mapP1(final F f) { * * @return This function promoted to return its result in an Option. */ - static public F> optionK(final F f) { + public static F> optionK(final F f) { return a -> some(f.f(a)); } @@ -166,7 +166,7 @@ static public F> optionK(final F f) { * * @return This function promoted to map over an optional value. */ - static public F, Option> mapOption(final F f) { + public static F, Option> mapOption(final F f) { return o -> o.map(f); } @@ -175,7 +175,7 @@ static public F, Option> mapOption(final F f) { * * @return This function promoted to return its result in a List. */ - static public F> listK(final F f) { + public static F> listK(final F f) { return a -> List.single(f.f(a)); } @@ -184,7 +184,7 @@ static public F> listK(final F f) { * * @return This function promoted to map over a List. */ - static public F, List> mapList(final F f) { + public static F, List> mapList(final F f) { return x -> x.map(f); } @@ -193,7 +193,7 @@ static public F, List> mapList(final F f) { * * @return This function promoted to return its result in a Stream. */ - static public F> streamK(final F f) { + public static F> streamK(final F f) { return a -> Stream.single(f.f(a)); } @@ -202,7 +202,7 @@ static public F> streamK(final F f) { * * @return This function promoted to map over a Stream. */ - static public F, Stream> mapStream(final F f) { + public static F, Stream> mapStream(final F f) { return x -> x.map(f); } @@ -211,7 +211,7 @@ static public F, Stream> mapStream(final F f) { * * @return This function promoted to return its result in a Array. */ - static public F> arrayK(final F f) { + public static F> arrayK(final F f) { return a -> Array.single(f.f(a)); } @@ -221,7 +221,7 @@ static public F> arrayK(final F f) { * * @return This function promoted to map over a Array. */ - static public F, Array> mapArray(final F f) { + public static F, Array> mapArray(final F f) { return x -> x.map(f); } @@ -230,7 +230,7 @@ static public F, Array> mapArray(final F f) { * * @return A function that contramaps over a given actor. */ - static public F, Actor> contramapActor(final F f) { + public static F, Actor> contramapActor(final F f) { return a -> a.contramap(f); } @@ -240,7 +240,7 @@ static public F, Actor> contramapActor(final F f) { * @param s A parallel strategy for concurrent execution. * @return A concurrent function that returns a Promise of a value. */ - static public F> promiseK(final F f, final Strategy s) { + public static F> promiseK(final F f, final Strategy s) { return Promise.promise(s, f); } @@ -249,7 +249,7 @@ static public F> promiseK(final F f, final Strategy F, Promise> mapPromise(final F f) { + public static F, Promise> mapPromise(final F f) { return p -> p.fmap(f); } @@ -260,7 +260,7 @@ static public F, Promise> mapPromise(final F f) { * @return This function promoted to return its result on the left side of an Either. */ @SuppressWarnings({"unchecked"}) - static public F> eitherLeftK(final F f) { + public static F> eitherLeftK(final F f) { return o(Either.left_(), f); } @@ -271,7 +271,7 @@ static public F> eitherLeftK(final F f) { * @return This function promoted to return its result on the right side of an Either. */ @SuppressWarnings({"unchecked"}) - static public F> eitherRightK(final F f) { + public static F> eitherRightK(final F f) { return o(Either.right_(), f); } @@ -281,7 +281,7 @@ static public F> eitherRightK(final F f) { * @return This function promoted to map over the left side of an Either. */ @SuppressWarnings({"unchecked"}) - static public F, Either> mapLeft(final F f) { + public static F, Either> mapLeft(final F f) { return Either.leftMap_().f(f); } @@ -291,7 +291,7 @@ static public F, Either> mapLeft(final F f) { * @return This function promoted to map over the right side of an Either. */ @SuppressWarnings({"unchecked"}) - static public F, Either> mapRight(final F f) { + public static F, Either> mapRight(final F f) { return Either.rightMap_().f(f); } @@ -300,7 +300,7 @@ static public F, Either> mapRight(final F f) * * @return a function that returns the left side of a given Either, or this function applied to the right side. */ - static public F, B> onLeft(final F f) { + public static F, B> onLeft(final F f) { return e -> e.left().on(f); } @@ -309,7 +309,7 @@ static public F, B> onLeft(final F f) { * * @return a function that returns the right side of a given Either, or this function applied to the left side. */ - static public F, B> onRight(final F f) { + public static F, B> onRight(final F f) { return e -> e.right().on(f); } @@ -319,7 +319,7 @@ static public F, B> onRight(final F f) { * @return This function promoted to return its value in an Iterable. */ @SuppressWarnings({"unchecked"}) - static public F> iterableK(final F f) { + public static F> iterableK(final F f) { return IterableW.arrow().f(f); } @@ -329,7 +329,7 @@ static public F> iterableK(final F f) { * @return This function promoted to map over Iterables. */ @SuppressWarnings({"unchecked"}) - static public F, IterableW> mapIterable(final F f) { + public static F, IterableW> mapIterable(final F f) { return F1Functions.o(IterableW.map().f(f), IterableW.>wrap()); } @@ -339,7 +339,7 @@ static public F, IterableW> mapIterable(final F f) { * @return This function promoted to return its value in a NonEmptyList. */ @SuppressWarnings({"unchecked"}) - static public F> nelK(final F f) { + public static F> nelK(final F f) { return o(NonEmptyList.nel(), f); } @@ -348,7 +348,7 @@ static public F> nelK(final F f) { * * @return This function promoted to map over a NonEmptyList. */ - static public F, NonEmptyList> mapNel(final F f) { + public static F, NonEmptyList> mapNel(final F f) { return list -> list.map(f); } @@ -358,7 +358,7 @@ static public F, NonEmptyList> mapNel(final F f) * @param o An order for the set. * @return This function promoted to return its value in a Set. */ - static public F> setK(final F f, final Ord o + public static F> setK(final F f, final Ord o ) { return a -> Set.single(o, f.f(a)); } @@ -369,7 +369,7 @@ static public F> setK(final F f, final Ord o * @param o An order for the resulting set. * @return This function promoted to map over a Set. */ - static public F, Set> mapSet(final F f, final Ord o) { + public static F, Set> mapSet(final F f, final Ord o) { return s -> s.map(o, f); } @@ -378,7 +378,7 @@ static public F, Set> mapSet(final F f, final Ord o) { * * @return This function promoted to return its value in a Tree. */ - static public F> treeK(final F f) { + public static F> treeK(final F f) { return a -> Tree.leaf(f.f(a)); } @@ -388,7 +388,7 @@ static public F> treeK(final F f) { * @return This function promoted to map over a Tree. */ @SuppressWarnings({"unchecked"}) - static public F, Tree> mapTree(final F f) { + public static F, Tree> mapTree(final F f) { return Tree.fmap_().f(f); } @@ -398,7 +398,7 @@ static public F, Tree> mapTree(final F f) { * @param m The monoid with which to fold the mapped tree. * @return a function that maps this function over a tree and folds it with the given monoid. */ - static public F, B> foldMapTree(final F f, final Monoid m) { + public static F, B> foldMapTree(final F f, final Monoid m) { return Tree.foldMap_(f, m); } @@ -407,7 +407,7 @@ static public F, B> foldMapTree(final F f, final Monoid * * @return This function promoted to return its value in a TreeZipper. */ - static public F> treeZipperK(final F f) { + public static F> treeZipperK(final F f) { return andThen(treeK(f), TreeZipper.fromTree()); } @@ -416,7 +416,7 @@ static public F> treeZipperK(final F f) { * * @return This function promoted to map over a TreeZipper. */ - static public F, TreeZipper> mapTreeZipper(final F f) { + public static F, TreeZipper> mapTreeZipper(final F f) { return (z) -> z.map(f); } @@ -426,7 +426,7 @@ static public F, TreeZipper> mapTreeZipper(final F * * @return This function promoted to return its result on the failure side of a Validation. */ - static public F> failK(final F f) { + public static F> failK(final F f) { return a -> Validation.fail(f.f(a)); } @@ -437,7 +437,7 @@ static public F> failK(final F f) { * * @return This function promoted to return its result on the success side of an Validation. */ - static public F> successK(final F f) { + public static F> successK(final F f) { return a -> Validation.success(f.f(a)); } @@ -446,7 +446,7 @@ static public F> successK(final F f) { * * @return This function promoted to map over the failure side of a Validation. */ - static public F, Validation> mapFail(final F f) { + public static F, Validation> mapFail(final F f) { return v -> v.f().map(f); } @@ -455,7 +455,7 @@ static public F, Validation> mapFail(final F F, Validation> mapSuccess(final F f) { + public static F, Validation> mapSuccess(final F f) { return v -> v.map(f); } @@ -466,7 +466,7 @@ static public F, Validation> mapSuccess(final F * @return a function that returns the failure side of a given Validation, * or this function applied to the success side. */ - static public F, B> onFail(final F f) { + public static F, B> onFail(final F f) { return v -> v.f().on(f); } @@ -477,7 +477,7 @@ static public F, B> onFail(final F f) { * @return a function that returns the success side of a given Validation, * or this function applied to the failure side. */ - static public F, B> onSuccess(final F f) { + public static F, B> onSuccess(final F f) { return v -> v.on(f); } @@ -486,7 +486,7 @@ static public F, B> onSuccess(final F f) { * * @return This function promoted to return its value in a Zipper. */ - static public F> zipperK(final F f) { + public static F> zipperK(final F f) { return andThen(streamK(f), s -> fromStream(s).some()); } @@ -495,7 +495,7 @@ static public F> zipperK(final F f) { * * @return This function promoted to map over a Zipper. */ - static public F, Zipper> mapZipper(final F f) { + public static F, Zipper> mapZipper(final F f) { return z -> z.map(f); } @@ -504,7 +504,7 @@ static public F, Zipper> mapZipper(final F f) { * * @return This function promoted to map over an Equal as a contravariant functor. */ - static public F, Equal> contramapEqual(final F f) { + public static F, Equal> contramapEqual(final F f) { return e -> e.contramap(f); } @@ -513,7 +513,7 @@ static public F, Equal> contramapEqual(final F f) { * * @return This function promoted to map over a Hash as a contravariant functor. */ - static public F, Hash> contramapHash(final F f) { + public static F, Hash> contramapHash(final F f) { return h -> h.contramap(f); } @@ -522,7 +522,7 @@ static public F, Hash> contramapHash(final F f) { * * @return This function promoted to map over a Show as a contravariant functor. */ - static public F, Show> contramapShow(final F f) { + public static F, Show> contramapShow(final F f) { return s -> s.contramap(f); } @@ -531,7 +531,7 @@ static public F, Show> contramapShow(final F f) { * * @return This function promoted to map over the first element of a pair. */ - static public F, P2> mapFst(final F f) { + public static F, P2> mapFst(final F f) { return P2.map1_(f); } @@ -540,7 +540,7 @@ static public F, P2> mapFst(final F f) { * * @return This function promoted to map over the second element of a pair. */ - static public F, P2> mapSnd(final F f) { + public static F, P2> mapSnd(final F f) { return P2.map2_(f); } @@ -549,7 +549,7 @@ static public F, P2> mapSnd(final F f) { * * @return This function promoted to map over both elements of a pair. */ - static public F, P2> mapBoth(final F f) { + public static F, P2> mapBoth(final F f) { return p2 -> P2.map(f, p2); } @@ -559,7 +559,7 @@ static public F, P2> mapBoth(final F f) { * @param as A SynchronousQueue to map this function over. * @return A new SynchronousQueue with this function applied to each element. */ - static public SynchronousQueue mapJ(final F f, final SynchronousQueue as) { + public static SynchronousQueue mapJ(final F f, final SynchronousQueue as) { final SynchronousQueue bs = new SynchronousQueue(); bs.addAll(iterableStream(as).map(f).toCollection()); return bs; @@ -572,7 +572,7 @@ static public SynchronousQueue mapJ(final F f, final Synchronous * @param as A PriorityBlockingQueue to map this function over. * @return A new PriorityBlockingQueue with this function applied to each element. */ - static public PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { + public static PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { return new PriorityBlockingQueue(iterableStream(as).map(f).toCollection()); } @@ -582,7 +582,7 @@ static public PriorityBlockingQueue mapJ(final F f, final Priori * @param as A LinkedBlockingQueue to map this function over. * @return A new LinkedBlockingQueue with this function applied to each element. */ - static public LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { + public static LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { return new LinkedBlockingQueue(iterableStream(as).map(f).toCollection()); } @@ -592,7 +592,7 @@ static public LinkedBlockingQueue mapJ(final F f, final LinkedBl * @param as A CopyOnWriteArraySet to map this function over. * @return A new CopyOnWriteArraySet with this function applied to each element. */ - static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { + public static CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { return new CopyOnWriteArraySet(iterableStream(as).map(f).toCollection()); } @@ -602,7 +602,7 @@ static public CopyOnWriteArraySet mapJ(final F f, final CopyOnWr * @param as A CopyOnWriteArrayList to map this function over. * @return A new CopyOnWriteArrayList with this function applied to each element. */ - static public CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { + public static CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { return new CopyOnWriteArrayList(iterableStream(as).map(f).toCollection()); } @@ -612,7 +612,7 @@ static public CopyOnWriteArrayList mapJ(final F f, final CopyOnW * @param as A ConcurrentLinkedQueue to map this function over. * @return A new ConcurrentLinkedQueue with this function applied to each element. */ - static public ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { + public static ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { return new ConcurrentLinkedQueue(iterableStream(as).map(f).toCollection()); } @@ -622,7 +622,7 @@ static public ConcurrentLinkedQueue mapJ(final F f, final Concur * @param as An ArrayBlockingQueue to map this function over. * @return A new ArrayBlockingQueue with this function applied to each element. */ - static public ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { + public static ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); bs.addAll(iterableStream(as).map(f).toCollection()); return bs; @@ -635,7 +635,7 @@ static public ArrayBlockingQueue mapJ(final F f, final ArrayBloc * @param as A TreeSet to map this function over. * @return A new TreeSet with this function applied to each element. */ - static public TreeSet mapJ(final F f, final TreeSet as) { + public static TreeSet mapJ(final F f, final TreeSet as) { return new TreeSet(iterableStream(as).map(f).toCollection()); } @@ -645,7 +645,7 @@ static public TreeSet mapJ(final F f, final TreeSet as) { * @param as A PriorityQueue to map this function over. * @return A new PriorityQueue with this function applied to each element. */ - static public PriorityQueue mapJ(final F f, final PriorityQueue as) { + public static PriorityQueue mapJ(final F f, final PriorityQueue as) { return new PriorityQueue(iterableStream(as).map(f).toCollection()); } @@ -655,7 +655,7 @@ static public PriorityQueue mapJ(final F f, final PriorityQueue< * @param as A LinkedList to map this function over. * @return A new LinkedList with this function applied to each element. */ - static public LinkedList mapJ(final F f, final LinkedList as) { + public static LinkedList mapJ(final F f, final LinkedList as) { return new LinkedList(iterableStream(as).map(f).toCollection()); } @@ -665,15 +665,15 @@ static public LinkedList mapJ(final F f, final LinkedList as) * @param as An ArrayList to map this function over. * @return A new ArrayList with this function applied to each element. */ - static public ArrayList mapJ(final F f, final ArrayList as) { + public static ArrayList mapJ(final F f, final ArrayList as) { return new ArrayList(iterableStream(as).map(f).toCollection()); } - static public F map(F target, F f) { + public static F map(F target, F f) { return andThen(target, f); } - static public F contramap(F target, F f) { + public static F contramap(F target, F f) { return andThen(f, target); } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java index 9ce1cc0a..f69e02ed 100644 --- a/core/src/main/java/fj/F2Functions.java +++ b/core/src/main/java/fj/F2Functions.java @@ -25,7 +25,7 @@ private F2Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F f(final F2 f, final A a) { + public static F f(final F2 f, final A a) { return b -> f.f(a, b); } @@ -34,7 +34,7 @@ static public F f(final F2 f, final A a) { * * @return a wrapped function of arity-1 that returns another wrapped function. */ - static public F> curry(final F2 f) { + public static F> curry(final F2 f) { return a -> b -> f.f(a, b); } @@ -43,7 +43,7 @@ static public F> curry(final F2 f) { * * @return A new function with the arguments of this function flipped. */ - static public F2 flip(final F2 f) { + public static F2 flip(final F2 f) { return (b, a) -> f.f(a, b); } @@ -52,7 +52,7 @@ static public F2 flip(final F2 f) { * * @return A new function that calls this function with the elements of a given tuple. */ - static public F, C> tuple(final F2 f) { + public static F, C> tuple(final F2 f) { return p -> f.f(p._1(), p._2()); } @@ -61,7 +61,7 @@ static public F, C> tuple(final F2 f) { * * @return This function promoted to transform Arrays. */ - static public F2, Array, Array> arrayM(final F2 f) { + public static F2, Array, Array> arrayM(final F2 f) { return (a, b) -> a.bind(b, curry(f)); } @@ -70,7 +70,7 @@ static public F2, Array, Array> arrayM(final F2 F2, Promise, Promise> promiseM(final F2 f) { + public static F2, Promise, Promise> promiseM(final F2 f) { return (a, b) -> a.bind(b, curry(f)); } @@ -79,7 +79,7 @@ static public F2, Promise, Promise> promiseM(final F2 * * @return This function promoted to transform Iterables. */ - static public F2, Iterable, IterableW> iterableM(final F2 f) { + public static F2, Iterable, IterableW> iterableM(final F2 f) { return (a, b) -> IterableW.liftM2(curry(f)).f(a).f(b); } @@ -88,7 +88,7 @@ static public F2, Iterable, IterableW> iterableM(fin * * @return This function promoted to transform Lists. */ - static public F2, List, List> listM(final F2 f) { + public static F2, List, List> listM(final F2 f) { return (a, b) -> List.liftM2(curry(f)).f(a).f(b); } @@ -97,7 +97,7 @@ static public F2, List, List> listM(final F2 f) * * @return This function promoted to transform non-empty lists. */ - static public F2, NonEmptyList, NonEmptyList> nelM(final F2 f) { + public static F2, NonEmptyList, NonEmptyList> nelM(final F2 f) { return (as, bs) -> NonEmptyList.fromList(as.toList().bind(bs.toList(), f)).some(); } @@ -106,7 +106,7 @@ static public F2, NonEmptyList, NonEmptyList> ne * * @return This function promoted to transform Options. */ - static public F2, Option, Option> optionM(final F2 f) { + public static F2, Option, Option> optionM(final F2 f) { return (a, b) -> Option.liftM2(curry(f)).f(a).f(b); } @@ -116,7 +116,7 @@ static public F2, Option, Option> optionM(final F2 F2, Set, Set> setM(final F2 f, final Ord o) { + public static F2, Set, Set> setM(final F2 f, final Ord o) { return (as, bs) -> { Set cs = Set.empty(o); for (final A a : as) @@ -131,7 +131,7 @@ static public F2, Set, Set> setM(final F2 f, fin * * @return This function promoted to transform Streams. */ - static public F2, Stream, Stream> streamM(final F2 f) { + public static F2, Stream, Stream> streamM(final F2 f) { return (as, bs) -> as.bind(bs, f); } @@ -140,7 +140,7 @@ static public F2, Stream, Stream> streamM(final F2 F2, Tree, Tree> treeM(final F2 f) { + public static F2, Tree, Tree> treeM(final F2 f) { return new F2, Tree, Tree>() { public Tree f(final Tree as, final Tree bs) { final F2, Tree, Tree> self = this; @@ -154,7 +154,7 @@ public Tree f(final Tree as, final Tree bs) { * * @return A function that zips two arrays with this function. */ - static public F2, Array, Array> zipArrayM(final F2 f) { + public static F2, Array, Array> zipArrayM(final F2 f) { return (as, bs) -> as.zipWith(bs, f); } @@ -163,7 +163,7 @@ static public F2, Array, Array> zipArrayM(final F2 F2, Iterable, Iterable> zipIterableM(final F2 f) { + public static F2, Iterable, Iterable> zipIterableM(final F2 f) { return (as, bs) -> wrap(as).zipWith(bs, f); } @@ -172,7 +172,7 @@ static public F2, Iterable, Iterable> zipIterableM(f * * @return A function that zips two lists with this function. */ - static public F2, List, List> zipListM(final F2 f) { + public static F2, List, List> zipListM(final F2 f) { return (as, bs) -> as.zipWith(bs, f); } @@ -182,7 +182,7 @@ static public F2, List, List> zipListM(final F2 * * @return A function that zips two streams with this function. */ - static public F2, Stream, Stream> zipStreamM(final F2 f) { + public static F2, Stream, Stream> zipStreamM(final F2 f) { return (as, bs) -> as.zipWith(bs, f); } @@ -191,7 +191,7 @@ static public F2, Stream, Stream> zipStreamM(final F2< * * @return A function that zips two non-empty lists with this function. */ - static public F2, NonEmptyList, NonEmptyList> zipNelM(final F2 f) { + public static F2, NonEmptyList, NonEmptyList> zipNelM(final F2 f) { return (as, bs) -> NonEmptyList.fromList(as.toList().zipWith(bs.toList(), f)).some(); } @@ -201,7 +201,7 @@ static public F2, NonEmptyList, NonEmptyList> zi * @param o An ordering for the resulting set. * @return A function that zips two sets with this function. */ - static public F2, Set, Set> zipSetM(final F2 f, final Ord o) { + public static F2, Set, Set> zipSetM(final F2 f, final Ord o) { return (as, bs) -> iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); } @@ -211,7 +211,7 @@ static public F2, Set, Set> zipSetM(final F2 f, * * @return A function that zips two trees with this function. */ - static public F2, Tree, Tree> zipTreeM(final F2 f) { + public static F2, Tree, Tree> zipTreeM(final F2 f) { return new F2, Tree, Tree>() { public Tree f(final Tree ta, final Tree tb) { final F2, Tree, Tree> self = this; @@ -226,7 +226,7 @@ public Tree f(final Tree ta, final Tree tb) { * * @return A function that zips two zippers with this function. */ - static public F2, Zipper, Zipper> zipZipperM(final F2 f) { + public static F2, Zipper, Zipper> zipZipperM(final F2 f) { return (ta, tb) -> { final F2, Stream, Stream> sf = zipStreamM(f); return zipper(sf.f(ta.lefts(), tb.lefts()), f.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); @@ -239,7 +239,7 @@ static public F2, Zipper, Zipper> zipZipperM(final F2< * * @return A function that zips two TreeZippers with this function. */ - static public F2, TreeZipper, TreeZipper> zipTreeZipperM(final F2 f) { + public static F2, TreeZipper, TreeZipper> zipTreeZipperM(final F2 f) { return (ta, tb) -> { final F2>, Stream>, Stream>> sf = zipStreamM(treeM(f)); final @@ -254,19 +254,19 @@ static public F2, TreeZipper, TreeZipper> zipTreeZ }; } - static public F2 contramapFirst(F2 target, F f) { + public static F2 contramapFirst(F2 target, F f) { return (z, b) -> target.f(f.f(z), b); } - static public F2 contramapSecond(F2 target, F f) { + public static F2 contramapSecond(F2 target, F f) { return (a, z) -> target.f(a, f.f(z)); } - static public F2 contramap(F2 target, F f, F g) { + public static F2 contramap(F2 target, F f, F g) { return contramapSecond(contramapFirst(target, f), g); } - static public F2 map(F2 target, F f) { + public static F2 map(F2 target, F f) { return (a, b) -> f.f(target.f(a, b)); } diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index 77a8fa74..a1e0b8f7 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -21,7 +21,7 @@ private F3Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F2 f(final F3 f, final A a) { + public static F2 f(final F3 f, final A a) { return (b, c) -> f.f(a, b, c); } diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index ab57247b..04525167 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -17,7 +17,7 @@ private F4Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F3 f(final F4 f, final A a) { + public static F3 f(final F4 f, final A a) { return (b, c, d) -> f.f(a, b, c, d); } diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index 6345de01..d8dda4da 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -17,7 +17,7 @@ private F5Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F4 f(final F5 f, final A a) { + public static F4 f(final F5 f, final A a) { return (b, c, d, e) -> f.f(a, b, c, d, e); } diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 19269e40..69ce270a 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -17,7 +17,7 @@ private F6Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F5 f(final F6 func, final A a) { + public static F5 f(final F6 func, final A a) { return (b, c, d, e, f) -> func.f(a, b, c, d, e, f); } diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 4abcb986..0f2f25ac 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -17,7 +17,7 @@ private F7Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F6 f(final F7 func, final A a) { + public static F6 f(final F7 func, final A a) { return (b, c, d, e, f, g) -> func.f(a, b, c, d, e, f, g); } diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index 5cb9bb3b..5eafe1f3 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -17,7 +17,7 @@ private F8Functions() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - static public F7 f(final F8 func, final A a) { + public static F7 f(final F8 func, final A a) { return (b, c, d, e, f, g, h) -> func.f(a, b, c, d, e, f, g, h); } diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index c5829b01..d18d7dbd 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -25,7 +25,7 @@ private Try() { * @return A Validation with an Exception on the failure side and its result on the success side. */ @SuppressWarnings("unchecked") - static public P1> f(final Try0 t) { + public static P1> f(final Try0 t) { return P.lazy(() -> { try { return success(t.f()); @@ -42,7 +42,7 @@ static public P1> f(final Try0 t * @return A Validation with an Exception on the failure side and its result on the success side. */ @SuppressWarnings("unchecked") - static public F> f(final Try1 t) { + public static F> f(final Try1 t) { return a -> { try { return Validation.success(t.f(a)); @@ -59,7 +59,7 @@ static public F> f(final Try1 F2> f(final Try2 t) { + public static F2> f(final Try2 t) { return (a, b) -> { try { return success(t.f(a, b)); @@ -76,7 +76,7 @@ static public F2> f(final * @return A Validation with an Exception on the failure side and its result on the success side. */ @SuppressWarnings("unchecked") - static public F3> f(final Try3 t) { + public static F3> f(final Try3 t) { return (a, b, c) -> { try { return success(t.f(a, b, c)); @@ -93,7 +93,7 @@ static public F3> f( * @return A Validation with an Exception on the failure side and its result on the success side. */ @SuppressWarnings("unchecked") - static public F4> f(final Try4 t) { + public static F4> f(final Try4 t) { return (a, b, c, d) -> { try { return success(t.f(a, b, c, d)); @@ -110,7 +110,7 @@ static public F4 F5> f(final Try5 t) { + public static F5> f(final Try5 t) { return (a, b, c, d, e) -> { try { return success(t.f(a, b, c, d, e)); @@ -127,7 +127,7 @@ static public F5 F6> f(final Try6 t) { + public static F6> f(final Try6 t) { return (a, b, c, d, e, f) -> { try { return success(t.f(a, b, c, d, e, f)); @@ -144,7 +144,7 @@ static public F6 F7> f(final Try7 t) { + public static F7> f(final Try7 t) { return (a, b, c, d, e, f, g) -> { try { return success(t.f(a, b, c, d, e, f, g)); diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index f609fb0f..49b6bb61 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -15,7 +15,7 @@ public abstract class Trampoline { // A Normal Trampoline is either done or suspended, and is allowed to be a subcomputation of a Codense. // This is the pointed functor part of the Trampoline monad. - private static abstract class Normal extends Trampoline { + private abstract static class Normal extends Trampoline { public abstract R foldNormal(final F pure, final F>, R> k); public Trampoline bind(final F> f) { diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 5405f70a..f6cfb624 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -616,7 +616,7 @@ public static F, F P1> TryEffect_P(final TryEffect0 t) { + public static P1> TryEffect_P(final TryEffect0 t) { return TryEffect.f(t); } diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index e4cd3530..7b413293 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -15,7 +15,7 @@ public final class Iteratee { /** The input to an iteratee. */ - public static abstract class Input { + public abstract static class Input { Input() {} // sealed @@ -53,7 +53,7 @@ public Z apply(final F0 empty, final F0> el, final F0 eof) { } /** A pure iteratee computation which is either done or needs more input */ - public static abstract class IterV { + public abstract static class IterV { IterV() {} // sealed diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 03e310d2..93fd1e9e 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -75,27 +75,27 @@ public static F, BiFunction> F2_BiFunction() { return f -> (a, b) -> f.f(a, b); } - static public Supplier> TryCatch0_Supplier(final Try0 t) { + public static Supplier> TryCatch0_Supplier(final Try0 t) { return Java8.TryCatch0_Supplier().f(t); } - static public F, Supplier>> TryCatch0_Supplier() { + public static F, Supplier>> TryCatch0_Supplier() { return t -> () -> Try.f(t)._1(); } - static public Function> TryCatch1_Function(final Try1 t) { + public static Function> TryCatch1_Function(final Try1 t) { return Java8.TryCatch1_Function().f(t); } - static public F, Function>> TryCatch1_Function() { + public static F, Function>> TryCatch1_Function() { return t -> a -> Try.f(t).f(a); } - static public BiFunction> TryCatch2_BiFunction(final Try2 t) { + public static BiFunction> TryCatch2_BiFunction(final Try2 t) { return Java8.TryCatch2_BiFunction().f(t); } - static public F, BiFunction>> TryCatch2_BiFunction() { + public static F, BiFunction>> TryCatch2_BiFunction() { return t -> (a, b) -> Try.f(t).f(a, b); } @@ -103,23 +103,23 @@ public static java.util.stream.Stream List_JavaStream(final List list) return Iterable_JavaStream(list); } - static public Option Optional_Option(final Optional o) { + public static Option Optional_Option(final Optional o) { return Java8.Optional_Option().f(o); } - static public F, Option> Optional_Option() { + public static F, Option> Optional_Option() { return o -> o.isPresent() ? Option.fromNull(o.get()) : Option.none(); } - static public Optional Option_Optional(final Option o) { + public static Optional Option_Optional(final Option o) { return Java8.Option_Optional().f(o); } - static public F, Optional> Option_Optional() { + public static F, Optional> Option_Optional() { return o -> o.isSome() ? Optional.ofNullable(o.some()) : Optional.empty(); } - static public F, F> Consumer_F() { + public static F, F> Consumer_F() { return c -> Consumer_F(c); } @@ -130,31 +130,31 @@ public static F Consumer_F(final Consumer c) { }; } - static public java.util.stream.Stream Stream_JavaStream(final fj.data.Stream s) { + public static java.util.stream.Stream Stream_JavaStream(final fj.data.Stream s) { return Iterable_JavaStream(s); } - static public java.util.stream.Stream Iterable_JavaStream(final Iterable it) { + public static java.util.stream.Stream Iterable_JavaStream(final Iterable it) { return StreamSupport.stream(it.spliterator(), false); } - static public java.util.stream.Stream Iterator_JavaStream(final Iterator it) { + public static java.util.stream.Stream Iterator_JavaStream(final Iterator it) { return Iterable_JavaStream(() -> it); } - static public F, java.util.stream.Stream> Stream_JavaStream() { + public static F, java.util.stream.Stream> Stream_JavaStream() { return s -> Stream_JavaStream(s); } - static public Stream JavaStream_Stream(final java.util.stream.Stream s) { + public static Stream JavaStream_Stream(final java.util.stream.Stream s) { return s.collect(Collectors.toStream()); } - static public List JavaStream_List(final java.util.stream.Stream s) { + public static List JavaStream_List(final java.util.stream.Stream s) { return s.collect(Collectors.toList()); } - static public Array JavaStream_Array(final java.util.stream.Stream s) { + public static Array JavaStream_Array(final java.util.stream.Stream s) { return s.collect(Collectors.toArray()); } From 045471917902d4e4948a01804091f6cfc97b3cea Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 17:10:30 +0100 Subject: [PATCH 504/811] Simplify annotations --- core/src/main/java/fj/Bottom.java | 2 +- core/src/main/java/fj/Class.java | 2 +- core/src/main/java/fj/F1Functions.java | 18 +++---- core/src/main/java/fj/F1W.java | 18 +++---- core/src/main/java/fj/Monoid.java | 2 +- core/src/main/java/fj/P6.java | 2 +- core/src/main/java/fj/P7.java | 2 +- core/src/main/java/fj/P8.java | 2 +- core/src/main/java/fj/data/$.java | 2 +- core/src/main/java/fj/data/Array.java | 16 +++--- core/src/main/java/fj/data/HashMap.java | 2 +- core/src/main/java/fj/data/IterableW.java | 4 +- core/src/main/java/fj/data/List.java | 8 +-- core/src/main/java/fj/data/Option.java | 4 +- core/src/main/java/fj/data/Set.java | 4 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/TreeMap.java | 2 +- core/src/main/java/fj/data/Validation.java | 8 +-- core/src/main/java/fj/data/Zipper.java | 2 +- .../java/fj/demo/concurrent/PingPong.java | 2 +- .../java/fj/demo/test/ListFunctorLaws.java | 2 +- demo/src/main/java/fj/demo/test/Reflect.java | 2 +- .../src/main/java/fj/test/Arbitrary.java | 28 +++++------ .../src/main/java/fj/test/CheckResult.java | 2 +- .../src/main/java/fj/test/Coarbitrary.java | 50 +++++++++---------- .../src/main/java/fj/test/Property.java | 4 +- quickcheck/src/main/java/fj/test/Result.java | 2 +- quickcheck/src/main/java/fj/test/Shrink.java | 4 +- .../src/main/java/fj/test/reflect/Check.java | 4 +- 29 files changed, 101 insertions(+), 101 deletions(-) diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index a9951928..0f828102 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -72,7 +72,7 @@ public static Error decons(final A a, final Show sa) { * @param c The type being deconstructed. * @return A deconstruction failure that was non-exhaustive. */ - @SuppressWarnings({"UnnecessaryFullyQualifiedName"}) + @SuppressWarnings("UnnecessaryFullyQualifiedName") public static Error decons(final java.lang.Class c) { return error("Deconstruction failure on type " + c); } diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index 6eac6e39..e2630569 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -39,7 +39,7 @@ public java.lang.Class _1() { return c2; } - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public java.lang.Class _2() { return c2.getSuperclass(); } diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 5821a893..12f565b2 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -49,7 +49,7 @@ public static F, F> o(final F f) { * @param g A function with which to compose this one. * @return The composed function such that this function is applied first. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F andThen(final F f, final F g) { return o(g, f); } @@ -259,7 +259,7 @@ public static F, Promise> mapPromise(final F f) { * * @return This function promoted to return its result on the left side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F> eitherLeftK(final F f) { return o(Either.left_(), f); } @@ -270,7 +270,7 @@ public static F> eitherLeftK(final F f) { * * @return This function promoted to return its result on the right side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F> eitherRightK(final F f) { return o(Either.right_(), f); } @@ -280,7 +280,7 @@ public static F> eitherRightK(final F f) { * * @return This function promoted to map over the left side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F, Either> mapLeft(final F f) { return Either.leftMap_().f(f); } @@ -290,7 +290,7 @@ public static F, Either> mapLeft(final F f) { * * @return This function promoted to map over the right side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F, Either> mapRight(final F f) { return Either.rightMap_().f(f); } @@ -318,7 +318,7 @@ public static F, B> onRight(final F f) { * * @return This function promoted to return its value in an Iterable. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F> iterableK(final F f) { return IterableW.arrow().f(f); } @@ -328,7 +328,7 @@ public static F> iterableK(final F f) { * * @return This function promoted to map over Iterables. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F, IterableW> mapIterable(final F f) { return F1Functions.o(IterableW.map().f(f), IterableW.>wrap()); } @@ -338,7 +338,7 @@ public static F, IterableW> mapIterable(final F f) { * * @return This function promoted to return its value in a NonEmptyList. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F> nelK(final F f) { return o(NonEmptyList.nel(), f); } @@ -387,7 +387,7 @@ public static F> treeK(final F f) { * * @return This function promoted to map over a Tree. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static F, Tree> mapTree(final F f) { return Tree.fmap_().f(f); } diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java index 73545411..7fe50e35 100644 --- a/core/src/main/java/fj/F1W.java +++ b/core/src/main/java/fj/F1W.java @@ -41,7 +41,7 @@ public F1W, F> o() { * @param g A function with which to compose this one. * @return The composed function such that this function is applied first. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W andThen(final F g) { return lift(F1Functions.andThen(this, g)); } @@ -254,7 +254,7 @@ public F1W, Promise> mapPromise() { * * @return This function promoted to return its result on the left side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W> eitherLeftK() { return lift(F1Functions.eitherLeftK(this)); } @@ -265,7 +265,7 @@ public F1W> eitherLeftK() { * * @return This function promoted to return its result on the right side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W> eitherRightK() { return lift(F1Functions.eitherRightK(this)); } @@ -275,7 +275,7 @@ public F1W> eitherRightK() { * * @return This function promoted to map over the left side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W, Either> mapLeft() { return lift(F1Functions.mapLeft(this)); } @@ -285,7 +285,7 @@ public F1W, Either> mapLeft() { * * @return This function promoted to map over the right side of an Either. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W, Either> mapRight() { return lift(F1Functions.mapRight(this)); } @@ -313,7 +313,7 @@ public F1W, B> onRight() { * * @return This function promoted to return its value in an Iterable. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W> iterableK() { return lift( F1Functions.iterableK(this)); } @@ -323,7 +323,7 @@ public F1W> iterableK() { * * @return This function promoted to map over Iterables. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W, IterableW> mapIterable() { return lift( F1Functions.mapIterable(this)); } @@ -333,7 +333,7 @@ public F1W, IterableW> mapIterable() { * * @return This function promoted to return its value in a NonEmptyList. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W> nelK() { return lift(F1Functions.nelK(this)); } @@ -381,7 +381,7 @@ public F1W> treeK() { * * @return This function promoted to map over a Tree. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public F1W, Tree> mapTree() { return lift(F1Functions.mapTree(this)); } diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index c2214748..a85a4712 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -381,7 +381,7 @@ public static Monoid> streamMonoid() { * * @return A monoid for arrays. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static Monoid> arrayMonoid() { return monoid(Semigroup.arraySemigroup(), Array.empty()); } diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index a6ed6c8f..c2983298 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -5,7 +5,7 @@ * * @version %build.number% */ -@SuppressWarnings({"UnnecessaryFullyQualifiedName"}) +@SuppressWarnings("UnnecessaryFullyQualifiedName") public abstract class P6 { /** * Access the first element of the product. diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 76900fc4..478e3d87 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -5,7 +5,7 @@ * * @version %build.number% */ -@SuppressWarnings({"UnnecessaryFullyQualifiedName"}) +@SuppressWarnings("UnnecessaryFullyQualifiedName") public abstract class P7 { /** * Access the first element of the product. diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index d9e9f42c..62fef46e 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -5,7 +5,7 @@ * * @version %build.number% */ -@SuppressWarnings({"UnnecessaryFullyQualifiedName"}) +@SuppressWarnings("UnnecessaryFullyQualifiedName") public abstract class P8 { /** * Access the first element of the product. diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 3ddf92d3..212216bc 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -6,7 +6,7 @@ * The constant arrow, for attaching a new name to an existing type. For every pair of types A and B, this type * is the identity morphism from B to B. */ -@SuppressWarnings({"UnusedDeclaration"}) +@SuppressWarnings("UnusedDeclaration") public final class $ extends P1 { private final B b; diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index ea8c7312..f9ed8abb 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -202,7 +202,7 @@ public String toString() { * @param f The function to map across this array. * @return A new array after the given function has been applied to each element. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Array map(final F f) { final Object[] bs = new Object[a.length]; @@ -323,7 +323,7 @@ public B foldLeft(final F2 f, final B b) { * @param b The beginning value to start the application from. * @return The array containing all intermediate results of the left-fold reduction. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Array scanLeft(final F> f, final B b) { final Object[] bs = new Object[a.length]; B x = b; @@ -357,7 +357,7 @@ public Array scanLeft(final F2 f, final B b) { * @param f The function to apply on each argument pair (next array element and first array element/previous result) * @return The array containing all intermediate results of the left-fold reduction. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Array scanLeft1(final F> f) { final Object[] bs = new Object[a.length]; A x = get(0); @@ -392,7 +392,7 @@ public Array scanLeft1(final F2 f) { * @param b The beginning value to start the application from. * @return The array containing all intermediate results of the right-fold reduction. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Array scanRight(final F>f, final B b) { final Object[] bs = new Object[a.length]; B x = b; @@ -426,7 +426,7 @@ public Array scanRight(final F2 f, final B b) { * @param f The function to apply on each argument pair (previous array element and last array element/previous result) * @return The array containing all intermediate results of the right-fold reduction. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Array scanRight1(final F>f) { final Object[] bs = new Object[a.length]; A x = get(length() - 1); @@ -459,7 +459,7 @@ public Array scanRight1(final F2 f) { * @param f The function to apply to each element of this array. * @return A new array after performing the map, then final join. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Array bind(final F> f) { List> x = List.nil(); int len = 0; @@ -849,7 +849,7 @@ public static Array arrayArray(final A...as) { * @param xs The array of pairs to transform. * @return An array of first components and an array of second components. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static P2, Array> unzip(final Array> xs) { final int len = xs.length(); final Array aa = new Array(new Object[len]); @@ -1079,7 +1079,7 @@ public static T[] copyOf(final U[] a, final int len, final Class T[] copyOf(final T[] a, final int len) { return (T[]) copyOf(a, len, a.getClass()); } diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 7cd9c8dd..3e6ff3b3 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -32,7 +32,7 @@ K k() { return k; } - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public boolean equals(final Object o) { return o instanceof Key && e.eq(k, (K) ((Key) o).k()); } diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 52be7d6b..523b4152 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -324,7 +324,7 @@ public boolean isEmpty() { return iterableStream(IterableW.this).isEmpty(); } - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public boolean contains(final Object o) { return iterableStream(IterableW.this).exists(Equal.anyEqual().eq((A) o)); } @@ -337,7 +337,7 @@ public Object[] toArray() { return Array.iterableArray(iterableStream(IterableW.this)).array(); } - @SuppressWarnings({"SuspiciousToArrayCall"}) + @SuppressWarnings("SuspiciousToArrayCall") public T[] toArray(final T[] a) { return iterableStream(IterableW.this).toCollection().toArray(a); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 4920e021..26ec5e33 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -195,7 +195,7 @@ public final Stream toStream() { * * @return A array projection of this list. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public final Array toArray() { return mkArray(toArrayObject()); } @@ -1124,7 +1124,7 @@ public final List intersperse(final A a) { * @param as The list to intersperse through. * @return This list through the given list then joins the results. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public final List intercalate(final List> as) { return join(as.intersperse(this)); } @@ -1154,7 +1154,7 @@ public final List nub(final Equal eq) { * @param o An ordering for the elements. * @return A list without duplicates. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public final List nub(final Ord o) { return sort(o).group(o.equal()).map(List.head_()); } @@ -2044,7 +2044,7 @@ public static Buffer iterableBuffer(final Iterable i) { return b; } - @SuppressWarnings({"ObjectEquality"}) + @SuppressWarnings("ObjectEquality") private void copy() { List s = start; final Cons t = tail; diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 476d38db..cb58e61f 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -542,7 +542,7 @@ public final Stream toStream() { * * @return An array projection of this optional value. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public final Array toArray() { return isSome() ? Array.array(some()) : Array.empty(); } @@ -553,7 +553,7 @@ public final Array toArray() { * @param c The class type of the array to return. * @return An array projection of this optional value. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public final Array toArray(final Class c) { if (isSome()) { final A[] a = (A[]) java.lang.reflect.Array.newInstance(c.getComponentType(), 1); diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 6c23d6d5..09d80279 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -31,7 +31,7 @@ public final boolean isEmpty() { return this instanceof Empty; } - @SuppressWarnings({"ClassEscapesDefinedScope"}) + @SuppressWarnings("ClassEscapesDefinedScope") abstract Color color(); abstract Set l(); @@ -209,7 +209,7 @@ private Set makeBlack() { return new Tree(ord, Color.B, l(), head(), r()); } - @SuppressWarnings({"SuspiciousNameCombination"}) + @SuppressWarnings("SuspiciousNameCombination") private static Tree tr(final Ord o, final Set a, final A x, final Set b, final A y, diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 2e7ca879..cb6fe8d0 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -957,7 +957,7 @@ public final java.util.List toJavaList() { * * @return A array projection of this stream. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public final Array toArray() { final int l = length(); final Object[] a = new Object[l]; diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 307c279e..e35e6592 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -358,7 +358,7 @@ public P3, Option, TreeMap> splitLookup(final K k) { * @param f A function to apply to the values of this TreeMap. * @return A new TreeMap with the values transformed by the given function. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public TreeMap map(final F f) { final F>, P2>> g = P2.map2_(F1Functions.mapOption(f)); final F>> coord = flip(P.>p2()).f(Option.none()); diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 3a2cfa23..a87b4585 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -172,7 +172,7 @@ public void foreachDoEffect(final Effect1 f) { * @param f The function to map. * @return A new validation with the function mapped. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Validation map(final F f) { return isFail() ? Validation.fail(fail()) : @@ -185,7 +185,7 @@ public Validation map(final F f) { * @param f The function to bind across this validation. * @return A new validation value after binding. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Validation bind(final F> f) { return isSuccess() ? f.f(success()) : Validation.fail(fail()); } @@ -313,7 +313,7 @@ public Stream toStream() { * @return A failing validation if this or the given validation failed (with errors accumulated if both) or a * succeeding validation if both succeeded. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Validation accumapply(final Semigroup s, final Validation> v) { return isFail() ? Validation.fail(v.isFail() ? @@ -1080,7 +1080,7 @@ public Iterator iterator() { * * @return A validation with its failing value in a non-empty list if there is one. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Validation, T> nel() { return isSuccess() ? Validation., T>success(success()) : diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index a4377507..6de0d39c 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -169,7 +169,7 @@ public static Zipper single(final A a) { * @param a The stream from which to create a zipper. * @return a new zipper if the provided stream has at least one element, otherwise None. */ - @SuppressWarnings({"IfMayBeConditional"}) + @SuppressWarnings("IfMayBeConditional") public static Option> fromStream(final Stream a) { if (a.isEmpty()) return none(); diff --git a/demo/src/main/java/fj/demo/concurrent/PingPong.java b/demo/src/main/java/fj/demo/concurrent/PingPong.java index 59038679..d6bddbbf 100644 --- a/demo/src/main/java/fj/demo/concurrent/PingPong.java +++ b/demo/src/main/java/fj/demo/concurrent/PingPong.java @@ -16,7 +16,7 @@ * Example of parallel synchronous messaging using Actors in Functional Java. * Author: Runar */ -@SuppressWarnings({"ArithmeticOnVolatileField"}) +@SuppressWarnings("ArithmeticOnVolatileField") public class PingPong { private final int actors; private final int pings; diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index b2c230a5..e0c99f64 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -39,7 +39,7 @@ For any list, mapping the identity function (\x -> x) produces the same list. Note that to test this second law requires the generation of arbitrary functions. */ -@SuppressWarnings({"PackageVisibleField"}) +@SuppressWarnings("PackageVisibleField") @CheckParams(minSuccessful = 1000) public final class ListFunctorLaws { final Property identity = property(arbList(arbString), x -> prop(listEqual(stringEqual).eq(x, x.map(Function.identity())))); diff --git a/demo/src/main/java/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java index 8831314e..79d013dc 100644 --- a/demo/src/main/java/fj/demo/test/Reflect.java +++ b/demo/src/main/java/fj/demo/test/Reflect.java @@ -82,7 +82,7 @@ Property leave() { throw error("this should not be executed"); } - @SuppressWarnings({"UnusedDeclaration"}) + @SuppressWarnings("UnusedDeclaration") Property leave(final int i) { throw error("this should not be executed"); } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index d46f4d4e..34a17ae1 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -95,7 +95,7 @@ public final class Arbitrary { /** * The generator associated with this arbitrary. */ - @SuppressWarnings({"PublicField"}) + @SuppressWarnings("PublicField") public final Gen gen; private Arbitrary(final Gen gen) { @@ -668,7 +668,7 @@ public StringBuilder f(final String s) { */ public static Arbitrary> arbGen(final Arbitrary aa) { return arbitrary(sized(new F>>() { - @SuppressWarnings({"IfMayBeConditional"}) + @SuppressWarnings("IfMayBeConditional") public Gen> f(final Integer i) { if (i == 0) return fail(); @@ -711,7 +711,7 @@ public Option f(final A a) { * defined. * @return An arbitrary implementation for the disjoint union. */ - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public static Arbitrary> arbEither(final Arbitrary aa, final Arbitrary ab) { final Gen> left = aa.gen.map(new F>() { public Either f(final A a) { @@ -916,7 +916,7 @@ public static > Arbitrary arbEnumValue(final Class clazz public static , V> Arbitrary> arbEnumMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, EnumMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public EnumMap f(final Hashtable ht) { return new EnumMap(ht); } @@ -959,7 +959,7 @@ public GregorianCalendar f(final Long i) { */ public static Arbitrary> arbHashMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, HashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public HashMap f(final Hashtable ht) { return new HashMap(ht); } @@ -993,7 +993,7 @@ public static Arbitrary> arbHashtable(final Arbitrary return arbitrary(arbList(ak).gen.bind(arbList(av).gen, new F, F, Hashtable>>() { public F, Hashtable> f(final List ks) { return new F, Hashtable>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Hashtable f(final List vs) { final Hashtable t = new Hashtable(); @@ -1022,7 +1022,7 @@ public void f(final P2 kv) { public static Arbitrary> arbIdentityHashMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, IdentityHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public IdentityHashMap f(final Hashtable ht) { return new IdentityHashMap(ht); } @@ -1040,7 +1040,7 @@ public IdentityHashMap f(final Hashtable ht) { */ public static Arbitrary> arbLinkedHashMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, LinkedHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public LinkedHashMap f(final Hashtable ht) { return new LinkedHashMap(ht); } @@ -1094,7 +1094,7 @@ public PriorityQueue f(final Array a) { */ public static final Arbitrary arbProperties = arbitrary(arbHashtable(arbString, arbString).gen.map(new F, Properties>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Properties f(final Hashtable ht) { final Properties p = new Properties(); @@ -1132,7 +1132,7 @@ public Stack f(final Array a) { */ public static Arbitrary> arbJavaTreeMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, java.util.TreeMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public java.util.TreeMap f(final Hashtable ht) { return new java.util.TreeMap(ht); } @@ -1196,10 +1196,10 @@ public TreeSet f(final Array a) { * @param aa An arbitrary implementation for the type over which the vector is defined. * @return An arbitrary implementation for vectors. */ - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public static Arbitrary> arbVector(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.map(new F, Vector>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Vector f(final Array a) { return new Vector(a.toCollection()); } @@ -1217,7 +1217,7 @@ public Vector f(final Array a) { */ public static Arbitrary> arbWeakHashMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, WeakHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public WeakHashMap f(final Hashtable ht) { return new WeakHashMap(ht); } @@ -1265,7 +1265,7 @@ public ArrayBlockingQueue f(final Boolean fair) { public static Arbitrary> arbConcurrentHashMap(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbHashtable(ak, av).gen.map(new F, ConcurrentHashMap>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public ConcurrentHashMap f(final Hashtable ht) { return new ConcurrentHashMap(ht); } diff --git a/quickcheck/src/main/java/fj/test/CheckResult.java b/quickcheck/src/main/java/fj/test/CheckResult.java index fe3ca92a..dc0195d7 100644 --- a/quickcheck/src/main/java/fj/test/CheckResult.java +++ b/quickcheck/src/main/java/fj/test/CheckResult.java @@ -236,7 +236,7 @@ private String arguments(final CheckResult r) { return args.length() == 1 ? "argument: " + sa.showS(args.head()) : "arguments: " + listShow(sa).showS(args); } - @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"}) + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") public String f(final CheckResult r) { if (r.isProven()) return "OK, property proven with " + arguments(r); diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index 8b778188..bb607aa5 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -530,7 +530,7 @@ public String f(final Throwable t) { */ public static Coarbitrary> coarbArrayList(final Coarbitrary ca) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final ArrayList as, final Gen g) { return coarbArray(ca).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -580,7 +580,7 @@ public Gen coarbitrary(final Date d, final Gen g) { public static , V> Coarbitrary> coarbEnumMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final EnumMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -595,7 +595,7 @@ public Gen coarbitrary(final EnumMap m, final Gen g) { */ public static > Coarbitrary> coarbEnumSet(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final EnumSet as, final Gen g) { return coarbHashSet(c).coarbitrary(new HashSet(as), g); } @@ -620,7 +620,7 @@ public Gen coarbitrary(final GregorianCalendar c, final Gen g) { */ public static Coarbitrary> coarbHashMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final HashMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -635,7 +635,7 @@ public Gen coarbitrary(final HashMap m, final Gen g) { */ public static Coarbitrary> coarbHashSet(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final HashSet as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -651,7 +651,7 @@ public Gen coarbitrary(final HashSet as, final Gen g) { */ public static Coarbitrary> coarbHashtable(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final Hashtable h, final Gen g) { List> x = nil(); @@ -674,7 +674,7 @@ public Gen coarbitrary(final Hashtable h, final Gen g) { public static Coarbitrary> coarbIdentityHashMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final IdentityHashMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -691,7 +691,7 @@ public Gen coarbitrary(final IdentityHashMap m, final Gen g) { public static Coarbitrary> coarbLinkedHashMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final LinkedHashMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -706,7 +706,7 @@ public Gen coarbitrary(final LinkedHashMap m, final Gen g) { */ public static Coarbitrary> coarbLinkedHashSet(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final LinkedHashSet as, final Gen g) { return coarbHashSet(c).coarbitrary(new HashSet(as), g); } @@ -721,7 +721,7 @@ public Gen coarbitrary(final LinkedHashSet as, final Gen g) { */ public static Coarbitrary> coarbLinkedList(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final LinkedList as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -736,7 +736,7 @@ public Gen coarbitrary(final LinkedList as, final Gen g) { */ public static Coarbitrary> coarbPriorityQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final PriorityQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -747,7 +747,7 @@ public Gen coarbitrary(final PriorityQueue as, final Gen g) { * A coarbitrary for properties. */ public static final Coarbitrary coarbProperties = new Coarbitrary() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final Properties p, final Gen g) { final Hashtable t = new Hashtable(); @@ -767,7 +767,7 @@ public Gen coarbitrary(final Properties p, final Gen g) { */ public static Coarbitrary> coarbStack(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final Stack as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -783,7 +783,7 @@ public Gen coarbitrary(final Stack as, final Gen g) { */ public static Coarbitrary> coarbTreeMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final TreeMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -798,7 +798,7 @@ public Gen coarbitrary(final TreeMap m, final Gen g) { */ public static Coarbitrary> coarbTreeSet(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final TreeSet as, final Gen g) { return coarbHashSet(c).coarbitrary(new HashSet(as), g); } @@ -830,7 +830,7 @@ public Gen coarbitrary(final Vector as, final Gen g) { public static Coarbitrary> coarbWeakHashMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final WeakHashMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -849,7 +849,7 @@ public Gen coarbitrary(final WeakHashMap m, final Gen g) { */ public static Coarbitrary> coarbArrayBlockingQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final ArrayBlockingQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -866,7 +866,7 @@ public Gen coarbitrary(final ArrayBlockingQueue as, final Gen g) { public static Coarbitrary> coarbConcurrentHashMap(final Coarbitrary ck, final Coarbitrary cv) { return new Coarbitrary>() { - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final ConcurrentHashMap m, final Gen g) { return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); } @@ -881,7 +881,7 @@ public Gen coarbitrary(final ConcurrentHashMap m, final Gen g) { */ public static Coarbitrary> coarbConcurrentLinkedQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final ConcurrentLinkedQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -896,7 +896,7 @@ public Gen coarbitrary(final ConcurrentLinkedQueue as, final Gen g) */ public static Coarbitrary> coarbCopyOnWriteArrayList(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final CopyOnWriteArrayList as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -911,7 +911,7 @@ public Gen coarbitrary(final CopyOnWriteArrayList as, final Gen g) */ public static Coarbitrary> coarbCopyOnWriteArraySet(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final CopyOnWriteArraySet as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -926,7 +926,7 @@ public Gen coarbitrary(final CopyOnWriteArraySet as, final Gen g) { */ public static Coarbitrary> coarbDelayQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final DelayQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -941,7 +941,7 @@ public Gen coarbitrary(final DelayQueue as, final Gen g) { */ public static Coarbitrary> coarbLinkedBlockingQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final LinkedBlockingQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -956,7 +956,7 @@ public Gen coarbitrary(final LinkedBlockingQueue as, final Gen g) { */ public static Coarbitrary> coarbPriorityBlockingQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final PriorityBlockingQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } @@ -971,7 +971,7 @@ public Gen coarbitrary(final PriorityBlockingQueue as, final Gen g) */ public static Coarbitrary> coarbSynchronousQueue(final Coarbitrary c) { return new Coarbitrary>() { - @SuppressWarnings({"unchecked"}) + @SuppressWarnings("unchecked") public Gen coarbitrary(final SynchronousQueue as, final Gen g) { return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); } diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 18baccc3..3231cf2e 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -133,7 +133,7 @@ public Result f(final Result res2) { * @param maxSize The maximum size to use for checking. * @return A result after checking this property. */ - @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"}) + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") public CheckResult check(final Rand r, final int minSuccessful, final int maxDiscarded, @@ -453,7 +453,7 @@ public F f(final Integer i) { return new F() { public Result f(final Rand r) { final class Util { - @SuppressWarnings({"IfMayBeConditional"}) + @SuppressWarnings("IfMayBeConditional") Option> first(final Stream as, final int shrinks) { final Stream>> results = as.map(new F>>() { public Option> f(final A a) { diff --git a/quickcheck/src/main/java/fj/test/Result.java b/quickcheck/src/main/java/fj/test/Result.java index 40a388d6..eb6b973b 100644 --- a/quickcheck/src/main/java/fj/test/Result.java +++ b/quickcheck/src/main/java/fj/test/Result.java @@ -142,7 +142,7 @@ public Result addArg(final Arg a) { * * @return A potential result for this result. */ - @SuppressWarnings({"IfMayBeConditional"}) + @SuppressWarnings("IfMayBeConditional") public Option toOption() { if(isNoResult()) return none(); diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index d1403ee7..a9d1aa21 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -241,7 +241,7 @@ else if (as.tail().isEmpty()) } } - @SuppressWarnings({"IfMayBeConditional"}) + @SuppressWarnings("IfMayBeConditional") Stream> shrinkOne(final List as) { if (as.isEmpty()) return nil(); @@ -402,7 +402,7 @@ public static Shrink> shrinkHashSet(final Shrink sa) { * @param sv The shrink stratgey for values. * @return A shrink strategy for hash tables. */ - @SuppressWarnings({"UseOfObsoleteCollectionType"}) + @SuppressWarnings("UseOfObsoleteCollectionType") public static Shrink> shrinkHashtable(final Shrink sk, final Shrink sv) { return shrinkList(shrinkP2(sk, sv)).map(kvs -> { final Hashtable h = new Hashtable(); diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index 199f399a..079dcb22 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -260,14 +260,14 @@ private interface PropertyMember { AnnotatedElement element(); String name(); int modifiers(); - @SuppressWarnings({"ProhibitedExceptionDeclared"}) + @SuppressWarnings("ProhibitedExceptionDeclared") Property invoke(X x) throws Exception; boolean isProperty(); } private static Array>> properties(final Array ms, final java.lang.Class declaringClass, final String... categories) { final Option t = emptyCtor(declaringClass).map(new F, T>() { - @SuppressWarnings({"OverlyBroadCatchBlock"}) + @SuppressWarnings("OverlyBroadCatchBlock") public T f(final Constructor ctor) { try { ctor.setAccessible(true); From 673bfd6dc27f86dd9a8b764e70cf07cc6e8312ee Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 18:31:53 +0100 Subject: [PATCH 505/811] Fix non-sense in List_map demo --- demo/src/main/java/fj/demo/List_map.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demo/src/main/java/fj/demo/List_map.java b/demo/src/main/java/fj/demo/List_map.java index 55216810..a07f0015 100644 --- a/demo/src/main/java/fj/demo/List_map.java +++ b/demo/src/main/java/fj/demo/List_map.java @@ -9,8 +9,8 @@ public final class List_map { public static void main(final String[] args) { final List a = list(1, 2, 3); - final List b = a.map(add.f(42)); - final List c = a.map(i -> i = 42); + final List b = a.map(add.f(42)); // or equivalently: + final List c = a.map(i -> i + 42); listShow(intShow).println(b); // [43,44,45] } } From df48c32bf6ab51b8cef3f16ad4fe89ed756edb46 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 18:38:26 +0100 Subject: [PATCH 506/811] Use e.printStackTrace() instead of println(e) --- quickcheck/src/main/java/fj/test/reflect/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickcheck/src/main/java/fj/test/reflect/Main.java b/quickcheck/src/main/java/fj/test/reflect/Main.java index a7e8be3c..b0b5fb95 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Main.java +++ b/quickcheck/src/main/java/fj/test/reflect/Main.java @@ -43,7 +43,7 @@ public void f(final P2 r) { } }); } catch(ClassNotFoundException e) { - System.err.println(e); + e.printStackTrace(); //noinspection CallToSystemExit exit(144); } From 2a27fa8203b241df29b8955e7d13916add709f4a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 19:47:50 +0100 Subject: [PATCH 507/811] Remove unnecessary qualification of static methods --- core/src/main/java/fj/Equal.java | 2 +- core/src/main/java/fj/F1Functions.java | 2 +- core/src/main/java/fj/Function.java | 2 +- core/src/main/java/fj/Hash.java | 2 +- core/src/main/java/fj/P.java | 4 +- core/src/main/java/fj/Show.java | 6 +-- core/src/main/java/fj/Try.java | 2 +- .../java/fj/control/parallel/Callables.java | 2 +- .../java/fj/control/parallel/Promise.java | 14 +++--- core/src/main/java/fj/data/Array.java | 10 ++-- core/src/main/java/fj/data/Conversions.java | 2 +- core/src/main/java/fj/data/DList.java | 4 +- core/src/main/java/fj/data/Either.java | 12 ++--- core/src/main/java/fj/data/Enumerator.java | 4 +- core/src/main/java/fj/data/HashMap.java | 2 +- core/src/main/java/fj/data/IOFunctions.java | 14 +++--- core/src/main/java/fj/data/IOW.java | 2 +- core/src/main/java/fj/data/IterableW.java | 2 +- core/src/main/java/fj/data/LazyString.java | 2 +- core/src/main/java/fj/data/List.java | 44 +++++++++--------- core/src/main/java/fj/data/Option.java | 2 +- core/src/main/java/fj/data/Seq.java | 2 +- core/src/main/java/fj/data/State.java | 2 +- core/src/main/java/fj/data/Stream.java | 24 +++++----- core/src/main/java/fj/data/Tree.java | 4 +- core/src/main/java/fj/data/TreeMap.java | 18 ++++---- core/src/main/java/fj/data/Validation.java | 46 +++++++++---------- core/src/main/java/fj/data/Writer.java | 2 +- .../java/fj/data/fingertrees/FingerTree.java | 2 +- .../main/java/fj/data/fingertrees/Single.java | 2 +- .../main/java/fj/demo/realworld/Chapter7.java | 2 +- .../src/main/java/fj/test/Arbitrary.java | 10 ++-- .../src/main/java/fj/test/Property.java | 4 +- 33 files changed, 127 insertions(+), 127 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 23ceffd3..27973afc 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -538,7 +538,7 @@ public static Equal> setEqual(final Equal e) { } public static Equal> treeMapEqual(Equal k, Equal v) { - return equal(t1 -> t2 -> Equal.streamEqual(p2Equal(k, v)).eq(t1.toStream(), t2.toStream())); + return equal(t1 -> t2 -> streamEqual(p2Equal(k, v)).eq(t1.toStream(), t2.toStream())); } public static Equal> writerEqual(Equal eq1, Equal eq2) { diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 12f565b2..3faf1b5e 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -330,7 +330,7 @@ public static F> iterableK(final F f) { */ @SuppressWarnings("unchecked") public static F, IterableW> mapIterable(final F f) { - return F1Functions.o(IterableW.map().f(f), IterableW.>wrap()); + return o(IterableW.map().f(f), IterableW.>wrap()); } /** diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 4d4b14a2..b3b96870 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -60,7 +60,7 @@ public static F> compose2(final F f, final F F, F, F>> andThen() { - return g -> f -> Function.andThen(g, f); + return g -> f -> andThen(g, f); } /** diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 26f42049..61c5e1cd 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -268,7 +268,7 @@ public static Hash> treeHash(final Hash ha) { } public static Hash> treeMapHash(final Hash h, final Hash v) { - return hash(t -> streamHash(Hash.p2Hash(h, v)).hash(t.toStream())); + return hash(t -> streamHash(p2Hash(h, v)).hash(t.toStream())); } /** diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 073de4f6..2826b6b0 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -234,7 +234,7 @@ public H _8() { } public static P2 lazyProduct(F0> f) { - return P.lazy(() -> f.f()._1(), () -> f.f()._2()); + return lazy(() -> f.f()._1(), () -> f.f()._2()); } /** @@ -552,7 +552,7 @@ public static P1 lazy(F f) { } public static P2 lazy(F fa, F fb) { - return P.lazy(() -> fa.f(unit()), () -> fb.f(unit())); + return lazy(() -> fa.f(unit()), () -> fb.f(unit())); } public static P3 lazy(F fa, F fb, F fc) { diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index b67f662a..7e832c6c 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -159,7 +159,7 @@ public static Show showS(final F f) { * @return A show instance that uses {@link Object#toString()} to perform the display rendering. */ public static Show anyShow() { - return show(a -> Stream.fromString((a == null) ? "null" : a.toString())); + return show(a -> fromString((a == null) ? "null" : a.toString())); } /** @@ -325,7 +325,7 @@ public static Show> setShow(final Show sa) { public static Show> treeMapShow(final Show sk, final Show sv) { return show(tm -> { Stream> stream = Stream.iteratorStream(tm.iterator()); - return streamShow(Show.p2MapShow(sk, sv), "TreeMap(", ",", ")").show(stream); + return streamShow(p2MapShow(sk, sv), "TreeMap(", ",", ")").show(stream); }); } @@ -425,7 +425,7 @@ public static Show> p1Show(final Show sa) { } public static Show> p1ShowLazy(final Show sa) { - return show(p -> Stream.fromString("(?)")); + return show(p -> fromString("(?)")); } public static Show> p1ShowEager(final Show sa) { diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index d18d7dbd..d8a30130 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -45,7 +45,7 @@ public static P1> f(final Try0 t public static F> f(final Try1 t) { return a -> { try { - return Validation.success(t.f(a)); + return success(t.f(a)); } catch (Exception e) { return fail((E) e); } diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index 1b6114fe..aeb9a312 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -93,7 +93,7 @@ public static Callable bind(final Callable a, final F F, Callable> fmap(final F f) { - return a -> Callables.bind(a, callable(f)); + return a -> bind(a, callable(f)); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 100b50f6..42f9e3c2 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -75,7 +75,7 @@ public void f(final P2, Actor>, Promise> p) { */ public static Promise promise(final Strategy s, final P1 a) { final Promise p = mkPromise(s); - p.actor.act(P.p(Either., Actor>left(a), p)); + p.actor.act(p(Either., Actor>left(a), p)); return p; } @@ -118,7 +118,7 @@ public static F> promise(final Strategy s, final F a) { - actor.act(P.p(Either., Actor>right(a), this)); + actor.act(p(Either., Actor>right(a), this)); } /** @@ -176,7 +176,7 @@ public Promise bind(final F> f) { final Promise r = mkPromise(s); final Actor ab = actor(s, new Effect1() { public void f(final B b) { - r.actor.act(P.p(Either., Actor>left(P.p(b)), r)); + r.actor.act(p(Either., Actor>left(p(b)), r)); } }); to(ab.promise().contramap(f)); @@ -233,7 +233,7 @@ public static F, F, Promise>> liftM2(final F< * @return A single promise for the given List. */ public static Promise> sequence(final Strategy s, final List> as) { - return join(foldRight(s, liftM2(List.cons()), promise(s, P.p(List.nil()))).f(as)); + return join(foldRight(s, liftM2(List.cons()), promise(s, p(List.nil()))).f(as)); } /** @@ -254,7 +254,7 @@ public static F>, Promise>> sequence(final Strategy< * @return A single promise for the given Stream. */ public static Promise> sequence(final Strategy s, final Stream> as) { - return join(foldRightS(s, curry((Promise o, P1>> p) -> o.bind(a -> p._1().fmap(Stream.cons_().f(a)))), promise(s, P.p(Stream.nil()))).f(as)); + return join(foldRightS(s, curry((Promise o, P1>> p) -> o.bind(a -> p._1().fmap(Stream.cons_().f(a)))), promise(s, p(Stream.nil()))).f(as)); } /** @@ -289,7 +289,7 @@ public static Promise> sequence(final Strategy s, final P1 F, Promise> foldRight(final Strategy s, final F> f, final B b) { return new F, Promise>() { public Promise f(final List as) { - return as.isEmpty() ? promise(s, p(b)) : liftM2(f).f(promise(s, P.p(as.head()))).f( + return as.isEmpty() ? promise(s, p(b)) : liftM2(f).f(promise(s, p(as.head()))).f( join(s, P1.curry(this).f(as.tail()))); } }; @@ -307,7 +307,7 @@ public static F, Promise> foldRightS(final Strategy s, final B b) { return new F, Promise>() { public Promise f(final Stream as) { - return as.isEmpty() ? promise(s, P.p(b)) : liftM2(f).f(promise(s, P.p(as.head()))).f( + return as.isEmpty() ? promise(s, p(b)) : liftM2(f).f(promise(s, p(as.head()))).f( Promise.>join(s, P.lazy(() -> f(as.tail()._1()).fmap(P.p1())))); } }; diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index f9ed8abb..d9231cb8 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -859,7 +859,7 @@ public static P2, Array> unzip(final Array> xs) { aa.set(i, p._1()); ab.set(i, p._2()); } - return P.p(aa, ab); + return p(aa, ab); } /** @@ -1074,8 +1074,8 @@ public static T[] copyOf(final U[] a, final int len, final Class " + to); final char[] copy = new char[len]; - System.arraycopy(a, from, copy, 0, - Math.min(a.length - from, len)); + arraycopy(a, from, copy, 0, + min(a.length - from, len)); return copy; } } diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index f6cfb624..055da1dd 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -293,7 +293,7 @@ public static F, F> Effect1_F() { public static IO Effect_IO(Effect0 e) { return () ->{ e.f(); - return Unit.unit(); + return unit(); }; } diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 3f7b2fe3..7e44ef9b 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -104,7 +104,7 @@ public static DList single(A a) { * @return the new DList. */ public DList cons(A a) { - return DList.single(a).append(this); + return single(a).append(this); } /** @@ -113,7 +113,7 @@ public DList cons(A a) { * @return the new DList. */ public DList snoc(A a) { - return this.append(DList.single(a)); + return this.append(single(a)); } /** diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 8581664f..6381ee78 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -417,7 +417,7 @@ public Collection toCollection() { public Option> traverseOption(F> f) { return isLeft() ? f.f(value()).map(x -> Either.left(x)) : - Option.some(Either.right(e.right().value())); + some(Either.right(e.right().value())); } public Stream> traverseStream(F> f) { @@ -561,7 +561,7 @@ public Either sequence(final Either e) { */ public List> traverseList(final F> f) { return isRight() ? - f.f(value()).map(x -> Either.right(x)) : + f.f(value()).map(x -> right(x)) : list(Either.left(e.left().value())); } @@ -580,13 +580,13 @@ public IO> traverseIO(final F> f) { public P1> traverseP1(final F> f) { return isRight() ? f.f(value()).map(x -> Either.right(x)) : - P.p(Either.left(e.left().value())); + p(Either.left(e.left().value())); } public Option> traverseOption(final F> f) { return isRight() ? f.f(value()).map(x -> Either.right(x)) : - Option.some(Either.left(e.left().value())); + some(Either.left(e.left().value())); } /** @@ -693,8 +693,8 @@ public Collection toCollection() { public Stream> traverseStream(F> f) { return isRight() ? - f.f(value()).map(x -> Either.right(x)) : - Stream.>single(Either.left(e.left().value())); + f.f(value()).map(x -> right(x)) : + Stream.>single(left(e.left().value())); } } diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index fe57a643..cc143f33 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -368,12 +368,12 @@ else if (l < 0L) { * An enumerator for Natural */ public static final Enumerator naturalEnumerator = enumerator( - n -> Option.some(n.succ()), + n -> some(n.succ()), n -> n.pred(), Option.none(), some(Natural.ZERO), naturalOrd, curry((n, l) -> some(n).apply( - Natural.natural(l).map(Function.curry((n1, n2) -> n1.add(n2))) + Natural.natural(l).map(curry((n1, n2) -> n1.add(n2))) ) ) ); diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 3e6ff3b3..cde1e607 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -347,7 +347,7 @@ public static HashMap fromMap(java.util.Map map) { } public static HashMap fromMap(Equal eq, Hash h, java.util.Map map) { - HashMap m = HashMap.hashMap(eq, h); + HashMap m = hashMap(eq, h); for (Map.Entry e: map.entrySet()) { m.set(e.getKey(), e.getValue()); } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 1a3e93ff..755ce9fa 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -126,7 +126,7 @@ public static IO> enumFileChars(final File f, final Opti } public static IO bufferedReader(final File f, final Option encoding) { - return IOFunctions.map(fileReader(f, encoding), a -> new BufferedReader(a)); + return map(fileReader(f, encoding), a -> new BufferedReader(a)); } public static IO fileReader(final File f, final Option encoding) { @@ -372,15 +372,15 @@ public static IO unless(final Boolean b, final IO io) { */ public static IO> sequence(List> list) { F2, IO>, IO>> f2 = (io, ioList) -> - IOFunctions.bind(ioList, (xs) -> map(io, x -> List.cons(x, xs))); - return list.foldRight(f2, IOFunctions.unit(List.nil())); + bind(ioList, (xs) -> map(io, x -> List.cons(x, xs))); + return list.foldRight(f2, unit(List.nil())); } public static IO> sequence(Stream> stream) { F2>, IO, IO>> f2 = (ioList, io) -> - IOFunctions.bind(ioList, (xs) -> map(io, x -> Stream.cons(x, () -> xs))); - return stream.foldLeft(f2, IOFunctions.unit(Stream.nil())); + bind(ioList, (xs) -> map(io, x -> Stream.cons(x, () -> xs))); + return stream.foldLeft(f2, unit(Stream.nil())); } @@ -418,7 +418,7 @@ public static IO flatMap(final IO io, final F> f) { * @param transform Function to change line value */ public static IO interactWhile(F condition, F transform) { - Stream> s1 = Stream.repeat(IOFunctions.stdinReadLine()); + Stream> s1 = Stream.repeat(stdinReadLine()); IO> io = sequenceWhile(s1, condition); return () -> runSafe(io).foreach(s -> runSafe(stdoutPrintln(transform.f(s)))); } @@ -507,7 +507,7 @@ public static IO stdoutPrint(final String s) { public static IO getContents() { Stream> s = Stream.>repeat(() -> (int) stdinBufferedReader.read()); - return IOFunctions.map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> { + return map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> { return (char) i.intValue(); }))); } diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java index 8b1b2ac6..adb0c7af 100644 --- a/core/src/main/java/fj/data/IOW.java +++ b/core/src/main/java/fj/data/IOW.java @@ -40,6 +40,6 @@ public IOW getContents() { } public IOW interact(F f) { - return IOW.lift(() -> IOFunctions.interact(f).run()); + return lift(() -> IOFunctions.interact(f).run()); } } diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 523b4152..9c701a98 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -420,7 +420,7 @@ public ListIterator listIterator(final int index) { } public List subList(final int fromIndex, final int toIndex) { - return wrap(Stream.iterableStream(IterableW.this).drop(fromIndex).take(toIndex - fromIndex)).toStandardList(); + return wrap(iterableStream(IterableW.this).drop(fromIndex).take(toIndex - fromIndex)).toStandardList(); } private ListIterator toListIterator(final Option> z) { diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index 95160de1..2583621f 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -224,7 +224,7 @@ public LazyString reverse() { * @return The first index of the given character in this lazy string, or None if the character is not present. */ public Option indexOf(final char c) { - return s.indexOf(Equal.charEqual.eq(c)); + return s.indexOf(charEqual.eq(c)); } /** diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 26ec5e33..f12d5a26 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -122,7 +122,7 @@ public final boolean isNotEmpty() { */ @Deprecated public final B list(final B nil, final F, B>> cons) { - return uncons(Function.uncurryF2(cons), nil); + return uncons(uncurryF2(cons), nil); } public final B uncons(final F2, B> cons, final B nil) { @@ -410,9 +410,9 @@ public final P2, List> span(final F p) { if (p.f(xs.head())) b.snoc(xs.head()); else - return P.p(b.toList(), xs); + return p(b.toList(), xs); } - return P.p(b.toList(), List.nil()); + return p(b.toList(), List.nil()); } /** @@ -614,7 +614,7 @@ public final List sequence(final List bs) { public Option> traverseOption(final F> f) { return foldRight( (a, obs) -> f.f(a).bind(o -> obs.map(os -> os.cons(o))), - Option.some(List.nil()) + some(List.nil()) ); } @@ -641,7 +641,7 @@ public Stream> traverseStream(final F> f) { public P1> traverseP1(final F> f){ return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - P.p(List.nil()) + p(List.nil()) ); } @@ -656,7 +656,7 @@ public F> traverseF(F> f) { return this.foldRight( (a, acc) -> Function.bind(acc, (bs) -> Function.> compose(b -> bs.cons(b), f.f(a))), - Function.constant(List. nil()) + constant(List. nil()) ); } @@ -675,7 +675,7 @@ public Promise> traversePromise(final F> f) { public List> traverseList(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - List.single(List. nil())); + single(List. nil())); } public Validation> traverseValidation(final F> f) { @@ -707,7 +707,7 @@ public final List apply(final List> lf) { * @return A new list that has appended the given list. */ public final List append(final List as) { - return Buffer.fromList(this).prependToList(as); + return fromList(this).prependToList(as); } /** @@ -830,7 +830,7 @@ public final A index(final int i) { * @return A new list with a length the same, or less than, this list. */ public final List take(final int i) { - Buffer result = Buffer.empty(); + Buffer result = empty(); List list = this; int index = i; while (index > 0 && list.isNotEmpty()) { @@ -868,7 +868,7 @@ public final List drop(final int i) { public final P2, List> splitAt(final int i) { int c = 0; List first = List.nil(); - List second = List.nil(); + List second = nil(); for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) { final A h = xs.head(); if (c < i) { @@ -878,7 +878,7 @@ public final P2, List> splitAt(final int i) { } c++; } - return P.p(first.reverse(), second.reverse()); + return p(first.reverse(), second.reverse()); } /** @@ -906,10 +906,10 @@ public final List> partition(final int n) { */ public P2, List> partition(F f) { P2, List> p2 = foldLeft(acc -> a -> - f.f(a) ? P.p(acc._1().cons(a), acc._2()) : P.p(acc._1(), acc._2().cons(a)), - P.p(nil(), nil()) + f.f(a) ? p(acc._1().cons(a), acc._2()) : p(acc._1(), acc._2().cons(a)), + p(nil(), nil()) ); - return P.p(p2._1().reverse(), p2._2().reverse()); + return p(p2._1().reverse(), p2._2().reverse()); } /** @@ -1115,7 +1115,7 @@ public final Option find(final F f) { public final List intersperse(final A a) { return isEmpty() || tail().isEmpty() ? this : - cons(head(), tail().bind(a2 -> List.list(a, a2))); + cons(head(), tail().bind(a2 -> list(a, a2))); } /** @@ -1320,7 +1320,7 @@ public final TreeMap> groupBy(final F keyFunction) { * @return A TreeMap containing the keys with the accumulated list of matched elements. */ public final TreeMap> groupBy(final F keyFunction, final Ord keyOrd) { - return groupBy(keyFunction, Function.identity(), keyOrd); + return groupBy(keyFunction, identity(), keyOrd); } /** @@ -1372,7 +1372,7 @@ public final TreeMap groupBy( final Monoid monoid, final Ord keyOrd) { return groupBy(keyFunction, valueFunction, monoid.zero(), - Function.uncurryF2(monoid.sum()), keyOrd); + uncurryF2(monoid.sum()), keyOrd); } /** @@ -1709,7 +1709,7 @@ public static P2, List> unzip(final List> xs) { ba = ba.snoc(p._1()); bb = bb.snoc(p._2()); } - return P.p(ba.toList(), bb.toList()); + return p(ba.toList(), bb.toList()); } /** @@ -1720,7 +1720,7 @@ public static P2, List> unzip(final List> xs) { * @return A list of the given value replicated the given number of times. */ public static List replicate(final int n, final A a) { - List list = List.nil(); + List list = nil(); for (int i = 0; i < n; i++) { list = list.cons(a); } return list; } @@ -1735,7 +1735,7 @@ public static List replicate(final int n, final A a) { * to value (exclusive). */ public static List range(final int from, final int to) { - final Buffer buf = Buffer.empty(); + final Buffer buf = empty(); for (int i = from; i < to; i++) { buf.snoc(i); } @@ -1815,7 +1815,7 @@ public static List single(final A a) { */ public static List iterateWhile(final F f, final F p, final A a) { return unfold( - o -> Option.iif(p2 -> p.f(o), P.p(o, f.f(o))) + o -> Option.iif(p2 -> p.f(o), p(o, f.f(o))) , a); } @@ -2210,7 +2210,7 @@ public static Prism, Unit> nil() { * Cons prism */ public static Prism, P2>> cons() { - return prism(l -> l.>>> list(none(), h -> tail -> some(P.p(h, tail))), c -> List.cons(c._1(), c._2())); + return prism(l -> l.>>> list(none(), h -> tail -> some(p(h, tail))), c -> List.cons(c._1(), c._2())); } } diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index cb58e61f..5bec1ea4 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -432,7 +432,7 @@ public Stream> traverseStream(F> f) { } public P1> traverseP1(F> f) { - return map(a -> f.f(a).map(b -> some(b))).orSome(P.p(none())); + return map(a -> f.f(a).map(b -> some(b))).orSome(p(none())); } public Seq> traverseSeq(F> f) { diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 00868ef3..84b26d6e 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -106,7 +106,7 @@ public static Seq listSeq(final List list) { * @return A sequence with the elements of the iterable. */ public static Seq iterableSeq(final Iterable i) { - Seq s = Seq.empty(); + Seq s = empty(); for (final A a: i) { s = s.snoc(a); } diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index c54d6cb7..2d87234f 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -79,7 +79,7 @@ public State gets() { } public static State put(S s) { - return State.unit((S z) -> p(s, Unit.unit())); + return unit((S z) -> p(s, Unit.unit())); } public A eval(S s) { diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index cb6fe8d0..485ca1ad 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -351,7 +351,7 @@ public final Stream removeAll(final F f) { * and returns a stream of the results. */ public static F> sequence_(final Stream> fs) { - return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), Function.curry((a, stream) -> cons(a, p(stream)))), Function + return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), curry((a, stream) -> cons(a, p(stream)))), Function .>constant(Stream.nil())); } @@ -531,7 +531,7 @@ public static Stream> sequence(final IO> io) { * @return The stream of (pre-calculated) lazy values after sequencing. */ public static Stream> sequence(final F0> p) { - return p.f().map(a -> P.p(a)); + return p.f().map(a -> p(a)); } /** @@ -541,7 +541,7 @@ public static Stream> sequence(final F0> p) { * @return The stream of options after sequencing. */ public static Stream> sequence(final Option> o) { - return o.isNone() ? Stream.nil() : o.some().map(a -> Option.some(a)); + return o.isNone() ? nil() : o.some().map(a -> some(a)); } /** @@ -566,9 +566,9 @@ public final Stream interleave(final Stream as) { public static Stream enumerationStream(Enumeration e) { if (e.hasMoreElements()) { - return Stream.cons(e.nextElement(), () -> enumerationStream(e)); + return cons(e.nextElement(), () -> enumerationStream(e)); } else { - return Stream.nil(); + return nil(); } } @@ -627,7 +627,7 @@ public final Stream sort(final Ord o, final Strategy s) { private Promise> qs(final Ord o, final Strategy s) { if (isEmpty()) - return promise(s, P.p(this)); + return promise(s, p(this)); else { final F id = identity(); final A x = head(); @@ -797,7 +797,7 @@ public static Stream range(final Enumerator e, final A from, final A t */ public static Stream range(final Enumerator e, final A from, final A to, final long step) { final Ordering o = e.order().compare(from, to); - return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, () -> Stream.join(e.plus(from, step).filter(a -> !(o == LT + return o == EQ || step > 0L && o == GT || step < 0L && o == LT ? single(from) : cons(from, () -> join(e.plus(from, step).filter(a -> !(o == LT ? e.order().isLessThan(to, a) : e.order().isGreaterThan(to, a))).map(a1 -> range(e, a1, to, step)).toStream())); } @@ -1336,7 +1336,7 @@ public final Stream> tails() { * @return a stream of the prefixes of this stream, starting with the stream itself. */ public final Stream> inits() { - final Stream> nil = Stream.cons(Stream.nil(), () -> nil()); + final Stream> nil = cons(Stream.nil(), () -> nil()); return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.cons_().f(head()))); } @@ -1418,8 +1418,8 @@ public static Stream fromFunction(final Enumerator e, final F public static P2, Stream> unzip(final Stream> xs) { return xs.foldRight((p, ps) -> { final P2, Stream> pp = ps._1(); - return P.p(cons(p._1(), P.p(pp._1())), cons(p._2(), P.p(pp._2()))); - }, P.p(Stream.nil(), Stream.nil())); + return p(cons(p._1(), p(pp._1())), cons(p._2(), p(pp._2()))); + }, p(Stream.nil(), Stream.nil())); } /** @@ -1591,7 +1591,7 @@ public static Stream unfold(final F>> f, final B b) */ public static Stream iterateWhile(final F f, final F p, final A a) { return unfold( - o -> Option.iif(p2 -> p.f(o), P.p(o, f.f(o))) + o -> Option.iif(p2 -> p.f(o), p(o, f.f(o))) , a); } @@ -1609,7 +1609,7 @@ public static Stream iterableStream(final Iterable i) { public static Stream arrayStream(final A...as) { return as.length == 0 ? Stream.nil() : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.>>none() - : some(P.p(as[i], P.p(as, i + 1)))), P.p(as, 0)); + : some(p(as[i], p(as, i + 1)))), p(as, 0)); } /** diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index f02a6e73..004e0910 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -252,7 +252,7 @@ private static Stream drawSubTrees(final Show s, final Stream shift(final String f, final String o, final Stream s) { - return Stream.repeat(o).cons(f).zipWith(s, Monoid.stringMonoid.sum()); + return repeat(o).cons(f).zipWith(s, Monoid.stringMonoid.sum()); } private Stream drawTree(final Show s) { @@ -328,7 +328,7 @@ public Tree zipWith(final Tree bs, final F> f) { public static Tree bottomUp(Tree t, final F>, B> f) { final F, Tree> recursiveCall = a -> bottomUp(a, f); final Stream> tbs = t.subForest()._1().map(recursiveCall); - return Tree.node(f.f(P.p(t.root(), tbs.map(Tree. getRoot()))), tbs); + return node(f.f(P.p(t.root(), tbs.map(Tree. getRoot()))), tbs); } /** diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index e35e6592..2bdf70a9 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -129,7 +129,7 @@ public static TreeMap arrayTreeMap(final Ord keyOrd, final P2 get(final K k) { - final Option>> x = tree.split(P.p(k, Option.none()))._2(); + final Option>> x = tree.split(p(k, Option.none()))._2(); return x.bind(P2.>__2()); } @@ -142,7 +142,7 @@ public Option get(final K k) { * @return A new tree map with the given value mapped to the given key. */ public TreeMap set(final K k, final V v) { - return new TreeMap(tree.insert(P.p(k, Option.some(v)))); + return new TreeMap(tree.insert(p(k, Option.some(v)))); } /** @@ -152,7 +152,7 @@ public TreeMap set(final K k, final V v) { * @return A new tree map with the entry corresponding to the given key removed. */ public TreeMap delete(final K k) { - return new TreeMap(tree.delete(P.p(k, Option.none()))); + return new TreeMap(tree.delete(p(k, Option.none()))); } /** @@ -198,7 +198,7 @@ public List keys() { * @return true if this tree map contains the given key, false otherwise. */ public boolean contains(final K k) { - return tree.member(P.p(k, Option.none())); + return tree.member(p(k, Option.none())); } /** @@ -218,7 +218,7 @@ public Iterator> iterator() { * @return A new mutable map isomorphic to this tree map. */ public Map toMutableMap() { - final F>> fakePair = k -> P.p(k, Option.none()); + final F>> fakePair = k -> p(k, Option.none()); final Comparator comparator = tree.ord().contramap(fakePair).toComparator(); final Map m = new java.util.TreeMap(comparator); for (final P2 e : this) { @@ -278,7 +278,7 @@ public F> get() { public P2> update(final K k, final F f) { final P2>>> up = tree.update(p(k, Option.none()), compose(P2.tuple(P.p2()), P2., Option>map2_(Option.map().f(f)))); - return P.p(up._1(), new TreeMap(up._2())); + return p(up._1(), new TreeMap(up._2())); } /** @@ -347,9 +347,9 @@ private static TreeMap treeMap(Ord ord, Set>> s) * given key if present, otherwise None. */ public P3, Option, TreeMap> splitLookup(final K k) { - P3>>, Option>>, Set>>> p3 = tree.split(P.p(k, get(k))); - Ord o = tree.ord().contramap(k2 -> P.p(k2, Option.none())); - return P.p(treeMap(o, p3._1()), get(k), treeMap(o, p3._3())); + P3>>, Option>>, Set>>> p3 = tree.split(p(k, get(k))); + Ord o = tree.ord().contramap(k2 -> p(k2, Option.none())); + return p(treeMap(o, p3._1()), get(k), treeMap(o, p3._3())); } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index a87b4585..3e622f68 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -208,7 +208,7 @@ public static Validation> sequence(final Semigroup s, final if (list.exists(v -> v.isFail())) { return Validation.>fail(list.filter(v -> v.isFail()).map(v -> v.fail()).foldLeft1((e1, e2) -> s.sum(e1, e2))); } else { - return Validation.success(list.foldLeft((List acc, Validation v) -> acc.cons(v.success()), List.nil()).reverse()); + return success(list.foldLeft((List acc, Validation v) -> acc.cons(v.success()), List.nil()).reverse()); } } @@ -722,17 +722,17 @@ public Iterator iterator() { public Validation, T> accumulate() { if (isFail()) { - return Validation.fail(List.single(fail())); + return fail(List.single(fail())); } else { - return Validation.success(success()); + return success(success()); } } public Validation, B> accumulate(F f) { if (isFail()) { - return Validation.fail(List.single(fail())); + return fail(List.single(fail())); } else { - return Validation.success(f.f(success())); + return success(f.f(success())); } } @@ -746,9 +746,9 @@ public Validation, C> accumulate(Validation v2, F2 list = list.cons(v2.fail()); } if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success())); + return success(f.f(success(), v2.success())); } } @@ -757,27 +757,27 @@ public Validation, C> accumulate(Validation v2, F2 public Validation, D> accumulate(Validation v2, Validation v3, F3 f) { List list = fails(list(this, v2, v3)); if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success(), v3.success())); + return success(f.f(success(), v2.success(), v3.success())); } } public Validation, $E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { List list = fails(list(this, v2, v3, v4)); if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success())); + return success(f.f(success(), v2.success(), v3.success(), v4.success())); } } public Validation, $F> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, F5 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success())); + return success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success())); } } @@ -785,27 +785,27 @@ public Validation, D> accumulate(Validation v2, Validati public Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success())); + return success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success())); } } public Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success(), v7.success())); + return success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success(), v7.success())); } } public Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { - return Validation.fail(list); + return fail(list); } else { - return Validation.success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success(), v7.success(), v8.success())); + return success(f.f(success(), v2.success(), v3.success(), v4.success(), v5.success(), v6.success(), v7.success(), v8.success())); } } @@ -818,10 +818,10 @@ public Validation, D> accumulate(Validation v2, Validati public static Validation, List> sequenceNonCumulative(List> list) { if (list.exists(v -> v.isFail())) { F2, Validation, List> f = (acc, v) -> acc.cons(v.fail()); - return Validation.fail(list.filter(v -> v.isFail()).foldLeft(f, List.nil()).reverse()); + return fail(list.filter(v -> v.isFail()).foldLeft(f, List.nil()).reverse()); } else { F2, Validation, List> f = (acc, v) -> acc.cons(v.success()); - return Validation.success(list.filter(v -> v.isSuccess()).foldLeft(f, List.nil()).reverse()); + return success(list.filter(v -> v.isSuccess()).foldLeft(f, List.nil()).reverse()); } } @@ -852,7 +852,7 @@ public IO> traverseIO(F> f){ public P1> traverseP1(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : - P.p(fail(e.left().value())); + p(fail(e.left().value())); } @@ -1276,7 +1276,7 @@ public static Validation parseShort(final String s * Partitions the list into the list of fails and the list of successes */ public static P2, List> partition(List> list) { - return P.p( + return p( list.filter(v -> v.isFail()).map(v -> v.fail()), list.filter(v -> v.isSuccess()).map(v -> v.success()) ); diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index 7ff57d07..b384e259 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -59,7 +59,7 @@ public static Writer unit(B b) { } public static F> stringLogger() { - return a -> Writer.unit(a, Monoid.stringMonoid); + return a -> unit(a, Monoid.stringMonoid); } } diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index 9f86db45..1078374b 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -225,7 +225,7 @@ public final P3, A, FingerTree> split1(final F FingerTree emptyIntAddition() { - return FingerTree.mkTree(FingerTree.measured(intAdditionMonoid, Function.constant(1))).empty(); + return mkTree(FingerTree.measured(intAdditionMonoid, Function.constant(1))).empty(); } } diff --git a/core/src/main/java/fj/data/fingertrees/Single.java b/core/src/main/java/fj/data/fingertrees/Single.java index 410378f1..1bbe7884 100644 --- a/core/src/main/java/fj/data/fingertrees/Single.java +++ b/core/src/main/java/fj/data/fingertrees/Single.java @@ -81,7 +81,7 @@ public V measure() { @Override P3, A, FingerTree> split1(final F predicate, final V acc) { final Empty empty = new Empty<>(measured()); - return P.p(empty, a, empty); + return p(empty, a, empty); } @Override public P2 lookup(final F o, final int i) { return p(i, a); } diff --git a/demo/src/main/java/fj/demo/realworld/Chapter7.java b/demo/src/main/java/fj/demo/realworld/Chapter7.java index 2f6ed8a4..f9263683 100644 --- a/demo/src/main/java/fj/demo/realworld/Chapter7.java +++ b/demo/src/main/java/fj/demo/realworld/Chapter7.java @@ -36,7 +36,7 @@ public static void toUpperLazy() { * Read each line, convert to uppercase and print on stdout, until an empty line */ public static void toUpperByLine() { - Stream> s1 = Stream.repeat(IOFunctions.stdinReadLine()); + Stream> s1 = Stream.repeat(stdinReadLine()); IO> io = sequenceWhile(s1, s -> s.trim().length() > 0); runSafe(io).foreachDoEffect(s -> runSafe(stdoutPrintln(s.toUpperCase()))); } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 34a17ae1..5222df9e 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -128,7 +128,7 @@ public Gen f(final A x) { } public static Arbitrary> arbReader(Coarbitrary aa, Arbitrary ab) { - return arbitrary(Arbitrary.arbF(aa, ab).gen.map(f -> Reader.unit(f))); + return arbitrary(arbF(aa, ab).gen.map(f -> Reader.unit(f))); } /** @@ -819,7 +819,7 @@ public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { } public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, int max) { - Gen> g = Gen.choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.iterableSet(ord, list)); + Gen> g = choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.iterableSet(ord, list)); return arbitrary(g); } @@ -902,7 +902,7 @@ public Date f(final Long i) { * @return An arbitrary for instances of the supplied enum type. */ public static > Arbitrary arbEnumValue(final Class clazz) { - return arbitrary(Gen.elements(clazz.getEnumConstants())); + return arbitrary(elements(clazz.getEnumConstants())); } /** @@ -1161,7 +1161,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb if (i < 0) { Bottom.error("Undefined: arbitrary natural is negative (" + i + ")"); } - return Gen.sequenceN(Math.max(i, 0), Arbitrary.arbP2(ak, av).gen); + return Gen.sequenceN(Math.max(i, 0), arbP2(ak, av).gen); }); return arbTreeMap(ord, arbitrary(gl2)); } @@ -1173,7 +1173,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb if (maxSize < 0) { Bottom.error("Undefined: arbitrary natural is negative (" + maxSize + ")"); } - return arbTreeMap(ord, ak, av, arbitrary(Gen.choose(0, maxSize))); + return arbTreeMap(ord, ak, av, arbitrary(choose(0, maxSize))); } /** diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 3231cf2e..1486a695 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -367,7 +367,7 @@ public Result f(final Rand r) { * will be taken from the given boolean b. */ public static Property impliesBoolean(final boolean a, final boolean b) { - return implies(a, () -> Property.prop(b)); + return implies(a, () -> prop(b)); } /** @@ -375,7 +375,7 @@ public static Property impliesBoolean(final boolean a, final boolean b) { * will be taken from the given lazy boolean b. */ public static Property impliesBoolean(final boolean a, final F0 b) { - return implies(a, () -> Property.prop(b.f())); + return implies(a, () -> prop(b.f())); } /** From 3655b4d143cb3a52d604ea41da110839684c9b74 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 20:17:43 +0100 Subject: [PATCH 508/811] Remove redundant public/abstract modifiers on interfaces --- core/src/main/java/fj/F.java | 2 +- core/src/main/java/fj/F0.java | 2 +- core/src/main/java/fj/F2.java | 2 +- core/src/main/java/fj/F3.java | 2 +- core/src/main/java/fj/F4.java | 2 +- core/src/main/java/fj/F5.java | 2 +- core/src/main/java/fj/F6.java | 2 +- core/src/main/java/fj/F7.java | 2 +- core/src/main/java/fj/F8.java | 2 +- core/src/main/java/fj/data/IO.java | 2 +- core/src/main/java/fj/data/SafeIO.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java index 1b524fdc..2a0136bf 100644 --- a/core/src/main/java/fj/F.java +++ b/core/src/main/java/fj/F.java @@ -45,6 +45,6 @@ public interface F { * @param a The A to transform. * @return The result of the transformation. */ - public abstract B f(A a); + B f(A a); } diff --git a/core/src/main/java/fj/F0.java b/core/src/main/java/fj/F0.java index e85689da..eab82a01 100644 --- a/core/src/main/java/fj/F0.java +++ b/core/src/main/java/fj/F0.java @@ -5,6 +5,6 @@ */ public interface F0 { - public A f(); + A f(); } diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index 0aa82585..1723927a 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -33,6 +33,6 @@ public interface F2 { * @param b The B to transform. * @return The result of the transformation. */ - public C f(A a, B b); + C f(A a, B b); } diff --git a/core/src/main/java/fj/F3.java b/core/src/main/java/fj/F3.java index 68e7627a..540afdaa 100644 --- a/core/src/main/java/fj/F3.java +++ b/core/src/main/java/fj/F3.java @@ -15,5 +15,5 @@ public interface F3 { * @param c The C to transform. * @return The result of the transformation. */ - public D f(A a, B b, C c); + D f(A a, B b, C c); } diff --git a/core/src/main/java/fj/F4.java b/core/src/main/java/fj/F4.java index 9447389a..84dcfafa 100644 --- a/core/src/main/java/fj/F4.java +++ b/core/src/main/java/fj/F4.java @@ -16,5 +16,5 @@ public interface F4 { * @param d The D to transform. * @return The result of the transformation. */ - public E f(A a, B b, C c, D d); + E f(A a, B b, C c, D d); } diff --git a/core/src/main/java/fj/F5.java b/core/src/main/java/fj/F5.java index ff7184f2..5fea676b 100644 --- a/core/src/main/java/fj/F5.java +++ b/core/src/main/java/fj/F5.java @@ -19,5 +19,5 @@ public interface F5 { * @param e The E to transform. * @return The result of the transformation. */ - public F$ f(A a, B b, C c, D d, E e); + F$ f(A a, B b, C c, D d, E e); } diff --git a/core/src/main/java/fj/F6.java b/core/src/main/java/fj/F6.java index f403eb0a..20101cf7 100644 --- a/core/src/main/java/fj/F6.java +++ b/core/src/main/java/fj/F6.java @@ -20,5 +20,5 @@ public interface F6 { * @param f The F$ to transform. * @return The result of the transformation. */ - public G f(A a, B b, C c, D d, E e, F$ f); + G f(A a, B b, C c, D d, E e, F$ f); } diff --git a/core/src/main/java/fj/F7.java b/core/src/main/java/fj/F7.java index be9d87e1..5a3ea1ef 100644 --- a/core/src/main/java/fj/F7.java +++ b/core/src/main/java/fj/F7.java @@ -21,5 +21,5 @@ public interface F7 { * @param g The G to transform. * @return The result of the transformation. */ - public H f(A a, B b, C c, D d, E e, F$ f, G g); + H f(A a, B b, C c, D d, E e, F$ f, G g); } diff --git a/core/src/main/java/fj/F8.java b/core/src/main/java/fj/F8.java index 5ad75489..8b986456 100644 --- a/core/src/main/java/fj/F8.java +++ b/core/src/main/java/fj/F8.java @@ -22,5 +22,5 @@ public interface F8 { * @param h The H to transform. * @return The result of the transformation. */ - public I f(A a, B b, C c, D d, E e, F$ f, G g, H h); + I f(A a, B b, C c, D d, E e, F$ f, G g, H h); } diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index eefd11b9..ee27bdb7 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -15,6 +15,6 @@ */ public interface IO { - public A run() throws IOException; + A run() throws IOException; } diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index 2935ca83..13bbbcc5 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -8,7 +8,7 @@ public interface SafeIO extends IO { @Override - public A run(); + A run(); } From a60afe9732d7a367fe8eabd3bd7fa9155f18addc Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 20:39:49 +0100 Subject: [PATCH 509/811] Remove unnecessary parentheses --- core/src/main/java/fj/Semigroup.java | 2 +- core/src/main/java/fj/data/Stream.java | 2 +- core/src/main/java/fj/data/optic/PTraversal.java | 2 +- demo/src/main/java/fj/demo/Array_foldLeft.java | 2 +- demo/src/main/java/fj/demo/StateDemo_VendingMachine.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 18172990..5d4b995d 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -92,7 +92,7 @@ static A multiply1p(F> sum, int n, A a) { } } xTmp = sum.f(xTmp).f(xTmp); - yTmp = (yTmp) >>> 1; + yTmp = yTmp >>> 1; } } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 485ca1ad..fcb6c1d0 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -374,7 +374,7 @@ public final F> mapM(final F> f) { * @return A new stream after performing the map, then final join. */ public final Stream bind(final F> f) { - return foldRight(h -> (t -> f.f(h).append(t)), nil()); + return foldRight(h -> t -> f.f(h).append(t), nil()); } /** diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index 8e98cf2f..50c1e14c 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -533,7 +533,7 @@ public F foldMap(final Monoid monoid, final F f) { public static PTraversal pTraversal(final F get1, final F get2, final F get3, final F4 set) { - return fromCurried(pTraversal(get1, get2, (b1, b2, s) -> (b3 -> set.f(b1, b2, b3, s))), get3); + return fromCurried(pTraversal(get1, get2, (b1, b2, s) -> b3 -> set.f(b1, b2, b3, s)), get3); } public static PTraversal pTraversal(final F get1, final F get2, final F get3, diff --git a/demo/src/main/java/fj/demo/Array_foldLeft.java b/demo/src/main/java/fj/demo/Array_foldLeft.java index 9acb86be..f7f1ce58 100644 --- a/demo/src/main/java/fj/demo/Array_foldLeft.java +++ b/demo/src/main/java/fj/demo/Array_foldLeft.java @@ -12,7 +12,7 @@ public static void main(final String[] args) { // WARNING: In JDK 8, update 20 and 25 (current version) the following code triggers an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. // final int c = a.foldLeft(i -> (j -> i + j), 0); - F> add2 = i -> (j -> i + j); + F> add2 = i -> j -> i + j; final int c = a.foldLeft(add2, 0); System.out.println(b); // 1774 } diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index 0f09318a..e31c9f27 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -48,7 +48,7 @@ public boolean equals(Object o) { */ @Override public int hashCode() { - int result = (locked ? 1 : 0); + int result = locked ? 1 : 0; result = 31 * result + items; result = 31 * result + coins; return result; From 2b7633f5409c3d6a222bf70a3bb8476e61fb2b6e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 20:40:36 +0100 Subject: [PATCH 510/811] Remove unnecessary semicolon --- demo/src/main/java/fj/demo/StateDemo_VendingMachine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index e31c9f27..3178e37b 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -12,7 +12,7 @@ */ public class StateDemo_VendingMachine { - public enum Input { COIN, TURN }; + public enum Input { COIN, TURN } public static class VendingMachine { From 702202297bc4427556e94ffed84502aad01b52b3 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 16:49:36 +0100 Subject: [PATCH 511/811] Remove usage of deprecated API --- core/src/main/java/fj/P1.java | 4 ++-- core/src/main/java/fj/data/HashMap.java | 6 +++--- core/src/main/java/fj/data/List.java | 8 ++++---- core/src/test/java/fj/data/ListTest.java | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 1995352e..0cb92a89 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -86,7 +86,7 @@ public static F> curry(final F f) { */ public P1 apply(final P1> cf) { P1 self = this; - return cf.bind(f -> fmap(f).f(self)); + return cf.bind(f -> map_(f).f(self)); } /** @@ -97,7 +97,7 @@ public P1 apply(final P1> cf) { * @return A new P1 after performing the map, then final join. */ public P1 bind(final P1 cb, final F> f) { - return cb.apply(fmap(f).f(this)); + return cb.apply(map_(f).f(this)); } /** diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index cde1e607..e45d94a5 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -272,11 +272,11 @@ public HashMap map(F keyFunction, } public HashMap map(F, P2> function, Equal equal, Hash hash) { - return from(toStream().map(function), equal, hash); + return iterableHashMap(equal, hash, toStream().map(function)); } public HashMap map(F, P2> function) { - return from(toStream().map(function)); + return iterableHashMap(toStream().map(function)); } public HashMap mapKeys(F keyFunction, Equal equal, Hash hash) { @@ -339,7 +339,7 @@ public java.util.Map toMap() { */ @Deprecated public static HashMap from(final Iterable> entries) { - return iterableHashMap(Equal.anyEqual(), Hash.anyHash(), entries); + return iterableHashMap(entries); } public static HashMap fromMap(java.util.Map map) { diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index f12d5a26..31c4a4af 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -2188,15 +2188,15 @@ public static Traversal, A> traversal() { * Optional targeted on Cons head. */ public static Optional, A> head() { - return optional(l -> l.toOption(), a -> l -> l.>list(l, constant(cons_(a)))); + return optional(List::headOption, a -> l -> l.uncons((__, as) -> as.cons(a), l)); } /** * Optional targeted on Cons tail. */ public static Optional, List> tail() { - return optional(l -> l.>> list(none(), h -> tail -> some(tail)), - tail -> l -> l.list(l, h -> constant(List.cons(h, tail)))); + return optional(l -> l.uncons((__, tail) -> some(tail), none()), + tail -> l -> l.uncons((h, __) -> List.cons(h, tail), l)); } /** @@ -2210,7 +2210,7 @@ public static Prism, Unit> nil() { * Cons prism */ public static Prism, P2>> cons() { - return prism(l -> l.>>> list(none(), h -> tail -> some(p(h, tail))), c -> List.cons(c._1(), c._2())); + return prism(l -> l.>>> uncons((h, tail) -> some(p(h, tail)), none()), c -> List.cons(c._1(), c._2())); } } diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 8725ef05..3b720fe6 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -82,13 +82,13 @@ public void listReduce() { } @Test - public void toJavaArray() { + public void array() { final int max = 3; Integer[] ints = new Integer[max]; for (int i = 0; i < max; i++) { ints[i] = i + 1; }; - assertThat(List.range(1, max + 1).toJavaArray(), equalTo(ints)); + assertThat(List.range(1, max + 1).array(Integer[].class), equalTo(ints)); } } From 9fa7b497d238f9be83fc23e9b544a9466f1fda29 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 20:59:47 +0100 Subject: [PATCH 512/811] simplify boolean expression --- core/src/main/java/fj/Semigroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 5d4b995d..6e091d7f 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -240,7 +240,7 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that XORs booleans. */ - public static final Semigroup exclusiveDisjunctionSemiGroup = semigroup((p, q) -> p && !q || !p && q); + public static final Semigroup exclusiveDisjunctionSemiGroup = semigroup((p, q) -> p ? !q : q); /** * A semigroup that ANDs booleans. From 00a5fdc34c5b97758a8a12f34cde4db3dd175f0f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 21:09:10 +0100 Subject: [PATCH 513/811] Add test for Ordering#reverse --- core/src/test/java/fj/OrderingTest.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 core/src/test/java/fj/OrderingTest.java diff --git a/core/src/test/java/fj/OrderingTest.java b/core/src/test/java/fj/OrderingTest.java new file mode 100644 index 00000000..9b980e67 --- /dev/null +++ b/core/src/test/java/fj/OrderingTest.java @@ -0,0 +1,21 @@ +package fj; + +import org.hamcrest.Matcher; +import org.hamcrest.core.Is; +import org.junit.Test; + +import static fj.Ordering.EQ; +import static fj.Ordering.GT; +import static fj.Ordering.LT; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class OrderingTest { + + @Test + public void reverse() throws Exception { + assertThat(GT.reverse(), is(LT)); + assertThat(LT.reverse(), is(GT)); + assertThat(EQ.reverse(), is(EQ)); + } +} \ No newline at end of file From a4fb2dfb6a7eb17db11f4d7f89a0442515fc1f43 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 21:19:46 +0100 Subject: [PATCH 514/811] More regular for loop --- core/src/main/java/fj/data/List.java | 4 +--- core/src/main/java/fj/data/Stream.java | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 31c4a4af..0b5a0d4c 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -848,11 +848,9 @@ public final List take(final int i) { * @return A list with a length the same, or less than, this list. */ public final List drop(final int i) { - int c = 0; - List xs = this; - for (; xs.isNotEmpty() && c < i; xs = xs.tail()) + for (int c = 0; xs.isNotEmpty() && c < i; xs = xs.tail()) c++; return xs; diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index fcb6c1d0..6dbcf778 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1072,11 +1072,9 @@ public final Stream take(final int n) { * @return A stream with a length the same, or less than, this stream. */ public final Stream drop(final int i) { - int c = 0; - Stream xs = this; - for (; xs.isNotEmpty() && c < i; xs = xs.tail()._1()) + for (int c = 0; xs.isNotEmpty() && c < i; xs = xs.tail()._1()) c++; return xs; From f374e16989844354fc6dc252a1adb017157d45fe Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 21:50:08 +0100 Subject: [PATCH 515/811] Improve error handling in DbState#run --- core/src/main/java/fj/control/db/DbState.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/control/db/DbState.java b/core/src/main/java/fj/control/db/DbState.java index 1243c309..228dff37 100644 --- a/core/src/main/java/fj/control/db/DbState.java +++ b/core/src/main/java/fj/control/db/DbState.java @@ -94,18 +94,21 @@ public Unit run(final Connection c) throws SQLException { * @throws SQLException in case of a database error. */ public A run(final DB dba) throws SQLException { - final Connection c = pc.connect(); - c.setAutoCommit(false); - try { - final A a = dba.run(c); + try (Connection c = pc.connect()) { + c.setAutoCommit(false); + final A a; + try { + a = dba.run(c); + } catch (RuntimeException | SQLException e) { + try { + c.rollback(); + } catch (Exception re) { + e.addSuppressed(re); + } + throw e; + } terminal.run(c); return a; - } catch (SQLException e) { - c.rollback(); - throw e; - } - finally { - c.close(); } } } From c45b0d64c66681d6779fa6ed021d263b2476b6f1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 22:01:17 +0100 Subject: [PATCH 516/811] Fix IOFunctions#bracket --- core/src/main/java/fj/data/IOFunctions.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 755ce9fa..6aa5db12 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -5,6 +5,7 @@ import static fj.Function.partialApply2; import java.io.BufferedReader; +import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -141,12 +142,8 @@ public static IO bracket(final IO init, final F> fin, f @Override public C run() throws IOException { final A a = init.run(); - try { + try(Closeable finAsCloseable = fin.f(a)::run) { return body.f(a).run(); - } catch (final IOException e) { - throw e; - } finally { - fin.f(a); } } }; From a069fa5e2ecdb8b7653bd1c40de0a1fb0a53a5a9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 22:08:58 +0100 Subject: [PATCH 517/811] Remove unused import statements --- core/src/main/java/fj/Class.java | 1 - core/src/main/java/fj/F.java | 32 ------------------- core/src/main/java/fj/F2.java | 19 ----------- core/src/main/java/fj/F2W.java | 7 ---- core/src/main/java/fj/F3Functions.java | 6 ---- core/src/main/java/fj/F4Functions.java | 3 -- core/src/main/java/fj/F5Functions.java | 3 -- core/src/main/java/fj/F6Functions.java | 3 -- core/src/main/java/fj/F7Functions.java | 3 -- core/src/main/java/fj/F8Functions.java | 3 -- core/src/main/java/fj/TryEffect.java | 4 --- core/src/main/java/fj/data/Enumerator.java | 2 +- core/src/main/java/fj/data/IterableW.java | 2 -- core/src/main/java/fj/data/Iteratee.java | 1 - core/src/main/java/fj/data/Java.java | 3 -- core/src/main/java/fj/data/Natural.java | 2 +- core/src/main/java/fj/data/SafeIO.java | 2 -- core/src/main/java/fj/data/State.java | 2 -- .../main/java/fj/data/fingertrees/Empty.java | 1 - .../main/java/fj/data/fingertrees/Node.java | 1 - core/src/main/java/fj/data/hlist/HPre.java | 1 - core/src/main/java/fj/data/vector/V.java | 1 - .../main/java/fj/function/BigIntegers.java | 1 - .../src/main/java/fj/function/Characters.java | 1 - core/src/main/java/fj/function/Doubles.java | 1 - core/src/main/java/fj/function/Integers.java | 2 +- core/src/main/java/fj/function/Longs.java | 2 +- core/src/main/java/fj/function/Visitor.java | 1 - core/src/main/java/fj/parser/Result.java | 2 +- demo/src/main/java/fj/demo/Array_bind.java | 1 - demo/src/main/java/fj/demo/ChequeWrite.java | 1 - .../main/java/fj/demo/Comonad_example.java | 1 - .../main/java/fj/demo/HList_foldRight.java | 2 -- demo/src/main/java/fj/demo/Primes2.java | 2 +- demo/src/main/java/fj/demo/Set_map.java | 1 - .../fj/demo/StateDemo_VendingMachine.java | 1 - .../main/java/fj/demo/concurrent/Fibs.java | 2 +- .../main/java/fj/demo/concurrent/Ping.java | 1 - .../java/fj/demo/concurrent/PingPong.java | 1 - .../main/java/fj/demo/concurrent/Pong.java | 1 - .../java/fj/demo/concurrent/WordCount.java | 1 - .../src/main/java/fj/demo/euler/Problem1.java | 1 - .../src/main/java/fj/demo/euler/Problem3.java | 2 -- .../src/main/java/fj/demo/euler/Problem4.java | 1 - .../java/fj/demo/test/AdditionCommutes.java | 1 - .../demo/test/AdditionCommutesParallel.java | 2 -- .../java/fj/demo/test/EqualsHashCode.java | 3 -- .../java/fj/demo/test/IntegerOverflow.java | 1 - .../java/fj/demo/test/JavaLinkedList.java | 1 - .../java/fj/demo/test/ListFunctorLaws.java | 2 -- .../fj/demo/test/OptionMonadFunctorLaw.java | 2 -- demo/src/main/java/fj/demo/test/Reflect.java | 2 -- .../fj/demo/test/StringBuilderReverse.java | 2 -- .../main/java/fj/demo/test/Triangulation.java | 1 - .../src/main/java/fj/test/Arbitrary.java | 1 - quickcheck/src/main/java/fj/test/Bool.java | 2 +- quickcheck/src/main/java/fj/test/Result.java | 1 - .../src/main/java/fj/test/reflect/Check.java | 1 - .../java/fj/test/reflect/CheckParams.java | 1 - 59 files changed, 8 insertions(+), 146 deletions(-) diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index e2630569..da214af1 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -2,7 +2,6 @@ import fj.data.List; import static fj.data.List.unfold; -import fj.data.Option; import static fj.data.Option.none; import static fj.data.Option.some; import fj.data.Tree; diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java index 2a0136bf..e2db316e 100644 --- a/core/src/main/java/fj/F.java +++ b/core/src/main/java/fj/F.java @@ -1,37 +1,5 @@ package fj; -import fj.control.parallel.Actor; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import fj.data.Array; -import fj.data.Either; -import fj.data.IterableW; -import fj.data.List; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Set; -import fj.data.Stream; -import fj.data.Tree; -import fj.data.TreeZipper; -import fj.data.Validation; -import fj.data.Zipper; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.PriorityQueue; -import java.util.TreeSet; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.concurrent.SynchronousQueue; - -import static fj.data.Option.some; -import static fj.data.Stream.iterableStream; -import static fj.data.Zipper.fromStream; - /** * A transformation or function from A to B. This type can be represented * using the Java 7 closure syntax. diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index 1723927a..63555fd5 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -1,24 +1,5 @@ package fj; -import fj.control.parallel.Promise; -import fj.data.Array; -import fj.data.IterableW; -import fj.data.List; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Set; -import fj.data.Stream; -import fj.data.Tree; -import fj.data.TreeZipper; -import fj.data.Zipper; - -import static fj.data.Tree.node; -import static fj.P.p; -import static fj.data.IterableW.wrap; -import static fj.data.Set.iterableSet; -import static fj.data.TreeZipper.treeZipper; -import static fj.data.Zipper.zipper; - /** * A transformation function of arity-2 from A and B to C. * This type can be represented using the Java 7 closure syntax. diff --git a/core/src/main/java/fj/F2W.java b/core/src/main/java/fj/F2W.java index 7a2f6e19..eb2fb590 100644 --- a/core/src/main/java/fj/F2W.java +++ b/core/src/main/java/fj/F2W.java @@ -3,13 +3,6 @@ import fj.control.parallel.Promise; import fj.data.*; -import static fj.P.p; -import static fj.data.IterableW.wrap; -import static fj.data.Set.iterableSet; -import static fj.data.Tree.node; -import static fj.data.TreeZipper.treeZipper; -import static fj.data.Zipper.zipper; - /** * Created by MarkPerry on 22/01/2015. */ diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java index a1e0b8f7..18e811d9 100644 --- a/core/src/main/java/fj/F3Functions.java +++ b/core/src/main/java/fj/F3Functions.java @@ -1,11 +1,5 @@ package fj; -import fj.data.Validation; -import fj.function.Try3; - -import static fj.data.Validation.fail; -import static fj.data.Validation.success; - /** * Created by MarkPerry on 6/04/2014. */ diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java index 04525167..cb353764 100644 --- a/core/src/main/java/fj/F4Functions.java +++ b/core/src/main/java/fj/F4Functions.java @@ -1,8 +1,5 @@ package fj; -import fj.data.Validation; -import fj.function.Try4; - /** * Created by MarkPerry on 6/04/2014. */ diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java index d8dda4da..c39b228f 100644 --- a/core/src/main/java/fj/F5Functions.java +++ b/core/src/main/java/fj/F5Functions.java @@ -1,8 +1,5 @@ package fj; -import fj.data.Validation; -import fj.function.Try5; - /** * Created by MarkPerry on 6/04/2014. */ diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java index 69ce270a..320b95f4 100644 --- a/core/src/main/java/fj/F6Functions.java +++ b/core/src/main/java/fj/F6Functions.java @@ -1,8 +1,5 @@ package fj; -import fj.data.Validation; -import fj.function.Try6; - /** * Created by MarkPerry on 6/04/2014. */ diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java index 0f2f25ac..e583ba4b 100644 --- a/core/src/main/java/fj/F7Functions.java +++ b/core/src/main/java/fj/F7Functions.java @@ -1,8 +1,5 @@ package fj; -import fj.data.Validation; -import fj.function.Try7; - /** * Created by MarkPerry on 6/04/2014. */ diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index 5eafe1f3..071cb6bc 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -1,8 +1,5 @@ package fj; -import fj.data.Validation; -import fj.function.Try8; - /** * Created by MarkPerry on 6/04/2014. */ diff --git a/core/src/main/java/fj/TryEffect.java b/core/src/main/java/fj/TryEffect.java index 90acaf06..cd1f75ab 100644 --- a/core/src/main/java/fj/TryEffect.java +++ b/core/src/main/java/fj/TryEffect.java @@ -1,12 +1,8 @@ package fj; -import fj.data.IO; -import fj.data.IOFunctions; import fj.data.Validation; import fj.function.*; -import java.io.IOException; - /** * Created by mperry on 29/08/2014. */ diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index cc143f33..14edff71 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -1,7 +1,7 @@ package fj.data; import fj.F; -import fj.F2; + import static fj.Function.*; import static fj.data.Option.none; import static fj.data.Option.some; diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 9c701a98..9e36e710 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -5,8 +5,6 @@ import fj.Equal; import fj.F; import fj.F2; -import fj.F3; -import fj.P1; import fj.P2; import static fj.Function.curry; import static fj.Function.identity; diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index 7b413293..5912ec1b 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -5,7 +5,6 @@ import fj.F1Functions; import fj.Function; import fj.P; -import fj.P1; import fj.P2; import fj.Unit; diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 29c5714c..e2f9adfd 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -4,9 +4,6 @@ import static fj.P.p; -import fj.function.Effect1; - -import static fj.data.List.list; import static fj.data.Option.some; import java.util.Arrays; diff --git a/core/src/main/java/fj/data/Natural.java b/core/src/main/java/fj/data/Natural.java index 25cd11d5..396aa39c 100644 --- a/core/src/main/java/fj/data/Natural.java +++ b/core/src/main/java/fj/data/Natural.java @@ -2,7 +2,7 @@ import static fj.Bottom.error; import fj.F; -import fj.F2; + import static fj.Monoid.naturalAdditionMonoid; import static fj.Monoid.naturalMultiplicationMonoid; import static fj.Function.curry; diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index 13bbbcc5..ef4c608c 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -1,7 +1,5 @@ package fj.data; -import java.io.IOException; - /** * Created by MarkPerry on 3/07/2014. */ diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 2d87234f..81146f95 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -2,8 +2,6 @@ import fj.*; -import java.util.*; - import static fj.P.p; /** diff --git a/core/src/main/java/fj/data/fingertrees/Empty.java b/core/src/main/java/fj/data/fingertrees/Empty.java index 17ea5927..9f2b9bd2 100644 --- a/core/src/main/java/fj/data/fingertrees/Empty.java +++ b/core/src/main/java/fj/data/fingertrees/Empty.java @@ -1,7 +1,6 @@ package fj.data.fingertrees; import fj.F; -import fj.P; import fj.P2; import fj.P3; diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index 3e451766..d107c8d4 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -1,7 +1,6 @@ package fj.data.fingertrees; import fj.F; -import fj.F2; import fj.P2; import fj.P3; import fj.data.Option; diff --git a/core/src/main/java/fj/data/hlist/HPre.java b/core/src/main/java/fj/data/hlist/HPre.java index a37c3b78..6a2556de 100644 --- a/core/src/main/java/fj/data/hlist/HPre.java +++ b/core/src/main/java/fj/data/hlist/HPre.java @@ -1,6 +1,5 @@ package fj.data.hlist; -import fj.F; import fj.Show; /** diff --git a/core/src/main/java/fj/data/vector/V.java b/core/src/main/java/fj/data/vector/V.java index 84481d96..26a86462 100644 --- a/core/src/main/java/fj/data/vector/V.java +++ b/core/src/main/java/fj/data/vector/V.java @@ -7,7 +7,6 @@ import fj.F5; import fj.P; import fj.P1; -import fj.P2; /** * Functions across vectors. diff --git a/core/src/main/java/fj/function/BigIntegers.java b/core/src/main/java/fj/function/BigIntegers.java index b60d29f4..97f1a520 100644 --- a/core/src/main/java/fj/function/BigIntegers.java +++ b/core/src/main/java/fj/function/BigIntegers.java @@ -1,7 +1,6 @@ package fj.function; import fj.F; -import fj.F2; import fj.Monoid; import fj.data.List; import static fj.Function.curry; diff --git a/core/src/main/java/fj/function/Characters.java b/core/src/main/java/fj/function/Characters.java index 8aebde7b..9191bd5a 100644 --- a/core/src/main/java/fj/function/Characters.java +++ b/core/src/main/java/fj/function/Characters.java @@ -1,7 +1,6 @@ package fj.function; import fj.F; -import fj.F2; import static fj.Function.curry; diff --git a/core/src/main/java/fj/function/Doubles.java b/core/src/main/java/fj/function/Doubles.java index a15a4042..1a85a100 100644 --- a/core/src/main/java/fj/function/Doubles.java +++ b/core/src/main/java/fj/function/Doubles.java @@ -1,7 +1,6 @@ package fj.function; import fj.F; -import fj.F2; import fj.Monoid; import fj.data.List; import fj.data.Option; diff --git a/core/src/main/java/fj/function/Integers.java b/core/src/main/java/fj/function/Integers.java index 10fd3b15..c51359e4 100644 --- a/core/src/main/java/fj/function/Integers.java +++ b/core/src/main/java/fj/function/Integers.java @@ -1,7 +1,7 @@ package fj.function; import fj.F; -import fj.F2; + import static fj.Function.curry; import fj.Monoid; diff --git a/core/src/main/java/fj/function/Longs.java b/core/src/main/java/fj/function/Longs.java index 89c2babd..a1bd60eb 100644 --- a/core/src/main/java/fj/function/Longs.java +++ b/core/src/main/java/fj/function/Longs.java @@ -1,7 +1,7 @@ package fj.function; import fj.F; -import fj.F2; + import static fj.Function.curry; import static fj.Semigroup.longAdditionSemigroup; import static fj.Semigroup.longMultiplicationSemigroup; diff --git a/core/src/main/java/fj/function/Visitor.java b/core/src/main/java/fj/function/Visitor.java index ebd18c03..0f8c3846 100644 --- a/core/src/main/java/fj/function/Visitor.java +++ b/core/src/main/java/fj/function/Visitor.java @@ -3,7 +3,6 @@ import fj.Equal; import fj.F; import fj.F0; -import fj.F2; import fj.Function; import fj.Monoid; import fj.P1; diff --git a/core/src/main/java/fj/parser/Result.java b/core/src/main/java/fj/parser/Result.java index bcec7d8b..f450a054 100644 --- a/core/src/main/java/fj/parser/Result.java +++ b/core/src/main/java/fj/parser/Result.java @@ -1,7 +1,7 @@ package fj.parser; import fj.F; -import fj.F2; + import static fj.Function.curry; import java.util.Iterator; diff --git a/demo/src/main/java/fj/demo/Array_bind.java b/demo/src/main/java/fj/demo/Array_bind.java index a0182dd1..6048ce62 100644 --- a/demo/src/main/java/fj/demo/Array_bind.java +++ b/demo/src/main/java/fj/demo/Array_bind.java @@ -1,6 +1,5 @@ package fj.demo; -import fj.F; import fj.data.Array; import static fj.data.Array.array; import static fj.Show.arrayShow; diff --git a/demo/src/main/java/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java index 44ee2956..d2d07d3d 100644 --- a/demo/src/main/java/fj/demo/ChequeWrite.java +++ b/demo/src/main/java/fj/demo/ChequeWrite.java @@ -1,7 +1,6 @@ package fj.demo; import fj.F; -import fj.F2; import fj.P2; import fj.data.List; import fj.data.Option; diff --git a/demo/src/main/java/fj/demo/Comonad_example.java b/demo/src/main/java/fj/demo/Comonad_example.java index 70230e1d..9a64c34e 100644 --- a/demo/src/main/java/fj/demo/Comonad_example.java +++ b/demo/src/main/java/fj/demo/Comonad_example.java @@ -1,6 +1,5 @@ package fj.demo; -import fj.F; import fj.F1Functions; import fj.P; import static fj.data.List.asString; diff --git a/demo/src/main/java/fj/demo/HList_foldRight.java b/demo/src/main/java/fj/demo/HList_foldRight.java index 4f5ee3e1..51f6f4c2 100644 --- a/demo/src/main/java/fj/demo/HList_foldRight.java +++ b/demo/src/main/java/fj/demo/HList_foldRight.java @@ -4,8 +4,6 @@ import static fj.Function.identity; import fj.P2; import fj.Unit; -import static fj.Unit.unit; -import static java.lang.System.out; import fj.data.hlist.HList; import static fj.data.hlist.HList.single; diff --git a/demo/src/main/java/fj/demo/Primes2.java b/demo/src/main/java/fj/demo/Primes2.java index 4a5b9dbd..96a852f3 100644 --- a/demo/src/main/java/fj/demo/Primes2.java +++ b/demo/src/main/java/fj/demo/Primes2.java @@ -1,7 +1,7 @@ package fj.demo; import fj.F1Functions; -import fj.P1; + import static fj.data.Enumerator.naturalEnumerator; import fj.Show; diff --git a/demo/src/main/java/fj/demo/Set_map.java b/demo/src/main/java/fj/demo/Set_map.java index ff5428df..054fbc15 100644 --- a/demo/src/main/java/fj/demo/Set_map.java +++ b/demo/src/main/java/fj/demo/Set_map.java @@ -1,6 +1,5 @@ package fj.demo; -import fj.F; import fj.data.Set; import static fj.data.Set.empty; import fj.Ord; diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index 3178e37b..167a08f5 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -1,6 +1,5 @@ package fj.demo; -import fj.F2; import fj.data.List; import fj.data.State; diff --git a/demo/src/main/java/fj/demo/concurrent/Fibs.java b/demo/src/main/java/fj/demo/concurrent/Fibs.java index b3aae799..5e95e597 100644 --- a/demo/src/main/java/fj/demo/concurrent/Fibs.java +++ b/demo/src/main/java/fj/demo/concurrent/Fibs.java @@ -1,7 +1,7 @@ package fj.demo.concurrent; import static fj.Bottom.error; -import fj.Effect; + import fj.F; import fj.P; import fj.P2; diff --git a/demo/src/main/java/fj/demo/concurrent/Ping.java b/demo/src/main/java/fj/demo/concurrent/Ping.java index 82aad6b3..3ba934fb 100644 --- a/demo/src/main/java/fj/demo/concurrent/Ping.java +++ b/demo/src/main/java/fj/demo/concurrent/Ping.java @@ -1,6 +1,5 @@ package fj.demo.concurrent; -import fj.Effect; import fj.Unit; import fj.P1; import fj.control.parallel.Actor; diff --git a/demo/src/main/java/fj/demo/concurrent/PingPong.java b/demo/src/main/java/fj/demo/concurrent/PingPong.java index d6bddbbf..b0b09011 100644 --- a/demo/src/main/java/fj/demo/concurrent/PingPong.java +++ b/demo/src/main/java/fj/demo/concurrent/PingPong.java @@ -2,7 +2,6 @@ import static fj.Bottom.error; import fj.Unit; -import fj.Effect; import fj.control.parallel.Strategy; import fj.control.parallel.Actor; import fj.function.Effect1; diff --git a/demo/src/main/java/fj/demo/concurrent/Pong.java b/demo/src/main/java/fj/demo/concurrent/Pong.java index d85eda7e..b0f0ad57 100644 --- a/demo/src/main/java/fj/demo/concurrent/Pong.java +++ b/demo/src/main/java/fj/demo/concurrent/Pong.java @@ -1,6 +1,5 @@ package fj.demo.concurrent; -import fj.Effect; import fj.Unit; import fj.P1; import fj.control.parallel.Actor; diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 67fef136..b4d3dae2 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -19,7 +19,6 @@ import java.util.concurrent.ExecutorService; import fj.F; -import fj.F2; import fj.Monoid; import fj.P; import fj.P1; diff --git a/demo/src/main/java/fj/demo/euler/Problem1.java b/demo/src/main/java/fj/demo/euler/Problem1.java index 82dc53c0..e20f9a97 100644 --- a/demo/src/main/java/fj/demo/euler/Problem1.java +++ b/demo/src/main/java/fj/demo/euler/Problem1.java @@ -1,6 +1,5 @@ package fj.demo.euler; -import fj.F; import fj.data.Stream; import static fj.data.List.range; diff --git a/demo/src/main/java/fj/demo/euler/Problem3.java b/demo/src/main/java/fj/demo/euler/Problem3.java index bde87126..e429e0e9 100644 --- a/demo/src/main/java/fj/demo/euler/Problem3.java +++ b/demo/src/main/java/fj/demo/euler/Problem3.java @@ -1,7 +1,5 @@ package fj.demo.euler; -import fj.F; -import fj.P; import fj.P1; import static fj.data.Enumerator.naturalEnumerator; import fj.data.Natural; diff --git a/demo/src/main/java/fj/demo/euler/Problem4.java b/demo/src/main/java/fj/demo/euler/Problem4.java index f1947057..60c04d85 100644 --- a/demo/src/main/java/fj/demo/euler/Problem4.java +++ b/demo/src/main/java/fj/demo/euler/Problem4.java @@ -1,6 +1,5 @@ package fj.demo.euler; -import fj.F; import static fj.Function.flip; import fj.data.Stream; import static fj.data.Stream.iterate; diff --git a/demo/src/main/java/fj/demo/test/AdditionCommutes.java b/demo/src/main/java/fj/demo/test/AdditionCommutes.java index 8aea4f03..7b2a6571 100644 --- a/demo/src/main/java/fj/demo/test/AdditionCommutes.java +++ b/demo/src/main/java/fj/demo/test/AdditionCommutes.java @@ -1,6 +1,5 @@ package fj.demo.test; -import fj.F2; import static fj.test.Arbitrary.arbInteger; import static fj.test.CheckResult.summary; import fj.test.Property; diff --git a/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java index b1629c21..d61ffeb0 100644 --- a/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java +++ b/demo/src/main/java/fj/demo/test/AdditionCommutesParallel.java @@ -1,8 +1,6 @@ package fj.demo.test; -import fj.F2; import fj.P; -import fj.P1; import fj.control.parallel.Strategy; import static fj.test.Arbitrary.arbInteger; import static fj.test.CheckResult.summary; diff --git a/demo/src/main/java/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java index 20a732a2..814f7112 100644 --- a/demo/src/main/java/fj/demo/test/EqualsHashCode.java +++ b/demo/src/main/java/fj/demo/test/EqualsHashCode.java @@ -1,8 +1,5 @@ package fj.demo.test; -import fj.F; -import fj.F2; -import fj.F3; import static fj.Function.curry; import fj.test.Arbitrary; import static fj.test.Arbitrary.arbByte; diff --git a/demo/src/main/java/fj/demo/test/IntegerOverflow.java b/demo/src/main/java/fj/demo/test/IntegerOverflow.java index 155f8495..48b9d2dc 100644 --- a/demo/src/main/java/fj/demo/test/IntegerOverflow.java +++ b/demo/src/main/java/fj/demo/test/IntegerOverflow.java @@ -1,6 +1,5 @@ package fj.demo.test; -import fj.F2; import static fj.test.Arbitrary.arbIntegerBoundaries; import static fj.test.Bool.bool; import static fj.test.CheckResult.summary; diff --git a/demo/src/main/java/fj/demo/test/JavaLinkedList.java b/demo/src/main/java/fj/demo/test/JavaLinkedList.java index 0954c705..5ce11fba 100644 --- a/demo/src/main/java/fj/demo/test/JavaLinkedList.java +++ b/demo/src/main/java/fj/demo/test/JavaLinkedList.java @@ -1,6 +1,5 @@ package fj.demo.test; -import fj.F2; import static fj.test.Arbitrary.arbInteger; import static fj.test.Arbitrary.arbLinkedList; import static fj.test.CheckResult.summary; diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index e0c99f64..03095e80 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -1,7 +1,5 @@ package fj.demo.test; -import fj.F; -import fj.F3; import fj.Function; import static fj.Function.compose; import fj.P2; diff --git a/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java index 675c8eff..18d1b5d7 100644 --- a/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java +++ b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java @@ -1,7 +1,5 @@ package fj.demo.test; -import fj.F; -import fj.F2; import static fj.Function.andThen; import fj.data.Option; import static fj.Equal.optionEqual; diff --git a/demo/src/main/java/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java index 79d013dc..d5ebfd36 100644 --- a/demo/src/main/java/fj/demo/test/Reflect.java +++ b/demo/src/main/java/fj/demo/test/Reflect.java @@ -2,8 +2,6 @@ import static fj.Bottom.error; -import fj.F; -import fj.F2; import fj.P2; import fj.data.List; import static fj.data.List.list; diff --git a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java index 9338065b..b0897044 100644 --- a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java +++ b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java @@ -1,7 +1,5 @@ package fj.demo.test; -import fj.F; -import fj.F2; import static fj.data.List.list; import static fj.Equal.stringBuilderEqual; import static fj.test.Arbitrary.arbCharacter; diff --git a/demo/src/main/java/fj/demo/test/Triangulation.java b/demo/src/main/java/fj/demo/test/Triangulation.java index 56d110f2..10de64ea 100644 --- a/demo/src/main/java/fj/demo/test/Triangulation.java +++ b/demo/src/main/java/fj/demo/test/Triangulation.java @@ -1,6 +1,5 @@ package fj.demo.test; -import fj.F; import static fj.test.Arbitrary.arbInteger; import static fj.test.CheckResult.summary; import fj.test.Property; diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 5222df9e..1e619f21 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -69,7 +69,6 @@ import java.util.PriorityQueue; import java.util.Properties; import java.util.Stack; -import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; import java.util.WeakHashMap; diff --git a/quickcheck/src/main/java/fj/test/Bool.java b/quickcheck/src/main/java/fj/test/Bool.java index deb072cf..18239fa6 100644 --- a/quickcheck/src/main/java/fj/test/Bool.java +++ b/quickcheck/src/main/java/fj/test/Bool.java @@ -1,7 +1,7 @@ package fj.test; import fj.F0; -import fj.P1; + import static fj.test.Property.prop; /** diff --git a/quickcheck/src/main/java/fj/test/Result.java b/quickcheck/src/main/java/fj/test/Result.java index eb6b973b..40130542 100644 --- a/quickcheck/src/main/java/fj/test/Result.java +++ b/quickcheck/src/main/java/fj/test/Result.java @@ -1,7 +1,6 @@ package fj.test; import fj.F; -import fj.P1; import fj.data.List; import fj.data.Option; import static fj.data.Option.none; diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index 079dcb22..5b7dbbb3 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -1,6 +1,5 @@ package fj.test.reflect; -import static fj.Bottom.error; import fj.Class; import static fj.Class.clas; import fj.F; diff --git a/quickcheck/src/main/java/fj/test/reflect/CheckParams.java b/quickcheck/src/main/java/fj/test/reflect/CheckParams.java index 725a7504..8c8445c1 100644 --- a/quickcheck/src/main/java/fj/test/reflect/CheckParams.java +++ b/quickcheck/src/main/java/fj/test/reflect/CheckParams.java @@ -1,6 +1,5 @@ package fj.test.reflect; -import fj.P1; import fj.test.Property; import java.lang.annotation.Documented; From 316d1d48768ed6c6730843393f799451c7e5cd68 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 22:29:38 +0100 Subject: [PATCH 518/811] Use method reference (over lambda) whenever possible --- core/src/main/java/fj/Bottom.java | 4 +- core/src/main/java/fj/Class.java | 2 +- core/src/main/java/fj/Digit.java | 8 +- core/src/main/java/fj/Effect.java | 2 +- core/src/main/java/fj/Equal.java | 4 +- core/src/main/java/fj/Function.java | 24 +-- core/src/main/java/fj/Hash.java | 2 +- core/src/main/java/fj/Monoid.java | 6 +- core/src/main/java/fj/Ord.java | 6 +- core/src/main/java/fj/P.java | 2 +- core/src/main/java/fj/P1.java | 16 +- core/src/main/java/fj/P2.java | 14 +- core/src/main/java/fj/P3.java | 6 +- core/src/main/java/fj/P4.java | 8 +- core/src/main/java/fj/P5.java | 10 +- core/src/main/java/fj/P6.java | 36 +--- core/src/main/java/fj/P7.java | 42 +--- core/src/main/java/fj/P8.java | 48 +---- core/src/main/java/fj/Semigroup.java | 20 +- core/src/main/java/fj/Show.java | 2 +- core/src/main/java/fj/control/Trampoline.java | 10 +- .../java/fj/control/parallel/Callables.java | 16 +- .../java/fj/control/parallel/ParModule.java | 18 +- .../java/fj/control/parallel/Promise.java | 2 +- .../java/fj/control/parallel/Strategy.java | 6 +- core/src/main/java/fj/data/Array.java | 6 +- core/src/main/java/fj/data/Conversions.java | 70 +++---- core/src/main/java/fj/data/Either.java | 26 +-- core/src/main/java/fj/data/Enumerator.java | 2 +- core/src/main/java/fj/data/HashMap.java | 2 +- core/src/main/java/fj/data/IOFunctions.java | 21 +- core/src/main/java/fj/data/IterableW.java | 10 +- core/src/main/java/fj/data/Java.java | 40 ++-- core/src/main/java/fj/data/List.java | 26 +-- core/src/main/java/fj/data/Natural.java | 12 +- core/src/main/java/fj/data/NonEmptyList.java | 6 +- core/src/main/java/fj/data/Option.java | 36 ++-- core/src/main/java/fj/data/Set.java | 8 +- core/src/main/java/fj/data/State.java | 6 +- core/src/main/java/fj/data/Stream.java | 42 ++-- core/src/main/java/fj/data/Tree.java | 10 +- core/src/main/java/fj/data/TreeMap.java | 6 +- core/src/main/java/fj/data/TreeZipper.java | 12 +- core/src/main/java/fj/data/Validation.java | 36 ++-- core/src/main/java/fj/data/Zipper.java | 8 +- .../main/java/fj/data/fingertrees/Digit.java | 4 +- .../java/fj/data/fingertrees/Measured.java | 4 +- .../main/java/fj/data/optic/POptional.java | 2 +- core/src/main/java/fj/data/optic/PPrism.java | 2 +- core/src/main/java/fj/data/vector/V.java | 10 +- core/src/main/java/fj/data/vector/V2.java | 10 +- core/src/main/java/fj/data/vector/V3.java | 14 +- core/src/main/java/fj/data/vector/V4.java | 16 +- core/src/main/java/fj/data/vector/V5.java | 18 +- core/src/main/java/fj/data/vector/V6.java | 20 +- core/src/main/java/fj/data/vector/V7.java | 22 +-- core/src/main/java/fj/data/vector/V8.java | 24 +-- .../main/java/fj/function/BigIntegers.java | 15 +- .../src/main/java/fj/function/Characters.java | 46 ++--- core/src/main/java/fj/function/Doubles.java | 4 +- core/src/main/java/fj/function/Integers.java | 2 +- core/src/main/java/fj/function/Longs.java | 2 +- core/src/main/java/fj/function/Strings.java | 8 +- core/src/main/java/fj/parser/Parser.java | 38 ++-- core/src/main/java/fj/parser/Result.java | 8 +- demo/src/main/java/fj/demo/IODemo.java | 2 +- .../java/fj/demo/concurrent/WordCount.java | 2 +- .../main/java/fj/demo/realworld/Chapter7.java | 4 +- .../java/fj/demo/test/EqualsHashCode.java | 2 +- java8/src/main/java/fj/data/Java8.java | 16 +- .../src/main/java/fj/test/Arbitrary.java | 184 ++++-------------- quickcheck/src/main/java/fj/test/Gen.java | 18 +- .../src/main/java/fj/test/Property.java | 6 +- quickcheck/src/main/java/fj/test/Result.java | 2 +- quickcheck/src/main/java/fj/test/Shrink.java | 30 +-- .../src/main/java/fj/test/reflect/Check.java | 6 +- 76 files changed, 514 insertions(+), 726 deletions(-) diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index 0f828102..a70629f1 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -83,7 +83,7 @@ public static Error decons(final java.lang.Class c) { * @return A function that returns the toString for a throwable. */ public static F eToString() { - return t -> t.toString(); + return Throwable::toString; } /** @@ -92,6 +92,6 @@ public static F eToString() { * @return A function that returns the getMessage for a throwable. */ public static F eMessage() { - return t -> t.getMessage(); + return Throwable::getMessage; } } diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index da214af1..d34aedb7 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -45,7 +45,7 @@ public java.lang.Class _2() { }; return some(p); } - }, c).map(c1 -> clas(c1)); + }, c).map(Class::clas); } /** diff --git a/core/src/main/java/fj/Digit.java b/core/src/main/java/fj/Digit.java index ba3c2245..7213e278 100644 --- a/core/src/main/java/fj/Digit.java +++ b/core/src/main/java/fj/Digit.java @@ -176,20 +176,20 @@ public static Option fromChar(final char c) { /** * First-class conversion from digit to a long. */ - public static final F toLong = d -> d.toLong(); + public static final F toLong = Digit::toLong; /** * First-class conversion from a long to a digit. */ - public static final F fromLong = i -> fromLong(i); + public static final F fromLong = Digit::fromLong; /** * First-class conversion from a digit to a character. */ - public static final F toChar = d -> d.toChar(); + public static final F toChar = Digit::toChar; /** * First-class conversion from a character to a digit. */ - public static final F> fromChar = c -> fromChar(c); + public static final F> fromChar = Digit::fromChar; } diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 6e5e7b7f..80680cac 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -100,7 +100,7 @@ public static Effect1 contramap(Effect1 e1, final F f) { } public static Effect1 lazy(final F f) { - return a -> f.f(a); + return f::f; } diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 27973afc..f503d096 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -55,7 +55,7 @@ public boolean notEq(final A a1, final A a2) { * @return A function that returns true if the two given arguments are equal. */ public F2 eq() { - return (a, a1) -> eq(a, a1); + return this::eq; } /** @@ -96,7 +96,7 @@ public static Equal equal(final F> f) { * equality. */ public static Equal anyEqual() { - return equal(a1 -> a2 -> a1.equals(a2)); + return equal(a1 -> a1::equals); } /** diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index b3b96870..8d832798 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -89,7 +89,7 @@ public static F identity() { * @return A function that given an argument, returns a function that ignores its argument. */ public static F> constant() { - return b -> constant(b); + return Function::constant; } /** @@ -109,7 +109,7 @@ public static F constant(final B b) { * @return A co- and contravariant function that invokes f on its argument. */ public static F vary(final F f) { - return a -> f.f(a); + return f::f; } /** @@ -118,7 +118,7 @@ public static F vary(final F f) { * @return A function that varies and covaries a function. */ public static F, F> vary() { - return f -> Function.vary(f); + return Function::vary; } /** @@ -127,7 +127,7 @@ public static F, F> vary() { * @return A function that takes a function and flips its arguments. */ public static F>, F>> flip() { - return f -> flip(f); + return Function::flip; } /** @@ -156,7 +156,7 @@ public static F2 flip(final F2 f) { * @return A function that flips the arguments of a given function. */ public static F, F2> flip2() { - return f -> flip(f); + return Function::flip; } /** @@ -198,7 +198,7 @@ public static F curry(final F2 f, final A a) { * @return An uncurried function. */ public static F>, F2> uncurryF2() { - return f -> uncurryF2(f); + return Function::uncurryF2; } /** @@ -250,7 +250,7 @@ public static F curry(final F3 f, final A a, fina * @return An uncurried function. */ public static F>>, F3> uncurryF3() { - return f -> uncurryF3(f); + return Function::uncurryF3; } /** @@ -315,7 +315,7 @@ public static F curry(final F4 f, final A a * @return An uncurried function. */ public static F>>>, F4> uncurryF4() { - return f -> uncurryF4(f); + return Function::uncurryF4; } /** @@ -396,7 +396,7 @@ public static F4 uncurryF4(final F F>>>>, F5> uncurryF5() { - return f -> uncurryF5(f); + return Function::uncurryF5; } /** @@ -425,7 +425,7 @@ public static F4 uncurryF4(final F F>>>>>, F6> uncurryF6() { - return f -> uncurryF6(f); + return Function::uncurryF6; } /** @@ -543,7 +543,7 @@ public static F4 uncurryF4(final F F>>>>>>, F7> uncurryF7() { - return f -> uncurryF7(f); + return Function::uncurryF7; } /** @@ -682,7 +682,7 @@ public static F4 uncurryF4(final F F>>>>>>>, F8> uncurryF8() { - return f -> uncurryF8(f); + return Function::uncurryF8; } /** diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 61c5e1cd..acb2a62c 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -62,7 +62,7 @@ public static Hash hash(final F f) { * @return A hash that uses {@link Object#hashCode()}. */ public static Hash anyHash() { - return hash(a -> a.hashCode()); + return hash(Object::hashCode); } /** diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index a85a4712..be5215bb 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -156,7 +156,7 @@ public A sumLeft(final Stream as) { * @return a function that sums the given values with left-fold. */ public F, A> sumLeft() { - return as -> sumLeft(as); + return this::sumLeft; } /** @@ -165,7 +165,7 @@ public F, A> sumLeft() { * @return a function that sums the given values with right-fold. */ public F, A> sumRight() { - return as -> sumRight(as); + return this::sumRight; } /** @@ -174,7 +174,7 @@ public F, A> sumRight() { * @return a function that sums the given values with left-fold. */ public F, A> sumLeftS() { - return as -> sumLeft(as); + return this::sumLeft; } /** diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 780f5edf..57d7e389 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -150,12 +150,12 @@ public A min(final A a1, final A a2) { /** * A function that returns the greater of its two arguments. */ - public final F> max = curry((a, a1) -> max(a, a1)); + public final F> max = curry(this::max); /** * A function that returns the lesser of its two arguments. */ - public final F> min = curry((a, a1) -> min(a, a1)); + public final F> min = curry(this::min); public Ord reverse() { return ord(Function.flip(f)); } @@ -428,7 +428,7 @@ public static Ord> arrayOrd(final Ord oa) { * @return An order instance for the {@link Set} type. */ public static Ord> setOrd(final Ord oa) { - return streamOrd(oa).contramap(as -> as.toStream()); + return streamOrd(oa).contramap(Set::toStream); } /** diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 2826b6b0..1ff82475 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -18,7 +18,7 @@ private P() { * @return A function that puts an element in a product-1. */ public static F> p1() { - return a -> p(a); + return P::p; } /** diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 0cb92a89..796daf22 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -33,7 +33,7 @@ public final A f() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return p -> p._1(); + return P1::_1; } /** @@ -147,7 +147,7 @@ public static P1> sequence(final List> as) { * @return A function from a List of P1s to a single P1 of a List. */ public static F>, P1>> sequenceList() { - return as -> sequence(as); + return P1::sequence; } /** @@ -164,7 +164,7 @@ public static P1> sequence(final Stream> as) { * Turns an optional P1 into a lazy option. */ public static P1> sequence(final Option> o) { - return P.lazy(() -> o.map(p -> p._1())); + return P.lazy(() -> o.map(P1::_1)); } /** @@ -184,7 +184,7 @@ public static P1> sequence(final Array> as) { * @return A List of P1 */ public List> traverseList(final F> f){ - return f.f(_1()).map(b -> P.p(b)); + return f.f(_1()).map(P::p); } /** @@ -194,7 +194,7 @@ public List> traverseList(final F> f){ * @return An Either of P1 */ public Either> traverseEither(final F> f){ - return f.f(_1()).right().map(b -> P.p(b)); + return f.f(_1()).right().map(P::p); } /** @@ -204,7 +204,7 @@ public Either> traverseEither(final F> f){ * @return An Option of P1 */ public Option> traverseOption(final F> f){ - return f.f(_1()).map(b -> P.p(b)); + return f.f(_1()).map(P::p); } /** @@ -214,7 +214,7 @@ public Option> traverseOption(final F> f){ * @return An Validation of P1 */ public Validation> traverseValidation(final F> f){ - return f.f(_1()).map(b -> P.p(b)); + return f.f(_1()).map(P::p); } /** @@ -224,7 +224,7 @@ public Validation> traverseValidation(final F */ public Stream> traverseStream(final F> f){ - return f.f(_1()).map(b -> P.p(b)); + return f.f(_1()).map(P::p); } /** diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 3283f344..d564df35 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -42,7 +42,7 @@ public int hashCode() { * @return A new product-2 with the elements swapped. */ public final P2 swap() { - return P.lazy(() -> P2.this._2(), () -> P2.this._1()); + return P.lazy(P2.this::_2, P2.this::_1); } /** @@ -53,7 +53,7 @@ public final P2 swap() { */ public final P2 map1(final F f) { P2 self = this; - return P.lazy(() -> f.f(self._1()), () -> self._2()); + return P.lazy(() -> f.f(self._1()), self::_2); } /** @@ -63,7 +63,7 @@ public final P2 map1(final F f) { * @return A product with the given function applied. */ public final P2 map2(final F f) { - return P.lazy(() -> P2.this._1(), () -> f.f(P2.this._2())); + return P.lazy(P2.this::_1, () -> f.f(P2.this._2())); } @@ -90,7 +90,7 @@ public final P2 split(final F f, final F g) { */ public final P2 cobind(final F, C> k) { P2 self = this; - return P.lazy(() -> k.f(self), () -> self._2()); + return P.lazy(() -> k.f(self), self::_2); } /** @@ -258,7 +258,7 @@ public static P2 map(final F f, final P2 p) { * @return A curried form of {@link #swap()}. */ public static F, P2> swap_() { - return p -> p.swap(); + return P2::swap; } /** @@ -267,7 +267,7 @@ public static F, P2> swap_() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return p -> p._1(); + return P2::_1; } /** @@ -276,7 +276,7 @@ public static F, A> __1() { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return p -> p._2(); + return P2::_2; } /** diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 9f473f56..8760562b 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -152,7 +152,7 @@ public C _3() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return p -> p._1(); + return P3::_1; } /** @@ -161,7 +161,7 @@ public static F, A> __1() { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return p -> p._2(); + return P3::_2; } /** @@ -170,7 +170,7 @@ public static F, B> __2() { * @return A function that returns the third element of a product. */ public static F, C> __3() { - return p -> p._3(); + return P3::_3; } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 7ba55b5d..7f71943e 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -212,7 +212,7 @@ public D _4() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return p -> p._1(); + return P4::_1; } /** @@ -221,7 +221,7 @@ public static F, A> __1() { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return p -> p._2(); + return P4::_2; } /** @@ -230,7 +230,7 @@ public static F, B> __2() { * @return A function that returns the third element of a product. */ public static F, C> __3() { - return p -> p._3(); + return P4::_3; } /** @@ -239,7 +239,7 @@ public static F, C> __3() { * @return A function that returns the fourth element of a product. */ public static F, D> __4() { - return p -> p._4(); + return P4::_4; } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 6059e22a..57199302 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -278,7 +278,7 @@ public E _5() { * @return A function that returns the first element of a product. */ public static F, A> __1() { - return p -> p._1(); + return P5::_1; } /** @@ -287,7 +287,7 @@ public static F, A> __1() { * @return A function that returns the second element of a product. */ public static F, B> __2() { - return p -> p._2(); + return P5::_2; } /** @@ -296,7 +296,7 @@ public static F, B> __2() { * @return A function that returns the third element of a product. */ public static F, C> __3() { - return p -> p._3(); + return P5::_3; } /** @@ -305,7 +305,7 @@ public static F, C> __3() { * @return A function that returns the fourth element of a product. */ public static F, D> __4() { - return p -> p._4(); + return P5::_4; } /** @@ -314,7 +314,7 @@ public static F, D> __4() { * @return A function that returns the fifth element of a product. */ public static F, E> __5() { - return p -> p._5(); + return P5::_5; } @Override diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index c2983298..d1f32b87 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -355,11 +355,7 @@ public F _6() { * @return A function that returns the first element of a product. */ public static fj.F, A> __1() { - return new fj.F, A>() { - public A f(final P6 p) { - return p._1(); - } - }; + return P6::_1; } /** @@ -368,11 +364,7 @@ public A f(final P6 p) { * @return A function that returns the second element of a product. */ public static fj.F, B> __2() { - return new fj.F, B>() { - public B f(final P6 p) { - return p._2(); - } - }; + return P6::_2; } /** @@ -381,11 +373,7 @@ public B f(final P6 p) { * @return A function that returns the third element of a product. */ public static fj.F, C> __3() { - return new fj.F, C>() { - public C f(final P6 p) { - return p._3(); - } - }; + return P6::_3; } /** @@ -394,11 +382,7 @@ public C f(final P6 p) { * @return A function that returns the fourth element of a product. */ public static fj.F, D> __4() { - return new fj.F, D>() { - public D f(final P6 p) { - return p._4(); - } - }; + return P6::_4; } /** @@ -407,11 +391,7 @@ public D f(final P6 p) { * @return A function that returns the fifth element of a product. */ public static fj.F, E> __5() { - return new fj.F, E>() { - public E f(final P6 p) { - return p._5(); - } - }; + return P6::_5; } /** @@ -420,11 +400,7 @@ public E f(final P6 p) { * @return A function that returns the sixth element of a product. */ public static fj.F, F$> __6() { - return new fj.F, F$>() { - public F$ f(final P6 p) { - return p._6(); - } - }; + return P6::_6; } @Override diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 478e3d87..e81a2480 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -437,11 +437,7 @@ public G _7() { * @return A function that returns the first element of a product. */ public static fj.F, A> __1() { - return new fj.F, A>() { - public A f(final P7 p) { - return p._1(); - } - }; + return P7::_1; } /** @@ -450,11 +446,7 @@ public A f(final P7 p) { * @return A function that returns the second element of a product. */ public static fj.F, B> __2() { - return new fj.F, B>() { - public B f(final P7 p) { - return p._2(); - } - }; + return P7::_2; } /** @@ -463,11 +455,7 @@ public B f(final P7 p) { * @return A function that returns the third element of a product. */ public static fj.F, C> __3() { - return new fj.F, C>() { - public C f(final P7 p) { - return p._3(); - } - }; + return P7::_3; } /** @@ -476,11 +464,7 @@ public C f(final P7 p) { * @return A function that returns the fourth element of a product. */ public static fj.F, D> __4() { - return new fj.F, D>() { - public D f(final P7 p) { - return p._4(); - } - }; + return P7::_4; } /** @@ -489,11 +473,7 @@ public D f(final P7 p) { * @return A function that returns the fifth element of a product. */ public static fj.F, E> __5() { - return new fj.F, E>() { - public E f(final P7 p) { - return p._5(); - } - }; + return P7::_5; } /** @@ -502,11 +482,7 @@ public E f(final P7 p) { * @return A function that returns the sixth element of a product. */ public static fj.F, F$> __6() { - return new fj.F, F$>() { - public F$ f(final P7 p) { - return p._6(); - } - }; + return P7::_6; } /** @@ -515,11 +491,7 @@ public E f(final P7 p) { * @return A function that returns the seventh element of a product. */ public static fj.F, G> __7() { - return new fj.F, G>() { - public G f(final P7 p) { - return p._7(); - } - }; + return P7::_7; } @Override diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index 62fef46e..982dca58 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -530,11 +530,7 @@ public H _8() { * @return A function that returns the first element of a product. */ public static fj.F, A> __1() { - return new fj.F, A>() { - public A f(final P8 p) { - return p._1(); - } - }; + return P8::_1; } /** @@ -543,11 +539,7 @@ public A f(final P8 p) { * @return A function that returns the second element of a product. */ public static fj.F, B> __2() { - return new fj.F, B>() { - public B f(final P8 p) { - return p._2(); - } - }; + return P8::_2; } /** @@ -556,11 +548,7 @@ public B f(final P8 p) { * @return A function that returns the third element of a product. */ public static fj.F, C> __3() { - return new fj.F, C>() { - public C f(final P8 p) { - return p._3(); - } - }; + return P8::_3; } /** @@ -569,11 +557,7 @@ public C f(final P8 p) { * @return A function that returns the fourth element of a product. */ public static fj.F, D> __4() { - return new fj.F, D>() { - public D f(final P8 p) { - return p._4(); - } - }; + return P8::_4; } /** @@ -582,11 +566,7 @@ public D f(final P8 p) { * @return A function that returns the fifth element of a product. */ public static fj.F, E> __5() { - return new fj.F, E>() { - public E f(final P8 p) { - return p._5(); - } - }; + return P8::_5; } /** @@ -595,11 +575,7 @@ public E f(final P8 p) { * @return A function that returns the sixth element of a product. */ public static fj.F, F$> __6() { - return new fj.F, F$>() { - public F$ f(final P8 p) { - return p._6(); - } - }; + return P8::_6; } /** @@ -608,11 +584,7 @@ public E f(final P8 p) { * @return A function that returns the seventh element of a product. */ public static fj.F, G> __7() { - return new fj.F, G>() { - public G f(final P8 p) { - return p._7(); - } - }; + return P8::_7; } /** @@ -621,11 +593,7 @@ public G f(final P8 p) { * @return A function that returns the eighth element of a product. */ public static fj.F, H> __8() { - return new fj.F, H>() { - public H f(final P8 p) { - return p._8(); - } - }; + return P8::_8; } @Override diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 6e091d7f..e7cd4c35 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -150,13 +150,13 @@ public static Semigroup semigroup(final F2 sum) { * A semigroup that adds big integers. */ public static final Semigroup bigintAdditionSemigroup = - semigroup((i1, i2) -> i1.add(i2)); + semigroup(BigInteger::add); /** * A semigroup that multiplies big integers. */ public static final Semigroup bigintMultiplicationSemigroup = - semigroup((i1, i2) -> i1.multiply(i2)); + semigroup(BigInteger::multiply); /** * A semigroup that yields the maximum of big integers. @@ -172,13 +172,13 @@ public static Semigroup semigroup(final F2 sum) { * A semigroup that adds big decimals. */ public static final Semigroup bigdecimalAdditionSemigroup = - semigroup((i1, i2) -> i1.add(i2)); + semigroup(BigDecimal::add); /** * A semigroup that multiplies big decimals. */ public static final Semigroup bigdecimalMultiplicationSemigroup = - semigroup((i1, i2) -> i1.multiply(i2)); + semigroup(BigDecimal::multiply); /** * A semigroup that yields the maximum of big decimals. @@ -194,13 +194,13 @@ public static Semigroup semigroup(final F2 sum) { * A semigroup that multiplies natural numbers. */ public static final Semigroup naturalMultiplicationSemigroup = - semigroup((n1, n2) -> n1.multiply(n2)); + semigroup(Natural::multiply); /** * A semigroup that multiplies natural numbers. */ public static final Semigroup naturalAdditionSemigroup = - semigroup((n1, n2) -> n1.add(n2)); + semigroup(Natural::add); /** * A semigroup that yields the maximum of natural numbers. @@ -294,7 +294,7 @@ public static Semigroup> functionSemigroup(final Semigroup sb) * @return A semigroup for lists. */ public static Semigroup> listSemigroup() { - return semigroup((a1, a2) -> a1.append(a2)); + return semigroup(List::append); } /** @@ -303,7 +303,7 @@ public static Semigroup> listSemigroup() { * @return A semigroup for non-empty lists. */ public static Semigroup> nonEmptyListSemigroup() { - return semigroup((a1, a2) -> a1.append(a2)); + return semigroup(NonEmptyList::append); } /** @@ -347,7 +347,7 @@ public static Semigroup> streamSemigroup() { * @return A semigroup for arrays. */ public static Semigroup> arraySemigroup() { - return semigroup((a1, a2) -> a1.append(a2)); + return semigroup(Array::append); } /** @@ -389,7 +389,7 @@ public static Semigroup> ioSemigroup(final Semigroup sa) { * @return a semigroup for sets. */ public static Semigroup> setSemigroup() { - return semigroup((a, b) -> a.union(b)); + return semigroup(Set::union); } } diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 7e832c6c..5e6fd8b0 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -79,7 +79,7 @@ public String showS(final A a) { * @return the transformation equivalent to this show. */ public F showS_() { - return a -> showS(a); + return this::showS; } /** diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 49b6bb61..140deeaa 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -57,7 +57,7 @@ public Either>, A> resume() { // WARNING: In JDK 8, update 25 (current version) the following code is a // workaround for an internal JDK compiler error, likely due to // https:bugs.openjdk.java.net/browse/JDK-8062253. - F, Trampoline> f = o -> o.foldNormal(o1 -> cont.f(o1), t -> t._1().bind(cont)); + F, Trampoline> f = o -> o.foldNormal(cont::f, t -> t._1().bind(cont)); F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); return ot.fold(f, g); }); @@ -117,7 +117,7 @@ protected static Codense codense(final Normal a, final F F> pure() { - return a -> pure(a); + return Trampoline::pure; } /** @@ -144,7 +144,7 @@ public static Trampoline suspend(final P1> a) { * @return The first-class version of `suspend`. */ public static F>, Trampoline> suspend_() { - return trampolineP1 -> suspend(trampolineP1); + return Trampoline::suspend; } protected abstract R fold(final F, R> n, final F, R> gs); @@ -185,7 +185,7 @@ public static F, F, Trampoline>> map_() { * @return The first-class version of `resume`. */ public static F, Either>, A>> resume_() { - return aTrampoline -> aTrampoline.resume(); + return Trampoline::resume; } /** @@ -221,7 +221,7 @@ public A run() { * @return A new Trampoline after applying the given function through this Trampoline. */ public final Trampoline apply(final Trampoline> lf) { - return lf.bind(f -> map(f)); + return lf.bind(this::map); } /** diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index aeb9a312..40c8e746 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -51,7 +51,7 @@ public static Callable callable(final Exception e) { * @return A function from a value to a Callable that completely preserves that value. */ public static F> callable() { - return a -> callable(a); + return Callables::callable; } /** @@ -72,7 +72,7 @@ public static F> callable(final F f) { * @return A transformation from a function to the equivalent Callable-valued function. */ public static F, F>> arrow() { - return f -> callable(f); + return Callables::callable; } /** @@ -156,7 +156,7 @@ public static Callable> sequence(final List> as) { * @return A function from a List of Callables to a single Callable of a List. */ public static F>, Callable>> sequence_() { - return as -> sequence(as); + return Callables::sequence; } /** @@ -181,7 +181,7 @@ public static P1> option(final Callable a) { * @return a function that turns a Callable into an optional value. */ public static F, P1>> option() { - return a -> option(a); + return Callables::option; } /** @@ -206,7 +206,7 @@ public static P1> either(final Callable a) { * @return a function that turns a Callable into an Either. */ public static F, P1>> either() { - return a -> either(a); + return Callables::either; } /** @@ -233,7 +233,7 @@ public A call() throws Exception { * @return a function that turns an Either into a Callable. */ public static F>, Callable> fromEither() { - return e -> fromEither(e); + return Callables::fromEither; } /** @@ -261,7 +261,7 @@ public A call() throws Exception { * or throws an exception in the case of no value. */ public static F>, Callable> fromOption() { - return o -> fromOption(o); + return Callables::fromOption; } /** @@ -285,7 +285,7 @@ public static Callable normalise(final Callable a) { * @return A function that normalises the given Callable by calling it and wrapping the result in a new Callable. */ public static F, Callable> normalise() { - return a -> normalise(a); + return Callables::normalise; } } diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 7d01139a..7e0fdb59 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -56,7 +56,7 @@ public Promise promise(final P1 p) { * @return a function that evaluates a given product concurrently and returns a Promise of the result. */ public F, Promise> promise() { - return ap1 -> promise(ap1); + return this::promise; } /** @@ -77,7 +77,7 @@ public F> promise(final F f) { * @return A higher-order function that takes pure functions to promise-valued functions. */ public F, F>> promisePure() { - return abf -> promise(abf); + return this::promise; } /** @@ -110,7 +110,7 @@ public Actor effect(final Effect1 e) { * @return A function that takes an effect and returns a concurrent effect. */ public F, Actor> effect() { - return effect -> effect(effect); + return this::effect; } /** @@ -129,7 +129,7 @@ public Actor actor(final Effect1 e) { * @return A function that takes an effect and returns an actor that processes messages in some order. */ public F, Actor> actor() { - return effect -> actor(effect); + return this::actor; } /** @@ -148,7 +148,7 @@ public Promise> sequence(final List> ps) { * @return A first-class function that traverses a list inside a promise. */ public F>, Promise>> sequenceList() { - return list -> sequence(list); + return this::sequence; } /** @@ -167,7 +167,7 @@ public Promise> sequence(final Stream> ps) { * @return A first-class function that traverses a stream inside a promise. */ public F>, Promise>> sequenceStream() { - return stream -> sequence(stream); + return this::sequence; } /** @@ -313,7 +313,7 @@ public F, F, Promise>>> parMapIterable() * @return A Promise of a new Array with the given function applied to each element. */ public Promise> parMap(final Array as, final F f) { - return parMap(as.toStream(), f).fmap(stream -> stream.toArray()); + return parMap(as.toStream(), f).fmap(Stream::toArray); } /** @@ -452,7 +452,7 @@ public Promise> parZipWith(final Stream as, final Stream< * @return A Promise of a new array with the results of applying the given function across the two arrays, stepwise. */ public Promise> parZipWith(final Array as, final Array bs, final F> f) { - return parZipWith(as.toStream(), bs.toStream(), f).fmap(stream -> stream.toArray()); + return parZipWith(as.toStream(), bs.toStream(), f).fmap(Stream::toArray); } /** @@ -515,7 +515,7 @@ public Promise parFoldMap(final Stream as, final F map, final public Promise parFoldMap(final Iterable as, final F map, final Monoid reduce, final F, P2, Iterable>> chunking) { return parFoldMap(iterableStream(as), map, reduce, (Stream stream) -> { - final F, Stream> is = iterable -> iterableStream(iterable); + final F, Stream> is = Stream::iterableStream; return chunking.f(stream).map1(is).map2(is); }); } diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index 42f9e3c2..fc20f491 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -190,7 +190,7 @@ public void f(final B b) { * @return A new promise after applying the given promised function to this promise. */ public Promise apply(final Promise> pf) { - return pf.bind(f -> fmap(f)); + return pf.bind(this::fmap); } /** diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index 28bd6d32..79e698b9 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -168,7 +168,7 @@ public F, P1>> parMapList(final F f) { * @return A function that promotes another function to a parallel function on lists. */ public F, F, P1>>> parMapList() { - return f1 -> parMapList(f1); + return this::parMapList; } /** @@ -196,7 +196,7 @@ public F, P1>> parMapArray(final F f) { * @return A function that promotes another function to a parallel function on arrays. */ public F, F, P1>>> parMapArray() { - return f1 -> parMapArray(f1); + return this::parMapArray; } /** @@ -311,7 +311,7 @@ public F2, Array, P1>> parZipArrayWith(final F2 F, P1> obtain() { - return t -> obtain(t); + return Strategy::obtain; } /** diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index d9231cb8..7890a0c8 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -527,7 +527,7 @@ public Array bind(final Array sb, final F2 f) { * @return A new array after applying the given array of functions through this array. */ public Array apply(final Array> lf) { - return lf.bind(f -> map(a -> f.f(a))); + return lf.bind(f -> map(f::f)); } /** @@ -606,7 +606,7 @@ public static Array single(final A a) { * @return A function that wraps a given array. */ public static F> wrap() { - return as -> array(as); + return Array::array; } /** @@ -635,7 +635,7 @@ public static Array join(final Array> o) { * @return A function that joins a array of arrays using a bind operation. */ public static F>, Array> join() { - return as -> join(as); + return Array::join; } /** diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 055da1dd..35cf68be 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -36,7 +36,7 @@ private Conversions() { * @return A function that converts lists to arrays. */ public static F, Array> List_Array() { - return as -> as.toArray(); + return List::toArray; } /** @@ -45,7 +45,7 @@ public static F, Array> List_Array() { * @return A function that converts lists to streams. */ public static F, Stream> List_Stream() { - return as -> as.toStream(); + return List::toStream; } /** @@ -54,7 +54,7 @@ public static F, Stream> List_Stream() { * @return A function that converts lists to options. */ public static F, Option> List_Option() { - return as -> as.headOption(); + return List::headOption; } /** @@ -69,7 +69,7 @@ public static F, F, Either>> List_Either() { /** * A function that converts lists to strings. */ - public static final F, String> List_String = cs -> asString(cs); + public static final F, String> List_String = List::asString; /** * A function that converts lists to string buffers. @@ -91,7 +91,7 @@ public static F, F, Either>> List_Either() { * @return A function that converts arrays to lists. */ public static F, List> Array_List() { - return as -> as.toList(); + return Array::toList; } /** @@ -100,7 +100,7 @@ public static F, List> Array_List() { * @return A function that converts arrays to streams. */ public static F, Stream> Array_Stream() { - return as -> as.toStream(); + return Array::toStream; } /** @@ -109,7 +109,7 @@ public static F, Stream> Array_Stream() { * @return A function that converts arrays to options. */ public static F, Option> Array_Option() { - return as -> as.toOption(); + return Array::toOption; } /** @@ -126,7 +126,7 @@ public static F, F, Either>> Array_Either() { */ public static final F, String> Array_String = cs -> { final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect(c -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb.toString(); }; @@ -135,7 +135,7 @@ public static F, F, Either>> Array_Either() { */ public static final F, StringBuffer> Array_StringBuffer = cs -> { final StringBuffer sb = new StringBuffer(); - cs.foreachDoEffect(c -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb; }; @@ -144,7 +144,7 @@ public static F, F, Either>> Array_Either() { */ public static final F, StringBuilder> Array_StringBuilder = cs -> { final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect((Character c) -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb; }; @@ -158,7 +158,7 @@ public static F, F, Either>> Array_Either() { * @return A function that converts streams to lists. */ public static F, List> Stream_List() { - return as -> as.toList(); + return Stream::toList; } /** @@ -167,7 +167,7 @@ public static F, List> Stream_List() { * @return A function that converts streams to arrays. */ public static F, Array> Stream_Array() { - return as -> as.toArray(); + return Stream::toArray; } /** @@ -176,7 +176,7 @@ public static F, Array> Stream_Array() { * @return A function that converts streams to options. */ public static F, Option> Stream_Option() { - return as -> as.toOption(); + return Stream::toOption; } /** @@ -193,7 +193,7 @@ public static F, F, Either>> Stream_Either() { */ public static final F, String> Stream_String = cs -> { final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect((Character c) -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb.toString(); }; @@ -202,7 +202,7 @@ public static F, F, Either>> Stream_Either() { */ public static final F, StringBuffer> Stream_StringBuffer = cs -> { final StringBuffer sb = new StringBuffer(); - cs.foreachDoEffect((Character c) -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb; }; @@ -211,7 +211,7 @@ public static F, F, Either>> Stream_Either() { */ public static final F, StringBuilder> Stream_StringBuilder = cs -> { final StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect((Character c) -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb; }; @@ -225,7 +225,7 @@ public static F, F, Either>> Stream_Either() { * @return A function that converts options to lists. */ public static F, List> Option_List() { - return o -> o.toList(); + return Option::toList; } /** @@ -234,7 +234,7 @@ public static F, List> Option_List() { * @return A function that converts options to arrays. */ public static F, Array> Option_Array() { - return o -> o.toArray(); + return Option::toArray; } /** @@ -243,7 +243,7 @@ public static F, Array> Option_Array() { * @return A function that converts options to streams. */ public static F, Stream> Option_Stream() { - return o -> o.toStream(); + return Option::toStream; } /** @@ -275,7 +275,7 @@ public static F, F, Either>> Option_Either() { // BEGIN Effect public static F> Effect0_P1() { - return e -> Effect0_P1(e); + return Conversions::Effect0_P1; } public static P1 Effect0_P1(Effect0 e) { @@ -287,7 +287,7 @@ public static F Effect1_F(Effect1 e) { } public static F, F> Effect1_F() { - return e -> Effect1_F(e); + return Conversions::Effect1_F; } public static IO Effect_IO(Effect0 e) { @@ -298,7 +298,7 @@ public static IO Effect_IO(Effect0 e) { } public static F> Effect_IO() { - return e -> Effect_IO(e); + return Conversions::Effect_IO; } public static SafeIO Effect_SafeIO(Effect0 e) { @@ -309,7 +309,7 @@ public static SafeIO Effect_SafeIO(Effect0 e) { } public static F> Effect_SafeIO() { - return e -> Effect_SafeIO(e); + return Conversions::Effect_SafeIO; } // END Effect @@ -451,7 +451,7 @@ public static SafeIO F_SafeIO(F f) { } public static F, SafeIO> F_SafeIO() { - return f -> F_SafeIO(f); + return Conversions::F_SafeIO; } // END F @@ -461,7 +461,7 @@ public static F, SafeIO> F_SafeIO() { /** * A function that converts strings to lists. */ - public static final F> String_List = s -> fromString(s); + public static final F> String_List = List::fromString; /** * A function that converts strings to arrays. @@ -490,12 +490,12 @@ public static F, F>> String_Either() { /** * A function that converts strings to string buffers. */ - public static final F String_StringBuffer = s -> new StringBuffer(s); + public static final F String_StringBuffer = StringBuffer::new; /** * A function that converts strings to string builders. */ - public static final F String_StringBuilder = s -> new StringBuilder(s); + public static final F String_StringBuilder = StringBuilder::new; // END String -> @@ -533,12 +533,12 @@ public static F, F>> StringBuffer_E /** * A function that converts string buffers to strings. */ - public static final F StringBuffer_String = s -> s.toString(); + public static final F StringBuffer_String = StringBuffer::toString; /** * A function that converts string buffers to string builders. */ - public static final F StringBuffer_StringBuilder = s -> new StringBuilder(s); + public static final F StringBuffer_StringBuilder = StringBuilder::new; // END StringBuffer -> @@ -576,12 +576,12 @@ public static F, F>> StringBuilder /** * A function that converts string builders to strings. */ - public static final F StringBuilder_String = s -> s.toString(); + public static final F StringBuilder_String = StringBuilder::toString; /** * A function that converts string builders to string buffers. */ - public static final F StringBuilder_StringBuffer = s -> new StringBuffer(s); + public static final F StringBuilder_StringBuffer = StringBuffer::new; // END StringBuilder -> @@ -593,15 +593,15 @@ public static SafeIO> Try_SafeIO(Tr } public static F, SafeIO>> Try_SafeIO() { - return t -> Try_SafeIO(t); + return Conversions::Try_SafeIO; } public static IO Try_IO(Try0 t) { - return () -> t.f(); + return t::f; } public static F, IO> Try_IO() { - return t -> Try_IO(t); + return Conversions::Try_IO; } public static F> Try_F(Try1 t) { @@ -609,7 +609,7 @@ public static F> Try_F(Try1 F, F>> Try_F() { - return t -> Try_F(t); + return Conversions::Try_F; } // END Try diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 6381ee78..1cbecb5d 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -296,7 +296,7 @@ public Either sequence(final Either e) { */ public List> traverseList(final F> f) { return isLeft() ? - f.f(value()).map(x -> Either.left(x)) : + f.f(value()).map(Either::left) : list(Either.right(e.right().value())); } @@ -308,7 +308,7 @@ public List> traverseList(final F> f) { */ public IO> traverseIO(final F> f) { return isRight() ? - IOFunctions.map(f.f(value()), x -> Either.left(x)) : + IOFunctions.map(f.f(value()), Either::left) : IOFunctions.unit(Either.right(e.right().value())); } @@ -335,7 +335,7 @@ public Option> filter(final F f) { * @return The result of function application within either. */ public Either apply(final Either, B> e) { - return e.left().bind(f -> map(f)); + return e.left().bind(this::map); } /** @@ -416,13 +416,13 @@ public Collection toCollection() { public Option> traverseOption(F> f) { return isLeft() ? - f.f(value()).map(x -> Either.left(x)) : + f.f(value()).map(Either::left) : some(Either.right(e.right().value())); } public Stream> traverseStream(F> f) { return isLeft() ? - f.f(value()).map(c -> Either.left(c)) : + f.f(value()).map(Either::left) : Stream.single(Either.right(e.right().value())); } } @@ -561,7 +561,7 @@ public Either sequence(final Either e) { */ public List> traverseList(final F> f) { return isRight() ? - f.f(value()).map(x -> right(x)) : + f.f(value()).map(Either::right) : list(Either.left(e.left().value())); } @@ -573,19 +573,19 @@ public List> traverseList(final F> f) { */ public IO> traverseIO(final F> f) { return isRight() ? - IOFunctions.map(f.f(value()), x -> Either.right(x)) : + IOFunctions.map(f.f(value()), Either::right) : IOFunctions.lazy(() -> Either.left(e.left().value())); } public P1> traverseP1(final F> f) { return isRight() ? - f.f(value()).map(x -> Either.right(x)) : + f.f(value()).map(Either::right) : p(Either.left(e.left().value())); } public Option> traverseOption(final F> f) { return isRight() ? - f.f(value()).map(x -> Either.right(x)) : + f.f(value()).map(Either::right) : some(Either.left(e.left().value())); } @@ -612,7 +612,7 @@ public Option> filter(final F f) { * @return The result of function application within either. */ public Either apply(final Either> e) { - return e.right().bind(f -> map(f)); + return e.right().bind(this::map); } /** @@ -693,7 +693,7 @@ public Collection toCollection() { public Stream> traverseStream(F> f) { return isRight() ? - f.f(value()).map(x -> right(x)) : + f.f(value()).map(Either::right) : Stream.>single(left(e.left().value())); } @@ -715,7 +715,7 @@ public static Either left(final A a) { * @return A function that constructs a left value of either. */ public static F> left_() { - return a -> left(a); + return Either::left; } /** @@ -724,7 +724,7 @@ public static F> left_() { * @return A function that constructs a right value of either. */ public static F> right_() { - return b -> right(b); + return Either::right; } /** diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index 14edff71..b7533ffd 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -369,7 +369,7 @@ else if (l < 0L) { */ public static final Enumerator naturalEnumerator = enumerator( n -> some(n.succ()), - n -> n.pred(), + Natural::pred, Option.none(), some(Natural.ZERO), naturalOrd, curry((n, l) -> some(n).apply( diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index e45d94a5..6b03a96a 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -161,7 +161,7 @@ public Option get(final K k) { * @return A curried version of {@link #get(Object)}. */ public F> get() { - return k -> get(k); + return this::get; } /** diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 6aa5db12..b62bb60e 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -18,6 +18,7 @@ import fj.data.Iteratee.Input; import fj.data.Iteratee.IterV; import fj.function.Try0; +import fj.function.Try1; /** * IO monad for processing files, with main methods {@link #enumFileLines }, @@ -35,7 +36,7 @@ private IOFunctions() { } public static Try0 toTry(IO io) { - return () -> io.run(); + return io::run; } public static P1> p(IO io) { @@ -47,10 +48,10 @@ public static IO fromF(F0 p) { } public static IO fromTry(Try0 t) { - return () -> t.f(); + return t::f; } - public static final F> closeReader = r -> closeReader(r); + public static final F> closeReader = IOFunctions::closeReader; /** * Convert io to a SafeIO, throwing any IOException wrapped inside a RuntimeException @@ -127,7 +128,7 @@ public static IO> enumFileChars(final File f, final Opti } public static IO bufferedReader(final File f, final Option encoding) { - return map(fileReader(f, encoding), a -> new BufferedReader(a)); + return map(fileReader(f, encoding), BufferedReader::new); } public static IO fileReader(final File f, final Option encoding) { @@ -386,7 +387,7 @@ public static IO join(IO> io1) { } public static SafeIO> toSafeValidation(IO io) { - return () -> Try.f(() -> io.run())._1(); + return () -> Try.f(io::run)._1(); } public static IO append(final IO io1, final IO io2) { @@ -458,8 +459,8 @@ public Stream run() throws IOException { return Stream.nil(); } else { IO> io2 = sequenceWhile(stream.tail()._1(), f); - SafeIO> s3 = toSafe(() -> io2.run()); - return Stream.cons(a, () -> s3.run()); + SafeIO> s3 = toSafe(io2::run); + return Stream.cons(a, s3::run); } } } @@ -467,7 +468,7 @@ public Stream run() throws IOException { } public static IO apply(IO io, IO> iof) { - return bind(iof, f -> map(io, a -> f.f(a))); + return bind(iof, f -> map(io, f::f)); } public static IO liftM2(IO ioa, IO iob, F2 f) { @@ -479,13 +480,13 @@ public static IO> replicateM(IO ioa, int n) { } public static IO>> readerState() { - return () -> State.unit((BufferedReader r) -> P.p(r, Try.f((BufferedReader r2) -> r2.readLine()).f(r))); + return () -> State.unit((BufferedReader r) -> P.p(r, Try.f((Try1) BufferedReader::readLine).f(r))); } public static final BufferedReader stdinBufferedReader = new BufferedReader(new InputStreamReader(System.in)); public static IO stdinReadLine() { - return () -> stdinBufferedReader.readLine(); + return stdinBufferedReader::readLine; } public static IO stdoutPrintln(final String s) { diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 9e36e710..0633ffd4 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -42,7 +42,7 @@ public static IterableW wrap(final Iterable a) { * @return A function that returns the given iterable, wrapped. */ public static > F> wrap() { - return a -> wrap(a); + return IterableW::wrap; } /** @@ -73,7 +73,7 @@ public static F> iterable(final F f) { * @return A transformation from a function to the equivalent Iterable-valued function. */ public static F, F>> arrow() { - return f -> iterable(f); + return IterableW::iterable; } /** @@ -93,7 +93,7 @@ public > IterableW bind(final F f) { * @return A new iterable after applying the given iterable function to the wrapped iterable. */ public IterableW apply(final Iterable> f) { - return wrap(f).bind(f1 -> map(f1)); + return wrap(f).bind(this::map); } /** @@ -143,7 +143,7 @@ public static > IterableW> sequence(final * @return a function that binds a given function across a given iterable. */ public static > F, F, IterableW>> bind() { - return a -> f -> a.bind(f); + return a -> a::bind; } /** @@ -163,7 +163,7 @@ public static > IterableW join(final Iterable as) * @return a function that joins an Iterable of Iterables into a single Iterable. */ public static > F, IterableW> join() { - return a -> join(a); + return IterableW::join; } /** diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index e2f9adfd..8836fe2f 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1433,7 +1433,7 @@ public static F> StringBuilder_Synchr * @return A function that converts array lists to lists. */ public static F, List> ArrayList_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1447,11 +1447,11 @@ public static F, List> ArrayList_List() { * @return A function that converts Java lists to lists. */ public static F, List> JUList_List() { - return as -> JavaList_List(as); + return Java::JavaList_List; } public static F, List> JavaList_List() { - return as -> JavaList_List(as); + return Java::JavaList_List; } public static List JavaList_List(java.util.List list) { @@ -1479,7 +1479,7 @@ public static List JavaList_List(java.util.List list) { * @return A function that converts enum sets to lists. */ public static > F, List> EnumSet_List() { - return as -> Collection_List(as); + return Java::Collection_List; } public static List Collection_List(Collection c) { @@ -1507,7 +1507,7 @@ private static E[] array(int length, E... array) { * @return A function that converts hash sets to lists. */ public static F, List> HashSet_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1522,7 +1522,7 @@ public static F, List> HashSet_List() { * @return A function that converts linked hash sets to lists. */ public static F, List> LinkedHashSet_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1537,7 +1537,7 @@ public static F, List> LinkedHashSet_List() { * @return A function that converts linked lists to lists. */ public static F, List> LinkedList_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1552,7 +1552,7 @@ public static F, List> LinkedList_List() { * @return A function that converts priority queues to lists. */ public static F, List> PriorityQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1567,7 +1567,7 @@ public static F, List> PriorityQueue_List() { * @return A function that converts stacks to lists. */ public static F, List> Stack_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1582,7 +1582,7 @@ public static F, List> Stack_List() { * @return A function that converts tree sets to lists. */ public static F, List> TreeSet_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1597,7 +1597,7 @@ public static F, List> TreeSet_List() { * @return A function that converts vectors to lists. */ public static F, List> Vector_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1612,7 +1612,7 @@ public static F, List> Vector_List() { * @return A function that converts array blocking queues to lists. */ public static F, List> ArrayBlockingQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1627,7 +1627,7 @@ public static F, List> ArrayBlockingQueue_List() { * @return A function that converts concurrent linked queues to lists. */ public static F, List> ConcurrentLinkedQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1642,7 +1642,7 @@ public static F, List> ConcurrentLinkedQueue_Lis * @return A function that converts copy on write array lists to lists. */ public static F, List> CopyOnWriteArrayList_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1657,7 +1657,7 @@ public static F, List> CopyOnWriteArrayList_List( * @return A function that converts copy on write array sets to lists. */ public static F, List> CopyOnWriteArraySet_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1672,7 +1672,7 @@ public static F, List> CopyOnWriteArraySet_List() * @return A function that converts delay queues to lists. */ public static F, List> DelayQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1687,7 +1687,7 @@ public static F, List> DelayQueue_List() { * @return A function that converts linked blocking queues to lists. */ public static F, List> LinkedBlockingQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1702,7 +1702,7 @@ public static F, List> LinkedBlockingQueue_List() * @return A function that converts priority blocking queues to lists. */ public static F, List> PriorityBlockingQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1717,7 +1717,7 @@ public static F, List> PriorityBlockingQueue_Lis * @return A function that converts synchronous queues to lists. */ public static F, List> SynchronousQueue_List() { - return as -> Collection_List(as); + return Java::Collection_List; } // todo @@ -1727,7 +1727,7 @@ public static F, List> SynchronousQueue_List() { // BEGIN Callable -> public static F, Callable> P1_Callable() { - return a -> () -> a._1(); + return a -> a::_1; } // END Callable -> diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 0b5a0d4c..5a2e2504 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -655,7 +655,7 @@ public IO> traverseIO(F> f) { public F> traverseF(F> f) { return this.foldRight( (a, acc) -> Function.bind(acc, - (bs) -> Function.> compose(b -> bs.cons(b), f.f(a))), + (bs) -> Function.> compose(bs::cons, f.f(a))), constant(List. nil()) ); } @@ -697,7 +697,7 @@ public V2> traverseV2(final F> f) { * @return A new list after applying the given list of functions through this list. */ public final List apply(final List> lf) { - return lf.bind(f -> map(f)); + return lf.bind(this::map); } /** @@ -1041,7 +1041,7 @@ public final List> zip(final List bs) { * @return A function that zips the given lists to produce a list of pairs. */ public static F, F, List>>> zip() { - return curry((as, bs) -> as.zip(bs)); + return curry(List::zip); } /** @@ -1164,7 +1164,7 @@ public final List nub(final Ord o) { * @return A function that gets the head of a given list. */ public static F, A> head_() { - return list -> list.head(); + return List::head; } @@ -1182,7 +1182,7 @@ public Option> tailOption() { * @return A function that gets the tail of a given list. */ public static F, List> tail_() { - return list -> list.tail(); + return List::tail; } /** @@ -1446,7 +1446,7 @@ public final boolean isSuffixOf(final Equal eq, final List xs) { * @return A function that gets the length of a given list. */ public static F, Integer> length_() { - return a -> a.length(); + return List::length; } /** @@ -1607,7 +1607,7 @@ public static F, List>> cons() { } public static F2, List> cons_() { - return (a, listA) -> cons(a, listA); + return List::cons; } /** @@ -1617,7 +1617,7 @@ public static F2, List> cons_() { * @return A function that prepends a value to the given list. */ public static F> cons(final List tail) { - return a -> tail.cons(a); + return tail::cons; } /** @@ -1647,7 +1647,7 @@ public static List cons(final A head, final List tail) { * @return A function that determines whether a given list is empty. */ public static F, Boolean> isEmpty_() { - return as -> as.isEmpty(); + return List::isEmpty; } /** @@ -1656,7 +1656,7 @@ public static F, Boolean> isEmpty_() { * @return A function that determines whether a given list is not empty. */ public static F, Boolean> isNotEmpty_() { - return as -> as.isNotEmpty(); + return List::isNotEmpty; } /** @@ -1676,7 +1676,7 @@ public static List join(final List> o) { * @return A function that joins a list of lists using a bind operation. */ public static F>, List> join() { - return as -> join(as); + return List::join; } /** @@ -1762,7 +1762,7 @@ public static List fromString(final String s) { * @return A first-class fromString. */ public static F> fromString() { - return s -> fromString(s); + return List::fromString; } /** @@ -1788,7 +1788,7 @@ public static String asString(final List cs) { * @return A first-class asString. */ public static F, String> asString() { - return cs -> asString(cs); + return List::asString; } /** diff --git a/core/src/main/java/fj/data/Natural.java b/core/src/main/java/fj/data/Natural.java index 396aa39c..1779d8c7 100644 --- a/core/src/main/java/fj/data/Natural.java +++ b/core/src/main/java/fj/data/Natural.java @@ -40,7 +40,7 @@ public static Option natural(final BigInteger i) { * A function that returns the natural number equal to a given BigInteger */ public static final F> fromBigInt = - i -> natural(i); + Natural::natural; /** * Returns the natural number equal to the given long @@ -77,7 +77,7 @@ public Natural succ() { * @return A function that returns the successor of a given natural number. */ public static F succ_() { - return natural -> natural.succ(); + return Natural::succ; } /** @@ -95,7 +95,7 @@ public Option pred() { * @return A function that returns the predecessor of a given natural number, or None if it's zero. */ public static F> pred_() { - return natural -> natural.pred(); + return Natural::pred; } /** @@ -111,7 +111,7 @@ public Natural add(final Natural n) { /** * A function that adds two natural numbers. */ - public static final F> add = curry((n1, n2) -> n1.add(n2)); + public static final F> add = curry(Natural::add); /** @@ -143,7 +143,7 @@ public Natural multiply(final Natural n) { /** * A function that multiplies a natural number by another. */ - public static final F> multiply = curry((n1, n2) -> n1.multiply(n2)); + public static final F> multiply = curry(Natural::multiply); /** @@ -245,7 +245,7 @@ public int intValue() { /** * A function that returns the BigInteger value of a given Natural. */ - public static final F bigIntegerValue = n -> n.bigIntegerValue(); + public static final F bigIntegerValue = Natural::bigIntegerValue; /** * Sums a stream of natural numbers. diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 0ebffc11..611bef93 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -127,7 +127,7 @@ public void f(final A a) { public NonEmptyList> sublists() { return fromList( somes(toList().toStream().substreams() - .map(F1Functions.o(list -> fromList(list), Conversions.Stream_List())).toList())).some(); + .map(F1Functions.o(NonEmptyList::fromList, Conversions.Stream_List())).toList())).some(); } /** @@ -137,7 +137,7 @@ public NonEmptyList> sublists() { * @return A NonEmptyList of the tails of this list. */ public NonEmptyList> tails() { - return fromList(somes(toList().tails().map(list -> fromList(list)))).some(); + return fromList(somes(toList().tails().map(NonEmptyList::fromList))).some(); } /** @@ -268,7 +268,7 @@ public Collection toCollection() { * @return A function that takes a non-empty list to a list. */ public static F, List> toList_() { - return as -> as.toList(); + return NonEmptyList::toList; } /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 5bec1ea4..5c8dca74 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -95,7 +95,7 @@ public final boolean isNone() { * @return A function that returns true if a given optional value has a value, otherwise false. */ public static F, Boolean> isSome_() { - return a -> a.isSome(); + return Option::isSome; } /** @@ -104,7 +104,7 @@ public static F, Boolean> isSome_() { * @return A function that returns false if a given optional value has a value, otherwise true. */ public static F, Boolean> isNone_() { - return a -> a.isNone(); + return Option::isNone; } /** @@ -412,15 +412,15 @@ public final Option sequence(final Option o) { } public Either> traverseEither(F> f) { - return map(a -> f.f(a).right().map(b -> some(b))).orSome(Either.right(none())); + return map(a -> f.f(a).right().map(Option::some)).orSome(Either.right(none())); } public IO> traverseIO(F> f) { - return map(a -> IOFunctions.map(f.f(a), b -> some(b))).orSome(IOFunctions.lazy(() -> none())); + return map(a -> IOFunctions.map(f.f(a), Option::some)).orSome(IOFunctions.lazy(Option::none)); } public List> traverseList(F> f) { - return map(a -> f.f(a).map(b -> some(b))).orSome(List.list()); + return map(a -> f.f(a).map(Option::some)).orSome(List.list()); } public Option> traverseOption(F> f) { @@ -428,28 +428,28 @@ public Option> traverseOption(F> f) { } public Stream> traverseStream(F> f) { - return map(a -> f.f(a).map(b -> some(b))).orSome(Stream.nil()); + return map(a -> f.f(a).map(Option::some)).orSome(Stream.nil()); } public P1> traverseP1(F> f) { - return map(a -> f.f(a).map(b -> some(b))).orSome(p(none())); + return map(a -> f.f(a).map(Option::some)).orSome(p(none())); } public Seq> traverseSeq(F> f) { - return map(a -> f.f(a).map(b -> some(b))).orSome(Seq.empty()); + return map(a -> f.f(a).map(Option::some)).orSome(Seq.empty()); } public Set> traverseSet(Ord ord, F> f) { Ord> optOrd = Ord.optionOrd(ord); - return map(a -> f.f(a).map(optOrd, b -> some(b))).orSome(Set.empty(optOrd)); + return map(a -> f.f(a).map(optOrd, Option::some)).orSome(Set.empty(optOrd)); } public F2, F>, Set>> traverseSet() { - return (o, f) -> traverseSet(o, f); + return this::traverseSet; } public Validation> traverseValidation(F> f) { - return map(a -> f.f(a).map(b -> some(b))).orSome(Validation.success(none())); + return map(a -> f.f(a).map(Option::some)).orSome(Validation.success(none())); } /** @@ -460,7 +460,7 @@ public Validation> traverseValidation(F> * optional value. */ public final Option apply(final Option> of) { - return of.bind(f -> map(a -> f.f(a))); + return of.bind(f -> map(f::f)); } /** @@ -516,7 +516,7 @@ public final Validation toValidation(final X x) { * return in left. */ public static F, F>> toEither() { - return curry((a, x) -> a.toEither(x)); + return curry(Option::toEither); } /** @@ -641,7 +641,7 @@ public A some() { public static F> some_() { - return t -> some(t); + return Option::some; } /** @@ -685,7 +685,7 @@ public static Option fromNull(final T t) { * @return If t == null then return none, otherwise, return it in some. */ public static F> fromNull() { - return t -> fromNull(t); + return Option::fromNull; } /** @@ -758,7 +758,7 @@ public static Option iif(final boolean p, final A a) { * holds on that argument, or no value otherwise. */ public static F2, A, Option> iif() { - return (p, a) -> iif(p, a); + return Option::iif; } /** @@ -808,7 +808,7 @@ public int hashCode() { * or no value if the string is empty. */ public static F> fromString() { - return s -> fromString(s); + return Option::fromString; } /** @@ -855,7 +855,7 @@ public static F>, F, Option>> bind() { * @return A function that joins an Option of an Option to make a single Option. */ public static F>, Option> join() { - return option -> join(option); + return Option::join; } /** diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 09d80279..4dcd10de 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -173,7 +173,7 @@ public final boolean member(final A x) { * @return A function that returns true if the given element if a member of the given set. */ public static F, F> member() { - return curry((s, a) -> s.member(a)); + return curry(Set::member); } /** @@ -394,7 +394,7 @@ public final Set union(final Set s) { * @see #union(Set) */ public static F, F, Set>> union() { - return curry((s1, s2) -> s1.union(s2)); + return curry(Set::union); } /** @@ -444,7 +444,7 @@ public final Set intersect(final Set s) { * @see #intersect(Set) */ public static F, F, Set>> intersect() { - return curry((s1, s2) -> s1.intersect(s2)); + return curry(Set::intersect); } /** @@ -464,7 +464,7 @@ public final Set minus(final Set s) { * @see #minus(Set) */ public static F, F, Set>> minus() { - return curry((s1, s2) -> s1.minus(s2)); + return curry(Set::minus); } public Option min() { diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 81146f95..47703e7b 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -93,7 +93,7 @@ public State withs(F f) { } public static State gets(F f) { - return State.init().map(s -> f.f(s)); + return State.init().map(f::f); } /** @@ -101,7 +101,7 @@ public static State gets(F f) { */ public static State> sequence(List> list) { return list.foldLeft((State> acc, State ma) -> - acc.flatMap((List xs) -> ma.map((A x) -> xs.snoc(x)) + acc.flatMap((List xs) -> ma.map(xs::snoc) ), constant(List.nil())); } @@ -111,7 +111,7 @@ public static State> sequence(List> list) { */ public static State> traverse(List list, F> f) { return list.foldLeft((State> acc, A a) -> - acc.flatMap(bs -> f.f(a).map(b -> bs.snoc(b)) + acc.flatMap(bs -> f.f(a).map(bs::snoc) ), constant(List.nil())); } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 6dbcf778..8e04e499 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -2,6 +2,7 @@ import fj.Equal; import fj.F0; +import fj.F3; import fj.Hash; import fj.Show; import fj.F; @@ -521,7 +522,7 @@ public final Stream sequence(final Stream bs) { * @return The stream of IOs after sequencing. */ public static Stream> sequence(final IO> io) { - return IOFunctions.runSafe(io).map(a -> IOFunctions.unit(a)); + return IOFunctions.runSafe(io).map(IOFunctions::unit); } /** @@ -531,7 +532,7 @@ public static Stream> sequence(final IO> io) { * @return The stream of (pre-calculated) lazy values after sequencing. */ public static Stream> sequence(final F0> p) { - return p.f().map(a -> p(a)); + return p.f().map(P::p); } /** @@ -541,7 +542,7 @@ public static Stream> sequence(final F0> p) { * @return The stream of options after sequencing. */ public static Stream> sequence(final Option> o) { - return o.isNone() ? nil() : o.some().map(a -> some(a)); + return o.isNone() ? nil() : o.some().map(Option::some); } /** @@ -551,7 +552,7 @@ public static Stream> sequence(final Option> o) { * @return A new stream after applying the given stream of functions through this stream. */ public final Stream apply(final Stream> sf) { - return sf.bind(f -> map(f)); + return sf.bind(this::map); } /** @@ -892,7 +893,7 @@ public final Stream> zip(final Stream bs) { * @return A new stream with the same length as this stream. */ public final Stream> zipIndex() { - return zipWith(range(0), (a, i) -> p(a, i)); + return zipWith(range(0), (F2>) P::p); } /** @@ -941,7 +942,7 @@ public final A[] toJavaArray() { */ public final List toList() { List.Buffer buf = List.Buffer.empty(); - foreachDoEffect(a -> buf.snoc(a)); + foreachDoEffect(buf::snoc); return buf.toList(); } @@ -1018,7 +1019,7 @@ public final Stream cons(final A a) { */ public static String asString(final Stream cs) { StringBuilder sb = new StringBuilder(); - cs.foreachDoEffect(c -> sb.append(c)); + cs.foreachDoEffect(sb::append); return sb.toString(); } @@ -1103,8 +1104,7 @@ public final Stream takeWhile(final F f) { public final IO> traverseIO(F> f) { return this.foldRight1((a, acc) -> IOFunctions.bind(acc, (Stream bs) -> - IOFunctions.map(f.f(a), b -> - bs.cons(b))), IOFunctions.unit(Stream.nil())); + IOFunctions.map(f.f(a), bs::cons)), IOFunctions.unit(Stream.nil())); } @@ -1114,7 +1114,7 @@ public final IO> traverseIO(F> f) { * @return traversed value */ public final Option> traverseOption(F> f) { - return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(b -> bs.cons(b))), some(Stream.nil())); + return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(bs::cons)), some(Stream.nil())); } /** @@ -1334,7 +1334,7 @@ public final Stream> tails() { * @return a stream of the prefixes of this stream, starting with the stream itself. */ public final Stream> inits() { - final Stream> nil = cons(Stream.nil(), () -> nil()); + final Stream> nil = cons(Stream.nil(), Stream::nil); return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.cons_().f(head()))); } @@ -1344,7 +1344,7 @@ public final Stream> inits() { * @return a stream of the infixes of this stream. */ public final Stream> substreams() { - return tails().bind(stream -> stream.inits()); + return tails().bind(Stream::inits); } /** @@ -1375,7 +1375,7 @@ public final Stream sequenceW(final Stream, B>> fs) { * @return A function from natural numbers to values with the corresponding position in this stream. */ public final F toFunction() { - return i -> index(i); + return this::index; } /** @@ -1426,7 +1426,7 @@ public static P2, Stream> unzip(final Stream> xs) { * @return a function that zips two given streams with a given function. */ public static F, F, F>, Stream>>> zipWith() { - return curry((as, bs, f) -> as.zipWith(bs, f)); + return curry((F3, Stream, F>, Stream>) Stream::zipWith); } private static final class Nil extends Stream { @@ -1491,7 +1491,7 @@ public static Stream nil() { * @return An empty stream. */ public static P1> nil_() { - return P.lazy(() -> new Nil()); + return P.lazy(Nil::new); } /** @@ -1500,7 +1500,7 @@ public static P1> nil_() { * @return A function that determines whether a given stream is empty. */ public static F, Boolean> isEmpty_() { - return as -> as.isEmpty(); + return Stream::isEmpty; } /** @@ -1509,7 +1509,7 @@ public static F, Boolean> isEmpty_() { * @return A function that determines whether a given stream is not empty. */ public static F, Boolean> isNotEmpty_() { - return as -> as.isNotEmpty(); + return Stream::isNotEmpty; } /** @@ -1519,7 +1519,7 @@ public static F, Boolean> isNotEmpty_() { * @return A stream of one element containing the given value. */ public static Stream single(final A a) { - return cons(a, () -> nil()); + return cons(a, Stream::nil); } /** @@ -1528,7 +1528,7 @@ public static Stream single(final A a) { * @return a function that yields a stream containing its argument. */ public static F> single() { - return a -> single(a); + return Stream::single; } /** @@ -1556,7 +1556,7 @@ public static Stream cons(final A head, final F0> tail) { * @return A function that joins a stream of streams using a bind operation. */ public static F>, Stream> join() { - return as -> join(as); + return Stream::join; } /** @@ -1651,7 +1651,7 @@ public static Stream iterate(final F f, final A a) { * starting at a given value. */ public static F, F>> iterate() { - return curry((f, a) -> iterate(f, a)); + return curry(Stream::iterate); } /** diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 004e0910..82e682bc 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -107,7 +107,7 @@ public P1>> subForest() { * @return A transformation from a tree to its root. */ public static F, A> root_() { - return a -> a.root(); + return Tree::root; } /** @@ -116,7 +116,7 @@ public static F, A> root_() { * @return A transformation from a tree to its subforest. */ public static F, P1>>> subForest_() { - return a -> a.subForest(); + return Tree::subForest; } /** @@ -142,7 +142,7 @@ public Stream f(final Tree t, final P1> xs) { * @return The elements of the tree in pre-order. */ public static F, Stream> flatten_() { - return t -> t.flatten(); + return Tree::flatten; } /** @@ -335,7 +335,7 @@ public static Tree bottomUp(Tree t, final F>, B> f) * @return a function getting the root of a Tree */ private static F, A> getRoot() { - return a -> a.root(); + return Tree::root; } public boolean isLeaf() { @@ -343,7 +343,7 @@ public boolean isLeaf() { } public int length() { - return 1 + subForest._1().map(t -> t.length()).foldLeft((acc, i) -> acc + i, 0); + return 1 + subForest._1().map(Tree::length).foldLeft((acc, i) -> acc + i, 0); } } \ No newline at end of file diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 2bdf70a9..de4876ec 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -264,7 +264,7 @@ public static TreeMap fromMutableMap(final Ord ord, final Map> get() { - return k -> get(k); + return this::get; } /** @@ -377,7 +377,7 @@ public Option> min() { * Returns the minimum key in the tree if the tree is not empty. */ public Option minKey() { - return tree.min().map(p -> p._1()); + return tree.min().map(P2::_1); } /** @@ -391,7 +391,7 @@ public Option> max() { * Returns the maximum key in the tree if the tree is not empty. */ public Option maxKey() { - return tree.max().map(p -> p._1()); + return tree.max().map(P2::_1); } /** diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 959de5a7..3cfeff7c 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -81,7 +81,7 @@ public static TreeZipper treeZipper(final Tree tree, F, F>, F>, F>, A, Stream>>>, TreeZipper>>>> treeZipper() { return curry( - (tree, lefts, rights, parents) -> treeZipper(tree, lefts, rights, parents)); + TreeZipper::treeZipper); } /** @@ -100,7 +100,7 @@ public P4, Stream>, Stream>, Stream>, */ public static F, P4, Stream>, Stream>, Stream>, A, Stream>>>>> p_() { - return a -> a.p(); + return TreeZipper::p; } /** @@ -167,7 +167,7 @@ public TreeZipper root() { * @return A function that returns a new tree-zipper focused on the root of the given tree zipper's tree. */ public static F, TreeZipper> root_() { - return a -> a.root(); + return TreeZipper::root; } /** @@ -553,7 +553,7 @@ public TreeZipper map(final F f) { * @return A function that takes a tree to its tree zipper representation. */ public static F, TreeZipper> fromTree() { - return t -> fromTree(t); + return TreeZipper::fromTree; } /** @@ -562,7 +562,7 @@ public static F, TreeZipper> fromTree() { * @return A function that focuses the given tree zipper on its left sibling. */ public static F, Option>> left_() { - return z -> z.left(); + return TreeZipper::left; } /** @@ -571,7 +571,7 @@ public static F, Option>> left_() { * @return A function that focuses the given tree zipper on its right sibling. */ public static F, Option>> right_() { - return z -> z.right(); + return TreeZipper::right; } /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 3e622f68..8328590f 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -205,8 +205,8 @@ public Validation sequence(final Validation v) { * all the failures using the semigroup, otherwise returns the successful list. */ public static Validation> sequence(final Semigroup s, final List> list) { - if (list.exists(v -> v.isFail())) { - return Validation.>fail(list.filter(v -> v.isFail()).map(v -> v.fail()).foldLeft1((e1, e2) -> s.sum(e1, e2))); + if (list.exists(Validation::isFail)) { + return Validation.>fail(list.filter(Validation::isFail).map(v -> v.fail()).foldLeft1((F2) s::sum)); } else { return success(list.foldLeft((List acc, Validation v) -> acc.cons(v.success()), List.nil()).reverse()); } @@ -816,12 +816,12 @@ public Validation, D> accumulate(Validation v2, Validati * single failure using a semigroup. */ public static Validation, List> sequenceNonCumulative(List> list) { - if (list.exists(v -> v.isFail())) { + if (list.exists(Validation::isFail)) { F2, Validation, List> f = (acc, v) -> acc.cons(v.fail()); - return fail(list.filter(v -> v.isFail()).foldLeft(f, List.nil()).reverse()); + return fail(list.filter(Validation::isFail).foldLeft(f, List.nil()).reverse()); } else { F2, Validation, List> f = (acc, v) -> acc.cons(v.success()); - return success(list.filter(v -> v.isSuccess()).foldLeft(f, List.nil()).reverse()); + return success(list.filter(Validation::isSuccess).foldLeft(f, List.nil()).reverse()); } } @@ -857,11 +857,11 @@ public P1> traverseP1(F> f){ public static List fails(List> list) { - return list.filter(v -> v.isFail()).map(v -> v.fail()); + return list.filter(Validation::isFail).map(v -> v.fail()); } public static List successes(List> list) { - return list.filter(v -> v.isSuccess()).map(v -> v.success()); + return list.filter(Validation::isSuccess).map(v -> v.success()); } /** @@ -1002,7 +1002,7 @@ public Option> filter(final F f) { * @return The result of function application in validation. */ public Validation apply(final Validation, T> v) { - return v.f().bind(f -> map(f)); + return v.f().bind(this::map); } /** @@ -1103,7 +1103,7 @@ public static Validation validation(final Either e) { * @return A function that constructs a validation with an either. */ public static F, Validation> validation() { - return e1 -> validation(e1); + return Validation::validation; } /** @@ -1112,7 +1112,7 @@ public static F, Validation> validation() { * @return A function that constructs an either with a validation. */ public static F, Either> either() { - return v -> v.toEither(); + return Validation::toEither; } /** @@ -1175,7 +1175,7 @@ public static Validation parseByte(final String s) /** * A function that parses a string into a byte. */ - public static final F> parseByte = s -> parseByte(s); + public static final F> parseByte = Validation::parseByte; /** * Parses the given string into a double. @@ -1194,7 +1194,7 @@ public static Validation parseDouble(final String /** * A function that parses a string into a double. */ - public static final F> parseDouble = s -> parseDouble(s); + public static final F> parseDouble = Validation::parseDouble; /** * Parses the given string into a float. @@ -1213,7 +1213,7 @@ public static Validation parseFloat(final String s /** * A function that parses a string into a float. */ - public static final F> parseFloat = s -> parseFloat(s); + public static final F> parseFloat = Validation::parseFloat; /** * Parses the given string into a integer. @@ -1232,7 +1232,7 @@ public static Validation parseInt(final String s /** * A function that parses a string into an integer. */ - public static final F> parseInt = s -> parseInt(s); + public static final F> parseInt = Validation::parseInt; /** * Parses the given string into a long. @@ -1251,7 +1251,7 @@ public static Validation parseLong(final String s) /** * A function that parses a string into a long. */ - public static final F> parseLong = s -> parseLong(s); + public static final F> parseLong = Validation::parseLong; /** * Parses the given string into a short. @@ -1270,15 +1270,15 @@ public static Validation parseShort(final String s /** * A function that parses a string into a short. */ - public static final F> parseShort = s -> parseShort(s); + public static final F> parseShort = Validation::parseShort; /** * Partitions the list into the list of fails and the list of successes */ public static P2, List> partition(List> list) { return p( - list.filter(v -> v.isFail()).map(v -> v.fail()), - list.filter(v -> v.isSuccess()).map(v -> v.success()) + list.filter(Validation::isFail).map(v -> v.fail()), + list.filter(Validation::isSuccess).map(v -> v.success()) ); } diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index 6de0d39c..f24ecf01 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -74,7 +74,7 @@ public static Zipper zipper(final P3, A, Stream> p) { * @return A function that yields a new zipper given streams on the left and right and a focus element. */ public static F3, A, Stream, Zipper> zipper() { - return (l, a, r) -> zipper(l, a, r); + return Zipper::zipper; } /** @@ -92,7 +92,7 @@ public P3, A, Stream> p() { * @return A first-class function that yields the product-3 representation of a given Zipper. */ public static F, P3, A, Stream>> p_() { - return a -> a.p(); + return Zipper::p; } /** @@ -255,7 +255,7 @@ public Zipper tryPrevious() { * @return A function that moves the given zipper's focus to the next element. */ public static F, Option>> next_() { - return as -> as.next(); + return Zipper::next; } /** @@ -264,7 +264,7 @@ public static F, Option>> next_() { * @return A function that moves the given zipper's focus to the previous element. */ public static F, Option>> previous_() { - return as -> as.previous(); + return Zipper::previous; } /** diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index debf2635..2b51f7a7 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -38,7 +38,7 @@ public abstract class Digit { */ public final A reduceRight(final F> f) { return match( - one -> one.value(), + One::value, two -> { final V2 v = two.values(); return f.f(v._1()).f(v._2()); @@ -62,7 +62,7 @@ public final A reduceRight(final F> f) { */ public final A reduceLeft(final F> f) { return match( - one -> one.value(), + One::value, two -> { final V2 v = two.values(); return f.f(v._1()).f(v._2()); diff --git a/core/src/main/java/fj/data/fingertrees/Measured.java b/core/src/main/java/fj/data/fingertrees/Measured.java index 777eb369..d33b5726 100644 --- a/core/src/main/java/fj/data/fingertrees/Measured.java +++ b/core/src/main/java/fj/data/fingertrees/Measured.java @@ -74,7 +74,7 @@ public V zero() { * @return A measured instance for nodes. */ public Measured> nodeMeasured() { - return new Measured>(m, node -> node.measure()); + return new Measured>(m, Node::measure); } /** @@ -83,7 +83,7 @@ public Measured> nodeMeasured() { * @return A measured instance for digits. */ public Measured> digitMeasured() { - return new Measured>(m, d -> d.measure()); + return new Measured>(m, Digit::measure); } } diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java index 92e4edf0..5c0bdd8c 100644 --- a/core/src/main/java/fj/data/optic/POptional.java +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -458,7 +458,7 @@ public F> modifyP1F(final F> f) { @Override public F> modifyValidationF(final F> f) { return s -> getOrModify.f(s).either( - t -> Validation. success(t), + Validation::success, t -> f.f(t).map(b -> set.f(b).f(s)) ); } diff --git a/core/src/main/java/fj/data/optic/PPrism.java b/core/src/main/java/fj/data/optic/PPrism.java index 476758a7..f6712989 100644 --- a/core/src/main/java/fj/data/optic/PPrism.java +++ b/core/src/main/java/fj/data/optic/PPrism.java @@ -126,7 +126,7 @@ public final F> modifyP1F(final F> f) { /** modify polymorphically the target of a {@link PPrism} with an Applicative function */ public final F> modifyValidationF(final F> f) { return s -> getOrModify(s).either( - t -> Validation. success(t), + Validation::success, t -> f.f(t).map(this::reverseGet) ); } diff --git a/core/src/main/java/fj/data/vector/V.java b/core/src/main/java/fj/data/vector/V.java index 26a86462..57249ac8 100644 --- a/core/src/main/java/fj/data/vector/V.java +++ b/core/src/main/java/fj/data/vector/V.java @@ -35,7 +35,7 @@ public static V2 v(final A a1, final A a2) { * @return The vector-2. */ public static V2 v(final F0 a1, final F0 a2) { - return V2.p(P.lazy(() -> a1.f(), () -> a2.f())); + return V2.p(P.lazy(a1::f, a2::f)); } /** @@ -44,7 +44,7 @@ public static V2 v(final F0 a1, final F0 a2) { * @return A function that puts elements in a vector-2. */ public static F2> v2() { - return (a, a1) -> v(a, a1); + return V::v; } /** @@ -77,7 +77,7 @@ public static V3 v(final P1 a1, final F0 a2, final F0 a3) { * @return A function that puts elements in a vector-3. */ public static F3> v3() { - return (a, a1, a2) -> v(a, a1, a2); + return V::v; } /** @@ -112,7 +112,7 @@ public static V4 v(final P1 a1, final P1 a2, final F0 a3, final * @return A function that puts elements in a vector-4. */ public static F4> v4() { - return (a, a1, a2, a3) -> v(a, a1, a2, a3); + return V::v; } @@ -150,7 +150,7 @@ public static V5 v(final P1 a1, final P1 a2, final P1 a3, final * @return A function that puts elements in a vector-5. */ public static F5> v5() { - return (a, a1, a2, a3, a4) -> v(a, a1, a2, a3, a4); + return V::v; } } diff --git a/core/src/main/java/fj/data/vector/V2.java b/core/src/main/java/fj/data/vector/V2.java index e5bf7bc1..700a8409 100644 --- a/core/src/main/java/fj/data/vector/V2.java +++ b/core/src/main/java/fj/data/vector/V2.java @@ -57,7 +57,7 @@ public A _2() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V2::_1; } /** @@ -66,7 +66,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V2::_2; } /** @@ -111,7 +111,7 @@ public Stream toStream() { * @return a function that transforms a vector-2 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V2::toStream; } /** @@ -120,7 +120,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-2 to the equivalent product-2. */ public static F, P2> p_() { - return v -> v.p(); + return V2::p; } /** @@ -193,7 +193,7 @@ public V2> vzip(final V2 bs) { * @return the first element of this vector as a product-1. */ public P1 head() { - return P.lazy(() -> V2.this._1()); + return P.lazy(V2.this::_1); } } diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index 22e11946..ceb492bc 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -31,8 +31,8 @@ private V3(final P1 head, final V2 tail) { */ public static V3 p(final P3 p) { return new V3( - P.lazy(() -> p._1()), - V2.p(P.lazy(() -> p._2(), () -> p._3())) + P.lazy(p::_1), + V2.p(P.lazy(p::_2, p::_3)) ); } @@ -211,7 +211,7 @@ public V3 map(final F f) { * @return a function that transforms a vector-3 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V3::toStream; } /** @@ -220,7 +220,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-3 to the equivalent product-3. */ public static F, P3> p_() { - return v -> v.p(); + return V3::p; } /** @@ -229,7 +229,7 @@ public static F, P3> p_() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V3::_1; } /** @@ -238,7 +238,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V3::_2; } /** @@ -247,7 +247,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return v -> v._3(); + return V3::_3; } } \ No newline at end of file diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 19ea2648..8e142023 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -30,7 +30,7 @@ private V4(final P1 head, final V3 tail) { * @return A new vector-4. */ public static V4 p(final P4 p) { - return new V4(P.lazy(() -> p._1()), + return new V4(P.lazy(p::_1), V3.p(new P3() { public A _1() { return p._2(); @@ -160,7 +160,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), () -> tail.toStream()); + return Stream.cons(head._1(), tail::toStream); } /** @@ -233,7 +233,7 @@ public V4> vzip(final V4 bs) { * @return a function that transforms a vector-4 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V4::toStream; } /** @@ -242,7 +242,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-4 to the equivalent product-4. */ public static F, P4> p_() { - return v -> v.p(); + return V4::p; } /** @@ -251,7 +251,7 @@ public static F, P4> p_() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V4::_1; } /** @@ -260,7 +260,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V4::_2; } /** @@ -269,7 +269,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return v -> v._3(); + return V4::_3; } /** @@ -278,6 +278,6 @@ public static F, A> __3() { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return v -> v._4(); + return V4::_4; } } diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 3aab13e3..d386cb32 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -30,7 +30,7 @@ private V5(final P1 head, final V4 tail) { * @return A new vector-5. */ public static V5 p(final P5 p) { - return new V5(P.lazy(() -> p._1()), + return new V5(P.lazy(p::_1), V4.p(new P4() { public A _1() { return p._2(); @@ -177,7 +177,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), () -> tail.toStream()); + return Stream.cons(head._1(), tail::toStream); } /** @@ -250,7 +250,7 @@ public V5> vzip(final V5 bs) { * @return a function that transforms a vector-5 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V5::toStream; } /** @@ -259,7 +259,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-5 to the equivalent product-5. */ public static F, P5> p_() { - return v -> v.p(); + return V5::p; } /** @@ -268,7 +268,7 @@ public static F, P5> p_() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V5::_1; } /** @@ -277,7 +277,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V5::_2; } /** @@ -286,7 +286,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return v -> v._3(); + return V5::_3; } /** @@ -295,7 +295,7 @@ public static F, A> __3() { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return v -> v._4(); + return V5::_4; } /** @@ -304,6 +304,6 @@ public static F, A> __4() { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return v -> v._5(); + return V5::_5; } } diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 66a5afca..107c01a5 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -30,7 +30,7 @@ private V6(final P1 head, final V5 tail) { * @return A new vector-6. */ public static V6 p(final P6 p) { - return new V6(P.lazy(() -> p._1()), + return new V6(P.lazy(p::_1), V5.p(new P5() { public A _1() { return p._2(); @@ -194,7 +194,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), () -> tail.toStream()); + return Stream.cons(head._1(), tail::toStream); } /** @@ -267,7 +267,7 @@ public V6> vzip(final V6 bs) { * @return a function that transforms a vector-6 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V6::toStream; } /** @@ -276,7 +276,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-6 to the equivalent product-6. */ public static F, P6> p_() { - return v -> v.p(); + return V6::p; } /** @@ -285,7 +285,7 @@ public static F, P6> p_() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V6::_1; } /** @@ -294,7 +294,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V6::_2; } /** @@ -303,7 +303,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return v -> v._3(); + return V6::_3; } /** @@ -312,7 +312,7 @@ public static F, A> __3() { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return v -> v._4(); + return V6::_4; } /** @@ -321,7 +321,7 @@ public static F, A> __4() { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return v -> v._5(); + return V6::_5; } /** @@ -330,7 +330,7 @@ public static F, A> __5() { * @return a function that gets the sixth element of a given vector. */ public static F, A> __6() { - return v -> v._6(); + return V6::_6; } } diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index c57e3551..52699481 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -30,7 +30,7 @@ private V7(final P1 head, final V6 tail) { * @return A new vector-7. */ public static V7 p(final P7 p) { - return new V7(P.lazy(() -> p._1()), + return new V7(P.lazy(p::_1), V6.p(new P6() { public A _1() { return p._2(); @@ -211,7 +211,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), () -> tail.toStream()); + return Stream.cons(head._1(), tail::toStream); } /** @@ -284,7 +284,7 @@ public V7> vzip(final V7 bs) { * @return a function that transforms a vector-7 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V7::toStream; } /** @@ -293,7 +293,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-7 to the equivalent product-7. */ public static F, P7> p_() { - return v -> v.p(); + return V7::p; } /** @@ -302,7 +302,7 @@ public static F, P7> p_() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V7::_1; } /** @@ -311,7 +311,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V7::_2; } /** @@ -320,7 +320,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return v -> v._3(); + return V7::_3; } /** @@ -329,7 +329,7 @@ public static F, A> __3() { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return v -> v._4(); + return V7::_4; } /** @@ -338,7 +338,7 @@ public static F, A> __4() { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return v -> v._5(); + return V7::_5; } /** @@ -347,7 +347,7 @@ public static F, A> __5() { * @return a function that gets the sixth element of a given vector. */ public static F, A> __6() { - return v -> v._6(); + return V7::_6; } /** @@ -356,7 +356,7 @@ public static F, A> __6() { * @return a function that gets the seventh element of a given vector. */ public static F, A> __7() { - return v -> v._7(); + return V7::_7; } } diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index 72af03f1..8ad96cdd 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -30,7 +30,7 @@ private V8(final P1 head, final V7 tail) { * @return A new vector-8. */ public static V8 p(final P8 p) { - return new V8(P.lazy(() -> p._1()), + return new V8(P.lazy(p::_1), V7.p(new P7() { public A _1() { return p._2(); @@ -228,7 +228,7 @@ public NonEmptyList toNonEmptyList() { * @return a stream of the elements of this vector. */ public Stream toStream() { - return Stream.cons(head._1(), () -> tail.toStream()); + return Stream.cons(head._1(), tail::toStream); } /** @@ -301,7 +301,7 @@ public V8> vzip(final V8 bs) { * @return a function that transforms a vector-8 to a stream of its elements. */ public static F, Stream> toStream_() { - return v -> v.toStream(); + return V8::toStream; } /** @@ -310,7 +310,7 @@ public static F, Stream> toStream_() { * @return a function that transforms a vector-8 to the equivalent product-8. */ public static F, P8> p_() { - return v -> v.p(); + return V8::p; } @@ -320,7 +320,7 @@ public static F, P8> p_() { * @return a function that gets the first element of a given vector. */ public static F, A> __1() { - return v -> v._1(); + return V8::_1; } /** @@ -329,7 +329,7 @@ public static F, A> __1() { * @return a function that gets the second element of a given vector. */ public static F, A> __2() { - return v -> v._2(); + return V8::_2; } /** @@ -338,7 +338,7 @@ public static F, A> __2() { * @return a function that gets the third element of a given vector. */ public static F, A> __3() { - return v -> v._3(); + return V8::_3; } /** @@ -347,7 +347,7 @@ public static F, A> __3() { * @return a function that gets the fourth element of a given vector. */ public static F, A> __4() { - return v -> v._4(); + return V8::_4; } /** @@ -356,7 +356,7 @@ public static F, A> __4() { * @return a function that gets the fifth element of a given vector. */ public static F, A> __5() { - return v -> v._5(); + return V8::_5; } /** @@ -365,7 +365,7 @@ public static F, A> __5() { * @return a function that gets the sixth element of a given vector. */ public static F, A> __6() { - return v -> v._6(); + return V8::_6; } /** @@ -374,7 +374,7 @@ public static F, A> __6() { * @return a function that gets the seventh element of a given vector. */ public static F, A> __7() { - return v -> v._7(); + return V8::_7; } /** @@ -383,7 +383,7 @@ public static F, A> __7() { * @return a function that gets the eighth element of a given vector. */ public static F, A> __8() { - return v -> v._8(); + return V8::_8; } } diff --git a/core/src/main/java/fj/function/BigIntegers.java b/core/src/main/java/fj/function/BigIntegers.java index 97f1a520..30d07a10 100644 --- a/core/src/main/java/fj/function/BigIntegers.java +++ b/core/src/main/java/fj/function/BigIntegers.java @@ -1,6 +1,7 @@ package fj.function; import fj.F; +import fj.F2; import fj.Monoid; import fj.data.List; import static fj.Function.curry; @@ -21,40 +22,40 @@ private BigIntegers() { * Curried Integer addition. */ public static final F> add = - curry((a1, a2) -> a1.add(a2)); + curry((F2) BigInteger::add); /** * Curried Integer multiplication. */ public static final F> multiply = - curry((a1, a2) -> a1.multiply(a2)); + curry(BigInteger::multiply); /** * Curried Integer subtraction. */ public static final F> subtract = - curry((a1, a2) -> a1.subtract(a2)); + curry((F2) BigInteger::subtract); /** * Negation. */ - public static final F negate = i -> i.negate(); + public static final F negate = BigInteger::negate; /** * Absolute value. */ - public static final F abs = i -> i.abs(); + public static final F abs = BigInteger::abs; /** * Remainder. */ public static final F> remainder = - curry((a1, a2) -> a1.remainder(a2)); + curry(BigInteger::remainder); /** * Power. */ - public static final F> power = curry((a1, a2) -> a1.pow(a2)); + public static final F> power = curry(BigInteger::pow); /** * Sums a list of big integers. diff --git a/core/src/main/java/fj/function/Characters.java b/core/src/main/java/fj/function/Characters.java index 9191bd5a..220bea7a 100644 --- a/core/src/main/java/fj/function/Characters.java +++ b/core/src/main/java/fj/function/Characters.java @@ -12,30 +12,30 @@ private Characters() { throw new UnsupportedOperationException(); } public static final F toString = c -> Character.toString(c); - public static final F isLowerCase = ch -> Character.isLowerCase(ch); - public static final F isUpperCase = ch -> Character.isUpperCase(ch); - public static final F isTitleCase = ch -> Character.isTitleCase(ch); - public static final F isDigit = ch -> Character.isDigit(ch); - public static final F isDefined = ch -> Character.isDefined(ch); - public static final F isLetter = ch -> Character.isLetter(ch); - public static final F isLetterOrDigit = ch -> Character.isLetterOrDigit(ch); - public static final F isJavaIdentifierStart = ch -> Character.isJavaIdentifierStart(ch); - public static final F isJavaIdentifierPart = ch -> Character.isJavaIdentifierPart(ch); - public static final F isUnicodeIdentifierStart = ch -> Character.isUnicodeIdentifierStart(ch); - public static final F isUnicodeIdentifierPart = ch -> Character.isUnicodeIdentifierPart(ch); - public static final F isIdentifierIgnorable = ch -> Character.isIdentifierIgnorable(ch); - public static final F toLowerCase = ch -> Character.toLowerCase(ch); - public static final F toUpperCase = ch -> Character.toUpperCase(ch); - public static final F toTitleCase = ch -> Character.toTitleCase(ch); + public static final F isLowerCase = Character::isLowerCase; + public static final F isUpperCase = Character::isUpperCase; + public static final F isTitleCase = Character::isTitleCase; + public static final F isDigit = Character::isDigit; + public static final F isDefined = Character::isDefined; + public static final F isLetter = Character::isLetter; + public static final F isLetterOrDigit = Character::isLetterOrDigit; + public static final F isJavaIdentifierStart = Character::isJavaIdentifierStart; + public static final F isJavaIdentifierPart = Character::isJavaIdentifierPart; + public static final F isUnicodeIdentifierStart = Character::isUnicodeIdentifierStart; + public static final F isUnicodeIdentifierPart = Character::isUnicodeIdentifierPart; + public static final F isIdentifierIgnorable = Character::isIdentifierIgnorable; + public static final F toLowerCase = Character::toLowerCase; + public static final F toUpperCase = Character::toUpperCase; + public static final F toTitleCase = Character::toTitleCase; public static final F> digit = curry((ch, radix) -> Character.digit(ch, radix)); - public static final F getNumericValue = ch -> Character.getNumericValue(ch); - public static final F isSpaceChar = ch -> Character.isSpaceChar(ch); - public static final F isWhitespace = ch -> Character.isWhitespace(ch); - public static final F isISOControl = ch -> Character.isISOControl(ch); - public static final F getType = ch -> Character.getType(ch); - public static final F getDirectionality = ch -> Character.getDirectionality(ch); - public static final F isMirrored = ch -> Character.isMirrored(ch); - public static final F reverseBytes = ch -> Character.reverseBytes(ch); + public static final F getNumericValue = Character::getNumericValue; + public static final F isSpaceChar = Character::isSpaceChar; + public static final F isWhitespace = Character::isWhitespace; + public static final F isISOControl = Character::isISOControl; + public static final F getType = Character::getType; + public static final F getDirectionality = Character::getDirectionality; + public static final F isMirrored = Character::isMirrored; + public static final F reverseBytes = Character::reverseBytes; public static final F isNewLine = c -> c == '\n'; } diff --git a/core/src/main/java/fj/function/Doubles.java b/core/src/main/java/fj/function/Doubles.java index 1a85a100..7bff2409 100644 --- a/core/src/main/java/fj/function/Doubles.java +++ b/core/src/main/java/fj/function/Doubles.java @@ -45,7 +45,7 @@ private Doubles() { /** * Absolute value. */ - public static final F abs = x -> abs(x); + public static final F abs = Math::abs; /** * Remainder. @@ -55,7 +55,7 @@ private Doubles() { /** * Power. */ - public static final F> power = curry((a, b) -> StrictMath.pow(a, b)); + public static final F> power = curry(StrictMath::pow); /** * Evenness. diff --git a/core/src/main/java/fj/function/Integers.java b/core/src/main/java/fj/function/Integers.java index c51359e4..4b1b14b5 100644 --- a/core/src/main/java/fj/function/Integers.java +++ b/core/src/main/java/fj/function/Integers.java @@ -47,7 +47,7 @@ private Integers() { /** * Absolute value. */ - public static final F abs = x -> abs(x); + public static final F abs = Math::abs; /** * Remainder. diff --git a/core/src/main/java/fj/function/Longs.java b/core/src/main/java/fj/function/Longs.java index a1bd60eb..18667699 100644 --- a/core/src/main/java/fj/function/Longs.java +++ b/core/src/main/java/fj/function/Longs.java @@ -41,7 +41,7 @@ private Longs() { /** * Absolute value. */ - public static final F abs = x -> abs(x); + public static final F abs = Math::abs; /** * Remainder. diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index 88e9cc2f..c64db043 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -61,7 +61,7 @@ private Strings() { /** * A curried version of {@link String#length()}. */ - public static final F length = s -> s.length(); + public static final F length = String::length; /** * A curried version of {@link String#contains(CharSequence)}. @@ -80,17 +80,17 @@ public static List lines(String s) { } public static F> lines() { - return s -> lines(s); + return Strings::lines; } public static String unlines(List list) { StringBuilder sb = new StringBuilder(); - list.intersperse(lineSeparator).foreachDoEffect(s -> sb.append(s)); + list.intersperse(lineSeparator).foreachDoEffect(sb::append); return sb.toString(); } public static F, String> unlines() { - return l -> unlines(l); + return Strings::unlines; } } diff --git a/core/src/main/java/fj/parser/Parser.java b/core/src/main/java/fj/parser/Parser.java index e5ce04c9..605125f0 100644 --- a/core/src/main/java/fj/parser/Parser.java +++ b/core/src/main/java/fj/parser/Parser.java @@ -210,7 +210,7 @@ public Parser sequence(final Parser p) { * @return A new parser after function application. */ public Parser apply(final Parser, E> p) { - return p.bind((F, Parser>) f1 -> map(f1)); + return p.bind((F, Parser>) this::map); } /** @@ -549,7 +549,7 @@ public static Parser, String, E> string(final E missing, f * @return A parser that produces a digit (0 to 9). */ public static Parser, Digit, E> digit(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isDigit(c)).map(c1 -> Digit.fromChar(c1).some()); + return StreamParser.satisfy(missing, sat, Character::isDigit).map(c1 -> Digit.fromChar(c1).some()); } /** @@ -572,7 +572,7 @@ public static Parser, Digit, E> digit(final E missing, fin * @see Character#isLowerCase(char) */ public static Parser, Character, E> lower(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isLowerCase(c)); + return StreamParser.satisfy(missing, sat, Character::isLowerCase); } /** @@ -596,7 +596,7 @@ public static Parser, Character, E> lower(final E missing, * @see Character#isUpperCase(char) */ public static Parser, Character, E> upper(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isUpperCase(c)); + return StreamParser.satisfy(missing, sat, Character::isUpperCase); } /** @@ -620,7 +620,7 @@ public static Parser, Character, E> upper(final E missing, * @see Character#isDefined(char) */ public static Parser, Character, E> defined(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isDefined(c)); + return StreamParser.satisfy(missing, sat, Character::isDefined); } /** @@ -645,7 +645,7 @@ public static Parser, Character, E> defined(final E missin */ public static Parser, Character, E> highSurrogate(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isHighSurrogate(c)); + return StreamParser.satisfy(missing, sat, Character::isHighSurrogate); } /** @@ -671,7 +671,7 @@ public static Parser, Character, E> highSurrogate(final E */ public static Parser, Character, E> identifierIgnorable(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isIdentifierIgnorable(c)); + return StreamParser.satisfy(missing, sat, Character::isIdentifierIgnorable); } /** @@ -697,7 +697,7 @@ public static Parser, Character, E> identifierIgnorable(fi */ public static Parser, Character, E> isoControl(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isISOControl(c)); + return StreamParser.satisfy(missing, sat, Character::isISOControl); } /** @@ -722,7 +722,7 @@ public static Parser, Character, E> isoControl(final E mis */ public static Parser, Character, E> javaIdentifierPart(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierPart(c)); + return StreamParser.satisfy(missing, sat, Character::isJavaIdentifierPart); } /** @@ -748,7 +748,7 @@ public static Parser, Character, E> javaIdentifierPart(fin */ public static Parser, Character, E> javaIdentifierStart(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isJavaIdentifierStart(c)); + return StreamParser.satisfy(missing, sat, Character::isJavaIdentifierStart); } /** @@ -773,7 +773,7 @@ public static Parser, Character, E> javaIdentifierStart(fi * @see Character#isLetter(char) */ public static Parser, Character, E> alpha(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isLetter(c)); + return StreamParser.satisfy(missing, sat, Character::isLetter); } /** @@ -797,7 +797,7 @@ public static Parser, Character, E> alpha(final E missing, * @see Character#isLetterOrDigit(char) */ public static Parser, Character, E> alphaNum(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isLetterOrDigit(c)); + return StreamParser.satisfy(missing, sat, Character::isLetterOrDigit); } /** @@ -822,7 +822,7 @@ public static Parser, Character, E> alphaNum(final E missi */ public static Parser, Character, E> lowSurrogate(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isLowSurrogate(c)); + return StreamParser.satisfy(missing, sat, Character::isLowSurrogate); } /** @@ -846,7 +846,7 @@ public static Parser, Character, E> lowSurrogate(final E m * @see Character#isMirrored(char) */ public static Parser, Character, E> mirrored(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isMirrored(c)); + return StreamParser.satisfy(missing, sat, Character::isMirrored); } /** @@ -870,7 +870,7 @@ public static Parser, Character, E> mirrored(final E missi * @see Character#isSpace(char) */ public static Parser, Character, E> space(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isSpaceChar(c)); + return StreamParser.satisfy(missing, sat, Character::isSpaceChar); } /** @@ -895,7 +895,7 @@ public static Parser, Character, E> space(final E missing, */ public static Parser, Character, E> titleCase(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isTitleCase(c)); + return StreamParser.satisfy(missing, sat, Character::isTitleCase); } /** @@ -920,7 +920,7 @@ public static Parser, Character, E> titleCase(final E miss */ public static Parser, Character, E> unicodeIdentiferPart(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isUnicodeIdentifierPart(c)); + return StreamParser.satisfy(missing, sat, Character::isUnicodeIdentifierPart); } /** @@ -946,7 +946,7 @@ public static Parser, Character, E> unicodeIdentiferPart(f */ public static Parser, Character, E> unicodeIdentiferStart(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isUnicodeIdentifierStart(c)); + return StreamParser.satisfy(missing, sat, Character::isUnicodeIdentifierStart); } /** @@ -972,7 +972,7 @@ public static Parser, Character, E> unicodeIdentiferStart( */ public static Parser, Character, E> whitespace(final F0 missing, final F sat) { - return StreamParser.satisfy(missing, sat, c -> Character.isWhitespace(c)); + return StreamParser.satisfy(missing, sat, Character::isWhitespace); } /** diff --git a/core/src/main/java/fj/parser/Result.java b/core/src/main/java/fj/parser/Result.java index f450a054..8f5a4b78 100644 --- a/core/src/main/java/fj/parser/Result.java +++ b/core/src/main/java/fj/parser/Result.java @@ -55,7 +55,7 @@ public Result mapRest(final F f) { * @return A first-class function mapping across the remainder of the parse input. */ public F, Result> mapRest() { - return f -> mapRest(f); + return this::mapRest; } /** @@ -74,7 +74,7 @@ public Result mapValue(final F f) { * @return A first-class function mapping across the parse value. */ public F, Result> mapValue() { - return f -> mapValue(f); + return this::mapValue; } /** @@ -94,7 +94,7 @@ public Result bimap(final F f, final F g) { * @return A first-class bifunctor map. */ public F, F, Result>> bimap() { - return curry((f, g) -> bimap(f, g)); + return curry(this::bimap); } /** @@ -142,7 +142,7 @@ public static Result result(final I i, final A a) { * @return A first-class function for construction of a result. */ public static F>> result() { - return curry((i, a) -> result(i, a)); + return curry(Result::result); } } diff --git a/demo/src/main/java/fj/demo/IODemo.java b/demo/src/main/java/fj/demo/IODemo.java index 316eafc4..0bc7db12 100644 --- a/demo/src/main/java/fj/demo/IODemo.java +++ b/demo/src/main/java/fj/demo/IODemo.java @@ -37,7 +37,7 @@ public void readFirstShortLine() { * Read a stream of input lazily using interact, in effect reading the first line */ public void readFirstLine() { - F f = lift((LazyString s) -> s.lines()).andThen(unlines_()); + F f = lift(LazyString::lines).andThen(unlines_()); runSafe(interact(f)); } diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index b4d3dae2..69b27202 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -298,7 +298,7 @@ private static P2, Map> writeSampleFiles( public static Map getWordsAndCountsFromFilesWithIteratee(final List fileNames, final F> fileNameToWordsAndCountsWithIteratee) { final List> maps = fileNames.map(fileNameToWordsAndCountsWithIteratee); - return maps.foldLeft((Map a, Map b) -> plus(a, b), new HashMap()); + return maps.foldLeft(WordCount::plus, new HashMap()); } public static Map getWordsAndCountsFromFilesInParallel( diff --git a/demo/src/main/java/fj/demo/realworld/Chapter7.java b/demo/src/main/java/fj/demo/realworld/Chapter7.java index f9263683..c239a5bf 100644 --- a/demo/src/main/java/fj/demo/realworld/Chapter7.java +++ b/demo/src/main/java/fj/demo/realworld/Chapter7.java @@ -28,7 +28,7 @@ public static void main(String[] args) { public static void toUpperLazy() { runSafe(interact(ls -> { Stream stream = ls.lines().map((LazyString ls2) -> ls2.eval().toUpperCase()); - return LazyString.unlines(stream.map(s -> LazyString.str(s))); + return LazyString.unlines(stream.map(LazyString::str)); })); } @@ -46,7 +46,7 @@ public static void toUpperByLine() { * uppercase line to stdout */ public static void toUpperInteract() { - runSafe(interactWhile(s -> s.trim().length() > 0, s -> s.toUpperCase())); + runSafe(interactWhile(s -> s.trim().length() > 0, String::toUpperCase)); } } diff --git a/demo/src/main/java/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java index 814f7112..c5b0a898 100644 --- a/demo/src/main/java/fj/demo/test/EqualsHashCode.java +++ b/demo/src/main/java/fj/demo/test/EqualsHashCode.java @@ -62,7 +62,7 @@ public static void main(final String[] args) { // Arbitrary for MyClass that uses the restrictive arbitraries above. // We are using the monad pattern (bind) to make this a trivial exercise. - final Arbitrary arbMyClass = arbitrary(arbByteR.gen.bind(arbStringR.gen, curry((b, s) -> new MyClass(b, s)))); + final Arbitrary arbMyClass = arbitrary(arbByteR.gen.bind(arbStringR.gen, curry(MyClass::new))); // Finally the property. // if m1 equals m2, then this implies that m1's hashCode is equal to m2's hashCode. diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index 93fd1e9e..d893a370 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -32,7 +32,7 @@ public static P1 Supplier_P1(final Supplier s) { } public static F, P1> Supplier_P1() { - return s -> P.lazy(() -> s.get()); + return s -> P.lazy(s::get); } public static Supplier P1_Supplier(final P1 p) { @@ -40,7 +40,7 @@ public static Supplier P1_Supplier(final P1 p) { } public static F, Supplier> P1_Supplier() { - return (p) -> () -> p._1(); + return (p) -> p::_1; } public static F Function_F(final Function f) { @@ -48,7 +48,7 @@ public static F Function_F(final Function f) { } public static F, F> Function_F() { - return f -> a -> f.apply(a); + return f -> f::apply; } public static Function F_Function(final F f) { @@ -56,7 +56,7 @@ public static Function F_Function(final F f) { } public static F, Function> F_Function() { - return f -> a -> f.f(a); + return f -> f::f; } public static F2 BiFunction_F2(final BiFunction f) { @@ -64,7 +64,7 @@ public static F2 BiFunction_F2(final BiFunction f) { } public static F, F2> BiFunction_F2() { - return f -> (a, b) -> f.apply(a, b); + return f -> f::apply; } public static BiFunction F2_BiFunction(final F2 f) { @@ -72,7 +72,7 @@ public static BiFunction F2_BiFunction(final F2 f) { } public static F, BiFunction> F2_BiFunction() { - return f -> (a, b) -> f.f(a, b); + return f -> f::f; } public static Supplier> TryCatch0_Supplier(final Try0 t) { @@ -120,7 +120,7 @@ public static F, Optional> Option_Optional() { } public static F, F> Consumer_F() { - return c -> Consumer_F(c); + return Java8::Consumer_F; } public static F Consumer_F(final Consumer c) { @@ -143,7 +143,7 @@ public static java.util.stream.Stream Iterator_JavaStream(final Iterator< } public static F, java.util.stream.Stream> Stream_JavaStream() { - return s -> Stream_JavaStream(s); + return Java8::Stream_JavaStream; } public static Stream JavaStream_Stream(final java.util.stream.Stream s) { diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 1e619f21..7b96d299 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -13,6 +13,8 @@ import static fj.Function.compose; import static fj.P.p; + +import fj.P; import fj.P1; import fj.P2; import fj.P3; @@ -32,6 +34,9 @@ import static fj.data.List.list; import static fj.data.Option.some; +import fj.data.List; +import fj.data.Set; +import fj.data.TreeMap; import fj.function.Effect1; import static fj.data.Stream.range; @@ -50,29 +55,13 @@ import java.math.BigInteger; import java.sql.Time; import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Calendar; -import java.util.Date; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Locale; +import java.util.*; + import static java.util.Locale.getAvailableLocales; -import java.util.PriorityQueue; -import java.util.Properties; -import java.util.Stack; -import java.util.TreeSet; -import java.util.Vector; -import java.util.WeakHashMap; import static java.util.EnumSet.copyOf; + +import java.util.HashMap; +import java.util.HashSet; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; @@ -127,21 +116,21 @@ public Gen f(final A x) { } public static Arbitrary> arbReader(Coarbitrary aa, Arbitrary ab) { - return arbitrary(arbF(aa, ab).gen.map(f -> Reader.unit(f))); + return arbitrary(arbF(aa, ab).gen.map(Reader::unit)); } /** * An arbitrary for state. */ public static Arbitrary> arbState(Arbitrary as, Coarbitrary cs, Arbitrary aa) { - return arbitrary(arbF(cs, arbP2(as, aa)).gen.map(f -> State.unit(f))); + return arbitrary(arbF(cs, arbP2(as, aa)).gen.map(State::unit)); } /** * An arbitrary for the LcgRng. */ public static Arbitrary arbLcgRng() { - return arbitrary(Arbitrary.arbLong.gen.map(l -> new LcgRng(l))); + return arbitrary(Arbitrary.arbLong.gen.map(LcgRng::new)); } /** @@ -611,11 +600,7 @@ public Gen f(final Integer i) { * An arbitrary implementation for string values. */ public static final Arbitrary arbString = - arbitrary(arbList(arbCharacter).gen.map(new F, String>() { - public String f(final List cs) { - return asString(cs); - } - })); + arbitrary(arbList(arbCharacter).gen.map(List::asString)); /** * An arbitrary implementation for string values with characters in the US-ASCII range. @@ -643,21 +628,13 @@ public Character f(final Character c) { * An arbitrary implementation for string buffer values. */ public static final Arbitrary arbStringBuffer = - arbitrary(arbString.gen.map(new F() { - public StringBuffer f(final String s) { - return new StringBuffer(s); - } - })); + arbitrary(arbString.gen.map(StringBuffer::new)); /** * An arbitrary implementation for string builder values. */ public static final Arbitrary arbStringBuilder = - arbitrary(arbString.gen.map(new F() { - public StringBuilder f(final String s) { - return new StringBuilder(s); - } - })); + arbitrary(arbString.gen.map(StringBuilder::new)); /** * Returns an arbitrary implementation for generators. @@ -672,11 +649,7 @@ public Gen> f(final Integer i) { if (i == 0) return fail(); else - return aa.gen.map(new F>() { - public Gen f(final A a) { - return value(a); - } - }).resize(i - 1); + return aa.gen.map(Gen::value).resize(i - 1); } })); } @@ -692,11 +665,7 @@ public static Arbitrary> arbOption(final Arbitrary aa) { public Gen> f(final Integer i) { return i == 0 ? value(Option.none()) : - aa.gen.map(new F>() { - public Option f(final A a) { - return some(a); - } - }).resize(i - 1); + aa.gen.map(Option::some).resize(i - 1); } })); } @@ -712,16 +681,8 @@ public Option f(final A a) { */ @SuppressWarnings("unchecked") public static Arbitrary> arbEither(final Arbitrary aa, final Arbitrary ab) { - final Gen> left = aa.gen.map(new F>() { - public Either f(final A a) { - return left(a); - } - }); - final Gen> right = ab.gen.map(new F>() { - public Either f(final B b) { - return right(b); - } - }); + final Gen> left = aa.gen.map(Either::left); + final Gen> right = ab.gen.map(Either::right); return arbitrary(oneOf(list(left, right))); } @@ -771,7 +732,7 @@ public static Arbitrary> arbNonEmptyList(final Arbitrary * Returns an arbitrary Validation for the given arbitrary parameters. */ public static Arbitrary> arbValidation(final Arbitrary aa, final Arbitrary ab) { - return arbitrary(arbBoolean.gen.bind(bool -> bool ? ab.gen.map(b -> Validation.success(b)) : aa.gen.map(a -> Validation.fail(a)))); + return arbitrary(arbBoolean.gen.bind(bool -> bool ? ab.gen.map(Validation::success) : aa.gen.map(Validation::fail))); } /** @@ -781,11 +742,7 @@ public static Arbitrary> arbValidation(final Arbitrary Arbitrary> arbStream(final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(new F, Stream>() { - public Stream f(final List as) { - return as.toStream(); - } - })); + return arbitrary(arbList(aa).gen.map(List::toStream)); } /** @@ -795,11 +752,7 @@ public Stream f(final List as) { * @return An arbitrary implementation for arrays. */ public static Arbitrary> arbArray(final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(new F, Array>() { - public Array f(final List as) { - return as.toArray(); - } - })); + return arbitrary(arbList(aa).gen.map(List::toArray)); } /** @@ -830,11 +783,7 @@ public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, in * @return An arbitrary implementation for throwables. */ public static Arbitrary arbThrowable(final Arbitrary as) { - return arbitrary(as.gen.map(new F() { - public Throwable f(final String msg) { - return new Throwable(msg); - } - })); + return arbitrary(as.gen.map(Throwable::new)); } /** @@ -888,11 +837,7 @@ public Calendar f(final Long i) { /** * An arbitrary implementation for dates. */ - public static final Arbitrary arbDate = arbitrary(arbLong.gen.map(new F() { - public Date f(final Long i) { - return new Date(i); - } - })); + public static final Arbitrary arbDate = arbitrary(arbLong.gen.map(Date::new)); /** * Returns an arbitrary implementation for a Java enumeration. @@ -914,12 +859,7 @@ public static > Arbitrary arbEnumValue(final Class clazz */ public static , V> Arbitrary> arbEnumMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, EnumMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public EnumMap f(final Hashtable ht) { - return new EnumMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(EnumMap::new)); } /** @@ -957,12 +897,7 @@ public GregorianCalendar f(final Long i) { * @return An arbitrary implementation for hash maps. */ public static Arbitrary> arbHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, HashMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public HashMap f(final Hashtable ht) { - return new HashMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(HashMap::new)); } /** @@ -1020,12 +955,7 @@ public void f(final P2 kv) { */ public static Arbitrary> arbIdentityHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, IdentityHashMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public IdentityHashMap f(final Hashtable ht) { - return new IdentityHashMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(IdentityHashMap::new)); } /** @@ -1038,12 +968,7 @@ public IdentityHashMap f(final Hashtable ht) { * @return An arbitrary implementation for linked hash maps. */ public static Arbitrary> arbLinkedHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, LinkedHashMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public LinkedHashMap f(final Hashtable ht) { - return new LinkedHashMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(LinkedHashMap::new)); } /** @@ -1130,12 +1055,7 @@ public Stack f(final Array a) { * @return An arbitrary implementation for tree maps. */ public static Arbitrary> arbJavaTreeMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, java.util.TreeMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public java.util.TreeMap f(final Hashtable ht) { - return new java.util.TreeMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(java.util.TreeMap::new)); } /** @@ -1215,12 +1135,7 @@ public Vector f(final Array a) { * @return An arbitrary implementation for weak hash maps. */ public static Arbitrary> arbWeakHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, WeakHashMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public WeakHashMap f(final Hashtable ht) { - return new WeakHashMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(WeakHashMap::new)); } // END java.util @@ -1263,12 +1178,7 @@ public ArrayBlockingQueue f(final Boolean fair) { */ public static Arbitrary> arbConcurrentHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(new F, ConcurrentHashMap>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public ConcurrentHashMap f(final Hashtable ht) { - return new ConcurrentHashMap(ht); - } - })); + return arbitrary(arbHashtable(ak, av).gen.map(ConcurrentHashMap::new)); } /** @@ -1388,29 +1298,17 @@ public SynchronousQueue f(final Boolean fair) { /** * An arbitrary implementation for SQL dates. */ - public static final Arbitrary arbSQLDate = arbitrary(arbLong.gen.map(new F() { - public java.sql.Date f(final Long i) { - return new java.sql.Date(i); - } - })); + public static final Arbitrary arbSQLDate = arbitrary(arbLong.gen.map(java.sql.Date::new)); /** * An arbitrary implementation for SQL times. */ - public static final Arbitrary Arbitrary> arbP1(final Arbitrary aa) { - return arbitrary(aa.gen.map(new F>() { - public P1 f(final A a) { - return p(a); - } - })); + return arbitrary(aa.gen.map(P::p)); } /** diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 0aa11adb..b3bb1371 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -294,11 +294,7 @@ public Gen bind(final Gen gb, final Gen gc, final Gen g public Gen apply(final Gen> gf) { return gf.bind(new F, Gen>() { public Gen f(final F f) { - return map(new F() { - public B f(final A a) { - return f.f(a); - } - }); + return map(f::f); } }); } @@ -492,11 +488,7 @@ public Gen f(final Integer i) { public static Gen elemFrequency(final List> as) { return frequency(as.map(new F, P2>>() { public P2> f(final P2 p) { - return p.map2(new F>() { - public Gen f(final A a) { - return value(a); - } - }); + return p.map2(Gen::value); } })); } @@ -525,11 +517,7 @@ public A f(final Integer i) { * requests. */ public static Gen oneOf(final List> gs) { - return gs.isEmpty() ? Gen.fail() : choose(0, gs.length() - 1).bind(new F>() { - public Gen f(final Integer i) { - return gs.index(i); - } - }); + return gs.isEmpty() ? Gen.fail() : choose(0, gs.length() - 1).bind(gs::index); } /** diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 1486a695..d0eeb5ae 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -469,11 +469,7 @@ public P2 f(final Result result) { if (results.isEmpty()) return none(); - else return results.find(new F>, Boolean>() { - public Boolean f(final Option> o) { - return failed(o); - } - }).orSome(() -> results.head()); + else return results.find(this::failed).orSome(results::head); } public boolean failed(final Option> o) { diff --git a/quickcheck/src/main/java/fj/test/Result.java b/quickcheck/src/main/java/fj/test/Result.java index 40130542..467e2ae2 100644 --- a/quickcheck/src/main/java/fj/test/Result.java +++ b/quickcheck/src/main/java/fj/test/Result.java @@ -156,7 +156,7 @@ public Option toOption() { * @return The result that may be {@link #noResult() noResult()}. */ public static Result noResult(final Option r) { - return r.orSome(() -> noResult()); + return r.orSome(Result::noResult); } /** diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index a9d1aa21..751a1307 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -235,7 +235,7 @@ else if (as.tail().isEmpty()) .map(aas1 -> aas1.append(as2)) .interleave(removeChunks(n2, as2) .filter(isNotEmpty) - .map(aas -> as1.append(aas))))); + .map(as1::append)))); }) ); } @@ -301,7 +301,7 @@ public static Shrink> shrinkStream(final Shrink sa) { * @return A shrink strategy for throwables. */ public static Shrink shrinkThrowable(final Shrink ss) { - return ss.map(s -> new Throwable(s), t -> t.getMessage()); + return ss.map(Throwable::new, Throwable::getMessage); } /** @@ -341,7 +341,7 @@ public static Shrink> shrinkArrayList(final Shrink sa) { * A shrink strategy for dates. */ public static final Shrink shrinkDate = - shrinkLong.map(i -> new Date(i), d -> d.getTime()); + shrinkLong.map(Date::new, Date::getTime); /** * A shrink strategy for enum maps. @@ -351,7 +351,7 @@ public static Shrink> shrinkArrayList(final Shrink sa) { * @return A shrink strategy for enum maps. */ public static , V> Shrink> shrinkEnumMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new EnumMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(EnumMap::new, Hashtable::new); } /** @@ -382,7 +382,7 @@ public static > Shrink> shrinkEnumSet(final Shrink< * @return A shrink strategy for hash maps. */ public static Shrink> shrinkHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new HashMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(HashMap::new, Hashtable::new); } /** @@ -427,7 +427,7 @@ public static Shrink> shrinkHashtable(final Shrink sk, * @return A shrink strategy for identity hash maps. */ public static Shrink> shrinkIdentityHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new IdentityHashMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(IdentityHashMap::new, Hashtable::new); } /** @@ -438,7 +438,7 @@ public static Shrink> shrinkIdentityHashMap(final S * @return A shrink strategy for linked hash maps. */ public static Shrink> shrinkLinkedHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new LinkedHashMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(LinkedHashMap::new, Hashtable::new); } /** @@ -511,7 +511,7 @@ public static Shrink> shrinkStack(final Shrink sa) { * @return A shrink strategy for tree maps. */ public static Shrink> shrinkTreeMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new TreeMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(TreeMap::new, Hashtable::new); } /** @@ -542,7 +542,7 @@ public static Shrink> shrinkVector(final Shrink sa) { * @return A shrink strategy for weak hash maps. */ public static Shrink> shrinkWeakHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new WeakHashMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(WeakHashMap::new, Hashtable::new); } // END java.util @@ -567,7 +567,7 @@ public static Shrink> shrinkArrayBlockingQueue(final S * @return A shrink strategy for concurrent hash maps. */ public static Shrink> shrinkConcurrentHashMap(final Shrink sk, final Shrink sv) { - return shrinkHashtable(sk, sv).map(h -> new ConcurrentHashMap(h), m -> new Hashtable(m)); + return shrinkHashtable(sk, sv).map(ConcurrentHashMap::new, Hashtable::new); } /** @@ -648,19 +648,19 @@ public static Shrink> shrinkSynchronousQueue(final Shrin * A shrink strategy for SQL dates. */ public static final Shrink shrinkSQLDate = - shrinkLong.map(i -> new java.sql.Date(i), c -> c.getTime()); + shrinkLong.map(java.sql.Date::new, Date::getTime); /** * A shrink strategy for SQL times. */ public static final Shrink Shrink> shrinkSynchronousQueue(final Shrin * A shrink strategy for big decimals. */ public static final Shrink shrinkBigDecimal = - shrinkBigInteger.map(i -> new BigDecimal(i), d -> d.toBigInteger()); + shrinkBigInteger.map(BigDecimal::new, BigDecimal::toBigInteger); // END java.math @@ -702,7 +702,7 @@ public static Shrink> shrinkSynchronousQueue(final Shrin * @return a shrinking strategy for product-1 values. */ public static Shrink> shrinkP1(final Shrink sa) { - return shrink(p -> sa.shrink(p._1()).map(a -> p(a))); + return shrink(p -> sa.shrink(p._1()).map(P::p)); } /** diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index 5b7dbbb3..a4994bcb 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -300,11 +300,7 @@ public Boolean f(final String cs) { } }; - final F nameS = new F() { - public String f(final Name name) { - return name.value(); - } - }; + final F nameS = Name::value; return ms.filter(new F() { public Boolean f(final PropertyMember m) { From a93c54c2d274b731c57b3fce6791e9e996b6b9ac Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 22:39:50 +0100 Subject: [PATCH 519/811] Use lambda syntax instead of anonymous class whenever possible --- core/src/main/java/fj/control/Trampoline.java | 18 +- .../java/fj/control/parallel/Callables.java | 28 +- .../java/fj/control/parallel/Strategy.java | 4 +- core/src/main/java/fj/data/IOFunctions.java | 245 +++--- core/src/main/java/fj/data/Iteratee.java | 11 +- core/src/main/java/fj/data/Java.java | 12 +- core/src/main/java/fj/data/NonEmptyList.java | 10 +- core/src/main/java/fj/data/TreeZipper.java | 19 +- .../main/java/fj/data/fingertrees/Deep.java | 712 +++++------------- demo/src/main/java/fj/demo/ChequeWrite.java | 24 +- demo/src/main/java/fj/demo/List_groupBy.java | 12 +- .../java/fj/demo/concurrent/PingPong.java | 16 +- .../java/fj/demo/concurrent/WordCount.java | 70 +- .../src/main/java/fj/demo/euler/Problem2.java | 5 +- .../java/fj/demo/test/ListFunctorLaws.java | 8 +- demo/src/main/java/fj/demo/test/Reflect.java | 8 +- .../fj/demo/test/StringBuilderReverse.java | 6 +- .../src/main/java/fj/test/Arbitrary.java | 454 ++--------- .../src/main/java/fj/test/Coarbitrary.java | 12 +- quickcheck/src/main/java/fj/test/Gen.java | 98 +-- .../src/main/java/fj/test/Property.java | 488 ++---------- .../src/main/java/fj/test/reflect/Check.java | 211 +++--- .../src/main/java/fj/test/reflect/Main.java | 8 +- 23 files changed, 640 insertions(+), 1839 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 140deeaa..a41c7a03 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -52,16 +52,14 @@ public Trampoline bind(final F> f) { // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result // gets shifted into the continuation. public Either>, A> resume() { - return left(sub.resume().either(p -> { - return p.map(ot -> { - // WARNING: In JDK 8, update 25 (current version) the following code is a - // workaround for an internal JDK compiler error, likely due to - // https:bugs.openjdk.java.net/browse/JDK-8062253. - F, Trampoline> f = o -> o.foldNormal(cont::f, t -> t._1().bind(cont)); - F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); - return ot.fold(f, g); - }); - }, o -> P.lazy(() -> cont.f(o)))); + return left(sub.resume().either(p -> p.map(ot -> { + // WARNING: In JDK 8, update 25 (current version) the following code is a + // workaround for an internal JDK compiler error, likely due to + // https:bugs.openjdk.java.net/browse/JDK-8062253. + F, Trampoline> f = o -> o.foldNormal(cont::f, t -> t._1().bind(cont)); + F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); + return ot.fold(f, g); + }), o -> P.lazy(() -> cont.f(o)))); } } diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index 40c8e746..7c2a7221 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -216,14 +216,12 @@ public static F, P1>> either() { * @return A Callable equivalent to the given Either value. */ public static Callable fromEither(final F0> e) { - return new Callable() { - public A call() throws Exception { - final Either e1 = e.f(); - if (e1.isLeft()) - throw e1.left().value(); - else - return e1.right().value(); - } + return () -> { + final Either e1 = e.f(); + if (e1.isLeft()) + throw e1.left().value(); + else + return e1.right().value(); }; } @@ -243,14 +241,12 @@ public static F>, Callable> fromEither() { * @return A Callable that yields some value or throws an exception in the case of no value. */ public static Callable fromOption(final F0> o) { - return new Callable() { - public A call() throws Exception { - final Option o1 = o.f(); - if (o1.isSome()) - return o1.some(); - else - throw new Exception("No value."); - } + return () -> { + final Option o1 = o.f(); + if (o1.isSome()) + return o1.some(); + else + throw new Exception("No value."); }; } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index 79e698b9..94e1f148 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -339,9 +339,7 @@ public static P1 obtain(final Future t) { * @return An effect, which, given a Future, waits for it to obtain a value, discarding the value. */ public static Effect1> discard() { - return a -> { - Strategy.obtain().f(a)._1(); - }; + return a -> Strategy.obtain().f(a)._1(); } /** diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index b62bb60e..c3d5fe01 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -76,12 +76,9 @@ public static A runSafe(IO io) { } public static IO closeReader(final Reader r) { - return new IO() { - @Override - public Unit run() throws IOException { - r.close(); - return Unit.unit(); - } + return () -> { + r.close(); + return Unit.unit(); }; } @@ -139,24 +136,16 @@ public static IO fileReader(final File f, final Option encoding } public static IO bracket(final IO init, final F> fin, final F> body) { - return new IO() { - @Override - public C run() throws IOException { - final A a = init.run(); - try(Closeable finAsCloseable = fin.f(a)::run) { - return body.f(a).run(); - } + return () -> { + final A a = init.run(); + try(Closeable finAsCloseable = fin.f(a)::run) { + return body.f(a).run(); } }; } public static IO unit(final A a) { - return new IO() { - @Override - public A run() throws IOException { - return a; - } - }; + return () -> a; } public static final IO ioUnit = unit(Unit.unit()); @@ -192,32 +181,24 @@ public Boolean f(final IterV i) { } }; - return new F, IO>>>() { - @Override - public F, IO>> f(final BufferedReader r) { - return new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + return r -> new F, IO>>() { + final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - IterV i = it; - while (!isDone.f(i)) { - final String s = r.readLine(); - if (s == null) { - return i; - } - final Input input = Input.el(s); - final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); - i = i.fold(done, cont)._1(); - } - return i; - } - }; + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return () -> { + IterV i = it; + while (!isDone.f(i)) { + final String s = r.readLine(); + if (s == null) { + return i; + } + final Input input = Input.el(s); + final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); + i = i.fold(done, cont)._1(); } + return i; }; } }; @@ -239,38 +220,30 @@ public Boolean f(final IterV i) { } }; - return new F, IO>>>() { - @Override - public F, IO>> f(final Reader r) { - return new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + return r -> new F, IO>>() { + final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { - return i; - } - if (numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - final Input input = Input.el(buffer); - final F, IterV>, P1>> cont = - F1Functions.lazy(Function., IterV>apply(input)); - i = i.fold(done, cont)._1(); - } - return i; - } - }; + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return () -> { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { + return i; + } + if (numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); + } + final Input input = Input.el(buffer); + final F, IterV>, P1>> cont = + F1Functions.lazy(Function., IterV>apply(input)); + i = i.fold(done, cont)._1(); } + return i; }; } }; @@ -292,52 +265,39 @@ public Boolean f(final IterV i) { } }; - return new F, IO>>>() { - @Override - public F, IO>> f(final Reader r) { - return new F, IO>>() { - final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ + return r -> new F, IO>>() { + final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return new IO>() { - @Override - public IterV run() throws IOException { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { - return i; - } - if (numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - for (int c = 0; c < buffer.length; c++) { - final Input input = Input.el(buffer[c]); - final F, IterV>, IterV> cont = - Function., IterV>apply(input); - i = i.fold(done, cont); - } - } - return i; - } - }; + @Override + public IO> f(final IterV it) { + // use loop instead of recursion because of missing TCO + return () -> { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { + return i; + } + if (numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); + } + for (int c = 0; c < buffer.length; c++) { + final Input input = Input.el(buffer[c]); + final F, IterV>, IterV> cont = + Function., IterV>apply(input); + i = i.fold(done, cont); + } } + return i; }; } }; } public static IO map(final IO io, final F f) { - return new IO() { - @Override - public B run() throws IOException { - return f.f(io.run()); - } - }; + return () -> f.f(io.run()); } public static IO as(final IO io, final B b) { @@ -349,12 +309,7 @@ public static IO voided(final IO io) { } public static IO bind(final IO io, final F> f) { - return new IO() { - @Override - public B run() throws IOException { - return f.f(io.run()).run(); - } - }; + return () -> f.f(io.run()).run(); } public static IO when(final Boolean b, final IO io) { @@ -422,46 +377,40 @@ public static IO interactWhile(F condition, F IO> sequenceWhileEager(final Stream> stream, final F f) { - return new IO>() { - @Override - public Stream run() throws IOException { - boolean loop = true; - Stream> input = stream; - Stream result = Stream.nil(); - while (loop) { - if (input.isEmpty()) { + return () -> { + boolean loop = true; + Stream> input = stream; + Stream result = Stream.nil(); + while (loop) { + if (input.isEmpty()) { + loop = false; + } else { + A a = input.head().run(); + if (!f.f(a)) { loop = false; } else { - A a = input.head().run(); - if (!f.f(a)) { - loop = false; - } else { - input = input.tail()._1(); - result = result.cons(a); - } + input = input.tail()._1(); + result = result.cons(a); } } - return result.reverse(); } + return result.reverse(); }; } public static IO> sequenceWhile(final Stream> stream, final F f) { - return new IO>() { - @Override - public Stream run() throws IOException { - if (stream.isEmpty()) { + return () -> { + if (stream.isEmpty()) { + return Stream.nil(); + } else { + IO io = stream.head(); + A a = io.run(); + if (!f.f(a)) { return Stream.nil(); } else { - IO io = stream.head(); - A a = io.run(); - if (!f.f(a)) { - return Stream.nil(); - } else { - IO> io2 = sequenceWhile(stream.tail()._1(), f); - SafeIO> s3 = toSafe(io2::run); - return Stream.cons(a, s3::run); - } + IO> io2 = sequenceWhile(stream.tail()._1(), f); + SafeIO> s3 = toSafe(io2::run); + return Stream.cons(a, s3::run); } } }; @@ -505,9 +454,7 @@ public static IO stdoutPrint(final String s) { public static IO getContents() { Stream> s = Stream.>repeat(() -> (int) stdinBufferedReader.read()); - return map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> { - return (char) i.intValue(); - }))); + return map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> (char) i.intValue()))); } public static IO interact(F f) { diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index 5912ec1b..391c4087 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -99,11 +99,9 @@ public Option f(final IterV i) { /** TODO more documentation */ public final IterV bind(final F> f) { final F>, IterV> done = - new F>, IterV>() { - @Override - public IterV f(final P2> xe) { + xe -> { final Input e = xe._2(); - final F>, IterV> done = + final F>, IterV> done1 = y_ -> { final B y = y_._1(); return done(y, e); @@ -111,9 +109,8 @@ public IterV f(final P2> xe) { final F, IterV>, IterV> cont = k -> k.f(e); final A x = xe._1(); - return f.f(x).fold(done, cont); - } - }; + return f.f(x).fold(done1, cont); + }; final F, IterV>, IterV> cont = k -> cont(e -> k.f(e).bind(f)); return this.fold(done, cont); diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 8836fe2f..0be648f2 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -59,9 +59,7 @@ public static F, ArrayList> List_ArrayList() { */ public static final F, BitSet> List_BitSet = bs -> { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(bi -> { - s.set(bi._2(), bi._1()); - }); + bs.zipIndex().foreachDoEffect(bi -> s.set(bi._2(), bi._1())); return s; }; @@ -238,9 +236,7 @@ public static F, ArrayList> Array_ArrayList() { public static final F, BitSet> Array_BitSet = bs -> { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(bi -> { - s.set(bi._2(), bi._1()); - }); + bs.zipIndex().foreachDoEffect(bi -> s.set(bi._2(), bi._1())); return s; }; @@ -445,9 +441,7 @@ public static F, ArrayList> Stream_ArrayList() { */ public static final F, BitSet> Stream_BitSet = bs -> { final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(bi -> { - s.set(bi._2(), bi._1()); - }); + bs.zipIndex().foreachDoEffect(bi -> s.set(bi._2(), bi._1())); return s; }; diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 611bef93..c8dd4cca 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -108,12 +108,10 @@ public NonEmptyList bind(final F> f) { final NonEmptyList p = f.f(head); b.snoc(p.head); b.append(p.tail); - tail.foreachDoEffect(new Effect1() { - public void f(final A a) { - final NonEmptyList p = f.f(a); - b.snoc(p.head); - b.append(p.tail); - } + tail.foreachDoEffect(a -> { + final NonEmptyList p1 = f.f(a); + b.snoc(p1.head); + b.append(p1.tail); }); final List bb = b.toList(); return nel(bb.head(), bb.tail()); diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 3cfeff7c..a9d92b5a 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -585,21 +585,14 @@ public TreeZipper> positions() { final Stream>> l = uf(TreeZipper.left_()); final Stream>> r = uf(TreeZipper.right_()); final Stream>>, TreeZipper, Stream>>>> p = unfold( - new F>, - Option>>, TreeZipper, Stream>>>, - Option>>>>() { - public Option { + Option>>, TreeZipper, Stream>>>, - Option>>> f(final Option> o) { - Option>>, TreeZipper, Stream>>>, - Option>>> r = none(); - for (final TreeZipper z : o) { - r = some(P.p(P.p(z.uf(TreeZipper.left_()), z, z.uf(TreeZipper.right_())), z.parent())); - } - return r; + Option>>> r1 = none(); + for (final TreeZipper z : o) { + r1 = some(P.p(P.p(z.uf(TreeZipper.left_()), z, z.uf(TreeZipper.right_())), z.parent())); } + return r1; }, parent()); return treeZipper(t, l, r, p); } diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index a33637d8..17e775e6 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -208,23 +208,21 @@ private static FingerTree> addDigits0( final MakeTree mk = mkTree(m); return s1.match( - one1 -> { - return p2.match( - one2 -> append1(m, m1, mk.node2(one1.value(), one2.value()), m2), - two2 -> { - final V2 vs = two2.values(); - return append1(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), m2); - }, - three -> { - final V3 vs = three.values(); - return append2(m, m1, mk.node2(one1.value(), vs._1()), mk.node2(vs._2(), vs._3()), m2); - }, - four -> { - final V4 vs = four.values(); - return append2(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), mk.node2(vs._3(), vs._4()), m2); - } - ); - }, + one1 -> p2.match( + one2 -> append1(m, m1, mk.node2(one1.value(), one2.value()), m2), + two2 -> { + final V2 vs = two2.values(); + return append1(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), m2); + }, + three -> { + final V3 vs = three.values(); + return append2(m, m1, mk.node2(one1.value(), vs._1()), mk.node2(vs._2(), vs._3()), m2); + }, + four -> { + final V4 vs = four.values(); + return append2(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), mk.node2(vs._3(), vs._4()), m2); + } + ), two1 -> { final V2 v1 = two1.values(); return p2.match( @@ -281,34 +279,12 @@ private static FingerTree> addDigits0( private static FingerTree> append1(final Measured m, final FingerTree> xs, final Node a, final FingerTree> ys) { - return xs.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return ys.cons(a); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return ys.cons(a).cons(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep1) { - return ys.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return xs.snoc(a); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return xs.snoc(a).snoc(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep2) { - final Measured> nm = m.nodeMeasured(); - return new Deep>(nm, m.sum(m.sum(deep1.v, nm.measure(a)), deep2.v), deep1.prefix, - addDigits1(nm, deep1.middle, deep1.suffix, a, deep2.prefix, deep2.middle), - deep2.suffix); - } - }); - } - }); + return xs.match(empty -> ys.cons(a), single -> ys.cons(a).cons(single.value()), deep1 -> ys.match(empty -> xs.snoc(a), single -> xs.snoc(a).snoc(single.value()), deep2 -> { + final Measured> nm = m.nodeMeasured(); + return new Deep>(nm, m.sum(m.sum(deep1.v, nm.measure(a)), deep2.v), deep1.prefix, + addDigits1(nm, deep1.middle, deep1.suffix, a, deep2.prefix, deep2.middle), + deep2.suffix); + })); } private static FingerTree>> addDigits1(final Measured> m, @@ -317,136 +293,54 @@ private static FingerTree>> addDigits1(final Measur final Digit> y, final FingerTree>> m2) { final MakeTree> mk = mkTree(m); - return x.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one1) { - return y.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one2) { - return append1(m, m1, mk.node3(one1.value(), n, one2.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append2(m, m1, mk.node2(one1.value(), n), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append2(m, m1, mk.node3(one1.value(), n, v2._1()), mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append2(m, m1, mk.node3(one1.value(), n, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two1) { - final V2> v1 = two1.values(); - return y.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append2(m, m1, mk.node2(v1), mk.node2(n, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append2(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - return append2(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node3(three.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), - m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v1 = three.values(); - return y.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append2(m, m1, mk.node3(v1), mk.node2(n, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v2 = two.values(); - return append2(m, m1, mk.node3(v1), mk.node3(n, v2._1(), v2._2()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append3(m, m1, mk.node3(v1), mk.node2(n, v2._1()), mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(v1), mk.node3(n, v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v1 = four.values(); - return y.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), n), mk.node2(two.values()), - m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, v2._1()), - mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, v2._1()), - mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } + return x.match(one1 -> y.match(one2 -> append1(m, m1, mk.node3(one1.value(), n, one2.value()), m2), two -> append2(m, m1, mk.node2(one1.value(), n), mk.node2(two.values()), m2), three -> { + final V3> v2 = three.values(); + return append2(m, m1, mk.node3(one1.value(), n, v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, four -> { + final V4> v2 = four.values(); + return append2(m, m1, mk.node3(one1.value(), n, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); + }), two1 -> { + final V2> v1 = two1.values(); + return y.match(one -> append2(m, m1, mk.node2(v1), mk.node2(n, one.value()), m2), two -> append2(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node2(two.values()), m2), three -> append2(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node3(three.values()), m2), four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), + m2); + }); + }, three -> { + final V3> v1 = three.values(); + return y.match(one -> append2(m, m1, mk.node3(v1), mk.node2(n, one.value()), m2), two -> { + final V2> v2 = two.values(); + return append2(m, m1, mk.node3(v1), mk.node3(n, v2._1(), v2._2()), m2); + }, three1 -> { + final V3> v2 = three1.values(); + return append3(m, m1, mk.node3(v1), mk.node2(n, v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(v1), mk.node3(n, v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); + }); + }, four -> { + final V4> v1 = four.values(); + return y.match(one -> append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, one.value()), m2), two -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), n), mk.node2(two.values()), + m2), three -> { + final V3> v2 = three.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, v2._1()), + mk.node2(v2._2(), v2._3()), m2); + }, four1 -> { + final V4> v2 = four1.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, v2._1()), + mk.node3(v2._2(), v2._3(), v2._4()), m2); + }); }); } private static FingerTree> append2(final Measured m, final FingerTree> t1, final Node n1, final Node n2, final FingerTree> t2) { - return t1.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return t2.cons(n2).cons(n1); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return t2.cons(n2).cons(n1).cons(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep) { - return t2.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return deep.snoc(n1).snoc(n2); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return deep.snoc(n1).snoc(n2).snoc(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep2) { - return new Deep>(m.nodeMeasured(), - m.sum(m.sum(m.sum(deep.measure(), n1.measure()), n2.measure()), - deep2.measure()), deep.prefix, - addDigits2(m.nodeMeasured(), deep.middle, deep.suffix, n1, n2, deep2.prefix, - deep2.middle), deep2.suffix); - } - }); - } - }); + return t1.match(empty -> t2.cons(n2).cons(n1), single -> t2.cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2), single -> deep.snoc(n1).snoc(n2).snoc(single.value()), deep2 -> new Deep>(m.nodeMeasured(), + m.sum(m.sum(m.sum(deep.measure(), n1.measure()), n2.measure()), + deep2.measure()), deep.prefix, + addDigits2(m.nodeMeasured(), deep.middle, deep.suffix, n1, n2, deep2.prefix, + deep2.middle), deep2.suffix))); } private static FingerTree>> addDigits2(final Measured> m, @@ -456,103 +350,43 @@ private static FingerTree>> addDigits2(final Measur final Digit> prefix, final FingerTree>> m2) { final MakeTree> mk = mkTree(m); - return suffix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one2) { - return append2(m, m1, mk.node2(one.value(), n1), mk.node2(n2, one2.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(three.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), - m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v1 = two.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two2) { - final V2> v2 = two2.values(); - return append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, v2._1(), v2._2()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, v2._1()), mk.node2(v2._2(), v2._3()), - m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, v2._1(), v2._2()), - mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v1 = three.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append2(m, m1, mk.node3(v1), mk.node3(n1, n2, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append3(m, m1, mk.node3(v1), mk.node2(n1, n2), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three2) { - final V3> v2 = three2.values(); - return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, v2._1()), mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v1 = four.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), n1), mk.node2(n2, one.value()), - m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node3(three.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four2) { - final V4> v2 = four2.values(); - return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); - } - }); - } + return suffix.match(one -> prefix.match(one2 -> append2(m, m1, mk.node2(one.value(), n1), mk.node2(n2, one2.value()), m2), two -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node2(two.values()), m2), three -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(three.values()), m2), four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), + m2); + }), two -> { + final V2> v1 = two.values(); + return prefix.match(one -> append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, one.value()), m2), two2 -> { + final V2> v2 = two2.values(); + return append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, v2._1(), v2._2()), m2); + }, three -> { + final V3> v2 = three.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, v2._1()), mk.node2(v2._2(), v2._3()), + m2); + }, four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, v2._1(), v2._2()), + mk.node2(v2._3(), v2._4()), m2); + }); + }, three -> { + final V3> v1 = three.values(); + return prefix.match(one -> append2(m, m1, mk.node3(v1), mk.node3(n1, n2, one.value()), m2), two -> append3(m, m1, mk.node3(v1), mk.node2(n1, n2), mk.node2(two.values()), m2), three2 -> { + final V3> v2 = three2.values(); + return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); + }); + }, four -> { + final V4> v1 = four.values(); + return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), n1), mk.node2(n2, one.value()), + m2), two -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node2(two.values()), m2), three -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node3(three.values()), m2), four2 -> { + final V4> v2 = four2.values(); + return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); + }); }); } @@ -561,34 +395,10 @@ private static FingerTree> append3(final Measured m, final Node n1, final Node n2, final Node n3, final FingerTree> t2) { final Measured> nm = m.nodeMeasured(); - return t1.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return t2.cons(n3).cons(n2).cons(n1); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return t2.cons(n3).cons(n2).cons(n1).cons(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep) { - return t2.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return deep.snoc(n1).snoc(n2).snoc(n3); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return deep.snoc(n1).snoc(n2).snoc(n3).snoc(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep2) { - return new Deep>(nm, nm.monoid().sumLeft( - list(deep.v, n1.measure(), n2.measure(), n3.measure(), deep2.v)), deep.prefix, - addDigits3(nm, deep.middle, deep.suffix, n1, n2, n3, deep2.prefix, - deep2.middle), deep2.suffix); - } - }); - } - }); + return t1.match(empty -> t2.cons(n3).cons(n2).cons(n1), single -> t2.cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2).snoc(n3), single -> deep.snoc(n1).snoc(n2).snoc(n3).snoc(single.value()), deep2 -> new Deep>(nm, nm.monoid().sumLeft( + list(deep.v, n1.measure(), n2.measure(), n3.measure(), deep2.v)), deep.prefix, + addDigits3(nm, deep.middle, deep.suffix, n1, n2, n3, deep2.prefix, + deep2.middle), deep2.suffix))); } private static FingerTree>> addDigits3(final Measured> m, @@ -599,105 +409,47 @@ private static FingerTree>> addDigits3(final Measur final Digit> prefix, final FingerTree>> m2) { final MakeTree> mk = mkTree(m); - return suffix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one2) { - return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, one2.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v2 = two.values(); - return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, v2._1(), v2._2()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, v2._1()), mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, v2._1(), v2._2()), - mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v1 = two.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, n3), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, v2._1()), mk.node2(v2._2(), v2._3()), - m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, v2._1()), - mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append3(m, m1, mk.node3(three.values()), mk.node2(n1, n2), mk.node2(n3, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append3(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three2) { - return append3(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node3(three2.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append4(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node2(v2._1(), v2._2()), - mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v1 = four.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node2(n3, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v2 = two.values(); - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node3(n3, v2._1(), v2._2()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), mk.node2(n3, v2._1()), - mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four2) { - final V4> v2 = four2.values(); - return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node3(n3, v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); - } - }); - } + return suffix.match(one -> prefix.match(one2 -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, one2.value()), m2), two -> { + final V2> v2 = two.values(); + return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, v2._1(), v2._2()), m2); + }, three -> { + final V3> v2 = three.values(); + return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, v2._1(), v2._2()), + mk.node2(v2._3(), v2._4()), m2); + }), two -> { + final V2> v1 = two.values(); + return prefix.match(one -> append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, one.value()), m2), two1 -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, n3), mk.node2(two1.values()), m2), three -> { + final V3> v2 = three.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, v2._1()), mk.node2(v2._2(), v2._3()), + m2); + }, four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, v2._1()), + mk.node3(v2._2(), v2._3(), v2._4()), m2); + }); + }, three -> prefix.match(one -> append3(m, m1, mk.node3(three.values()), mk.node2(n1, n2), mk.node2(n3, one.value()), m2), two -> append3(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node2(two.values()), m2), three2 -> append3(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node3(three2.values()), m2), four -> { + final V4> v2 = four.values(); + return append4(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node2(v2._1(), v2._2()), + mk.node2(v2._3(), v2._4()), m2); + }), four -> { + final V4> v1 = four.values(); + return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node2(n3, one.value()), m2), two -> { + final V2> v2 = two.values(); + return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node3(n3, v2._1(), v2._2()), m2); + }, three -> { + final V3> v2 = three.values(); + return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), mk.node2(n3, v2._1()), + mk.node2(v2._2(), v2._3()), m2); + }, four2 -> { + final V4> v2 = four2.values(); + return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node3(n3, v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2); + }); }); } @@ -710,34 +462,10 @@ private static FingerTree> append4(final Measured m, final Node n4, final FingerTree> t2) { final Measured> nm = m.nodeMeasured(); - return t1.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return t2.cons(n4).cons(n3).cons(n2).cons(n1); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return t2.cons(n4).cons(n3).cons(n2).cons(n1).cons(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep) { - return t2.match(new F>, FingerTree>>() { - public FingerTree> f(final Empty> empty) { - return t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Single> single) { - return t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4).snoc(single.value()); - } - }, new F>, FingerTree>>() { - public FingerTree> f(final Deep> deep2) { - return new Deep>(nm, m.monoid().sumLeft( - list(deep.v, n1.measure(), n2.measure(), n3.measure(), n4.measure(), deep2.v)), deep.prefix, - addDigits4(nm, deep.middle, deep.suffix, n1, n2, n3, n4, deep2.prefix, - deep2.middle), deep2.suffix); - } - }); - } - }); + return t1.match(empty -> t2.cons(n4).cons(n3).cons(n2).cons(n1), single -> t2.cons(n4).cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4), single -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4).snoc(single.value()), deep2 -> new Deep>(nm, m.monoid().sumLeft( + list(deep.v, n1.measure(), n2.measure(), n3.measure(), n4.measure(), deep2.v)), deep.prefix, + addDigits4(nm, deep.middle, deep.suffix, n1, n2, n3, n4, deep2.prefix, + deep2.middle), deep2.suffix))); } private static FingerTree>> addDigits4(final Measured> m, @@ -748,106 +476,48 @@ private static FingerTree>> addDigits4(final Measur final Digit> prefix, final FingerTree>> m2) { final MakeTree> mk = mkTree(m); - return suffix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one2) { - return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, one2.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, n4), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, v2._1()), mk.node2(v2._2(), v2._3()), - m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, v2._1()), - mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v1 = two.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, n3), mk.node2(n4, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two2) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node2(two2.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node3(three.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append4(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node2(v2._1(), v2._2()), - mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v1 = three.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node2(n4, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - final V2> v2 = two.values(); - return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node3(n4, v2._1(), v2._2()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append4(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node2(n4, v2._1()), mk.node2(v2._2(), v2._3()), - m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append4(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node3(n4, v2._1(), v2._2()), - mk.node2(v2._3(), v2._4()), m2); - } - }); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v1 = four.values(); - return prefix.match(new F>, FingerTree>>>() { - public FingerTree>> f(final One> one) { - return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node3(n3, n4, one.value()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Two> two) { - return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node2(n3, n4), mk.node2(two.values()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Three> three) { - final V3> v2 = three.values(); - return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node3(n3, n4, v2._1()), mk.node2(v2._2(), v2._3()), m2); - } - }, new F>, FingerTree>>>() { - public FingerTree>> f(final Four> four) { - final V4> v2 = four.values(); - return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), - mk.node3(n3, n4, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); - } - }); - } + return suffix.match(one -> prefix.match(one2 -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, one2.value()), m2), two -> append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, n4), mk.node2(two.values()), m2), three -> { + final V3> v2 = three.values(); + return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, v2._1()), mk.node2(v2._2(), v2._3()), + m2); + }, four -> { + final V4> v2 = four.values(); + return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, v2._1()), + mk.node3(v2._2(), v2._3(), v2._4()), m2); + }), two -> { + final V2> v1 = two.values(); + return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, n3), mk.node2(n4, one.value()), m2), two2 -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node2(two2.values()), m2), three -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node3(three.values()), m2), four -> { + final V4> v2 = four.values(); + return append4(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node2(v2._1(), v2._2()), + mk.node2(v2._3(), v2._4()), m2); + }); + }, three -> { + final V3> v1 = three.values(); + return prefix.match(one -> append3(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node2(n4, one.value()), m2), two -> { + final V2> v2 = two.values(); + return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node3(n4, v2._1(), v2._2()), m2); + }, three1 -> { + final V3> v2 = three1.values(); + return append4(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node2(n4, v2._1()), mk.node2(v2._2(), v2._3()), + m2); + }, four -> { + final V4> v2 = four.values(); + return append4(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node3(n4, v2._1(), v2._2()), + mk.node2(v2._3(), v2._4()), m2); + }); + }, four -> { + final V4> v1 = four.values(); + return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node3(n3, n4, one.value()), m2), two -> append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node2(n3, n4), mk.node2(two.values()), m2), three -> { + final V3> v2 = three.values(); + return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node3(n3, n4, v2._1()), mk.node2(v2._2(), v2._3()), m2); + }, four1 -> { + final V4> v2 = four1.values(); + return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), + mk.node3(n3, n4, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2); + }); }); } } diff --git a/demo/src/main/java/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java index d2d07d3d..ee958fc9 100644 --- a/demo/src/main/java/fj/demo/ChequeWrite.java +++ b/demo/src/main/java/fj/demo/ChequeWrite.java @@ -111,19 +111,17 @@ static boolean eq(final List a, final List b) { final List, Integer>> k = split(cs); final int c = k.head()._2(); - k.foreachDoEffect(new Effect1, Integer>>() { - public void f(final P2, Integer> z) { - final List w = z._1(); - final int i = z._2(); - - if (i == 0 && c > 0 && and(w)) - x.snoc(fromString("and")); - - if (existsNotZero(w)) { - x.snoc(show(w)); - if (i != 0) - x.snoc(illion(i - 1)); - } + k.foreachDoEffect(z -> { + final List w = z._1(); + final int i = z._2(); + + if (i == 0 && c > 0 && and(w)) + x.snoc(fromString("and")); + + if (existsNotZero(w)) { + x.snoc(show(w)); + if (i != 0) + x.snoc(illion(i - 1)); } }); diff --git a/demo/src/main/java/fj/demo/List_groupBy.java b/demo/src/main/java/fj/demo/List_groupBy.java index 1dc8866d..f557ec74 100644 --- a/demo/src/main/java/fj/demo/List_groupBy.java +++ b/demo/src/main/java/fj/demo/List_groupBy.java @@ -20,9 +20,7 @@ private static void keyDemo() { final List words = list("Hello", "World", "how", "are", "your", "doing"); final TreeMap> lengthMap = words.groupBy(String::length); - lengthMap.forEach(entry -> { - System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2())); - }); + lengthMap.forEach(entry -> System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2()))); } private static void keyValueDemo() { @@ -30,9 +28,7 @@ private static void keyValueDemo() { final List xs = list(1, 2, 3, 4, 5, 6, 7, 8, 9); final TreeMap> result = xs.groupBy(x -> x % 3, Integer::toBinaryString); - result.forEach(entry -> { - System.out.println(String.format("Numbers with reminder %d are %s", entry._1(), entry._2())); - }); + result.forEach(entry -> System.out.println(String.format("Numbers with reminder %d are %s", entry._1(), entry._2()))); } private static void keyValueAccDemo() { @@ -41,8 +37,6 @@ private static void keyValueAccDemo() { final TreeMap lengthCounts = words.groupBy(String::length, Function.identity(), 0, (word, sum) -> sum + 1, Ord.hashOrd()); - lengthCounts.forEach(entry -> { - System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2())); - }); + lengthCounts.forEach(entry -> System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2()))); } } diff --git a/demo/src/main/java/fj/demo/concurrent/PingPong.java b/demo/src/main/java/fj/demo/concurrent/PingPong.java index b0b09011..a9109585 100644 --- a/demo/src/main/java/fj/demo/concurrent/PingPong.java +++ b/demo/src/main/java/fj/demo/concurrent/PingPong.java @@ -30,15 +30,13 @@ public PingPong(final ExecutorService pool, final int actors, final int pings) { // This actor gives feedback to the user that work is being done // and also terminates the program when all work has been completed. - callback = Actor.queueActor(s, new Effect1() { - public void f(final Integer i) { - done++; - if (done >= actors) { - System.out.println("All done."); - pool.shutdown(); - } else if (actors < 10 || done % (actors / 10) == 0) - System.out.println(MessageFormat.format("{0} actors done ({1} total pongs).", done, pings * done)); - } + callback = Actor.queueActor(s, i -> { + done++; + if (done >= actors) { + System.out.println("All done."); + pool.shutdown(); + } else if (actors < 10 || done % (actors / 10) == 0) + System.out.println(MessageFormat.format("{0} actors done ({1} total pongs).", done, pings * done)); }); } diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 69b27202..dbbd035c 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -92,24 +92,21 @@ public F, IterV>> f(final P2>>>() { @Override public F>> _1() { - return new F>>() { - @Override - public IterV> f(final char[] e) { - StringBuilder sb = acc._1(); - Map map = acc._2(); - for(char c : e) { - if(Character.isWhitespace(c)) { - if(sb.length() > 0) { - map = update(map, sb.toString(), addOne, Integer.valueOf(0)); - sb = new StringBuilder(); - } - } - else { - sb.append(c); + return e -> { + StringBuilder sb = acc._1(); + Map map = acc._2(); + for(char c : e) { + if(Character.isWhitespace(c)) { + if(sb.length() > 0) { + map = update(map, sb.toString(), addOne, Integer.valueOf(0)); + sb = new StringBuilder(); } } - return IterV.cont(step.f(P.p(sb, map))); + else { + sb.append(c); + } } + return IterV.cont(step.f(P.p(sb, map))); }; } }; @@ -139,25 +136,23 @@ public static final IterV> wordCountsFromCha public F, IterV>> f(final P2> acc) { final P1>> empty = P.lazy(() -> IterV.cont(step.f(acc))); final P1>>> el = - P.lazy(() -> { - return e -> { - if(Character.isWhitespace(e.charValue())) { - final StringBuilder sb = acc._1(); - if(sb.length() > 0) { - final Map map = update(acc._2(), sb.toString(), addOne, Integer.valueOf(0)); - return IterV.cont(step.f(P.p(new StringBuilder(), map))); - } - else { - // another whitespace char, no word to push to the map - return IterV.cont(step.f(acc)); - } - } - else { - acc._1().append(e); - return IterV.cont(step.f(acc)); - } - }; - }); + P.lazy(() -> e -> { + if(Character.isWhitespace(e.charValue())) { + final StringBuilder sb = acc._1(); + if(sb.length() > 0) { + final Map map = update(acc._2(), sb.toString(), addOne, Integer.valueOf(0)); + return IterV.cont(step.f(P.p(new StringBuilder(), map))); + } + else { + // another whitespace char, no word to push to the map + return IterV.cont(step.f(acc)); + } + } + else { + acc._1().append(e); + return IterV.cont(step.f(acc)); + } + }); final P1>> eof = P.lazy(() -> { final StringBuilder sb = acc._1(); if(sb.length() > 0) { @@ -261,12 +256,7 @@ public static void main(String[] args) throws IOException { assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); // we have tmpfiles, but still want to be sure not to leave rubbish - fileNames.foreachDoEffect(new Effect1() { - @Override - public void f(final String a) { - new File(a).delete(); - } - }); + fileNames.foreachDoEffect(a -> new File(a).delete()); } @SuppressWarnings("unused") diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index 321a34b7..eda4a72d 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -29,10 +29,7 @@ public Stream f(final Integer a, final Integer b) { out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); } - static F2> fibsJava8 = (a, b) -> { - - return cons(a, F1Functions.lazy(F2Functions.curry(Problem2.fibsJava8).f(b)).f(a + b)); - }; + static F2> fibsJava8 = (a, b) -> cons(a, F1Functions.lazy(F2Functions.curry(Problem2.fibsJava8).f(b)).f(a + b)); static void java8() { out.println(sum(fibsJava8.f(1, 2).filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index 03095e80..8ed7a306 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -52,11 +52,9 @@ public final class ListFunctorLaws { // composition: OK, passed 1000 tests. @SuppressWarnings("unchecked") public static void main(final String[] args) { - check(ListFunctorLaws.class).foreachDoEffect(new Effect1>() { - public void f(final P2 r) { - System.out.print(r._1() + ": "); - summary.println(r._2()); - } + check(ListFunctorLaws.class).foreachDoEffect(r -> { + System.out.print(r._1() + ": "); + summary.println(r._2()); }); } } diff --git a/demo/src/main/java/fj/demo/test/Reflect.java b/demo/src/main/java/fj/demo/test/Reflect.java index d5ebfd36..78084b47 100644 --- a/demo/src/main/java/fj/demo/test/Reflect.java +++ b/demo/src/main/java/fj/demo/test/Reflect.java @@ -119,11 +119,9 @@ public static void main(final String[] args) { } private static void printResults(final List> results) { - results.foreachDoEffect(new Effect1>() { - public void f(final P2 result) { - summary.print(result._2()); - out.println(" (" + result._1() + ')'); - } + results.foreachDoEffect(result -> { + summary.print(result._2()); + out.println(" (" + result._1() + ')'); }); out.println("--------------------------------------------------------------------------------"); } diff --git a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java index b0897044..78a4cc82 100644 --- a/demo/src/main/java/fj/demo/test/StringBuilderReverse.java +++ b/demo/src/main/java/fj/demo/test/StringBuilderReverse.java @@ -34,10 +34,6 @@ public static void main(final String[] args) { //OK, passed 100 tests. //OK, passed 100 tests. //OK, passed 100 tests. - list(p1, p2, p3).foreachDoEffect(new Effect1() { - public void f(final Property p) { - summary.println(p.check()); - } - }); + list(p1, p2, p3).foreachDoEffect(p -> summary.println(p.check())); } } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 7b96d299..a9f05549 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -397,11 +397,7 @@ public static Arbitrary> arbF4Invariant(final /** * An arbitrary implementation for integer values. */ - public static final Arbitrary arbInteger = arbitrary(sized(new F>() { - public Gen f(final Integer i) { - return choose(-i, i); - } - })); + public static final Arbitrary arbInteger = arbitrary(sized(i -> choose(-i, i))); /** * An arbitrary implementation for integer values that checks boundary values (0, 1, -1, @@ -426,15 +422,7 @@ public Gen f(final Integer i) { * An arbitrary implementation for long values. */ public static final Arbitrary arbLong = - arbitrary(arbInteger.gen.bind(arbInteger.gen, new F>() { - public F f(final Integer i1) { - return new F() { - public Long f(final Integer i2) { - return (long) i1 << 32L & i2; - } - }; - } - })); + arbitrary(arbInteger.gen.bind(arbInteger.gen, i1 -> i2 -> (long) i1 << 32L & i2)); /** * An arbitrary implementation for long values that checks boundary values (0, 1, -1, max, @@ -458,11 +446,7 @@ public Gen f(final Integer i) { /** * An arbitrary implementation for byte values. */ - public static final Arbitrary arbByte = arbitrary(arbInteger.gen.map(new F() { - public Byte f(final Integer i) { - return (byte) i.intValue(); - } - })); + public static final Arbitrary arbByte = arbitrary(arbInteger.gen.map(i -> (byte) i.intValue())); /** * An arbitrary implementation for byte values that checks boundary values (0, 1, -1, max, @@ -486,11 +470,7 @@ public Gen f(final Integer i) { /** * An arbitrary implementation for short values. */ - public static final Arbitrary arbShort = arbitrary(arbInteger.gen.map(new F() { - public Short f(final Integer i) { - return (short) i.intValue(); - } - })); + public static final Arbitrary arbShort = arbitrary(arbInteger.gen.map(i -> (short) i.intValue())); /** * An arbitrary implementation for short values that checks boundary values (0, 1, -1, max, @@ -514,11 +494,7 @@ public Gen f(final Integer i) { /** * An arbitrary implementation for character values. */ - public static final Arbitrary arbCharacter = arbitrary(choose(0, 65536).map(new F() { - public Character f(final Integer i) { - return (char) i.intValue(); - } - })); + public static final Arbitrary arbCharacter = arbitrary(choose(0, 65536).map(i -> (char) i.intValue())); /** * An arbitrary implementation for character values that checks boundary values (max, min, @@ -539,11 +515,7 @@ public Gen f(final Integer i) { /** * An arbitrary implementation for double values. */ - public static final Arbitrary arbDouble = arbitrary(sized(new F>() { - public Gen f(final Integer i) { - return choose((double) -i, i); - } - })); + public static final Arbitrary arbDouble = arbitrary(sized(i -> choose((double) -i, i))); /** * An arbitrary implementation for double values that checks boundary values (0, 1, -1, max, @@ -569,11 +541,7 @@ public Gen f(final Integer i) { /** * An arbitrary implementation for float values. */ - public static final Arbitrary arbFloat = arbitrary(arbDouble.gen.map(new F() { - public Float f(final Double d) { - return (float) d.doubleValue(); - } - })); + public static final Arbitrary arbFloat = arbitrary(arbDouble.gen.map(d -> (float) d.doubleValue())); /** * An arbitrary implementation for float values that checks boundary values (0, 1, -1, max, @@ -606,15 +574,7 @@ public Gen f(final Integer i) { * An arbitrary implementation for string values with characters in the US-ASCII range. */ public static final Arbitrary arbUSASCIIString = - arbitrary(arbList(arbCharacter).gen.map(new F, String>() { - public String f(final List cs) { - return asString(cs.map(new F() { - public Character f(final Character c) { - return (char) (c % 128); - } - })); - } - })); + arbitrary(arbList(arbCharacter).gen.map(cs -> asString(cs.map(c -> (char) (c % 128))))); /** * An arbitrary implementation for string values with alpha-numeric characters. @@ -643,14 +603,11 @@ public Character f(final Character c) { * @return An arbitrary implementation for generators. */ public static Arbitrary> arbGen(final Arbitrary aa) { - return arbitrary(sized(new F>>() { - @SuppressWarnings("IfMayBeConditional") - public Gen> f(final Integer i) { - if (i == 0) - return fail(); - else - return aa.gen.map(Gen::value).resize(i - 1); - } + return arbitrary(sized(i -> { + if (i == 0) + return fail(); + else + return aa.gen.map(Gen::value).resize(i - 1); })); } @@ -661,13 +618,9 @@ public Gen> f(final Integer i) { * @return An arbitrary implementation for optional values. */ public static Arbitrary> arbOption(final Arbitrary aa) { - return arbitrary(sized(new F>>() { - public Gen> f(final Integer i) { - return i == 0 ? - value(Option.none()) : - aa.gen.map(Option::some).resize(i - 1); - } - })); + return arbitrary(sized(i -> i == 0 ? + value(Option.none()) : + aa.gen.map(Option::some).resize(i - 1))); } /** @@ -800,38 +753,26 @@ public static Arbitrary arbThrowable(final Arbitrary as) { * @return An arbitrary implementation for array lists. */ public static Arbitrary> arbArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, ArrayList>() { - public ArrayList f(final Array a) { - return new ArrayList(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new ArrayList(a.toCollection()))); } /** * An arbitrary implementation for bit sets. */ public static final Arbitrary arbBitSet = - arbitrary(arbList(arbBoolean).gen.map(new F, BitSet>() { - public BitSet f(final List bs) { - final BitSet s = new BitSet(bs.length()); - bs.zipIndex().foreachDoEffect(new Effect1>() { - public void f(final P2 bi) { - s.set(bi._2(), bi._1()); - } - }); - return s; - } + arbitrary(arbList(arbBoolean).gen.map(bs -> { + final BitSet s = new BitSet(bs.length()); + bs.zipIndex().foreachDoEffect(bi -> s.set(bi._2(), bi._1())); + return s; })); /** * An arbitrary implementation for calendars. */ - public static final Arbitrary arbCalendar = arbitrary(arbLong.gen.map(new F() { - public Calendar f(final Long i) { - final Calendar c = Calendar.getInstance(); - c.setTimeInMillis(i); - return c; - } + public static final Arbitrary arbCalendar = arbitrary(arbLong.gen.map(i -> { + final Calendar c = Calendar.getInstance(); + c.setTimeInMillis(i); + return c; })); /** @@ -869,23 +810,17 @@ public static , V> Arbitrary> arbEnumMap(final A * @return An arbitrary implementation for enum sets. */ public static > Arbitrary> arbEnumSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, EnumSet>() { - public EnumSet f(final Array a) { - return copyOf(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> copyOf(a.toCollection()))); } /** * An arbitrary implementation for gregorian calendars. */ public static final Arbitrary arbGregorianCalendar = - arbitrary(arbLong.gen.map(new F() { - public GregorianCalendar f(final Long i) { - final GregorianCalendar c = new GregorianCalendar(); - c.setTimeInMillis(i); - return c; - } + arbitrary(arbLong.gen.map(i -> { + final GregorianCalendar c = new GregorianCalendar(); + c.setTimeInMillis(i); + return c; })); /** @@ -907,11 +842,7 @@ public static Arbitrary> arbHashMap(final Arbitrary ak, * @return An arbitrary implementation for hash sets. */ public static Arbitrary> arbHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, HashSet>() { - public HashSet f(final Array a) { - return new HashSet(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new HashSet(a.toCollection()))); } /** @@ -924,23 +855,12 @@ public HashSet f(final Array a) { * @return An arbitrary implementation for hash tables. */ public static Arbitrary> arbHashtable(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbList(ak).gen.bind(arbList(av).gen, new F, F, Hashtable>>() { - public F, Hashtable> f(final List ks) { - return new F, Hashtable>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Hashtable f(final List vs) { - final Hashtable t = new Hashtable(); - - ks.zip(vs).foreachDoEffect(new Effect1>() { - public void f(final P2 kv) { - t.put(kv._1(), kv._2()); - } - }); - - return t; - } - }; - } + return arbitrary(arbList(ak).gen.bind(arbList(av).gen, ks -> vs -> { + final Hashtable t = new Hashtable(); + + ks.zip(vs).foreachDoEffect(kv -> t.put(kv._1(), kv._2())); + + return t; })); } @@ -978,11 +898,7 @@ public static Arbitrary> arbLinkedHashMap(final Arbit * @return An arbitrary implementation for hash sets. */ public static Arbitrary> arbLinkedHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, LinkedHashSet>() { - public LinkedHashSet f(final Array a) { - return new LinkedHashSet(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedHashSet(a.toCollection()))); } /** @@ -992,11 +908,7 @@ public LinkedHashSet f(final Array a) { * @return An arbitrary implementation for linked lists. */ public static Arbitrary> arbLinkedList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, LinkedList>() { - public LinkedList f(final Array a) { - return new LinkedList(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedList(a.toCollection()))); } /** @@ -1006,28 +918,21 @@ public LinkedList f(final Array a) { * @return An arbitrary implementation for priority queues. */ public static Arbitrary> arbPriorityQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, PriorityQueue>() { - public PriorityQueue f(final Array a) { - return new PriorityQueue(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new PriorityQueue(a.toCollection()))); } /** * An arbitrary implementation for properties. */ public static final Arbitrary arbProperties = - arbitrary(arbHashtable(arbString, arbString).gen.map(new F, Properties>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Properties f(final Hashtable ht) { - final Properties p = new Properties(); + arbitrary(arbHashtable(arbString, arbString).gen.map(ht -> { + final Properties p = new Properties(); - for (final String k : ht.keySet()) { - p.setProperty(k, ht.get(k)); - } - - return p; + for (final String k : ht.keySet()) { + p.setProperty(k, ht.get(k)); } + + return p; })); /** @@ -1037,12 +942,10 @@ public Properties f(final Hashtable ht) { * @return An arbitrary implementation for stacks. */ public static Arbitrary> arbStack(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, Stack>() { - public Stack f(final Array a) { - final Stack s = new Stack(); - s.addAll(a.toCollection()); - return s; - } + return arbitrary(arbArray(aa).gen.map(a -> { + final Stack s = new Stack(); + s.addAll(a.toCollection()); + return s; })); } @@ -1102,11 +1005,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb * @return An arbitrary implementation for tree sets. */ public static Arbitrary> arbTreeSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, TreeSet>() { - public TreeSet f(final Array a) { - return new TreeSet(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new TreeSet(a.toCollection()))); } /** @@ -1117,12 +1016,7 @@ public TreeSet f(final Array a) { */ @SuppressWarnings("UseOfObsoleteCollectionType") public static Arbitrary> arbVector(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, Vector>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Vector f(final Array a) { - return new Vector(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new Vector(a.toCollection()))); } /** @@ -1151,20 +1045,8 @@ public static Arbitrary> arbWeakHashMap(final Arbitrary */ public static Arbitrary> arbArrayBlockingQueue(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.bind(arbInteger.gen, arbBoolean.gen, - new F, F>>>() { - public F>> f(final Array a) { - return new F>>() { - public F> f(final Integer capacity) { - return new F>() { - public ArrayBlockingQueue f(final Boolean fair) { - return new ArrayBlockingQueue(a.length() + abs(capacity), - fair, a.toCollection()); - } - }; - } - }; - } - })); + a -> capacity -> fair -> new ArrayBlockingQueue(a.length() + abs(capacity), + fair, a.toCollection()))); } /** @@ -1189,11 +1071,7 @@ public static Arbitrary> arbConcurrentHashMap(fin * @return An arbitrary implementation for concurrent linked queues. */ public static Arbitrary> arbConcurrentLinkedQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, ConcurrentLinkedQueue>() { - public ConcurrentLinkedQueue f(final Array a) { - return new ConcurrentLinkedQueue(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new ConcurrentLinkedQueue(a.toCollection()))); } /** @@ -1204,11 +1082,7 @@ public ConcurrentLinkedQueue f(final Array a) { * @return An arbitrary implementation for copy-on-write array lists. */ public static Arbitrary> arbCopyOnWriteArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, CopyOnWriteArrayList>() { - public CopyOnWriteArrayList f(final Array a) { - return new CopyOnWriteArrayList(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArrayList(a.toCollection()))); } /** @@ -1219,11 +1093,7 @@ public CopyOnWriteArrayList f(final Array a) { * @return An arbitrary implementation for copy-on-write array sets. */ public static Arbitrary> arbCopyOnWriteArraySet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, CopyOnWriteArraySet>() { - public CopyOnWriteArraySet f(final Array a) { - return new CopyOnWriteArraySet(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArraySet(a.toCollection()))); } /** @@ -1233,11 +1103,7 @@ public CopyOnWriteArraySet f(final Array a) { * @return An arbitrary implementation for delay queues. */ public static Arbitrary> arbDelayQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, DelayQueue>() { - public DelayQueue f(final Array a) { - return new DelayQueue(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new DelayQueue(a.toCollection()))); } /** @@ -1248,11 +1114,7 @@ public DelayQueue f(final Array a) { * @return An arbitrary implementation for linked blocking queues. */ public static Arbitrary> arbLinkedBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, LinkedBlockingQueue>() { - public LinkedBlockingQueue f(final Array a) { - return new LinkedBlockingQueue(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedBlockingQueue(a.toCollection()))); } /** @@ -1263,11 +1125,7 @@ public LinkedBlockingQueue f(final Array a) { * @return An arbitrary implementation for priority blocking queues. */ public static Arbitrary> arbPriorityBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(new F, PriorityBlockingQueue>() { - public PriorityBlockingQueue f(final Array a) { - return new PriorityBlockingQueue(a.toCollection()); - } - })); + return arbitrary(arbArray(aa).gen.map(a -> new PriorityBlockingQueue(a.toCollection()))); } /** @@ -1278,16 +1136,10 @@ public PriorityBlockingQueue f(final Array a) { * @return An arbitrary implementation for priority blocking queues. */ public static Arbitrary> arbSynchronousQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.bind(arbBoolean.gen, new F, F>>() { - public F> f(final Array a) { - return new F>() { - public SynchronousQueue f(final Boolean fair) { - final SynchronousQueue q = new SynchronousQueue(fair); - q.addAll(a.toCollection()); - return q; - } - }; - } + return arbitrary(arbArray(aa).gen.bind(arbBoolean.gen, a -> fair -> { + final SynchronousQueue q = new SynchronousQueue(fair); + q.addAll(a.toCollection()); + return q; })); } @@ -1318,22 +1170,16 @@ public SynchronousQueue f(final Boolean fair) { * An arbitrary implementation for big integers. */ public static final Arbitrary arbBigInteger = - arbitrary(arbArray(arbByte).gen.bind(arbByte.gen, new F, F>() { - public F f(final Array a) { - return new F() { - public BigInteger f(final Byte b) { - final byte[] x = new byte[a.length() + 1]; + arbitrary(arbArray(arbByte).gen.bind(arbByte.gen, a -> b -> { + final byte[] x = new byte[a.length() + 1]; - for (int i = 0; i < a.array().length; i++) { - x[i] = a.get(i); - } + for (int i = 0; i < a.array().length; i++) { + x[i] = a.get(i); + } - x[a.length()] = b; + x[a.length()] = b; - return new BigInteger(x); - } - }; - } + return new BigInteger(x); })); /** @@ -1369,15 +1215,7 @@ public static Arbitrary> arbP1(final Arbitrary aa) { * @return An arbitrary implementation for product-2 values. */ public static Arbitrary> arbP2(final Arbitrary aa, final Arbitrary ab) { - return arbitrary(aa.gen.bind(ab.gen, new F>>() { - public F> f(final A a) { - return new F>() { - public P2 f(final B b) { - return p(a, b); - } - }; - } - })); + return arbitrary(aa.gen.bind(ab.gen, a -> b -> p(a, b))); } /** @@ -1393,19 +1231,7 @@ public P2 f(final B b) { */ public static Arbitrary> arbP3(final Arbitrary aa, final Arbitrary ab, final Arbitrary ac) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, new F>>>() { - public F>> f(final A a) { - return new F>>() { - public F> f(final B b) { - return new F>() { - public P3 f(final C c) { - return p(a, b, c); - } - }; - } - }; - } - })); + return arbitrary(aa.gen.bind(ab.gen, ac.gen, a -> b -> c -> p(a, b, c))); } /** @@ -1423,23 +1249,7 @@ public P3 f(final C c) { */ public static Arbitrary> arbP4(final Arbitrary aa, final Arbitrary ab, final Arbitrary ac, final Arbitrary ad) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, new F>>>>() { - public F>>> f(final A a) { - return new F>>>() { - public F>> f(final B b) { - return new F>>() { - public F> f(final C c) { - return new F>() { - public P4 f(final D d) { - return p(a, b, c, d); - } - }; - } - }; - } - }; - } - })); + return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, a -> b -> c -> d -> p(a, b, c, d))); } /** @@ -1460,27 +1270,7 @@ public P4 f(final D d) { public static Arbitrary> arbP5(final Arbitrary aa, final Arbitrary ab, final Arbitrary ac, final Arbitrary ad, final Arbitrary ae) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, new F>>>>>() { - public F>>>> f(final A a) { - return new F>>>>() { - public F>>> f(final B b) { - return new F>>>() { - public F>> f(final C c) { - return new F>>() { - public F> f(final D d) { - return new F>() { - public P5 f(final E e) { - return p(a, b, c, d, e); - } - }; - } - }; - } - }; - } - }; - } - })); + return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, a -> b -> c -> d -> e -> p(a, b, c, d, e))); } /** @@ -1505,31 +1295,7 @@ public P5 f(final E e) { final Arbitrary ae, final Arbitrary af) { return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, af.gen, - new F>>>>>>() { - public F>>>>> f(final A a) { - return new F>>>>>() { - public F>>>> f(final B b) { - return new F>>>>() { - public F>>> f(final C c) { - return new F>>>() { - public F>> f(final D d) { - return new F>>() { - public F> f(final E e) { - return new F>() { - public P6 f(final F$ f) { - return p(a, b, c, d, e, f); - } - }; - } - }; - } - }; - } - }; - } - }; - } - })); + a -> b -> c -> d -> e -> f -> p(a, b, c, d, e, f))); } /** @@ -1559,35 +1325,7 @@ public P5 f(final E e) { final Arbitrary af, final Arbitrary ag) { return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, af.gen, ag.gen, - new F>>>>>>>() { - public F>>>>>> f(final A a) { - return new F>>>>>>() { - public F>>>>> f(final B b) { - return new F>>>>>() { - public F>>>> f(final C c) { - return new F>>>>() { - public F>>> f(final D d) { - return new F>>>() { - public F>> f(final E e) { - return new F>>() { - public F> f(final F$ f) { - return new F>() { - public P7 f(final G g) { - return p(a, b, c, d, e, f, g); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - })); + a -> b -> c -> d -> e -> f -> g -> p(a, b, c, d, e, f, g))); } /** @@ -1620,42 +1358,6 @@ public P5 f(final E e) { final Arbitrary ag, final Arbitrary ah) { return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, af.gen, ag.gen, ah.gen, - new F>>>>>>>>() { - public F>>>>>>> f( - final A a) { - return new F>>>>>>>() { - public F>>>>>> f( - final B b) { - return new F>>>>>>() { - public F>>>>> f( - final C c) { - return new F>>>>>() { - public F>>>> f( - final D d) { - return new F>>>>() { - public F>>> f(final E e) { - return new F>>>() { - public F>> f(final F$ f) { - return new F>>() { - public F> f(final G g) { - return new F>() { - public P8 f(final H h) { - return p(a, b, c, d, e, f, g, h); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - })); + a -> b -> c -> d -> e -> f -> g -> h -> p(a, b, c, d, e, f, g, h))); } } diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index bb607aa5..9655aec2 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -76,11 +76,7 @@ public abstract class Coarbitrary { * @return A curried version of {@link #coarbitrary(Object, Gen)}. */ public final F, Gen> coarbitrary(final A a) { - return new F, Gen>() { - public Gen f(final Gen g) { - return coarbitrary(a, g); - } - }; + return g -> coarbitrary(a, g); } /** @@ -121,11 +117,7 @@ public Gen coarbitrary(final B b, final Gen g) { public static Coarbitrary> coarbF(final Arbitrary a, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F f, final Gen g) { - return a.gen.bind(new F>() { - public Gen f(final A a) { - return c.coarbitrary(f.f(a), g); - } - }); + return a.gen.bind(a1 -> c.coarbitrary(f.f(a1), g)); } }; } diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index b3bb1371..45a4429a 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -110,15 +110,7 @@ public A gen(final int i, final Rand r) { * @return A new generator after applying the mapping function. */ public Gen map(final F f) { - return new Gen(new F>() { - public F f(final Integer i) { - return new F() { - public B f(final Rand r) { - return f.f(gen(i, r)); - } - }; - } - }); + return new Gen(i -> r -> f.f(gen(i, r))); } /** @@ -169,15 +161,7 @@ public void foreachDoEffect(final Integer i, final Rand r, final Effect1 f) { * @return A new generator after binding the given function. */ public Gen bind(final F> f) { - return new Gen(new F>() { - public F f(final Integer i) { - return new F() { - public B f(final Rand r) { - return f.f(gen(i, r)).f.f(i).f(r); - } - }; - } - }); + return new Gen(i -> r -> f.f(gen(i, r)).f.f(i).f(r)); } /** @@ -292,11 +276,7 @@ public Gen bind(final Gen gb, final Gen gc, final Gen g * @return A new generator after function application. */ public Gen apply(final Gen> gf) { - return gf.bind(new F, Gen>() { - public Gen f(final F f) { - return map(f::f); - } - }); + return gf.bind(f1 -> map(f1::f)); } /** @@ -306,15 +286,7 @@ public Gen f(final F f) { * @return A new generator that uses the given size. */ public Gen resize(final int s) { - return new Gen(new F>() { - public F f(final Integer i) { - return new F() { - public A f(final Rand r) { - return f.f(s).f(r); - } - }; - } - }); + return new Gen(i -> r -> f.f(s).f(r)); } /** @@ -376,15 +348,7 @@ public static Gen sized(final F> f) { * @return A generator that always produces the given value. */ public static Gen value(final A a) { - return new Gen(new F>() { - public F f(final Integer i) { - return new F() { - public A f(final Rand r) { - return a; - } - }; - } - }); + return new Gen(i -> r -> a); } /** @@ -410,15 +374,7 @@ public static Gen choose(final int from, final int to) { public static Gen choose(final double from, final double to) { final double f = min(from, to); final double t = max(from, to); - return parameterised(new F>>() { - public F> f(final Integer i) { - return new F>() { - public Gen f(final Rand r) { - return value(r.choose(f, t)); - } - }; - } - }); + return parameterised(i -> r -> value(r.choose(f, t))); } /** @@ -427,14 +383,8 @@ public Gen f(final Rand r) { * @return A generator that never returns a value. */ public static Gen fail() { - return new Gen(new F>() { - public F f(final Integer i) { - return new F() { - public A f(final Rand r) { - throw error("Failing generator"); - } - }; - } + return new Gen(i -> r -> { + throw error("Failing generator"); }); } @@ -471,11 +421,7 @@ Gen pick(final int n, final List>> gs) { final F>, Integer> f = __1(); - return choose(1, intAdditionMonoid.sumLeft(gs.map(f))).bind(new F>() { - public Gen f(final Integer i) { - return new Pick().pick(i, gs); - } - }); + return choose(1, intAdditionMonoid.sumLeft(gs.map(f))).bind(i -> new Pick().pick(i, gs)); } /** @@ -486,11 +432,7 @@ public Gen f(final Integer i) { * @return A new generator that uses the given pairs of frequency and value. */ public static Gen elemFrequency(final List> as) { - return frequency(as.map(new F, P2>>() { - public P2> f(final P2 p) { - return p.map2(Gen::value); - } - })); + return frequency(as.map(p -> p.map2(Gen::value))); } /** @@ -501,11 +443,7 @@ public P2> f(final P2 p) { */ @SafeVarargs public static Gen elements(final A... as) { - return array(as).isEmpty() ? Gen.fail() : choose(0, as.length - 1).map(new F() { - public A f(final Integer i) { - return as[i]; - } - }); + return array(as).isEmpty() ? Gen.fail() : choose(0, as.length - 1).map(i -> as[i]); } /** @@ -785,18 +723,6 @@ public static Gen> someWordOf(int maxLength, List as) { * @return A generator for functions. */ public static Gen> promote(final F> f) { - return new Gen>(new F>>() { - public F> f(final Integer i) { - return new F>() { - public F f(final Rand r) { - return new F() { - public B f(final A a) { - return f.f(a).f.f(i).f(r); - } - }; - } - }; - } - }); + return new Gen>(i -> r -> a -> f.f(a).f.f(i).f(r)); } } diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index d0eeb5ae..d69d0c65 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -54,15 +54,7 @@ public Result prop(final int i, final Rand r) { * @return A generator of results from this property. */ public Gen gen() { - return Gen.gen(new F>() { - public F f(final Integer i) { - return new F() { - public Result f(final Rand r) { - return f.f(i).f(r); - } - }; - } - }); + return Gen.gen(i -> r -> f.f(i).f(r)); } /** @@ -72,15 +64,7 @@ public Result f(final Rand r) { * @return A conjunction of this property with the given property. */ public Property and(final Property p) { - return fromGen(gen().bind(p.gen(), new F>() { - public F f(final Result res1) { - return new F() { - public Result f(final Result res2) { - return res1.isException() || res1.isFalsified() ? res1 : res2.isException() || res2.isFalsified() ? res2 : res1.isProven() || res1.isUnfalsified() ? res2 : res2.isProven() || res2.isUnfalsified() ? res1 : noResult(); - } - }; - } - })); + return fromGen(gen().bind(p.gen(), res1 -> res2 -> res1.isException() || res1.isFalsified() ? res1 : res2.isException() || res2.isFalsified() ? res2 : res1.isProven() || res1.isUnfalsified() ? res2 : res2.isProven() || res2.isUnfalsified() ? res1 : noResult())); } /** @@ -90,15 +74,7 @@ public Result f(final Result res2) { * @return A disjunction of this property with the given property. */ public Property or(final Property p) { - return fromGen(gen().bind(p.gen(), new F>() { - public F f(final Result res1) { - return new F() { - public Result f(final Result res2) { - return res1.isException() || res1.isFalsified() ? res1 : res2.isException() || res2.isFalsified() ? res2 : res1.isProven() || res1.isUnfalsified() ? res1 : res2.isProven() || res2.isUnfalsified() ? res2 : noResult(); - } - }; - } - })); + return fromGen(gen().bind(p.gen(), res1 -> res2 -> res1.isException() || res1.isFalsified() ? res1 : res2.isException() || res2.isFalsified() ? res2 : res1.isProven() || res1.isUnfalsified() ? res1 : res2.isProven() || res2.isUnfalsified() ? res2 : noResult())); } /** @@ -111,15 +87,7 @@ public Result f(final Result res2) { * @return A sequence of this property with the given property. */ public Property sequence(final Property p) { - return fromGen(gen().bind(p.gen(), new F>() { - public F f(final Result res1) { - return new F() { - public Result f(final Result res2) { - return res1.isException() || res1.isProven() || res1.isUnfalsified() ? res1 : res2.isException() || res2.isProven() || res2.isUnfalsified() ? res2 : res1.isFalsified() ? res2 : res2.isFalsified() ? res1 : noResult(); - } - }; - } - })); + return fromGen(gen().bind(p.gen(), res1 -> res2 -> res1.isException() || res1.isProven() || res1.isUnfalsified() ? res1 : res2.isException() || res2.isProven() || res2.isUnfalsified() ? res2 : res1.isFalsified() ? res2 : res2.isFalsified() ? res1 : noResult())); } /** @@ -351,15 +319,7 @@ public CheckResult maxSize(final Rand r, final int maxSize) { * @return A property that produces a result only if the given condition satisfies. */ public static Property implies(final boolean b, final F0 p) { - return b ? p.f() : new Property(new F>() { - public F f(final Integer i) { - return new F() { - public Result f(final Rand r) { - return noResult(); - } - }; - } - }); + return b ? p.f() : new Property(i -> r -> noResult()); } /** @@ -395,15 +355,7 @@ public static Property prop(final F> f) { * @return A property that always has the given result. */ public static Property prop(final Result r) { - return new Property(new F>() { - public F f(final Integer integer) { - return new F() { - public Result f(final Rand x) { - return r; - } - }; - } - }); + return new Property(integer -> x -> r); } /** @@ -426,15 +378,7 @@ public static Property prop(final boolean b) { * @return A property from a generator of results. */ public static Property fromGen(final Gen g) { - return prop(new F>() { - public F f(final Integer i) { - return new F() { - public Result f(final Rand r) { - return g.gen(i, r); - } - }; - } - }); + return prop(i -> r -> g.gen(i, r)); } /** @@ -448,56 +392,44 @@ public Result f(final Rand r) { * application of its arguments. */ public static Property forall(final Gen g, final Shrink shrink, final F> f) { - return prop(new F>() { - public F f(final Integer i) { - return new F() { - public Result f(final Rand r) { - final class Util { - @SuppressWarnings("IfMayBeConditional") - Option> first(final Stream as, final int shrinks) { - final Stream>> results = as.map(new F>>() { - public Option> f(final A a) { - final Result result = exception(f.f(a)).prop(i, r); - - return result.toOption().map(new F>() { - public P2 f(final Result result) { - return p(a, result.provenAsUnfalsified().addArg(arg(a, shrinks))); - } - }); - } - }); - - if (results.isEmpty()) - return none(); - else return results.find(this::failed).orSome(results::head); - } - - public boolean failed(final Option> o) { - return o.isSome() && o.some()._2().failed(); - } - } - - final Util u = new Util(); - - Option> x = u.first(Stream.single(g.gen(i, r)), 0); - final F, Result> __2 = __2(); - if (u.failed(x)) { - Option or; - int shrinks = 0; - - do { - shrinks++; - or = x.map(__2); - x = u.first(shrink.shrink(x.some()._1()), shrinks); - } - while (u.failed(x)); - - return noResult(or); - } else - return noResult(x.map(__2)); - } - }; + return prop(i -> r -> { + final class Util { + @SuppressWarnings("IfMayBeConditional") + Option> first(final Stream as, final int shrinks) { + final Stream>> results = as.map(a -> { + final Result result = exception(f.f(a)).prop(i, r); + + return result.toOption().map(result1 -> p(a, result1.provenAsUnfalsified().addArg(arg(a, shrinks)))); + }); + + if (results.isEmpty()) + return none(); + else return results.find(this::failed).orSome(results::head); + } + + public boolean failed(final Option> o) { + return o.isSome() && o.some()._2().failed(); + } } + + final Util u = new Util(); + + Option> x = u.first(Stream.single(g.gen(i, r)), 0); + final F, Result> __2 = __2(); + if (u.failed(x)) { + Option or; + int shrinks = 0; + + do { + shrinks++; + or = x.map(__2); + x = u.first(shrink.shrink(x.some()._1()), shrinks); + } + while (u.failed(x)); + + return noResult(or); + } else + return noResult(x.map(__2)); }); } @@ -569,14 +501,10 @@ public static Property property(final Arbitrary aa, final F * application of its arguments. */ public static Property propertyP(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F>> f) { - return property(aa, sa, new F() { - public Property f(final A a) { - return propertyP(ab, sb, new F>() { - public P1 f(final B b) { - return f.f(a).f(b); - } - }); - } + return property(aa, sa, a -> { + return propertyP(ab, sb, b -> { + return f.f(a).f(b); + }); }); } @@ -607,15 +535,7 @@ public static Property property(final Arbitrary aa, final Arbitrary * application of its arguments. */ public static Property propertyP(final Arbitrary aa, final Arbitrary ab, final F>> f) { - return property(aa, new F() { - public Property f(final A a) { - return propertyP(ab, new F>() { - public P1 f(final B b) { - return f.f(a).f(b); - } - }); - } - }); + return property(aa, a -> propertyP(ab, b -> f.f(a).f(b))); } /** @@ -713,19 +633,9 @@ public static Property property(final Arbitrary aa, final Shrink sb, final Shrink sc, final F>> f) { - return property(aa, ab, sa, sb, new F>() { - public F f(final A a) { - return new F() { - public Property f(final B b) { - return property(ac, sc, new F() { - public Property f(final C c) { - return f.f(a).f(b).f(c); - } - }); - } - }; - } - }); + return property(aa, ab, sa, sb, a -> b -> property(ac, sc, c -> { + return f.f(a).f(b).f(c); + })); } /** @@ -743,19 +653,7 @@ public static Property property(final Arbitrary aa, final Arbitrary ab, final Arbitrary ac, final F>> f) { - return property(aa, ab, new F>() { - public F f(final A a) { - return new F() { - public Property f(final B b) { - return property(ac, new F() { - public Property f(final C c) { - return f.f(a).f(b).f(c); - } - }); - } - }; - } - }); + return property(aa, ab, a -> b -> property(ac, c -> f.f(a).f(b).f(c))); } /** @@ -825,23 +723,9 @@ public static Property property(final Arbitrary aa, final Shrink sc, final Shrink sd, final F>>> f) { - return property(aa, ab, ac, sa, sb, sc, new F>>() { - public F> f(final A a) { - return new F>() { - public F f(final B b) { - return new F() { - public Property f(final C c) { - return property(ad, sd, new F() { - public Property f(final D d) { - return f.f(a).f(b).f(c).f(d); - } - }); - } - }; - } - }; - } - }); + return property(aa, ab, ac, sa, sb, sc, a -> b -> c -> property(ad, sd, d -> { + return f.f(a).f(b).f(c).f(d); + })); } /** @@ -861,23 +745,7 @@ public static Property property(final Arbitrary aa, final Arbitrary ac, final Arbitrary ad, final F>>> f) { - return property(aa, ab, ac, new F>>() { - public F> f(final A a) { - return new F>() { - public F f(final B b) { - return new F() { - public Property f(final C c) { - return property(ad, new F() { - public Property f(final D d) { - return f.f(a).f(b).f(c).f(d); - } - }); - } - }; - } - }; - } - }); + return property(aa, ab, ac, a -> b -> c -> property(ad, d -> f.f(a).f(b).f(c).f(d))); } /** @@ -957,27 +825,9 @@ public static Property property(final Arbitrary aa, final Shrink sd, final Shrink se, final F>>>> f) { - return property(aa, ab, ac, ad, sa, sb, sc, sd, new F>>>() { - public F>> f(final A a) { - return new F>>() { - public F> f(final B b) { - return new F>() { - public F f(final C c) { - return new F() { - public Property f(final D d) { - return property(ae, se, new F() { - public Property f(final E e) { - return f.f(a).f(b).f(c).f(d).f(e); - } - }); - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, sa, sb, sc, sd, a -> b -> c -> d -> property(ae, se, e -> { + return f.f(a).f(b).f(c).f(d).f(e); + })); } /** @@ -999,27 +849,7 @@ public static Property property(final Arbitrary aa, final Arbitrary ad, final Arbitrary ae, final F>>>> f) { - return property(aa, ab, ac, ad, new F>>>() { - public F>> f(final A a) { - return new F>>() { - public F> f(final B b) { - return new F>() { - public F f(final C c) { - return new F() { - public Property f(final D d) { - return property(ae, new F() { - public Property f(final E e) { - return f.f(a).f(b).f(c).f(d).f(e); - } - }); - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, a -> b -> c -> d -> property(ae, e -> f.f(a).f(b).f(c).f(d).f(e))); } /** @@ -1109,31 +939,9 @@ public static Property property(final Arbitrary aa, final Shrink se, final Shrink sf, final F>>>>> f) { - return property(aa, ab, ac, ad, ae, sa, sb, sc, sd, se, new F>>>>() { - public F>>> f(final A a) { - return new F>>>() { - public F>> f(final B b) { - return new F>>() { - public F> f(final C c) { - return new F>() { - public F f(final D d) { - return new F() { - public Property f(final E e) { - return property(af, sf, new F() { - public Property f(final F$ f$) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$); - } - }); - } - }; - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, ae, sa, sb, sc, sd, se, a -> b -> c -> d -> e -> property(af, sf, f$ -> { + return f.f(a).f(b).f(c).f(d).f(e).f(f$); + })); } /** @@ -1157,31 +965,7 @@ public Property f(final F$ f$) { final Arbitrary ae, final Arbitrary af, final F>>>>> f) { - return property(aa, ab, ac, ad, ae, new F>>>>() { - public F>>> f(final A a) { - return new F>>>() { - public F>> f(final B b) { - return new F>>() { - public F> f(final C c) { - return new F>() { - public F f(final D d) { - return new F() { - public Property f(final E e) { - return property(af, new F() { - public Property f(final F$ f$) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$); - } - }); - } - }; - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, ae, a -> b -> c -> d -> e -> property(af, f$ -> f.f(a).f(b).f(c).f(d).f(e).f(f$))); } /** @@ -1281,35 +1065,9 @@ public Property f(final F$ f$) { final Shrink sf, final Shrink sg, final F>>>>>> f) { - return property(aa, ab, ac, ad, ae, af, sa, sb, sc, sd, se, sf, new F>>>>>() { - public F>>>> f(final A a) { - return new F>>>>() { - public F>>> f(final B b) { - return new F>>>() { - public F>> f(final C c) { - return new F>>() { - public F> f(final D d) { - return new F>() { - public F f(final E e) { - return new F() { - public Property f(final F$ f$) { - return property(ag, sg, new F() { - public Property f(final G g) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g); - } - }); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, ae, af, sa, sb, sc, sd, se, sf, a -> b -> c -> d -> e -> f$ -> property(ag, sg, g -> { + return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g); + })); } /** @@ -1335,35 +1093,7 @@ public Property f(final G g) { final Arbitrary af, final Arbitrary ag, final F>>>>>> f) { - return property(aa, ab, ac, ad, ae, af, new F>>>>>() { - public F>>>> f(final A a) { - return new F>>>>() { - public F>>> f(final B b) { - return new F>>>() { - public F>> f(final C c) { - return new F>>() { - public F> f(final D d) { - return new F>() { - public F f(final E e) { - return new F() { - public Property f(final F$ f$) { - return property(ag, new F() { - public Property f(final G g) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g); - } - }); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, ae, af, a -> b -> c -> d -> e -> f$ -> property(ag, g -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g))); } /** @@ -1473,39 +1203,9 @@ public Property f(final G g) { final Shrink sg, final Shrink sh, final F>>>>>>> f) { - return property(aa, ab, ac, ad, ae, af, ag, sa, sb, sc, sd, se, sf, sg, new F>>>>>>() { - public F>>>>> f(final A a) { - return new F>>>>>() { - public F>>>> f(final B b) { - return new F>>>>() { - public F>>> f(final C c) { - return new F>>>() { - public F>> f(final D d) { - return new F>>() { - public F> f(final E e) { - return new F>() { - public F f(final F$ f$) { - return new F() { - public Property f(final G g) { - return property(ah, sh, new F() { - public Property f(final H h) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h); - } - }); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, ae, af, ag, sa, sb, sc, sd, se, sf, sg, a -> b -> c -> d -> e -> f$ -> g -> property(ah, sh, h -> { + return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h); + })); } /** @@ -1533,39 +1233,7 @@ public Property f(final H h) { final Arbitrary ag, final Arbitrary ah, final F>>>>>>> f) { - return property(aa, ab, ac, ad, ae, af, ag, new F>>>>>>() { - public F>>>>> f(final A a) { - return new F>>>>>() { - public F>>>> f(final B b) { - return new F>>>>() { - public F>>> f(final C c) { - return new F>>>() { - public F>> f(final D d) { - return new F>>() { - public F> f(final E e) { - return new F>() { - public F f(final F$ f$) { - return new F() { - public Property f(final G g) { - return property(ah, new F() { - public Property f(final H h) { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h); - } - }); - } - }; - } - }; - } - }; - } - }; - } - }; - } - }; - } - }); + return property(aa, ab, ac, ad, ae, af, ag, a -> b -> c -> d -> e -> f$ -> g -> property(ah, h -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h))); } /** @@ -1652,15 +1320,7 @@ public static Property exception(final F0 p) { try { return p.f(); } catch (final Throwable t) { - return new Property(new F>() { - public F f(final Integer i) { - return new F() { - public Result f(final Rand r) { - return Result.exception(List.>nil(), t); - } - }; - } - }); + return new Property(i -> r -> Result.exception(List.>nil(), t)); } } diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index a4994bcb..f4da2459 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -80,11 +80,7 @@ public static List> check(final List List> check(final List> c, final Rand r, final String... categories) { - return join(c.map(new F, List>>() { - public List> f(final java.lang.Class c) { - return check(c, r, categories); - } - })); + return join(c.map(c1 -> check(c1, r, categories))); } /** @@ -142,18 +138,12 @@ public static List> check(final java.lang.Class c * @return The results of checking the properties on the given class. */ public static List> check(final java.lang.Class c, final Rand r, final String... categories) { - return join(clas(c).inheritance().map(new F, List>>>() { - public List>> f(final Class c) { - return properties(c.clas(), categories); - } - })).map(new F>, P2>() { - public P2 f(final P3> p) { - if(p._3().isSome()) { - final CheckParams ps = p._3().some(); - return p(p._2(), p._1().check(r, ps.minSuccessful(), ps.maxDiscarded(), ps.minSize(), ps.maxSize())); - } else - return p(p._2(), p._1().check(r)); - } + return join(clas(c).inheritance().map(c1 -> properties(c1.clas(), categories))).map(p -> { + if(p._3().isSome()) { + final CheckParams ps = p._3().some(); + return p(p._2(), p._1().check(r, ps.minSuccessful(), ps.maxDiscarded(), ps.minSize(), ps.maxSize())); + } else + return p(p._2(), p._1().check(r)); }); } @@ -187,68 +177,62 @@ public static List> check(final java.lang.Class c */ public static List>> properties(final java.lang.Class c, final String... categories) { //noinspection ClassEscapesDefinedScope - final Array>> propFields = properties(array(c.getDeclaredFields()).map(new F() { - public PropertyMember f(final Field f) { - return new PropertyMember() { - public java.lang.Class type() { - return f.getType(); - } - - public AnnotatedElement element() { - return f; - } - - public String name() { - return f.getName(); - } - - public int modifiers() { - return f.getModifiers(); - } - - public Property invoke(final X x) throws IllegalAccessException { - f.setAccessible(true); - return (Property)f.get(x); - } - - public boolean isProperty() { - return true; - } - }; + final Array>> propFields = properties(array(c.getDeclaredFields()).map((F) f -> new PropertyMember() { + public java.lang.Class type() { + return f.getType(); + } + + public AnnotatedElement element() { + return f; + } + + public String name() { + return f.getName(); + } + + public int modifiers() { + return f.getModifiers(); + } + + public Property invoke(final X x) throws IllegalAccessException { + f.setAccessible(true); + return (Property)f.get(x); + } + + public boolean isProperty() { + return true; } }), c, categories); //noinspection ClassEscapesDefinedScope - final Array>> propMethods = properties(array(c.getDeclaredMethods()).map(new F() { - public PropertyMember f(final Method m) { - //noinspection ProhibitedExceptionDeclared - return new PropertyMember() { - public java.lang.Class type() { - return m.getReturnType(); - } - - public AnnotatedElement element() { - return m; - } - - public String name() { - return m.getName(); - } - - public int modifiers() { - return m.getModifiers(); - } - - public Property invoke(final X x) throws Exception { - m.setAccessible(true); - return (Property)m.invoke(x); - } - - public boolean isProperty() { - return m.getParameterTypes().length == 0; - } - }; - } + final Array>> propMethods = properties(array(c.getDeclaredMethods()).map((F) m -> { + //noinspection ProhibitedExceptionDeclared + return new PropertyMember() { + public java.lang.Class type() { + return m.getReturnType(); + } + + public AnnotatedElement element() { + return m; + } + + public String name() { + return m.getName(); + } + + public int modifiers() { + return m.getModifiers(); + } + + public Property invoke(final X x) throws Exception { + m.setAccessible(true); + return (Property)m.invoke(x); + } + + public boolean isProperty() { + return m.getParameterTypes().length == 0; + } + }; }), c, categories); return propFields.append(propMethods).toList(); @@ -265,62 +249,41 @@ private interface PropertyMember { } private static Array>> properties(final Array ms, final java.lang.Class declaringClass, final String... categories) { - final Option t = emptyCtor(declaringClass).map(new F, T>() { - @SuppressWarnings("OverlyBroadCatchBlock") - public T f(final Constructor ctor) { - try { - ctor.setAccessible(true); - return ctor.newInstance(); - } catch(Exception e) { - throw new Error(e.getMessage(), e); - } + final Option t = emptyCtor(declaringClass).map(ctor -> { + try { + ctor.setAccessible(true); + return ctor.newInstance(); + } catch(Exception e) { + throw new Error(e.getMessage(), e); } }); - final F> p = new F>() { - public F f(final AnnotatedElement e) { - return new F() { - public Boolean f(final String s) { - final F p = new F() { - public Boolean f(final Category c) { - return array(c.value()).exists(new F() { - public Boolean f(final String cs) { - return cs.equals(s); - } - }); - } - }; - - @SuppressWarnings("unchecked") - final List bss = somes(list(fromNull(e.getAnnotation(Category.class)).map(p), - fromNull(declaringClass.getAnnotation(Category.class)).map(p))); - return bss.exists(Function.identity()); - } - }; - } + final F> p = e -> s -> { + final F p1 = c -> array(c.value()).exists(cs -> cs.equals(s)); + + @SuppressWarnings("unchecked") + final List bss = somes(list(fromNull(e.getAnnotation(Category.class)).map(p1), + fromNull(declaringClass.getAnnotation(Category.class)).map(p1))); + return bss.exists(Function.identity()); }; final F nameS = Name::value; - return ms.filter(new F() { - public Boolean f(final PropertyMember m) { - //noinspection ObjectEquality - return m.isProperty() && - m.type() == Property.class && - !m.element().isAnnotationPresent(NoCheck.class) && - !declaringClass.isAnnotationPresent(NoCheck.class) && - (categories.length == 0 || array(categories).exists(p.f(m.element()))) && - (t.isSome() || isStatic(m.modifiers())); - } - }).map(new F>>() { - public P3> f(final PropertyMember m) { - try { - final Option params = fromNull(m.element().getAnnotation(CheckParams.class)).orElse(fromNull(declaringClass.getAnnotation(CheckParams.class))); - final String name = fromNull(m.element().getAnnotation(Name.class)).map(nameS).orSome(m.name()); - return p(m.invoke(t.orSome(P.p(null))), name, params); - } catch(Exception e) { - throw new Error(e.getMessage(), e); - } + return ms.filter(m -> { + //noinspection ObjectEquality + return m.isProperty() && + m.type() == Property.class && + !m.element().isAnnotationPresent(NoCheck.class) && + !declaringClass.isAnnotationPresent(NoCheck.class) && + (categories.length == 0 || array(categories).exists(p.f(m.element()))) && + (t.isSome() || isStatic(m.modifiers())); + }).map(m -> { + try { + final Option params = fromNull(m.element().getAnnotation(CheckParams.class)).orElse(fromNull(declaringClass.getAnnotation(CheckParams.class))); + final String name = fromNull(m.element().getAnnotation(Name.class)).map(nameS).orSome(m.name()); + return p(m.invoke(t.orSome(P.p(null))), name, params); + } catch(Exception e) { + throw new Error(e.getMessage(), e); } }); } diff --git a/quickcheck/src/main/java/fj/test/reflect/Main.java b/quickcheck/src/main/java/fj/test/reflect/Main.java index b0b5fb95..5f6f3dfc 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Main.java +++ b/quickcheck/src/main/java/fj/test/reflect/Main.java @@ -36,11 +36,9 @@ public static void main(final String... args) { exit(441); } else { try { - check(forName(args[0]), array(args).toList().tail()).foreachDoEffect(new Effect1>() { - public void f(final P2 r) { - summary.print(r._2()); - out.println(" (" + r._1() + ')'); - } + check(forName(args[0]), array(args).toList().tail()).foreachDoEffect(r -> { + summary.print(r._2()); + out.println(" (" + r._1() + ')'); }); } catch(ClassNotFoundException e) { e.printStackTrace(); From 4b053ca403df1469db25c8d17cf7049460516c0a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 5 Mar 2016 23:16:42 +0100 Subject: [PATCH 520/811] Make use of type inference --- core/src/main/java/fj/Class.java | 4 +- core/src/main/java/fj/Equal.java | 24 +- core/src/main/java/fj/F1Functions.java | 32 +- core/src/main/java/fj/F1W.java | 2 +- core/src/main/java/fj/Function.java | 4 +- core/src/main/java/fj/Hash.java | 22 +- core/src/main/java/fj/LcgRng.java | 2 +- core/src/main/java/fj/Monoid.java | 22 +- core/src/main/java/fj/Ord.java | 12 +- core/src/main/java/fj/P1.java | 10 +- core/src/main/java/fj/P2.java | 4 +- core/src/main/java/fj/P3.java | 2 +- core/src/main/java/fj/P4.java | 2 +- core/src/main/java/fj/P5.java | 2 +- core/src/main/java/fj/P6.java | 14 +- core/src/main/java/fj/P7.java | 16 +- core/src/main/java/fj/P8.java | 18 +- core/src/main/java/fj/Semigroup.java | 4 +- core/src/main/java/fj/Show.java | 18 +- core/src/main/java/fj/control/Trampoline.java | 10 +- core/src/main/java/fj/control/db/DB.java | 2 +- .../main/java/fj/control/parallel/Actor.java | 8 +- .../java/fj/control/parallel/Callables.java | 5 +- .../java/fj/control/parallel/ParModule.java | 30 +- .../java/fj/control/parallel/Promise.java | 18 +- .../java/fj/control/parallel/Strategy.java | 20 +- core/src/main/java/fj/data/$.java | 2 +- core/src/main/java/fj/data/Array.java | 44 +-- core/src/main/java/fj/data/DList.java | 4 +- core/src/main/java/fj/data/Either.java | 88 +++--- core/src/main/java/fj/data/Enumerator.java | 90 +++--- core/src/main/java/fj/data/HashMap.java | 40 +-- core/src/main/java/fj/data/HashSet.java | 10 +- core/src/main/java/fj/data/IOFunctions.java | 32 +- core/src/main/java/fj/data/IterableW.java | 6 +- core/src/main/java/fj/data/Iteratee.java | 16 +- core/src/main/java/fj/data/Java.java | 290 +++++++++--------- core/src/main/java/fj/data/LazyString.java | 2 +- core/src/main/java/fj/data/List.java | 78 ++--- core/src/main/java/fj/data/Natural.java | 2 +- core/src/main/java/fj/data/NonEmptyList.java | 12 +- core/src/main/java/fj/data/Option.java | 48 +-- core/src/main/java/fj/data/Reader.java | 2 +- core/src/main/java/fj/data/Seq.java | 16 +- core/src/main/java/fj/data/Set.java | 38 +-- core/src/main/java/fj/data/State.java | 6 +- core/src/main/java/fj/data/Stream.java | 60 ++-- core/src/main/java/fj/data/Tree.java | 20 +- core/src/main/java/fj/data/TreeMap.java | 44 +-- core/src/main/java/fj/data/TreeZipper.java | 54 ++-- core/src/main/java/fj/data/Validation.java | 38 +-- core/src/main/java/fj/data/Writer.java | 4 +- core/src/main/java/fj/data/Zipper.java | 44 +-- .../main/java/fj/data/fingertrees/Deep.java | 40 +-- .../main/java/fj/data/fingertrees/Digit.java | 30 +- .../main/java/fj/data/fingertrees/Empty.java | 4 +- .../java/fj/data/fingertrees/FingerTree.java | 6 +- .../java/fj/data/fingertrees/MakeTree.java | 22 +- .../java/fj/data/fingertrees/Measured.java | 6 +- .../main/java/fj/data/fingertrees/Node.java | 4 +- .../main/java/fj/data/fingertrees/Node2.java | 2 +- .../main/java/fj/data/fingertrees/Node3.java | 2 +- .../main/java/fj/data/fingertrees/Single.java | 6 +- core/src/main/java/fj/data/hlist/HList.java | 10 +- core/src/main/java/fj/data/optic/Fold.java | 2 +- .../src/main/java/fj/data/optic/Optional.java | 4 +- .../main/java/fj/data/optic/POptional.java | 2 +- core/src/main/java/fj/data/optic/Prism.java | 2 +- core/src/main/java/fj/data/vector/V2.java | 2 +- core/src/main/java/fj/data/vector/V3.java | 8 +- core/src/main/java/fj/data/vector/V4.java | 34 +- core/src/main/java/fj/data/vector/V5.java | 42 +-- core/src/main/java/fj/data/vector/V6.java | 50 +-- core/src/main/java/fj/data/vector/V7.java | 58 ++-- core/src/main/java/fj/data/vector/V8.java | 54 ++-- core/src/main/java/fj/function/Visitor.java | 6 +- core/src/main/java/fj/parser/Parser.java | 26 +- core/src/main/java/fj/parser/Result.java | 2 +- demo/src/main/java/fj/demo/ChequeWrite.java | 10 +- .../main/java/fj/demo/Comonad_example.java | 4 +- demo/src/main/java/fj/demo/Option_bind.java | 6 +- .../fj/demo/StateDemo_VendingMachine.java | 2 +- .../main/java/fj/demo/concurrent/Fibs.java | 2 +- .../java/fj/demo/concurrent/MapReduce.java | 2 +- .../java/fj/demo/concurrent/WordCount.java | 20 +- .../java/fj/demo/test/JavaLinkedList.java | 2 +- .../java/fj/demo/test/ListFunctorLaws.java | 2 +- .../fj/demo/test/OptionMonadFunctorLaw.java | 2 +- .../src/main/java/fj/test/Arbitrary.java | 130 ++++---- quickcheck/src/main/java/fj/test/Arg.java | 2 +- .../src/main/java/fj/test/CheckResult.java | 10 +- .../src/main/java/fj/test/Coarbitrary.java | 22 +- quickcheck/src/main/java/fj/test/Gen.java | 24 +- .../src/main/java/fj/test/Property.java | 14 +- quickcheck/src/main/java/fj/test/Rand.java | 4 +- quickcheck/src/main/java/fj/test/Result.java | 8 +- quickcheck/src/main/java/fj/test/Shrink.java | 56 ++-- quickcheck/src/main/java/fj/test/Variant.java | 2 +- .../src/main/java/fj/test/reflect/Check.java | 4 +- 99 files changed, 1074 insertions(+), 1075 deletions(-) diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index d34aedb7..56222de1 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -101,7 +101,7 @@ public static Tree typeParameterTree(final Type t) { } types = Tree.node(pt.getRawType(), typeArgs); } else { - types = Tree.node(t, List.>nil()); + types = Tree.node(t, List.nil()); } return types; } @@ -122,6 +122,6 @@ public java.lang.Class clas() { * @return A class from the given argument. */ public static Class clas(final java.lang.Class c) { - return new Class(c); + return new Class<>(c); } } diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index f503d096..2282b04e 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -75,7 +75,7 @@ public F eq(final A a) { * @return A new equal. */ public Equal contramap(final F f) { - return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); + return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } /** @@ -85,7 +85,7 @@ public Equal contramap(final F f) { * @return An equal instance from the given function. */ public static Equal equal(final F> f) { - return new Equal(f); + return new Equal<>(f); } /** @@ -202,7 +202,7 @@ public static Equal> eitherEqual(final Equal ea, final Eq * @return An equal instance for the {@link Validation} type. */ public static Equal> validationEqual(final Equal ea, final Equal eb) { - return eitherEqual(ea, eb).contramap(Validation.either()); + return eitherEqual(ea, eb).contramap(Validation.either()); } /** @@ -235,7 +235,7 @@ public static Equal> listEqual(final Equal ea) { * @return An equal instance for the {@link NonEmptyList} type. */ public static Equal> nonEmptyListEqual(final Equal ea) { - return listEqual(ea).contramap(NonEmptyList.toList_()); + return listEqual(ea).contramap(NonEmptyList.toList_()); } /** @@ -302,7 +302,7 @@ public static Equal> arrayEqual(final Equal ea) { * @return An equal instance for the {@link Tree} type. */ public static Equal> treeEqual(final Equal ea) { - return Equal.>equal(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(Equal.treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); + return Equal.equal(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(Equal.treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); } /** @@ -443,7 +443,7 @@ public static Equal> p5Equal(final Equal ea * @return An equal instance for a vector-2. */ public static Equal> v2Equal(final Equal ea) { - return streamEqual(ea).contramap(V2.toStream_()); + return streamEqual(ea).contramap(V2.toStream_()); } /** @@ -453,7 +453,7 @@ public static Equal> v2Equal(final Equal ea) { * @return An equal instance for a vector-3. */ public static Equal> v3Equal(final Equal ea) { - return streamEqual(ea).contramap(V3.toStream_()); + return streamEqual(ea).contramap(V3.toStream_()); } /** @@ -463,7 +463,7 @@ public static Equal> v3Equal(final Equal ea) { * @return An equal instance for a vector-4. */ public static Equal> v4Equal(final Equal ea) { - return streamEqual(ea).contramap(V4.toStream_()); + return streamEqual(ea).contramap(V4.toStream_()); } /** @@ -473,7 +473,7 @@ public static Equal> v4Equal(final Equal ea) { * @return An equal instance for a vector-5. */ public static Equal> v5Equal(final Equal ea) { - return streamEqual(ea).contramap(V5.toStream_()); + return streamEqual(ea).contramap(V5.toStream_()); } /** @@ -483,7 +483,7 @@ public static Equal> v5Equal(final Equal ea) { * @return An equal instance for a vector-6. */ public static Equal> v6Equal(final Equal ea) { - return streamEqual(ea).contramap(V6.toStream_()); + return streamEqual(ea).contramap(V6.toStream_()); } /** @@ -493,7 +493,7 @@ public static Equal> v6Equal(final Equal ea) { * @return An equal instance for a vector-7. */ public static Equal> v7Equal(final Equal ea) { - return streamEqual(ea).contramap(V7.toStream_()); + return streamEqual(ea).contramap(V7.toStream_()); } /** @@ -503,7 +503,7 @@ public static Equal> v7Equal(final Equal ea) { * @return An equal instance for a vector-8. */ public static Equal> v8Equal(final Equal ea) { - return streamEqual(ea).contramap(V8.toStream_()); + return streamEqual(ea).contramap(V8.toStream_()); } /** diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 3faf1b5e..7b97675a 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -261,7 +261,7 @@ public static F, Promise> mapPromise(final F f) { */ @SuppressWarnings("unchecked") public static F> eitherLeftK(final F f) { - return o(Either.left_(), f); + return o(Either.left_(), f); } /** @@ -272,7 +272,7 @@ public static F> eitherLeftK(final F f) { */ @SuppressWarnings("unchecked") public static F> eitherRightK(final F f) { - return o(Either.right_(), f); + return o(Either.right_(), f); } /** @@ -330,7 +330,7 @@ public static F> iterableK(final F f) { */ @SuppressWarnings("unchecked") public static F, IterableW> mapIterable(final F f) { - return o(IterableW.map().f(f), IterableW.>wrap()); + return o(IterableW.map().f(f), IterableW.wrap()); } /** @@ -340,7 +340,7 @@ public static F, IterableW> mapIterable(final F f) { */ @SuppressWarnings("unchecked") public static F> nelK(final F f) { - return o(NonEmptyList.nel(), f); + return o(NonEmptyList.nel(), f); } /** @@ -408,7 +408,7 @@ public static F, B> foldMapTree(final F f, final Monoid * @return This function promoted to return its value in a TreeZipper. */ public static F> treeZipperK(final F f) { - return andThen(treeK(f), TreeZipper.fromTree()); + return andThen(treeK(f), TreeZipper.fromTree()); } /** @@ -560,7 +560,7 @@ public static F, P2> mapBoth(final F f) { * @return A new SynchronousQueue with this function applied to each element. */ public static SynchronousQueue mapJ(final F f, final SynchronousQueue as) { - final SynchronousQueue bs = new SynchronousQueue(); + final SynchronousQueue bs = new SynchronousQueue<>(); bs.addAll(iterableStream(as).map(f).toCollection()); return bs; } @@ -573,7 +573,7 @@ public static SynchronousQueue mapJ(final F f, final Synchronous * @return A new PriorityBlockingQueue with this function applied to each element. */ public static PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { - return new PriorityBlockingQueue(iterableStream(as).map(f).toCollection()); + return new PriorityBlockingQueue<>(iterableStream(as).map(f).toCollection()); } /** @@ -583,7 +583,7 @@ public static PriorityBlockingQueue mapJ(final F f, final Priori * @return A new LinkedBlockingQueue with this function applied to each element. */ public static LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { - return new LinkedBlockingQueue(iterableStream(as).map(f).toCollection()); + return new LinkedBlockingQueue<>(iterableStream(as).map(f).toCollection()); } /** @@ -593,7 +593,7 @@ public static LinkedBlockingQueue mapJ(final F f, final LinkedBl * @return A new CopyOnWriteArraySet with this function applied to each element. */ public static CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { - return new CopyOnWriteArraySet(iterableStream(as).map(f).toCollection()); + return new CopyOnWriteArraySet<>(iterableStream(as).map(f).toCollection()); } /** @@ -603,7 +603,7 @@ public static CopyOnWriteArraySet mapJ(final F f, final CopyOnWr * @return A new CopyOnWriteArrayList with this function applied to each element. */ public static CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { - return new CopyOnWriteArrayList(iterableStream(as).map(f).toCollection()); + return new CopyOnWriteArrayList<>(iterableStream(as).map(f).toCollection()); } /** @@ -613,7 +613,7 @@ public static CopyOnWriteArrayList mapJ(final F f, final CopyOnW * @return A new ConcurrentLinkedQueue with this function applied to each element. */ public static ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { - return new ConcurrentLinkedQueue(iterableStream(as).map(f).toCollection()); + return new ConcurrentLinkedQueue<>(iterableStream(as).map(f).toCollection()); } /** @@ -623,7 +623,7 @@ public static ConcurrentLinkedQueue mapJ(final F f, final Concur * @return A new ArrayBlockingQueue with this function applied to each element. */ public static ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { - final ArrayBlockingQueue bs = new ArrayBlockingQueue(as.size()); + final ArrayBlockingQueue bs = new ArrayBlockingQueue<>(as.size()); bs.addAll(iterableStream(as).map(f).toCollection()); return bs; } @@ -636,7 +636,7 @@ public static ArrayBlockingQueue mapJ(final F f, final ArrayBloc * @return A new TreeSet with this function applied to each element. */ public static TreeSet mapJ(final F f, final TreeSet as) { - return new TreeSet(iterableStream(as).map(f).toCollection()); + return new TreeSet<>(iterableStream(as).map(f).toCollection()); } /** @@ -646,7 +646,7 @@ public static TreeSet mapJ(final F f, final TreeSet as) { * @return A new PriorityQueue with this function applied to each element. */ public static PriorityQueue mapJ(final F f, final PriorityQueue as) { - return new PriorityQueue(iterableStream(as).map(f).toCollection()); + return new PriorityQueue<>(iterableStream(as).map(f).toCollection()); } /** @@ -656,7 +656,7 @@ public static PriorityQueue mapJ(final F f, final PriorityQueue< * @return A new LinkedList with this function applied to each element. */ public static LinkedList mapJ(final F f, final LinkedList as) { - return new LinkedList(iterableStream(as).map(f).toCollection()); + return new LinkedList<>(iterableStream(as).map(f).toCollection()); } /** @@ -666,7 +666,7 @@ public static LinkedList mapJ(final F f, final LinkedList as) * @return A new ArrayList with this function applied to each element. */ public static ArrayList mapJ(final F f, final ArrayList as) { - return new ArrayList(iterableStream(as).map(f).toCollection()); + return new ArrayList<>(iterableStream(as).map(f).toCollection()); } public static F map(F target, F f) { diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java index 7fe50e35..19a978dc 100644 --- a/core/src/main/java/fj/F1W.java +++ b/core/src/main/java/fj/F1W.java @@ -682,6 +682,6 @@ public B f(A a) { * Lifts the function into the fully featured function wrapper */ public static F1W lift(final F f) { - return new F1WFunc(f); + return new F1WFunc<>(f); } } diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 8d832798..87888fad 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -168,7 +168,7 @@ public static F, F2> flip2() { * not apply the value, instead returning an empty optional value. */ public static F> nullable(final F f) { - return a -> a == null ? Option.none() : Option.some(f.f(a)); + return a -> a == null ? Option.none() : Option.some(f.f(a)); } /** @@ -761,7 +761,7 @@ public static F, F, F>> lift(final Ff. */ public static F join(final F> f) { - return bind(f, Function.>identity()); + return bind(f, Function.identity()); } diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index acb2a62c..3e6c0ae8 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -165,7 +165,7 @@ public static Hash> eitherHash(final Hash ha, final Hash< * @return A hash instance for the {@link Validation} type. */ public static Hash> validationHash(final Hash ha, final Hash hb) { - return eitherHash(ha, hb).contramap(Validation.either()); + return eitherHash(ha, hb).contramap(Validation.either()); } /** @@ -196,7 +196,7 @@ public static Hash> listHash(final Hash ha) { * @return A hash instance for the {@link NonEmptyList} type. */ public static Hash> nonEmptyListHash(final Hash ha) { - return listHash(ha).contramap(NonEmptyList.toList_()); + return listHash(ha).contramap(NonEmptyList.toList_()); } /** @@ -264,7 +264,7 @@ public static Hash> arrayHash(final Hash ha) { * @return A hash instance for the {@link Tree} type. */ public static Hash> treeHash(final Hash ha) { - return streamHash(ha).contramap(Tree.flatten_()); + return streamHash(ha).contramap(Tree.flatten_()); } public static Hash> treeMapHash(final Hash h, final Hash v) { @@ -278,7 +278,7 @@ public static Hash> treeMapHash(final Hash h, final Hash * @return A hash instance for a product-1. */ public static Hash> p1Hash(final Hash ha) { - return ha.contramap(P1.__1()); + return ha.contramap(P1.__1()); } /** @@ -473,7 +473,7 @@ public static Hash> p5Hash(final Hash ha, f * @return A hash instance for a vector-2. */ public static Hash> v2Hash(final Hash ea) { - return streamHash(ea).contramap(V2.toStream_()); + return streamHash(ea).contramap(V2.toStream_()); } /** @@ -483,7 +483,7 @@ public static Hash> v2Hash(final Hash ea) { * @return A hash instance for a vector-3. */ public static Hash> v3Hash(final Hash ea) { - return streamHash(ea).contramap(V3.toStream_()); + return streamHash(ea).contramap(V3.toStream_()); } /** @@ -493,7 +493,7 @@ public static Hash> v3Hash(final Hash ea) { * @return A hash instance for a vector-4. */ public static Hash> v4Hash(final Hash ea) { - return streamHash(ea).contramap(V4.toStream_()); + return streamHash(ea).contramap(V4.toStream_()); } /** @@ -503,7 +503,7 @@ public static Hash> v4Hash(final Hash ea) { * @return A hash instance for a vector-5. */ public static Hash> v5Hash(final Hash ea) { - return streamHash(ea).contramap(V5.toStream_()); + return streamHash(ea).contramap(V5.toStream_()); } /** @@ -513,7 +513,7 @@ public static Hash> v5Hash(final Hash ea) { * @return A hash instance for a vector-6. */ public static Hash> v6Hash(final Hash ea) { - return streamHash(ea).contramap(V6.toStream_()); + return streamHash(ea).contramap(V6.toStream_()); } /** @@ -523,7 +523,7 @@ public static Hash> v6Hash(final Hash ea) { * @return A hash instance for a vector-7. */ public static Hash> v7Hash(final Hash ea) { - return streamHash(ea).contramap(V7.toStream_()); + return streamHash(ea).contramap(V7.toStream_()); } /** @@ -533,6 +533,6 @@ public static Hash> v7Hash(final Hash ea) { * @return A hash instance for a vector-8. */ public static Hash> v8Hash(final Hash ea) { - return streamHash(ea).contramap(V8.toStream_()); + return streamHash(ea).contramap(V8.toStream_()); } } diff --git a/core/src/main/java/fj/LcgRng.java b/core/src/main/java/fj/LcgRng.java index d2c244b6..50ee9e03 100644 --- a/core/src/main/java/fj/LcgRng.java +++ b/core/src/main/java/fj/LcgRng.java @@ -40,7 +40,7 @@ public P2 nextLong() { */ static P2 nextLong(long seed) { long newSeed = (seed * 0x5DEECE66DL + 0xBL) & 0xFFFFFFFFFFFFL; - long n = (Long) (newSeed >>> 16); + long n = newSeed >>> 16; return P.p(newSeed, n); } diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index be5215bb..af6d95f9 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -200,7 +200,7 @@ public A join(final Iterable as, final A a) { * @return A monoid instance that uses the given sun function and zero value. */ public static Monoid monoid(final F> sum, final A zero) { - return new Monoid(sum, zero); + return new Monoid<>(sum, zero); } /** @@ -212,7 +212,7 @@ public static Monoid monoid(final F> sum, final A zero) { * @return A monoid instance that uses the given sun function and zero value. */ public static Monoid monoid(final F2 sum, final A zero) { - return new Monoid(curry(sum), zero); + return new Monoid<>(curry(sum), zero); } /** @@ -223,7 +223,7 @@ public static Monoid monoid(final F2 sum, final A zero) { * @return A monoid instance that uses the given sun function and zero value. */ public static Monoid monoid(final Semigroup s, final A zero) { - return new Monoid(s.sum(), zero); + return new Monoid<>(s.sum(), zero); } /** @@ -328,7 +328,7 @@ public static Monoid monoid(final Semigroup s, final A zero) { * @return A monoid for functions. */ public static Monoid> functionMonoid(final Monoid mb) { - return monoid(Semigroup.functionSemigroup(mb.semigroup()), Function.constant(mb.zero)); + return monoid(Semigroup.functionSemigroup(mb.semigroup()), Function.constant(mb.zero)); } /** @@ -337,7 +337,7 @@ public static Monoid> functionMonoid(final Monoid mb) { * @return A monoid for lists. */ public static Monoid> listMonoid() { - return monoid(Semigroup.listSemigroup(), List.nil()); + return monoid(Semigroup.listSemigroup(), List.nil()); } /** @@ -346,7 +346,7 @@ public static Monoid> listMonoid() { * @return A monoid for options. */ public static Monoid> optionMonoid() { - return monoid(Semigroup.optionSemigroup(), Option.none()); + return monoid(Semigroup.optionSemigroup(), Option.none()); } /** @@ -355,7 +355,7 @@ public static Monoid> optionMonoid() { * @return A monoid for options that take the first available value. */ public static Monoid> firstOptionMonoid() { - return monoid(Semigroup.firstOptionSemigroup(), Option.none()); + return monoid(Semigroup.firstOptionSemigroup(), Option.none()); } /** @@ -364,7 +364,7 @@ public static Monoid> firstOptionMonoid() { * @return A monoid for options that take the last available value. */ public static Monoid> lastOptionMonoid() { - return monoid(Semigroup.lastOptionSemigroup(), Option.none()); + return monoid(Semigroup.lastOptionSemigroup(), Option.none()); } /** @@ -373,7 +373,7 @@ public static Monoid> lastOptionMonoid() { * @return A monoid for streams. */ public static Monoid> streamMonoid() { - return monoid(Semigroup.streamSemigroup(), Stream.nil()); + return monoid(Semigroup.streamSemigroup(), Stream.nil()); } /** @@ -383,7 +383,7 @@ public static Monoid> streamMonoid() { */ @SuppressWarnings("unchecked") public static Monoid> arrayMonoid() { - return monoid(Semigroup.arraySemigroup(), Array.empty()); + return monoid(Semigroup.arraySemigroup(), Array.empty()); } /** @@ -405,7 +405,7 @@ public static Monoid> ioMonoid(final Monoid ma) { * @return A monoid for sets whose elements have the given order. */ public static Monoid> setMonoid(final Ord o) { - return monoid(Semigroup.setSemigroup(), Set.empty(o)); + return monoid(Semigroup.setSemigroup(), Set.empty(o)); } } diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 57d7e389..471c110f 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -75,7 +75,7 @@ public Equal equal() { * @return A new ord. */ public Ord contramap(final F f) { - return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); + return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); } /** @@ -166,7 +166,7 @@ public A min(final A a1, final A a2) { * @return An order instance. */ public static Ord ord(final F> f) { - return new Ord(f); + return new Ord<>(f); } /** @@ -262,7 +262,7 @@ public static Ord ord(final F> f) { /** * An order instance for the {@link Ordering} type. */ - public static final Ord orderingOrd = Ord.ord(curry((o1, o2) -> o1 == o2 ? + public static final Ord orderingOrd = Ord.ord(curry((o1, o2) -> o1 == o2 ? Ordering.EQ : o1 == Ordering.LT ? Ordering.LT : @@ -334,7 +334,7 @@ public static Ord> eitherOrd(final Ord oa, final Ord o * @return An order instance for the {@link Validation} type. */ public static Ord> validationOrd(final Ord oa, final Ord ob) { - return eitherOrd(oa, ob).contramap(Validation.either()); + return eitherOrd(oa, ob).contramap(Validation.either()); } /** @@ -374,7 +374,7 @@ public static Ord> listOrd(final Ord oa) { * @return An order instance for the {@link NonEmptyList} type. */ public static Ord> nonEmptyListOrd(final Ord oa) { - return listOrd(oa).contramap(NonEmptyList.toList_()); + return listOrd(oa).contramap(NonEmptyList.toList_()); } /** @@ -443,7 +443,7 @@ public static Ord> setOrd(final Ord oa) { * @return An order instance for a product-1. */ public static Ord> p1Ord(final Ord oa) { - return oa.contramap(P1.__1()); + return oa.contramap(P1.__1()); } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 796daf22..5a1d9b8a 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -114,7 +114,7 @@ public P1 bind(final P1 cb, final F2 f) { * @return A new P1 that is the join of the given P1. */ public static P1 join(final P1> a) { - return a.bind(Function.>identity()); + return a.bind(Function.identity()); } /** @@ -138,7 +138,7 @@ public P1 liftM2(P1 pb, F2 f) { * @return A single P1 for the given List. */ public static P1> sequence(final List> as) { - return as.foldRight(liftM2(List.cons()), P.p(List.nil())); + return as.foldRight(liftM2(List.cons()), P.p(List.nil())); } /** @@ -157,7 +157,7 @@ public static F>, P1>> sequenceList() { * @return A single P1 for the given stream. */ public static P1> sequence(final Stream> as) { - return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); + return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); } /** @@ -174,7 +174,7 @@ public static P1> sequence(final Option> o) { * @return A single P1 for the given array. */ public static P1> sequence(final Array> as) { - return P.lazy(() -> as.map(P1.__1())); + return P.lazy(() -> as.map(P1.__1())); } /** @@ -341,7 +341,7 @@ public String toString() { @Override public boolean equals(Object other) { - return Equal.equals0(P1.class, this, other, () -> Equal.p1Equal(Equal.anyEqual())); + return Equal.equals0(P1.class, this, other, () -> Equal.p1Equal(Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index d564df35..be3be69b 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -28,7 +28,7 @@ public abstract class P2 { @Override public boolean equals(Object other) { - return Equal.equals0(P2.class, this, other, () -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(P2.class, this, other, () -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual())); } @Override @@ -155,7 +155,7 @@ public final Either> traverseEither(final F> */ public final Stream sequenceW(final Stream, C>> fs) { return fs.isEmpty() - ? Stream.nil() + ? Stream.nil() : Stream.cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 8760562b..c6bc38a9 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -181,7 +181,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P3.class, this, other, - () -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 7f71943e..6181b75e 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -250,7 +250,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P4.class, this, other, - () -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 57199302..2fd74ebe 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -325,7 +325,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P5.class, this, other, - () -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index d1f32b87..5c679a2c 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -355,7 +355,7 @@ public F _6() { * @return A function that returns the first element of a product. */ public static fj.F, A> __1() { - return P6::_1; + return P6::_1; } /** @@ -364,7 +364,7 @@ public F _6() { * @return A function that returns the second element of a product. */ public static fj.F, B> __2() { - return P6::_2; + return P6::_2; } /** @@ -373,7 +373,7 @@ public F _6() { * @return A function that returns the third element of a product. */ public static fj.F, C> __3() { - return P6::_3; + return P6::_3; } /** @@ -382,7 +382,7 @@ public F _6() { * @return A function that returns the fourth element of a product. */ public static fj.F, D> __4() { - return P6::_4; + return P6::_4; } /** @@ -391,7 +391,7 @@ public F _6() { * @return A function that returns the fifth element of a product. */ public static fj.F, E> __5() { - return P6::_5; + return P6::_5; } /** @@ -400,7 +400,7 @@ public F _6() { * @return A function that returns the sixth element of a product. */ public static fj.F, F$> __6() { - return P6::_6; + return P6::_6; } @Override @@ -412,7 +412,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P6.class, this, other, - () -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index e81a2480..eb0cb913 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -437,7 +437,7 @@ public G _7() { * @return A function that returns the first element of a product. */ public static fj.F, A> __1() { - return P7::_1; + return P7::_1; } /** @@ -446,7 +446,7 @@ public G _7() { * @return A function that returns the second element of a product. */ public static fj.F, B> __2() { - return P7::_2; + return P7::_2; } /** @@ -455,7 +455,7 @@ public G _7() { * @return A function that returns the third element of a product. */ public static fj.F, C> __3() { - return P7::_3; + return P7::_3; } /** @@ -464,7 +464,7 @@ public G _7() { * @return A function that returns the fourth element of a product. */ public static fj.F, D> __4() { - return P7::_4; + return P7::_4; } /** @@ -473,7 +473,7 @@ public G _7() { * @return A function that returns the fifth element of a product. */ public static fj.F, E> __5() { - return P7::_5; + return P7::_5; } /** @@ -482,7 +482,7 @@ public G _7() { * @return A function that returns the sixth element of a product. */ public static fj.F, F$> __6() { - return P7::_6; + return P7::_6; } /** @@ -491,7 +491,7 @@ public G _7() { * @return A function that returns the seventh element of a product. */ public static fj.F, G> __7() { - return P7::_7; + return P7::_7; } @Override @@ -502,7 +502,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P7.class, this, other, - () -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index 982dca58..de13749b 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -530,7 +530,7 @@ public H _8() { * @return A function that returns the first element of a product. */ public static fj.F, A> __1() { - return P8::_1; + return P8::_1; } /** @@ -539,7 +539,7 @@ public H _8() { * @return A function that returns the second element of a product. */ public static fj.F, B> __2() { - return P8::_2; + return P8::_2; } /** @@ -548,7 +548,7 @@ public H _8() { * @return A function that returns the third element of a product. */ public static fj.F, C> __3() { - return P8::_3; + return P8::_3; } /** @@ -557,7 +557,7 @@ public H _8() { * @return A function that returns the fourth element of a product. */ public static fj.F, D> __4() { - return P8::_4; + return P8::_4; } /** @@ -566,7 +566,7 @@ public H _8() { * @return A function that returns the fifth element of a product. */ public static fj.F, E> __5() { - return P8::_5; + return P8::_5; } /** @@ -575,7 +575,7 @@ public H _8() { * @return A function that returns the sixth element of a product. */ public static fj.F, F$> __6() { - return P8::_6; + return P8::_6; } /** @@ -584,7 +584,7 @@ public H _8() { * @return A function that returns the seventh element of a product. */ public static fj.F, G> __7() { - return P8::_7; + return P8::_7; } /** @@ -593,7 +593,7 @@ public H _8() { * @return A function that returns the eighth element of a product. */ public static fj.F, H> __8() { - return P8::_8; + return P8::_8; } @Override @@ -604,7 +604,7 @@ public String toString() { @Override public boolean equals(Object other) { return Equal.equals0(P8.class, this, other, - () -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + () -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index e7cd4c35..057596f5 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -103,7 +103,7 @@ static A multiply1p(F> sum, int n, A a) { * @return A semigroup from the given function. */ public static Semigroup semigroup(final F> sum) { - return new Semigroup(sum); + return new Semigroup<>(sum); } /** @@ -113,7 +113,7 @@ public static Semigroup semigroup(final F> sum) { * @return A semigroup from the given function. */ public static Semigroup semigroup(final F2 sum) { - return new Semigroup(curry(sum)); + return new Semigroup<>(curry(sum)); } /** diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 5e6fd8b0..4d599693 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -282,7 +282,7 @@ public static Show> listShow(final Show sa) { * @return A show instance for the {@link NonEmptyList} type. */ public static Show> nonEmptyListShow(final Show sa) { - return listShow(sa).contramap(NonEmptyList.toList_()); + return listShow(sa).contramap(NonEmptyList.toList_()); } /** @@ -557,7 +557,7 @@ public static Show> p5Show(final Show sa, f * @return A show instance for a vector-2. */ public static Show> v2Show(final Show ea) { - return streamShow(ea, "V2(", ",", ")").contramap(V2.toStream_()); + return streamShow(ea, "V2(", ",", ")").contramap(V2.toStream_()); } /** @@ -567,7 +567,7 @@ public static Show> v2Show(final Show ea) { * @return A show instance for a vector-3. */ public static Show> v3Show(final Show ea) { - return streamShow(ea, "V3(", ",", ")").contramap(V3.toStream_()); + return streamShow(ea, "V3(", ",", ")").contramap(V3.toStream_()); } /** @@ -577,7 +577,7 @@ public static Show> v3Show(final Show ea) { * @return A show instance for a vector-4. */ public static Show> v4Show(final Show ea) { - return streamShow(ea, "V4(", ",", ")").contramap(V4.toStream_()); + return streamShow(ea, "V4(", ",", ")").contramap(V4.toStream_()); } /** @@ -587,7 +587,7 @@ public static Show> v4Show(final Show ea) { * @return A show instance for a vector-5. */ public static Show> v5Show(final Show ea) { - return streamShow(ea, "V5(", ",", ")").contramap(V5.toStream_()); + return streamShow(ea, "V5(", ",", ")").contramap(V5.toStream_()); } /** @@ -597,7 +597,7 @@ public static Show> v5Show(final Show ea) { * @return A show instance for a vector-6. */ public static Show> v6Show(final Show ea) { - return streamShow(ea, "V6(", ",", ")").contramap(V6.toStream_()); + return streamShow(ea, "V6(", ",", ")").contramap(V6.toStream_()); } /** @@ -607,7 +607,7 @@ public static Show> v6Show(final Show ea) { * @return A show instance for a vector-7. */ public static Show> v7Show(final Show ea) { - return streamShow(ea, "V7(", ",", ")").contramap(V7.toStream_()); + return streamShow(ea, "V7(", ",", ")").contramap(V7.toStream_()); } /** @@ -617,7 +617,7 @@ public static Show> v7Show(final Show ea) { * @return A show instance for a vector-8. */ public static Show> v8Show(final Show ea) { - return streamShow(ea, "V8(", ",", ")").contramap(V8.toStream_()); + return streamShow(ea, "V8(", ",", ")").contramap(V8.toStream_()); } /** @@ -643,7 +643,7 @@ public static Show> unlineShow(final Show sa) { /** * A show instance for the empty heterogeneous Stream. */ - public static final Show HListShow = showS(Function.constant("Nil")); + public static final Show HListShow = showS(Function.constant("Nil")); /** * A show instance for heterogeneous Streams. diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index a41c7a03..fa07df3c 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -108,7 +108,7 @@ public Either>, A> resume() { @SuppressWarnings("unchecked") protected static Codense codense(final Normal a, final F> k) { - return new Codense((Normal) a, (F>) k); + return new Codense<>((Normal) a, (F>) k); } /** @@ -125,7 +125,7 @@ public static F> pure() { * @return A trampoline that results in the given value. */ public static Trampoline pure(final A a) { - return new Pure(a); + return new Pure<>(a); } /** @@ -135,7 +135,7 @@ public static Trampoline pure(final A a) { * @return A trampoline whose next step runs the given thunk. */ public static Trampoline suspend(final P1> a) { - return new Suspend(a); + return new Suspend<>(a); } /** @@ -162,7 +162,7 @@ public static F>, Trampoline> suspend_() { * @return A new trampoline that runs this trampoline, then applies the given function to the result. */ public final Trampoline map(final F f) { - return bind(F1Functions.o(Trampoline.pure(), f)); + return bind(F1Functions.o(Trampoline.pure(), f)); } /** @@ -257,7 +257,7 @@ public Trampoline zipWith(final Trampoline b, final F2 f) final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.>lazy(() -> ta.zipWith(tb, f)))))); + return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.lazy(() -> ta.zipWith(tb, f)))))); } for (final B y : eb.right()) { return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); diff --git a/core/src/main/java/fj/control/db/DB.java b/core/src/main/java/fj/control/db/DB.java index 8e8590b6..a7ba6a7f 100644 --- a/core/src/main/java/fj/control/db/DB.java +++ b/core/src/main/java/fj/control/db/DB.java @@ -103,6 +103,6 @@ public B run(final Connection c) throws SQLException { * @return A new database action equivalent to the result of the given action. */ public static DB join(final DB> a) { - return a.bind(Function.>identity()); + return a.bind(Function.identity()); } } diff --git a/core/src/main/java/fj/control/parallel/Actor.java b/core/src/main/java/fj/control/parallel/Actor.java index bd1956bd..c5985c7c 100644 --- a/core/src/main/java/fj/control/parallel/Actor.java +++ b/core/src/main/java/fj/control/parallel/Actor.java @@ -33,13 +33,13 @@ public final class Actor { * as they are sent. */ public static Actor queueActor(final Strategy s, final Effect1 ea) { - return actor(Strategy.seqStrategy(), new Effect1() { + return actor(Strategy.seqStrategy(), new Effect1() { // Lock to ensure the actor only acts on one message at a time final AtomicBoolean suspended = new AtomicBoolean(true); // Queue to hold pending messages - final ConcurrentLinkedQueue mbox = new ConcurrentLinkedQueue(); + final ConcurrentLinkedQueue mbox = new ConcurrentLinkedQueue<>(); // Product so the actor can use its strategy (to act on messages in other threads, // to handle exceptions, etc.) @@ -90,7 +90,7 @@ private Actor(final Strategy s, final F> e) { * @return A new actor that uses the given parallelization strategy and has the given side-effect. */ public static Actor actor(final Strategy s, final Effect1 e) { - return new Actor(s, P1.curry(Effect.f(e))); + return new Actor<>(s, P1.curry(Effect.f(e))); } /** @@ -101,7 +101,7 @@ public static Actor actor(final Strategy s, final Effect1 e) { * @return A new actor that uses the given parallelization strategy and has the given side-effect. */ public static Actor actor(final Strategy s, final F> e) { - return new Actor(s, e); + return new Actor<>(s, e); } /** diff --git a/core/src/main/java/fj/control/parallel/Callables.java b/core/src/main/java/fj/control/parallel/Callables.java index 7c2a7221..995780c4 100644 --- a/core/src/main/java/fj/control/parallel/Callables.java +++ b/core/src/main/java/fj/control/parallel/Callables.java @@ -126,7 +126,7 @@ public static Callable bind(final Callable ca, final Callable * @return A new Callable that is the join of the given Callable. */ public static Callable join(final Callable> a) { - return bind(a, Function.>identity()); + return bind(a, Function.identity()); } /** @@ -146,8 +146,7 @@ public static F, F, Callable>> liftM2(final * @return A single callable for the given List. */ public static Callable> sequence(final List> as) { - return as.foldRight(Callables., - List>liftM2(List.cons()), callable(List.nil())); + return as.foldRight(Callables.liftM2(List.cons()), callable(List.nil())); } /** diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 7e0fdb59..514988aa 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -261,7 +261,7 @@ public F, F, Promise>>> parMapList() { * @return A Promise of a new NonEmptyList with the given function applied to each element. */ public Promise> parMap(final NonEmptyList as, final F f) { - return mapM(as.toList(), promise(f)).fmap((F, NonEmptyList>) list -> NonEmptyList.fromList(list).some()); + return mapM(as.toList(), promise(f)).fmap(list -> NonEmptyList.fromList(list).some()); } /** @@ -293,7 +293,7 @@ public F, F, Promise>>> parMapStream() { */ public Promise> parMap(final Iterable as, final F f) { return parMap(iterableStream(as), f) - .fmap(Function., Iterable>vary(Function.>identity())); + .fmap(Function.vary(Function.identity())); } /** @@ -334,7 +334,7 @@ public F, F, Promise>>> parMapArray() { */ public Promise> parMap(final Zipper za, final F f) { return parMap(za.rights(), f) - .apply(promise(f).f(za.focus()).apply(parMap(za.lefts(), f).fmap(curry(Zipper.zipper())))); + .apply(promise(f).f(za.focus()).apply(parMap(za.lefts(), f).fmap(curry(Zipper.zipper())))); } /** @@ -346,7 +346,7 @@ public Promise> parMap(final Zipper za, final F f) { */ public Promise> parMap(final Tree ta, final F f) { return mapM(ta.subForest(), this., Tree>mapStream().f(this.parMapTree().f(f))) - .apply(promise(f).f(ta.root()).fmap(Tree.node())); + .apply(promise(f).f(ta.root()).fmap(Tree.node())); } /** @@ -370,8 +370,8 @@ public Promise> parMap(final TreeZipper za, final F, Stream>, Stream>, Stream>, A, Stream>>>> p = za.p(); return mapM(p._4(), p3 -> parMap(p3._3(), tf).apply(promise(f).f(p3._2()).apply( - parMap(p3._1(), tf).fmap(P.>, B, Stream>>p3())))).apply(parMap(za.rights(), tf).apply( - parMap(za.lefts(), tf).apply(parMap(p._1(), f).fmap(TreeZipper.treeZipper())))); + parMap(p3._1(), tf).fmap(P.p3())))).apply(parMap(za.rights(), tf).apply( + parMap(za.lefts(), tf).apply(parMap(p._1(), f).fmap(TreeZipper.treeZipper())))); } /** @@ -382,7 +382,7 @@ public Promise> parMap(final TreeZipper za, final F Promise> parFlatMap(final List as, final F> f) { - return parFoldMap(as, f, Monoid.listMonoid()); + return parFoldMap(as, f, Monoid.listMonoid()); } /** @@ -393,7 +393,7 @@ public Promise> parFlatMap(final List as, final F> * @return A promise of a new Stream with the given function bound across its elements. */ public Promise> parFlatMap(final Stream as, final F> f) { - return parFoldMap(as, f, Monoid.streamMonoid()); + return parFoldMap(as, f, Monoid.streamMonoid()); } /** @@ -404,7 +404,7 @@ public Promise> parFlatMap(final Stream as, final F Promise> parFlatMap(final Array as, final F> f) { - return parMap(as, f).fmap(Array.join()); + return parMap(as, f).fmap(Array.join()); } /** @@ -415,8 +415,8 @@ public Promise> parFlatMap(final Array as, final F Promise> parFlatMap(final Iterable as, final F> f) { - return parMap(as, f).fmap(IterableW.>join()) - .fmap(Function., Iterable>vary(Function.>identity())); + return parMap(as, f).fmap(IterableW.join()) + .fmap(Function.vary(Function.>identity())); } /** @@ -428,7 +428,7 @@ public Promise> parFlatMap(final Iterable as, final F Promise> parZipWith(final List as, final List bs, final F> f) { - return sequence(as.>zipWith(bs, promise(uncurryF2(f)))); + return sequence(as.zipWith(bs, promise(uncurryF2(f)))); } /** @@ -440,7 +440,7 @@ public Promise> parZipWith(final List as, final List bs, * @return A Promise of a new stream with the results of applying the given function across the two streams, stepwise. */ public Promise> parZipWith(final Stream as, final Stream bs, final F> f) { - return sequence(as.>zipWith(bs, promise(uncurryF2(f)))); + return sequence(as.zipWith(bs, promise(uncurryF2(f)))); } /** @@ -465,7 +465,7 @@ public Promise> parZipWith(final Array as, final Array */ public Promise> parZipWith(final Iterable as, final Iterable bs, final F> f) { return parZipWith(iterableStream(as), iterableStream(bs), f).fmap( - Function., Iterable>vary(Function.>identity())); + Function.vary(Function.>identity())); } /** @@ -496,7 +496,7 @@ public Promise parFoldMap(final Stream as, final F map, final */ public Promise parFoldMap(final Stream as, final F map, final Monoid reduce, final F, P2, Stream>> chunking) { - return parMap(Stream.unfold(stream -> stream.isEmpty() ? Option., Stream>>none() : some(chunking.f(stream)), as), Stream.map_().f(map)).bind(stream -> parMap(stream, reduce.sumLeftS()).fmap(reduce.sumLeftS())); + return parMap(Stream.unfold(stream -> stream.isEmpty() ? Option.none() : some(chunking.f(stream)), as), Stream.map_().f(map)).bind(stream -> parMap(stream, reduce.sumLeftS()).fmap(reduce.sumLeftS())); } /** diff --git a/core/src/main/java/fj/control/parallel/Promise.java b/core/src/main/java/fj/control/parallel/Promise.java index fc20f491..3689c286 100644 --- a/core/src/main/java/fj/control/parallel/Promise.java +++ b/core/src/main/java/fj/control/parallel/Promise.java @@ -37,7 +37,7 @@ public final class Promise { private final CountDownLatch l = new CountDownLatch(1); private volatile Option v = none(); - private final Queue> waiting = new LinkedList>(); + private final Queue> waiting = new LinkedList<>(); private Promise(final Strategy s, final Actor, Actor>, Promise>> qa) { this.s = s; @@ -62,7 +62,7 @@ public void f(final P2, Actor>, Promise> p) { p._1().right().value().act(snd.v.some()); } }); - return new Promise(s, q); + return new Promise<>(s, q); } /** @@ -75,7 +75,7 @@ public void f(final P2, Actor>, Promise> p) { */ public static Promise promise(final Strategy s, final P1 a) { final Promise p = mkPromise(s); - p.actor.act(p(Either., Actor>left(a), p)); + p.actor.act(p(Either.left(a), p)); return p; } @@ -118,7 +118,7 @@ public static F> promise(final Strategy s, final F a) { - actor.act(p(Either., Actor>right(a), this)); + actor.act(p(Either.right(a), this)); } /** @@ -176,7 +176,7 @@ public Promise bind(final F> f) { final Promise r = mkPromise(s); final Actor ab = actor(s, new Effect1() { public void f(final B b) { - r.actor.act(p(Either., Actor>left(p(b)), r)); + r.actor.act(p(Either.left(p(b)), r)); } }); to(ab.promise().contramap(f)); @@ -254,7 +254,7 @@ public static F>, Promise>> sequence(final Strategy< * @return A single promise for the given Stream. */ public static Promise> sequence(final Strategy s, final Stream> as) { - return join(foldRightS(s, curry((Promise o, P1>> p) -> o.bind(a -> p._1().fmap(Stream.cons_().f(a)))), promise(s, p(Stream.nil()))).f(as)); + return join(foldRightS(s, curry((Promise o, P1>> p) -> o.bind(a -> p._1().fmap(Stream.cons_().f(a)))), promise(s, p(Stream.nil()))).f(as)); } /** @@ -275,7 +275,7 @@ public static F>, Promise>> sequenceS(final Strategy * @return A promised product. */ public static Promise> sequence(final Strategy s, final P1> p) { - return join(promise(s, p)).fmap(P.p1()); + return join(promise(s, p)).fmap(P.p1()); } /** @@ -308,7 +308,7 @@ public static F, Promise> foldRightS(final Strategy s, return new F, Promise>() { public Promise f(final Stream as) { return as.isEmpty() ? promise(s, p(b)) : liftM2(f).f(promise(s, p(as.head()))).f( - Promise.>join(s, P.lazy(() -> f(as.tail()._1()).fmap(P.p1())))); + Promise.join(s, P.lazy(() -> f(as.tail()._1()).fmap(P.p1())))); } }; } @@ -381,7 +381,7 @@ public Promise> cojoin() { */ public Stream sequenceW(final Stream, B>> fs) { return fs.isEmpty() - ? Stream.nil() + ? Stream.nil() : Stream.cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } diff --git a/core/src/main/java/fj/control/parallel/Strategy.java b/core/src/main/java/fj/control/parallel/Strategy.java index 94e1f148..2b77a9e8 100644 --- a/core/src/main/java/fj/control/parallel/Strategy.java +++ b/core/src/main/java/fj/control/parallel/Strategy.java @@ -51,7 +51,7 @@ public F, P1> f() { * @return A strategy that uses the given function to evaluate product-1s. */ public static Strategy strategy(final F, P1> f) { - return new Strategy(f); + return new Strategy<>(f); } /** @@ -71,7 +71,7 @@ public P1 par(final P1 a) { * @return A function that executes concurrently when called, yielding a Future value. */ public F> concurry(final F f) { - return compose(f(), P1.curry(f)); + return compose(f(), P1.curry(f)); } /** @@ -91,7 +91,7 @@ public F>> concurry(final F2 f) { * @return A list of values extracted from the Futures in the argument list. */ public static List> mergeAll(final List> xs) { - return xs.map(Strategy.obtain()); + return xs.map(Strategy.obtain()); } /** @@ -136,7 +136,7 @@ public P1> parMap(final F f, final Array bs) { * @return A list with all of its elements transformed by the given function. */ public List parMap1(final F f, final List bs) { - return compose(P1.>__1(), parMapList(f)).f(bs); + return compose(P1.__1(), parMapList(f)).f(bs); } /** @@ -149,7 +149,7 @@ public List parMap1(final F f, final List bs) { * @return An array with all of its elements transformed by the given function. */ public Array parMap1(final F f, final Array bs) { - return compose(P1.>__1(), parMapArray(f)).f(bs); + return compose(P1.__1(), parMapArray(f)).f(bs); } /** @@ -248,7 +248,7 @@ public static P1> parFlatMap(final Strategy> s, public static P1> parListChunk(final Strategy> s, final int chunkLength, final List> as) { - return P1.map_(List.join()).f(s.parList(as.partition(chunkLength).map(P1.sequenceList()))); + return P1.map_(List.join()).f(s.parList(as.partition(chunkLength).map(P1.sequenceList()))); } /** @@ -351,7 +351,7 @@ public static Effect1> discard() { */ public static Strategy simpleThreadStrategy() { return strategy(p -> { - final FutureTask t = new FutureTask(Java.P1_Callable().f(p)); + final FutureTask t = new FutureTask<>(Java.P1_Callable().f(p)); new Thread(t).start(); return obtain(t); }); @@ -396,7 +396,7 @@ public static Strategy seqStrategy() { * @return A strategy that performs no evaluation of its argument. */ public static Strategy idStrategy() { - return strategy(Function.>identity()); + return strategy(Function.identity()); } /** @@ -417,7 +417,7 @@ public Strategy xmap(final F, P1> f, final F, P1> g) { * @return A new strategy that applies the given transformation after each application of this strategy. */ public Strategy map(final F, P1> f) { - return xmap(f, Function.>identity()); + return xmap(f, Function.identity()); } /** @@ -427,7 +427,7 @@ public Strategy map(final F, P1> f) { * @return A new strategy that applies the given transformation before each application of this strategy. */ public Strategy contramap(final F, P1> f) { - return xmap(Function.>identity(), f); + return xmap(Function.identity(), f); } /** diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 212216bc..17b2ac9e 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -30,7 +30,7 @@ public final class $ extends P1 { } public static $ constant(final B b) { - return new $(b); + return new $<>(b); } diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 7890a0c8..09b56f9a 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -88,7 +88,7 @@ public int length() { } public ImmutableProjection immutable() { - return new ImmutableProjection(this); + return new ImmutableProjection<>(this); } /** @@ -148,7 +148,7 @@ public A[] toJavaArray() { */ @SuppressWarnings("unchecked") public Option toOption() { - return a.length == 0 ? Option.none() : some((A) a[0]); + return a.length == 0 ? Option.none() : some((A) a[0]); } /** @@ -160,7 +160,7 @@ public Option toOption() { */ @SuppressWarnings("unchecked") public Either toEither(final F0 x) { - return a.length == 0 ? Either. left(x.f()) : Either. right((A) a[0]); + return a.length == 0 ? Either.left(x.f()) : Either.right((A) a[0]); } /** @@ -187,7 +187,7 @@ public List toList() { @SuppressWarnings("unchecked") public Stream toStream() { return Stream.unfold(o -> - a.length > o ? some(p((A) a[o], o + 1)) : Option.>none(), 0 + a.length > o ? some(p((A) a[o], o + 1)) : Option.none(), 0 ); } @@ -210,7 +210,7 @@ public Array map(final F f) { bs[i] = f.f((A) a[i]); } - return new Array(bs); + return new Array<>(bs); } /** @@ -333,7 +333,7 @@ public Array scanLeft(final F> f, final B b) { bs[i] = x; } - return new Array(bs); + return new Array<>(bs); } /** @@ -368,7 +368,7 @@ public Array scanLeft1(final F> f) { bs[i] = x; } - return new Array(bs); + return new Array<>(bs); } /** @@ -402,7 +402,7 @@ public Array scanRight(final F>f, final B b) { bs[i] = x; } - return new Array(bs); + return new Array<>(bs); } /** @@ -437,7 +437,7 @@ public Array scanRight1(final F>f) { bs[i] = x; } - return new Array(bs); + return new Array<>(bs); } /** @@ -482,7 +482,7 @@ public Unit f(final Array x) { } }); - return new Array(bs); + return new Array<>(bs); } /** @@ -542,7 +542,7 @@ public Array reverse() { x[a.length - 1 - i] = a[i]; } - return new Array(x); + return new Array<>(x); } /** @@ -557,7 +557,7 @@ public Array append(final Array aas) { arraycopy(a, 0, x, 0, a.length); arraycopy(aas.a, 0, x, a.length, aas.a.length); - return new Array(x); + return new Array<>(x); } /** @@ -566,7 +566,7 @@ public Array append(final Array aas) { * @return An empty array. */ public static Array empty() { - return new Array(new Object[0]); + return new Array<>(new Object[0]); } /** @@ -587,7 +587,7 @@ public static Array array(final A...as) { * @return A wrapped array. */ static Array mkArray(final Object[] a) { - return new Array(a); + return new Array<>(a); } /** @@ -597,7 +597,7 @@ static Array mkArray(final Object[] a) { * @return An array with the given single element. */ public static Array single(final A a) { - return new Array(new Object[]{a}); + return new Array<>(new Object[]{a}); } /** @@ -674,7 +674,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object o) { - return Equal.equals0(Array.class, this, o, () -> Equal.arrayEqual(Equal.anyEqual())); + return Equal.equals0(Array.class, this, o, () -> Equal.arrayEqual(Equal.anyEqual())); } /** @@ -707,7 +707,7 @@ public static Array range(final int from, final int to) { if (from >= to) return empty(); else { - final Array a = new Array(new Integer[to - from]); + final Array a = new Array<>(new Integer[to - from]); for (int i = from; i < to; i++) a.set(i - from, i); @@ -727,7 +727,7 @@ public static Array range(final int from, final int to) { */ public Array zipWith(final Array bs, final F> f) { final int len = min(a.length, bs.length()); - final Array x = new Array(new Object[len]); + final Array x = new Array<>(new Object[len]); for (int i = 0; i < len; i++) { x.set(i, f.f(get(i)).f(bs.get(i))); @@ -812,7 +812,7 @@ public int size() { * Returns a standard java.util.List projection of this array. */ java.util.List toJavaList() { - return new ArrayList(toCollection()); + return new ArrayList<>(toCollection()); } /** @@ -840,7 +840,7 @@ public static Array iteratorArray(final Iterator i) { */ @SafeVarargs public static Array arrayArray(final A...as) { - return new Array(as); + return new Array<>(as); } /** @@ -852,8 +852,8 @@ public static Array arrayArray(final A...as) { @SuppressWarnings("unchecked") public static P2, Array> unzip(final Array> xs) { final int len = xs.length(); - final Array aa = new Array(new Object[len]); - final Array ab = new Array(new Object[len]); + final Array aa = new Array<>(new Object[len]); + final Array ab = new Array<>(new Object[len]); for (int i = len - 1; i >= 0; i--) { final P2 p = xs.get(i); aa.set(i, p._1()); diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index 7e44ef9b..cf2f0af5 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -69,7 +69,7 @@ public static DList arrayDList(final A...as) { * @return the final List */ public List run() { - return appendFn.f(List.nil()).run(); + return appendFn.f(List.nil()).run(); } /** @@ -85,7 +85,7 @@ public java.util.List toJavaList() { * @return a empty DList. */ public static DList nil() { - return new DList<>(Trampoline.>pure()); + return new DList<>(Trampoline.pure()); } /** diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 1cbecb5d..0d944415 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -39,7 +39,7 @@ private Either() { * @return A left projection of this either. */ public final LeftProjection left() { - return new LeftProjection(this); + return new LeftProjection<>(this); } /** @@ -48,7 +48,7 @@ public final LeftProjection left() { * @return A right projection of this either. */ public final RightProjection right() { - return new RightProjection(this); + return new RightProjection<>(this); } /** @@ -93,7 +93,7 @@ public final Either bimap(final F left, final F right) @Override public boolean equals(Object other) { - return Equal.equals0(Either.class, this, other, () -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(Either.class, this, other, () -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override @@ -107,7 +107,7 @@ public int hashCode() { * @return The value of this either swapped to the opposing side. */ public final Either swap() { - return isLeft() ? new Right(((Left) this).a) : new Left(((Right) this).b); + return isLeft() ? new Right<>(((Left) this).a) : new Left<>(((Right) this).b); } private static final class Left extends Either { @@ -265,7 +265,7 @@ public void foreachDoEffect(final Effect1 f) { * @return A new either value after mapping. */ public Either map(final F f) { - return isLeft() ? new Left(f.f(value())) : new Right(e.right().value()); + return isLeft() ? new Left<>(f.f(value())) : new Right<>(e.right().value()); } /** @@ -275,7 +275,7 @@ public Either map(final F f) { * @return A new either value after binding. */ public Either bind(final F> f) { - return isLeft() ? f.f(value()) : new Right(e.right().value()); + return isLeft() ? f.f(value()) : new Right<>(e.right().value()); } /** @@ -285,7 +285,7 @@ public Either bind(final F> f) { * @return An either after binding through this projection. */ public Either sequence(final Either e) { - return bind(Function.>constant(e)); + return bind(Function.constant(e)); } /** @@ -297,7 +297,7 @@ public Either sequence(final Either e) { public List> traverseList(final F> f) { return isLeft() ? f.f(value()).map(Either::left) : - list(Either.right(e.right().value())); + list(Either.right(e.right().value())); } /** @@ -309,7 +309,7 @@ public List> traverseList(final F> f) { public IO> traverseIO(final F> f) { return isRight() ? IOFunctions.map(f.f(value()), Either::left) : - IOFunctions.unit(Either.right(e.right().value())); + IOFunctions.unit(Either.right(e.right().value())); } /** @@ -323,9 +323,9 @@ public IO> traverseIO(final F> f) { public Option> filter(final F f) { return isLeft() ? f.f(value()) ? - Option.>some(new Left<>(value())) : - Option.>none() : - Option.>none(); + Option.some(new Left<>(value())) : + Option.none() : + Option.none(); } /** @@ -368,7 +368,7 @@ public boolean exists(final F f) { * @return A single element list if this projection has a value, otherwise an empty list. */ public List toList() { - return isLeft() ? single(value()) : List.nil(); + return isLeft() ? single(value()) : List.nil(); } /** @@ -379,7 +379,7 @@ public List toList() { * None. */ public Option toOption() { - return isLeft() ? some(value()) : Option.none(); + return isLeft() ? some(value()) : Option.none(); } /** @@ -402,7 +402,7 @@ public Array toArray() { * @return A single element stream if this projection has a value, otherwise an empty stream. */ public Stream toStream() { - return isLeft() ? Stream.single(value()) : Stream.nil(); + return isLeft() ? Stream.single(value()) : Stream.nil(); } /** @@ -417,13 +417,13 @@ public Collection toCollection() { public Option> traverseOption(F> f) { return isLeft() ? f.f(value()).map(Either::left) : - some(Either.right(e.right().value())); + some(Either.right(e.right().value())); } public Stream> traverseStream(F> f) { return isLeft() ? f.f(value()).map(Either::left) : - Stream.single(Either.right(e.right().value())); + Stream.single(Either.right(e.right().value())); } } @@ -551,7 +551,7 @@ public Either bind(final F> f) { * @return An either after binding through this projection. */ public Either sequence(final Either e) { - return bind(Function.>constant(e)); + return bind(Function.constant(e)); } /** * Traverse with function that produces List (non-determinism). @@ -562,7 +562,7 @@ public Either sequence(final Either e) { public List> traverseList(final F> f) { return isRight() ? f.f(value()).map(Either::right) : - list(Either.left(e.left().value())); + list(Either.left(e.left().value())); } /** @@ -574,19 +574,19 @@ public List> traverseList(final F> f) { public IO> traverseIO(final F> f) { return isRight() ? IOFunctions.map(f.f(value()), Either::right) : - IOFunctions.lazy(() -> Either.left(e.left().value())); + IOFunctions.lazy(() -> Either.left(e.left().value())); } public P1> traverseP1(final F> f) { return isRight() ? f.f(value()).map(Either::right) : - p(Either.left(e.left().value())); + p(Either.left(e.left().value())); } public Option> traverseOption(final F> f) { return isRight() ? f.f(value()).map(Either::right) : - some(Either.left(e.left().value())); + some(Either.left(e.left().value())); } /** @@ -600,9 +600,9 @@ public Option> traverseOption(final F> f) { public Option> filter(final F f) { return isRight() ? f.f(value()) ? - Option.>some(new Right(value())) : - Option.>none() : - Option.>none(); + Option.some(new Right(value())) : + Option.none() : + Option.none(); } /** @@ -645,7 +645,7 @@ public boolean exists(final F f) { * @return A single element list if this projection has a value, otherwise an empty list. */ public List toList() { - return isRight() ? single(value()) : List.nil(); + return isRight() ? single(value()) : List.nil(); } /** @@ -656,7 +656,7 @@ public List toList() { * None. */ public Option toOption() { - return isRight() ? some(value()) : Option.none(); + return isRight() ? some(value()) : Option.none(); } /** @@ -679,7 +679,7 @@ public Array toArray() { * @return A single element stream if this projection has a value, otherwise an empty stream. */ public Stream toStream() { - return isRight() ? Stream.single(value()) : Stream.nil(); + return isRight() ? Stream.single(value()) : Stream.nil(); } /** @@ -694,7 +694,7 @@ public Collection toCollection() { public Stream> traverseStream(F> f) { return isRight() ? f.f(value()).map(Either::right) : - Stream.>single(left(e.left().value())); + Stream.single(left(e.left().value())); } } @@ -706,7 +706,7 @@ public Stream> traverseStream(F> f) { * @return A left value of either. */ public static Either left(final A a) { - return new Left(a); + return new Left<>(a); } /** @@ -734,7 +734,7 @@ public static F> right_() { * @return A right value of either. */ public static Either right(final B b) { - return new Right(b); + return new Right<>(b); } /** @@ -781,7 +781,7 @@ public static Either joinRight(final Either> e) { */ public static Either, X> sequenceLeft(final List> a) { return a.isEmpty() ? - Either., X>left(List.nil()) : + Either.left(List.nil()) : a.head().left().bind(aa -> sequenceLeft(a.tail()).left().map(cons_(aa))); } @@ -793,7 +793,7 @@ public static Either, X> sequenceLeft(final List> a) */ public static Either> sequenceRight(final List> a) { return a.isEmpty() ? - Either.>right(List.nil()) : + Either.right(List.nil()) : a.head().right().bind(bb -> sequenceRight(a.tail()).right().map(cons_(bb))); } @@ -803,7 +803,7 @@ public static Either> sequenceRight(final List> a * @return traversed value */ public List> traverseListRight(final F> f) { - return right().traverseList(f); + return right().traverseList(f); } /** @@ -812,7 +812,7 @@ public List> traverseListRight(final F> f) { * @return traversed value */ public List> traverseListLeft(final F> f) { - return left().traverseList(f); + return left().traverseList(f); } /** @@ -821,7 +821,7 @@ public List> traverseListLeft(final F> f) { * @return traversed value */ public IO> traverseIORight(final F> f) { - return right().traverseIO(f); + return right().traverseIO(f); } /** @@ -830,7 +830,7 @@ public IO> traverseIORight(final F> f) { * @return traversed value */ public IO> traverseIOLeft(final F> f) { - return left().traverseIO(f); + return left().traverseIO(f); } /** @@ -839,7 +839,7 @@ public IO> traverseIOLeft(final F> f) { * @return traversed value */ public Option> traverseOptionRight(final F> f) { - return right().traverseOption(f); + return right().traverseOption(f); } /** @@ -848,7 +848,7 @@ public Option> traverseOptionRight(final F> f) { * @return traversed value */ public Option> traverseOptionLeft(final F> f) { - return left().traverseOption(f); + return left().traverseOption(f); } /** @@ -857,7 +857,7 @@ public Option> traverseOptionLeft(final F> f) { * @return traversed value */ public Stream> traverseStreamRight(final F> f) { - return right().traverseStream(f); + return right().traverseStream(f); } /** @@ -866,7 +866,7 @@ public Stream> traverseStreamRight(final F> f) { * @return traversed value */ public Stream> traverseStreamLeft(final F> f) { - return left().traverseStream(f); + return left().traverseStream(f); } @@ -890,7 +890,7 @@ public static A reduce(final Either e) { * @return A constructed either based on the given condition. */ public static Either iif(final boolean c, final F0 right, final F0 left) { - return c ? new Right(right.f()) : new Left(left.f()); + return c ? new Right<>(right.f()) : new Left<>(left.f()); } /** @@ -900,7 +900,7 @@ public static Either iif(final boolean c, final F0 right, final * @return All the left values in the given list. */ public static List lefts(final List> es) { - return es.foldRight(e -> as -> e.isLeft() ? as.cons(e.left().value()) : as, List.nil()); + return es.foldRight(e -> as -> e.isLeft() ? as.cons(e.left().value()) : as, List.nil()); } /** @@ -910,7 +910,7 @@ public static List lefts(final List> es) { * @return All the right values in the given list. */ public static List rights(final List> es) { - return es.foldRight(e -> bs -> e.isRight() ? bs.cons(e.right().value()) : bs, List.nil()); + return es.foldRight(e -> bs -> e.isRight() ? bs.cons(e.right().value()) : bs, List.nil()); } public String toString() { diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index b7533ffd..1666d7b2 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -220,7 +220,7 @@ public Enumerator setMax(final Option max) { public static Enumerator enumerator(final F> successor, final F> predecessor, final Option max, final Option min, final Ord order, final F>> plus) { - return new Enumerator(successor, predecessor, max, min, order, plus); + return new Enumerator<>(successor, predecessor, max, min, order, plus); } /** @@ -236,30 +236,30 @@ public static Enumerator enumerator(final F> successor, fina */ public static Enumerator enumerator(final F> successor, final F> predecessor, final Option max, final Option min, final Ord order) { - return new Enumerator(successor, predecessor, max, min, order, curry((a, l) -> { - if (l == 0L) - return some(a); - else if (l < 0L) { - A aa = a; - for (long x = l; x < 0; x++) { - final Option s = predecessor.f(aa); - if (s.isNone()) - return none(); - else - aa = s.some(); - } - return some(aa); - } else { - A aa = a; - for (long x = l; x > 0; x--) { - final Option s = successor.f(aa); - if (s.isNone()) - return none(); - else - aa = s.some(); - } - return some(aa); + return new Enumerator<>(successor, predecessor, max, min, order, curry((a, l) -> { + if (l == 0L) + return some(a); + else if (l < 0L) { + A aa = a; + for (long x = l; x < 0; x++) { + final Option s = predecessor.f(aa); + if (s.isNone()) + return none(); + else + aa = s.some(); } + return some(aa); + } else { + A aa = a; + for (long x = l; x > 0; x--) { + final Option s = successor.f(aa); + if (s.isNone()) + return none(); + else + aa = s.some(); + } + return some(aa); + } })); } @@ -267,8 +267,8 @@ else if (l < 0L) { * An enumerator for boolean. */ public static final Enumerator booleanEnumerator = enumerator( - b -> b ? Option.none() : some(true), - b -> b ? some(false) : Option.none(), + b -> b ? Option.none() : some(true), + b -> b ? some(false) : Option.none(), some(true), some(false), booleanOrd ); @@ -276,8 +276,8 @@ else if (l < 0L) { * An enumerator for byte. */ public static final Enumerator byteEnumerator = enumerator( - b -> b == Byte.MAX_VALUE ? Option.none() : some((byte) (b + 1)), - b -> b == Byte.MIN_VALUE ? Option.none() : some((byte) (b - 1)), + b -> b == Byte.MAX_VALUE ? Option.none() : some((byte) (b + 1)), + b -> b == Byte.MIN_VALUE ? Option.none() : some((byte) (b - 1)), some(Byte.MAX_VALUE), some(Byte.MIN_VALUE), byteOrd ); @@ -285,8 +285,8 @@ else if (l < 0L) { * An enumerator for char. */ public static final Enumerator charEnumerator = enumerator( - c -> c == Character.MAX_VALUE ? Option.none() : some((char) (c + 1)), - c -> c == Character.MIN_VALUE ? Option.none() : some((char) (c - 1)), + c -> c == Character.MAX_VALUE ? Option.none() : some((char) (c + 1)), + c -> c == Character.MIN_VALUE ? Option.none() : some((char) (c - 1)), some(Character.MAX_VALUE), some(Character.MIN_VALUE), charOrd ); @@ -294,8 +294,8 @@ else if (l < 0L) { * An enumerator for double. */ public static final Enumerator doubleEnumerator = enumerator( - d -> d == Double.MAX_VALUE ? Option.none() : some(d + 1D), - d -> d == Double.MIN_VALUE ? Option.none() : some(d - 1D), + d -> d == Double.MAX_VALUE ? Option.none() : some(d + 1D), + d -> d == Double.MIN_VALUE ? Option.none() : some(d - 1D), some(Double.MAX_VALUE), some(Double.MIN_VALUE), doubleOrd ); @@ -303,8 +303,8 @@ else if (l < 0L) { * An enumerator for float. */ public static final Enumerator floatEnumerator = enumerator( - f -> f == Float.MAX_VALUE ? Option.none() : some(f + 1F), - f -> f == Float.MIN_VALUE ? Option.none() : some(f - 1F), + f -> f == Float.MAX_VALUE ? Option.none() : some(f + 1F), + f -> f == Float.MIN_VALUE ? Option.none() : some(f - 1F), some(Float.MAX_VALUE), some(Float.MIN_VALUE), floatOrd ); @@ -312,8 +312,8 @@ else if (l < 0L) { * An enumerator for int. */ public static final Enumerator intEnumerator = enumerator( - i -> i == Integer.MAX_VALUE ? Option.none() : some(i + 1), - i -> i == Integer.MIN_VALUE ? Option.none() : some(i - 1), + i -> i == Integer.MAX_VALUE ? Option.none() : some(i + 1), + i -> i == Integer.MIN_VALUE ? Option.none() : some(i - 1), some(Integer.MAX_VALUE), some(Integer.MIN_VALUE), intOrd ); @@ -323,7 +323,7 @@ else if (l < 0L) { public static final Enumerator bigintEnumerator = enumerator( i -> some(i.add(BigInteger.ONE)), i -> some(i.subtract(BigInteger.ONE)), - Option.none(), Option.none(), bigintOrd, + Option.none(), Option.none(), bigintOrd, curry((i, l) -> some(i.add(BigInteger.valueOf(l)))) ); @@ -333,7 +333,7 @@ else if (l < 0L) { public static final Enumerator bigdecimalEnumerator = enumerator( i -> some(i.add(BigDecimal.ONE)), i -> some(i.subtract(BigDecimal.ONE)), - Option.none(), Option.none(), bigdecimalOrd, + Option.none(), Option.none(), bigdecimalOrd, curry((d, l) -> some(d.add(BigDecimal.valueOf(l)))) ); @@ -341,8 +341,8 @@ else if (l < 0L) { * An enumerator for long. */ public static final Enumerator longEnumerator = enumerator( - i -> i == Long.MAX_VALUE ? Option.none() : some(i + 1L), - i -> i == Long.MIN_VALUE ? Option.none() : some(i - 1L), + i -> i == Long.MAX_VALUE ? Option.none() : some(i + 1L), + i -> i == Long.MIN_VALUE ? Option.none() : some(i - 1L), some(Long.MAX_VALUE), some(Long.MIN_VALUE), longOrd ); @@ -350,8 +350,8 @@ else if (l < 0L) { * An enumerator for short. */ public static final Enumerator shortEnumerator = enumerator( - i -> i == Short.MAX_VALUE ? Option.none() : some((short) (i + 1)), - i -> i == Short.MIN_VALUE ? Option.none() : some((short) (i - 1)), + i -> i == Short.MAX_VALUE ? Option.none() : some((short) (i + 1)), + i -> i == Short.MIN_VALUE ? Option.none() : some((short) (i - 1)), some(Short.MAX_VALUE), some(Short.MIN_VALUE), shortOrd ); @@ -359,8 +359,8 @@ else if (l < 0L) { * An enumerator for Ordering. */ public static final Enumerator orderingEnumerator = enumerator( - o -> o == LT ? some(EQ) : o == EQ ? some(GT) : Option.none(), - o -> o == GT ? some(EQ) : o == EQ ? some(LT) : Option.none(), + o -> o == LT ? some(EQ) : o == EQ ? some(GT) : Option.none(), + o -> o == GT ? some(EQ) : o == EQ ? some(LT) : Option.none(), some(GT), some(LT), orderingOrd ); @@ -370,7 +370,7 @@ else if (l < 0L) { public static final Enumerator naturalEnumerator = enumerator( n -> some(n.succ()), Natural::pred, - Option.none(), some(Natural.ZERO), naturalOrd, + Option.none(), some(Natural.ZERO), naturalOrd, curry((n, l) -> some(n).apply( Natural.natural(l).map(curry((n1, n2) -> n1.add(n2))) diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 6b03a96a..9a145b37 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -63,7 +63,7 @@ public Iterator iterator() { * @param h The hashing strategy. */ public HashMap(final Equal e, final Hash h) { - m = new java.util.HashMap, V>(); + m = new java.util.HashMap<>(); this.e = e; this.h = h; } @@ -83,13 +83,13 @@ public HashMap(java.util.Map map, final Equal e, final Hash h) { * @param initialCapacity The initial capacity. */ public HashMap(final Equal e, final Hash h, final int initialCapacity) { - m = new java.util.HashMap, V>(initialCapacity); + m = new java.util.HashMap<>(initialCapacity); this.e = e; this.h = h; } public HashMap(java.util.Map map) { - this(map, Equal.anyEqual(), Hash.anyHash()); + this(map, Equal.anyEqual(), Hash.anyHash()); } /** @@ -101,7 +101,7 @@ public HashMap(java.util.Map map) { * @param loadFactor The load factor. */ public HashMap(final Equal e, final Hash h, final int initialCapacity, final float loadFactor) { - m = new java.util.HashMap, V>(initialCapacity, loadFactor); + m = new java.util.HashMap<>(initialCapacity, loadFactor); this.e = e; this.h = h; } @@ -121,7 +121,7 @@ public static HashMap hashMap() { * @return A new hash map. */ public static HashMap hashMap(final Equal e, final Hash h) { - return new HashMap(e, h); + return new HashMap<>(e, h); } /** @@ -152,7 +152,7 @@ public int hash(final K k) { * @return A potential value for the given key. */ public Option get(final K k) { - return fromNull(m.get(new Key(k, e, h))); + return fromNull(m.get(new Key<>(k, e, h))); } /** @@ -178,7 +178,7 @@ public void clear() { * @return true if this hash map contains the given key, false otherwise. */ public boolean contains(final K k) { - return m.containsKey(new Key(k, e, h)); + return m.containsKey(new Key<>(k, e, h)); } /** @@ -187,7 +187,7 @@ public boolean contains(final K k) { * @return All key entries in this hash map. */ public List keys() { - final List.Buffer b = new List.Buffer(); + final List.Buffer b = new List.Buffer<>(); for (final Key k : m.keySet()) { b.snoc(k.k()); @@ -202,7 +202,7 @@ public List keys() { * @return All values in this hash map. */ public List values() { - return keys().map(k -> m.get(new Key(k, e, h))); + return keys().map(k -> m.get(new Key<>(k, e, h))); } /** @@ -231,7 +231,7 @@ public int size() { */ public void set(final K k, final V v) { if (v != null) { - m.put(new Key(k, e, h), v); + m.put(new Key<>(k, e, h), v); } } @@ -241,7 +241,7 @@ public void set(final K k, final V v) { * @param k The key to delete from this hash map. */ public void delete(final K k) { - m.remove(new Key(k, e, h)); + m.remove(new Key<>(k, e, h)); } /** @@ -251,13 +251,13 @@ public void delete(final K k) { * @return The value that was associated with the given key, if there was one. */ public Option getDelete(final K k) { - return fromNull(m.remove(new Key(k, e, h))); + return fromNull(m.remove(new Key<>(k, e, h))); } public HashMap map(F keyFunction, F valueFunction, Equal equal, Hash hash) { - final HashMap hashMap = new HashMap(equal, hash); + final HashMap hashMap = new HashMap<>(equal, hash); for (K key : keys()) { final A newKey = keyFunction.f(key); final B newValue = valueFunction.f(get(key).some()); @@ -268,7 +268,7 @@ public HashMap map(F keyFunction, public HashMap map(F keyFunction, F valueFunction) { - return map(keyFunction, valueFunction, Equal.anyEqual(), Hash.anyHash()); + return map(keyFunction, valueFunction, Equal.anyEqual(), Hash.anyHash()); } public HashMap map(F, P2> function, Equal equal, Hash hash) { @@ -280,15 +280,15 @@ public HashMap map(F, P2> function) { } public HashMap mapKeys(F keyFunction, Equal equal, Hash hash) { - return map(keyFunction, Function.identity(), equal, hash); + return map(keyFunction, Function.identity(), equal, hash); } public HashMap mapKeys(F function) { - return mapKeys(function, Equal.anyEqual(), Hash.anyHash()); + return mapKeys(function, Equal.anyEqual(), Hash.anyHash()); } public HashMap mapValues(F function) { - return map(Function.identity(), function, e, h); + return map(Function.identity(), function, e, h); } public void foreachDoEffect(Effect1> effect) { @@ -325,7 +325,7 @@ public Array> toArray() { } public java.util.Map toMap() { - final java.util.HashMap result = new java.util.HashMap(); + final java.util.HashMap result = new java.util.HashMap<>(); for (K key : keys()) { result.put(key, get(key).some()); } @@ -368,7 +368,7 @@ public static HashMap from(final Iterable> entries, final * Converts the Iterable to a HashMap */ public static HashMap iterableHashMap(final Equal equal, final Hash hash, final Iterable> entries) { - final HashMap map = new HashMap(equal, hash); + final HashMap map = new HashMap<>(equal, hash); for (P2 entry : entries) { map.set(entry._1(), entry._2()); } @@ -379,7 +379,7 @@ public static HashMap iterableHashMap(final Equal equal, final H * Converts the Iterable to a HashMap */ public static HashMap iterableHashMap(final Iterable> entries) { - return iterableHashMap(Equal.anyEqual(), Hash.anyHash(), entries); + return iterableHashMap(Equal.anyEqual(), Hash.anyHash(), entries); } /** diff --git a/core/src/main/java/fj/data/HashSet.java b/core/src/main/java/fj/data/HashSet.java index 1c6868e3..d7b2c832 100644 --- a/core/src/main/java/fj/data/HashSet.java +++ b/core/src/main/java/fj/data/HashSet.java @@ -36,7 +36,7 @@ public Iterator iterator() { * @param h The hashing strategy. */ public HashSet(final Equal e, final Hash h) { - m = new HashMap(e, h); + m = new HashMap<>(e, h); } /** @@ -47,7 +47,7 @@ public HashSet(final Equal e, final Hash h) { * @param initialCapacity The initial capacity. */ public HashSet(final Equal e, final Hash h, final int initialCapacity) { - m = new HashMap(e, h, initialCapacity); + m = new HashMap<>(e, h, initialCapacity); } /** @@ -59,7 +59,7 @@ public HashSet(final Equal e, final Hash h, final int initialCapacity) { * @param loadFactor The load factor. */ public HashSet(final Equal e, final Hash h, final int initialCapacity, final float loadFactor) { - m = new HashMap(e, h, initialCapacity, loadFactor); + m = new HashMap<>(e, h, initialCapacity, loadFactor); } /** @@ -87,7 +87,7 @@ public int hash(final A a) { * Creates a new HashSet using the given Equal and Hash */ public static HashSet empty(final Equal e, final Hash h) { - return new HashSet(e, h); + return new HashSet<>(e, h); } /** @@ -230,7 +230,7 @@ public java.util.List toJavaList() { } public java.util.Set toJavaSet() { - return new java.util.HashSet(toCollection()); + return new java.util.HashSet<>(toCollection()); } public static HashSet fromSet(java.util.Set s) { diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index c3d5fe01..cfe5eba2 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -94,8 +94,8 @@ public static IO closeReader(final Reader r) { */ public static IO> enumFileLines(final File f, final Option encoding, final IterV i) { return bracket(bufferedReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IOFunctions.lineReader(), i)); + , Function.vary(closeReader) + , partialApply2(IOFunctions.lineReader(), i)); } /** @@ -107,8 +107,8 @@ public static IO> enumFileLines(final File f, final Option< */ public static IO> enumFileCharChunks(final File f, final Option encoding, final IterV i) { return bracket(fileReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IOFunctions.charChunkReader(), i)); + , Function.vary(closeReader) + , partialApply2(IOFunctions.charChunkReader(), i)); } /** @@ -120,8 +120,8 @@ public static IO> enumFileCharChunks(final File f, final Op */ public static IO> enumFileChars(final File f, final Option encoding, final IterV i) { return bracket(fileReader(f, encoding) - , Function.>vary(closeReader) - , partialApply2(IOFunctions.charChunkReader2(), i)); + , Function.vary(closeReader) + , partialApply2(IOFunctions.charChunkReader2(), i)); } public static IO bufferedReader(final File f, final Option encoding) { @@ -194,8 +194,8 @@ public IO> f(final IterV it) { if (s == null) { return i; } - final Input input = Input.el(s); - final F, IterV>, P1>> cont = F1Functions.lazy(Function., IterV>apply(input)); + final Input input = Input.el(s); + final F, IterV>, P1>> cont = F1Functions.lazy(Function.apply(input)); i = i.fold(done, cont)._1(); } return i; @@ -238,9 +238,9 @@ public IO> f(final IterV it) { if (numRead < buffer.length) { buffer = Arrays.copyOfRange(buffer, 0, numRead); } - final Input input = Input.el(buffer); + final Input input = Input.el(buffer); final F, IterV>, P1>> cont = - F1Functions.lazy(Function., IterV>apply(input)); + F1Functions.lazy(Function.apply(input)); i = i.fold(done, cont)._1(); } return i; @@ -286,7 +286,7 @@ public IO> f(final IterV it) { for (int c = 0; c < buffer.length; c++) { final Input input = Input.el(buffer[c]); final F, IterV>, IterV> cont = - Function., IterV>apply(input); + Function.apply(input); i = i.fold(done, cont); } } @@ -326,14 +326,14 @@ public static IO unless(final Boolean b, final IO io) { public static IO> sequence(List> list) { F2, IO>, IO>> f2 = (io, ioList) -> bind(ioList, (xs) -> map(io, x -> List.cons(x, xs))); - return list.foldRight(f2, unit(List.nil())); + return list.foldRight(f2, unit(List.nil())); } public static IO> sequence(Stream> stream) { F2>, IO, IO>> f2 = (ioList, io) -> bind(ioList, (xs) -> map(io, x -> Stream.cons(x, () -> xs))); - return stream.foldLeft(f2, unit(Stream.nil())); + return stream.foldLeft(f2, unit(Stream.nil())); } @@ -380,7 +380,7 @@ public static IO> sequenceWhileEager(final Stream> stream, f return () -> { boolean loop = true; Stream> input = stream; - Stream result = Stream.nil(); + Stream result = Stream.nil(); while (loop) { if (input.isEmpty()) { loop = false; @@ -453,8 +453,8 @@ public static IO stdoutPrint(final String s) { } public static IO getContents() { - Stream> s = Stream.>repeat(() -> (int) stdinBufferedReader.read()); - return map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> (char) i.intValue()))); + Stream> s = Stream.repeat(() -> stdinBufferedReader.read()); + return map(sequenceWhile(s, i -> i != -1), s2 -> LazyString.fromStream(s2.map(i -> (char) i.intValue()))); } public static IO interact(F f) { diff --git a/core/src/main/java/fj/data/IterableW.java b/core/src/main/java/fj/data/IterableW.java index 0633ffd4..db75dbb5 100644 --- a/core/src/main/java/fj/data/IterableW.java +++ b/core/src/main/java/fj/data/IterableW.java @@ -33,7 +33,7 @@ private IterableW(final Iterable i) { * @return An iterable equipped with some useful functions. */ public static IterableW wrap(final Iterable a) { - return new IterableW(a); + return new IterableW<>(a); } /** @@ -128,9 +128,9 @@ public static F, F, IterableW>> liftM2(fina public static > IterableW> sequence(final Iterable as) { final Stream ts = iterableStream(as); return ts.isEmpty() ? - iterable(wrap(Option.none())) : + iterable(wrap(Option.none())) : wrap(ts.head()).bind(a -> - sequence(ts.tail().map(IterableW.>wrap())._1()).bind(as2 -> + sequence(ts.tail().map(IterableW.wrap())._1()).bind(as2 -> iterable(wrap(Stream.cons(a, () -> iterableStream(as2)))) ) ); diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index 391c4087..bcb03cc0 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -82,17 +82,17 @@ public Z fold(final F>, Z> done, final F, IterV, Option> runCont = new F, Option>() { - final F>, Option> done = F1Functions.andThen(P2.>__1(), Option.some_()); - final F, IterV>, Option> cont = Function.constant(Option.none()); + final F>, Option> done = F1Functions.andThen(P2.__1(), Option.some_()); + final F, IterV>, Option> cont = Function.constant(Option.none()); @Override public Option f(final IterV i) { return i.fold(done, cont); } }; - final F>, A> done = P2.>__1(); + final F>, A> done = P2.__1(); final F, IterV>, A> cont = - k -> runCont.f(k.f(Input.eof())).valueE("diverging iteratee"); + k -> runCont.f(k.f(Input.eof())).valueE("diverging iteratee"); return fold(done, cont); } @@ -154,7 +154,7 @@ public IterV f(final Input s) { } }; return n == 0 - ? done(Unit.unit(), Input.empty()) + ? done(Unit.unit(), Input.empty()) : cont(step); } @@ -166,7 +166,7 @@ public static IterV> head() { final F0>> empty = () -> cont(step); - final F0>>> el = () -> e -> done(Option.some(e), Input.empty()); + final F0>>> el = () -> e -> done(Option.some(e), Input.empty()); final F0>> eof = () -> done(Option.none(), Input.eof()); @@ -186,7 +186,7 @@ public static IterV> peek() { final F0>> empty = () -> cont(step); - final F0>>> el = () -> e -> done(Option.some(e), Input.el(e)); + final F0>>> el = () -> e -> done(Option.some(e), Input.el(e)); final F0>> eof = () -> done(Option.none(), Input.eof()); @@ -216,7 +216,7 @@ public F, IterV>> f(final List acc) { return s -> s.apply(empty, el, eof); } }; - return cont(step.f(List. nil())); + return cont(step.f(List.nil())); } } diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 0be648f2..b4b6173a 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -51,7 +51,7 @@ private Java() { * @return A function that converts lists to array lists. */ public static F, ArrayList> List_ArrayList() { - return as -> new ArrayList(as.toCollection()); + return as -> new ArrayList<>(as.toCollection()); } /** @@ -78,7 +78,7 @@ public static > F, EnumSet> List_EnumSet() { * @return A function that converts lists to hash sets. */ public static F, HashSet> List_HashSet() { - return as -> new HashSet(as.toCollection()); + return as -> new HashSet<>(as.toCollection()); } /** @@ -87,7 +87,7 @@ public static F, HashSet> List_HashSet() { * @return A function that converts lists to linked hash sets. */ public static F, LinkedHashSet> List_LinkedHashSet() { - return as -> new LinkedHashSet(as.toCollection()); + return as -> new LinkedHashSet<>(as.toCollection()); } /** @@ -96,7 +96,7 @@ public static F, LinkedHashSet> List_LinkedHashSet() { * @return A function that converts lists to linked lists. */ public static F, LinkedList> List_LinkedList() { - return as -> new LinkedList(as.toCollection()); + return as -> new LinkedList<>(as.toCollection()); } /** @@ -105,7 +105,7 @@ public static F, LinkedList> List_LinkedList() { * @return A function that converts lists to priority queues. */ public static F, PriorityQueue> List_PriorityQueue() { - return as -> new PriorityQueue(as.toCollection()); + return as -> new PriorityQueue<>(as.toCollection()); } /** @@ -115,7 +115,7 @@ public static F, PriorityQueue> List_PriorityQueue() { */ public static F, Stack> List_Stack() { return as -> { - final Stack s = new Stack(); + final Stack s = new Stack<>(); s.addAll(as.toCollection()); return s; }; @@ -127,7 +127,7 @@ public static F, Stack> List_Stack() { * @return A function that converts lists to stacks. */ public static F, TreeSet> List_TreeSet() { - return as -> new TreeSet(as.toCollection()); + return as -> new TreeSet<>(as.toCollection()); } /** @@ -136,7 +136,7 @@ public static F, TreeSet> List_TreeSet() { * @return A function that converts lists to vectors. */ public static F, Vector> List_Vector() { - return as -> new Vector(as.toCollection()); + return as -> new Vector<>(as.toCollection()); } /** @@ -146,7 +146,7 @@ public static F, Vector> List_Vector() { * @return A function that converts lists to array blocking queue. */ public static F, ArrayBlockingQueue> List_ArrayBlockingQueue(final boolean fair) { - return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); + return as -> new ArrayBlockingQueue<>(as.length(), fair, as.toCollection()); } /** @@ -155,7 +155,7 @@ public static F, ArrayBlockingQueue> List_ArrayBlockingQueue(fina * @return A function that converts lists to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> List_ConcurrentLinkedQueue() { - return as -> new ConcurrentLinkedQueue(as.toCollection()); + return as -> new ConcurrentLinkedQueue<>(as.toCollection()); } /** @@ -164,7 +164,7 @@ public static F, ConcurrentLinkedQueue> List_ConcurrentLinkedQueu * @return A function that converts lists to copy on write array lists. */ public static F, CopyOnWriteArrayList> List_CopyOnWriteArrayList() { - return as -> new CopyOnWriteArrayList(as.toCollection()); + return as -> new CopyOnWriteArrayList<>(as.toCollection()); } /** @@ -173,7 +173,7 @@ public static F, CopyOnWriteArrayList> List_CopyOnWriteArrayList( * @return A function that converts lists to copy on write array sets. */ public static F, CopyOnWriteArraySet> List_CopyOnWriteArraySet() { - return as -> new CopyOnWriteArraySet(as.toCollection()); + return as -> new CopyOnWriteArraySet<>(as.toCollection()); } /** @@ -182,7 +182,7 @@ public static F, CopyOnWriteArraySet> List_CopyOnWriteArraySet() * @return A function that converts lists to delay queues. */ public static F, DelayQueue> List_DelayQueue() { - return as -> new DelayQueue(as.toCollection()); + return as -> new DelayQueue<>(as.toCollection()); } /** @@ -191,7 +191,7 @@ public static F, DelayQueue> List_DelayQueue() { * @return A function that converts lists to linked blocking queues. */ public static F, LinkedBlockingQueue> List_LinkedBlockingQueue() { - return as -> new LinkedBlockingQueue(as.toCollection()); + return as -> new LinkedBlockingQueue<>(as.toCollection()); } /** @@ -200,7 +200,7 @@ public static F, LinkedBlockingQueue> List_LinkedBlockingQueue() * @return A function that converts lists to priority blocking queues. */ public static F, PriorityBlockingQueue> List_PriorityBlockingQueue() { - return as -> new PriorityBlockingQueue(as.toCollection()); + return as -> new PriorityBlockingQueue<>(as.toCollection()); } /** @@ -211,7 +211,7 @@ public static F, PriorityBlockingQueue> List_PriorityBlockingQueu */ public static F, SynchronousQueue> List_SynchronousQueue(final boolean fair) { return as -> { - final SynchronousQueue q = new SynchronousQueue(fair); + final SynchronousQueue q = new SynchronousQueue<>(fair); q.addAll(as.toCollection()); return q; }; @@ -227,7 +227,7 @@ public static F, SynchronousQueue> List_SynchronousQueue(final bo * @return A function that converts arrays to array lists. */ public static F, ArrayList> Array_ArrayList() { - return as -> new ArrayList(as.toCollection()); + return as -> new ArrayList<>(as.toCollection()); } /** @@ -255,7 +255,7 @@ public static > F, EnumSet> Array_EnumSet() { * @return A function that converts arrays to hash sets. */ public static F, HashSet> Array_HashSet() { - return as -> new HashSet(as.toCollection()); + return as -> new HashSet<>(as.toCollection()); } /** @@ -264,7 +264,7 @@ public static F, HashSet> Array_HashSet() { * @return A function that converts arrays to linked hash sets. */ public static F, LinkedHashSet> Array_LinkedHashSet() { - return as -> new LinkedHashSet(as.toCollection()); + return as -> new LinkedHashSet<>(as.toCollection()); } /** @@ -273,7 +273,7 @@ public static F, LinkedHashSet> Array_LinkedHashSet() { * @return A function that converts arrays to linked lists. */ public static F, LinkedList> Array_LinkedList() { - return as -> new LinkedList(as.toCollection()); + return as -> new LinkedList<>(as.toCollection()); } /** @@ -282,7 +282,7 @@ public static F, LinkedList> Array_LinkedList() { * @return A function that converts arrays to priority queues. */ public static F, PriorityQueue> Array_PriorityQueue() { - return as -> new PriorityQueue(as.toCollection()); + return as -> new PriorityQueue<>(as.toCollection()); } /** @@ -292,7 +292,7 @@ public static F, PriorityQueue> Array_PriorityQueue() { */ public static F, Stack> Array_Stack() { return as -> { - final Stack s = new Stack(); + final Stack s = new Stack<>(); s.addAll(as.toCollection()); return s; }; @@ -304,7 +304,7 @@ public static F, Stack> Array_Stack() { * @return A function that converts arrays to tree sets. */ public static F, TreeSet> Array_TreeSet() { - return as -> new TreeSet(as.toCollection()); + return as -> new TreeSet<>(as.toCollection()); } /** @@ -313,7 +313,7 @@ public static F, TreeSet> Array_TreeSet() { * @return A function that converts arrays to vectors. */ public static F, Vector> Array_Vector() { - return as -> new Vector(as.toCollection()); + return as -> new Vector<>(as.toCollection()); } /** @@ -323,7 +323,7 @@ public static F, Vector> Array_Vector() { * @return A function that converts arrays to array blocking queues. */ public static F, ArrayBlockingQueue> Array_ArrayBlockingQueue(final boolean fair) { - return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); + return as -> new ArrayBlockingQueue<>(as.length(), fair, as.toCollection()); } /** @@ -332,7 +332,7 @@ public static F, ArrayBlockingQueue> Array_ArrayBlockingQueue(fi * @return A function that converts arrays to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Array_ConcurrentLinkedQueue() { - return as -> new ConcurrentLinkedQueue(as.toCollection()); + return as -> new ConcurrentLinkedQueue<>(as.toCollection()); } /** @@ -341,7 +341,7 @@ public static F, ConcurrentLinkedQueue> Array_ConcurrentLinkedQu * @return A function that converts arrays to copy on write array lists. */ public static F, CopyOnWriteArrayList> Array_CopyOnWriteArrayList() { - return as -> new CopyOnWriteArrayList(as.toCollection()); + return as -> new CopyOnWriteArrayList<>(as.toCollection()); } /** @@ -350,7 +350,7 @@ public static F, CopyOnWriteArrayList> Array_CopyOnWriteArrayLis * @return A function that converts arrays to copy on write array sets. */ public static F, CopyOnWriteArraySet> Array_CopyOnWriteArraySet() { - return as -> new CopyOnWriteArraySet(as.toCollection()); + return as -> new CopyOnWriteArraySet<>(as.toCollection()); } /** @@ -359,7 +359,7 @@ public static F, CopyOnWriteArraySet> Array_CopyOnWriteArraySet( * @return A function that converts arrays to delay queues. */ public static F, DelayQueue> Array_DelayQueue() { - return as -> new DelayQueue(as.toCollection()); + return as -> new DelayQueue<>(as.toCollection()); } /** @@ -368,7 +368,7 @@ public static F, DelayQueue> Array_DelayQueue() * @return A function that converts arrays to linked blocking queues. */ public static F, LinkedBlockingQueue> Array_LinkedBlockingQueue() { - return as -> new LinkedBlockingQueue(as.toCollection()); + return as -> new LinkedBlockingQueue<>(as.toCollection()); } /** @@ -377,7 +377,7 @@ public static F, LinkedBlockingQueue> Array_LinkedBlockingQueue( * @return A function that converts arrays to priority blocking queues. */ public static F, PriorityBlockingQueue> Array_PriorityBlockingQueue() { - return as -> new PriorityBlockingQueue(as.toCollection()); + return as -> new PriorityBlockingQueue<>(as.toCollection()); } /** @@ -388,7 +388,7 @@ public static F, PriorityBlockingQueue> Array_PriorityBlockingQu */ public static F, SynchronousQueue> Array_SynchronousQueue(final boolean fair) { return as -> { - final SynchronousQueue q = new SynchronousQueue(fair); + final SynchronousQueue q = new SynchronousQueue<>(fair); q.addAll(as.toCollection()); return q; }; @@ -433,7 +433,7 @@ public void remove() { * @return A function that converts streams to array lists. */ public static F, ArrayList> Stream_ArrayList() { - return as -> new ArrayList(as.toCollection()); + return as -> new ArrayList<>(as.toCollection()); } /** @@ -460,7 +460,7 @@ public static > F, EnumSet> Stream_EnumSet() { * @return A function that converts streams to hash sets. */ public static F, HashSet> Stream_HashSet() { - return as -> new HashSet(as.toCollection()); + return as -> new HashSet<>(as.toCollection()); } /** @@ -469,7 +469,7 @@ public static F, HashSet> Stream_HashSet() { * @return A function that converts streams to linked hash sets. */ public static F, LinkedHashSet> Stream_LinkedHashSet() { - return as -> new LinkedHashSet(as.toCollection()); + return as -> new LinkedHashSet<>(as.toCollection()); } /** @@ -478,7 +478,7 @@ public static F, LinkedHashSet> Stream_LinkedHashSet() { * @return A function that converts streams to linked lists. */ public static F, LinkedList> Stream_LinkedList() { - return as -> new LinkedList(as.toCollection()); + return as -> new LinkedList<>(as.toCollection()); } /** @@ -487,7 +487,7 @@ public static F, LinkedList> Stream_LinkedList() { * @return A function that converts streams to priority queues. */ public static F, PriorityQueue> Stream_PriorityQueue() { - return as -> new PriorityQueue(as.toCollection()); + return as -> new PriorityQueue<>(as.toCollection()); } /** @@ -497,7 +497,7 @@ public static F, PriorityQueue> Stream_PriorityQueue() { */ public static F, Stack> Stream_Stack() { return as -> { - final Stack s = new Stack(); + final Stack s = new Stack<>(); s.addAll(as.toCollection()); return s; }; @@ -509,7 +509,7 @@ public static F, Stack> Stream_Stack() { * @return A function that converts streams to tree sets. */ public static F, TreeSet> Stream_TreeSet() { - return as -> new TreeSet(as.toCollection()); + return as -> new TreeSet<>(as.toCollection()); } /** @@ -518,7 +518,7 @@ public static F, TreeSet> Stream_TreeSet() { * @return A function that converts streams to vectors. */ public static F, Vector> Stream_Vector() { - return as -> new Vector(as.toCollection()); + return as -> new Vector<>(as.toCollection()); } /** @@ -528,7 +528,7 @@ public static F, Vector> Stream_Vector() { * @return A function that converts streams to array blocking queues. */ public static F, ArrayBlockingQueue> Stream_ArrayBlockingQueue(final boolean fair) { - return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); + return as -> new ArrayBlockingQueue<>(as.length(), fair, as.toCollection()); } /** @@ -537,7 +537,7 @@ public static F, ArrayBlockingQueue> Stream_ArrayBlockingQueue( * @return A function that converts streams to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Stream_ConcurrentLinkedQueue() { - return as -> new ConcurrentLinkedQueue(as.toCollection()); + return as -> new ConcurrentLinkedQueue<>(as.toCollection()); } /** @@ -546,7 +546,7 @@ public static F, ConcurrentLinkedQueue> Stream_ConcurrentLinked * @return A function that converts streams to copy on write array lists. */ public static F, CopyOnWriteArrayList> Stream_CopyOnWriteArrayList() { - return as -> new CopyOnWriteArrayList(as.toCollection()); + return as -> new CopyOnWriteArrayList<>(as.toCollection()); } /** @@ -555,7 +555,7 @@ public static F, CopyOnWriteArrayList> Stream_CopyOnWriteArrayL * @return A function that converts streams to copy on write array sets. */ public static F, CopyOnWriteArraySet> Stream_CopyOnWriteArraySet() { - return as -> new CopyOnWriteArraySet(as.toCollection()); + return as -> new CopyOnWriteArraySet<>(as.toCollection()); } /** @@ -564,7 +564,7 @@ public static F, CopyOnWriteArraySet> Stream_CopyOnWriteArraySe * @return A function that converts streams to delay queues. */ public static F, DelayQueue> Stream_DelayQueue() { - return as -> new DelayQueue(as.toCollection()); + return as -> new DelayQueue<>(as.toCollection()); } /** @@ -573,7 +573,7 @@ public static F, DelayQueue> Stream_DelayQueue( * @return A function that converts streams to linked blocking queues. */ public static F, LinkedBlockingQueue> Stream_LinkedBlockingQueue() { - return as -> new LinkedBlockingQueue(as.toCollection()); + return as -> new LinkedBlockingQueue<>(as.toCollection()); } /** @@ -582,7 +582,7 @@ public static F, LinkedBlockingQueue> Stream_LinkedBlockingQueu * @return A function that converts streams to priority blocking queues. */ public static F, PriorityBlockingQueue> Stream_PriorityBlockingQueue() { - return as -> new PriorityBlockingQueue(as.toCollection()); + return as -> new PriorityBlockingQueue<>(as.toCollection()); } /** @@ -593,7 +593,7 @@ public static F, PriorityBlockingQueue> Stream_PriorityBlocking */ public static F, SynchronousQueue> Stream_SynchronousQueue(final boolean fair) { return as -> { - final SynchronousQueue q = new SynchronousQueue(fair); + final SynchronousQueue q = new SynchronousQueue<>(fair); q.addAll(as.toCollection()); return q; }; @@ -609,7 +609,7 @@ public static F, SynchronousQueue> Stream_SynchronousQueue(fina * @return A function that converts options to array lists. */ public static F, ArrayList> Option_ArrayList() { - return as -> new ArrayList(as.toCollection()); + return as -> new ArrayList<>(as.toCollection()); } /** @@ -640,7 +640,7 @@ public static > F, EnumSet> Option_EnumSet() { * @return A function that converts options to hash sets. */ public static F, HashSet> Option_HashSet() { - return as -> new HashSet(as.toCollection()); + return as -> new HashSet<>(as.toCollection()); } /** @@ -649,7 +649,7 @@ public static F, HashSet> Option_HashSet() { * @return A function that converts options to linked hash sets. */ public static F, LinkedHashSet> Option_LinkedHashSet() { - return as -> new LinkedHashSet(as.toCollection()); + return as -> new LinkedHashSet<>(as.toCollection()); } /** @@ -658,7 +658,7 @@ public static F, LinkedHashSet> Option_LinkedHashSet() { * @return A function that converts options to linked lists. */ public static F, LinkedList> Option_LinkedList() { - return as -> new LinkedList(as.toCollection()); + return as -> new LinkedList<>(as.toCollection()); } /** @@ -667,7 +667,7 @@ public static F, LinkedList> Option_LinkedList() { * @return A function that converts options to priority queues. */ public static F, PriorityQueue> Option_PriorityQueue() { - return as -> new PriorityQueue(as.toCollection()); + return as -> new PriorityQueue<>(as.toCollection()); } /** @@ -677,7 +677,7 @@ public static F, PriorityQueue> Option_PriorityQueue() { */ public static F, Stack> Option_Stack() { return as -> { - final Stack s = new Stack(); + final Stack s = new Stack<>(); s.addAll(as.toCollection()); return s; }; @@ -689,7 +689,7 @@ public static F, Stack> Option_Stack() { * @return A function that converts options to tree sets. */ public static F, TreeSet> Option_TreeSet() { - return as -> new TreeSet(as.toCollection()); + return as -> new TreeSet<>(as.toCollection()); } /** @@ -698,7 +698,7 @@ public static F, TreeSet> Option_TreeSet() { * @return A function that converts options to vectors. */ public static F, Vector> Option_Vector() { - return as -> new Vector(as.toCollection()); + return as -> new Vector<>(as.toCollection()); } /** @@ -708,7 +708,7 @@ public static F, Vector> Option_Vector() { * @return A function that converts options to array blocking queues. */ public static F, ArrayBlockingQueue> Option_ArrayBlockingQueue(final boolean fair) { - return as -> new ArrayBlockingQueue(as.length(), fair, as.toCollection()); + return as -> new ArrayBlockingQueue<>(as.length(), fair, as.toCollection()); } /** @@ -717,7 +717,7 @@ public static F, ArrayBlockingQueue> Option_ArrayBlockingQueue( * @return A function that converts options to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Option_ConcurrentLinkedQueue() { - return as -> new ConcurrentLinkedQueue(as.toCollection()); + return as -> new ConcurrentLinkedQueue<>(as.toCollection()); } /** @@ -726,7 +726,7 @@ public static F, ConcurrentLinkedQueue> Option_ConcurrentLinked * @return A function that converts options to copy on write array lists. */ public static F, CopyOnWriteArrayList> Option_CopyOnWriteArrayList() { - return as -> new CopyOnWriteArrayList(as.toCollection()); + return as -> new CopyOnWriteArrayList<>(as.toCollection()); } /** @@ -735,7 +735,7 @@ public static F, CopyOnWriteArrayList> Option_CopyOnWriteArrayL * @return A function that converts options to copy on write array sets. */ public static F, CopyOnWriteArraySet> Option_CopyOnWriteArraySet() { - return as -> new CopyOnWriteArraySet(as.toCollection()); + return as -> new CopyOnWriteArraySet<>(as.toCollection()); } /** @@ -744,7 +744,7 @@ public static F, CopyOnWriteArraySet> Option_CopyOnWriteArraySe * @return A function that converts options to delay queues. */ public static F, DelayQueue> Option_DelayQueue() { - return as -> new DelayQueue(as.toCollection()); + return as -> new DelayQueue<>(as.toCollection()); } /** @@ -753,7 +753,7 @@ public static F, DelayQueue> Option_DelayQueue( * @return A function that converts options to linked blocking queues. */ public static F, LinkedBlockingQueue> Option_LinkedBlockingQueue() { - return as -> new LinkedBlockingQueue(as.toCollection()); + return as -> new LinkedBlockingQueue<>(as.toCollection()); } /** @@ -762,7 +762,7 @@ public static F, LinkedBlockingQueue> Option_LinkedBlockingQueu * @return A function that converts options to priority blocking queues. */ public static F, PriorityBlockingQueue> Option_PriorityBlockingQueue() { - return as -> new PriorityBlockingQueue(as.toCollection()); + return as -> new PriorityBlockingQueue<>(as.toCollection()); } /** @@ -773,7 +773,7 @@ public static F, PriorityBlockingQueue> Option_PriorityBlocking */ public static F, SynchronousQueue> Option_SynchronousQueue(final boolean fair) { return as -> { - final SynchronousQueue q = new SynchronousQueue(fair); + final SynchronousQueue q = new SynchronousQueue<>(fair); q.addAll(as.toCollection()); return q; }; @@ -789,7 +789,7 @@ public static F, SynchronousQueue> Option_SynchronousQueue(fina * @return A function that converts eithers to array lists. */ public static F, ArrayList> Either_ArrayListA() { - return Function.compose(Java.Option_ArrayList(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_ArrayList(), Conversions.Either_OptionA()); } /** @@ -798,7 +798,7 @@ public static F, ArrayList> Either_ArrayListA() { * @return A function that converts eithers to array lists. */ public static F, ArrayList> Either_ArrayListB() { - return Function.compose(Java.Option_ArrayList(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_ArrayList(), Conversions.Either_OptionB()); } /** @@ -807,7 +807,7 @@ public static F, ArrayList> Either_ArrayListB() { * @return A function that converts eithers to bit sets. */ public static F, BitSet> Either_BitSetA() { - return Function.compose(Option_BitSet, Conversions.Either_OptionA()); + return Function.compose(Option_BitSet, Conversions.Either_OptionA()); } /** @@ -816,7 +816,7 @@ public static F, BitSet> Either_BitSetA() { * @return A function that converts eithers to bit sets. */ public static F, BitSet> Either_BitSetB() { - return Function.compose(Option_BitSet, Conversions.Either_OptionB()); + return Function.compose(Option_BitSet, Conversions.Either_OptionB()); } /** @@ -843,7 +843,7 @@ public static > F, EnumSet> Either_EnumSetB * @return A function that converts eithers to hash sets. */ public static F, HashSet> Either_HashSetA() { - return Function.compose(Java.Option_HashSet(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_HashSet(), Conversions.Either_OptionA()); } /** @@ -852,7 +852,7 @@ public static F, HashSet> Either_HashSetA() { * @return A function that converts eithers to hash sets. */ public static F, HashSet> Either_HashSetB() { - return Function.compose(Java.Option_HashSet(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_HashSet(), Conversions.Either_OptionB()); } /** @@ -861,7 +861,7 @@ public static F, HashSet> Either_HashSetB() { * @return A function that converts eithers to linked hash sets. */ public static F, LinkedHashSet> Either_LinkedHashSetA() { - return Function.compose(Java.Option_LinkedHashSet(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_LinkedHashSet(), Conversions.Either_OptionA()); } /** @@ -870,7 +870,7 @@ public static F, LinkedHashSet> Either_LinkedHashSetA() { * @return A function that converts eithers to linked hash sets. */ public static F, LinkedHashSet> Either_LinkedHashSetB() { - return Function.compose(Java.Option_LinkedHashSet(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_LinkedHashSet(), Conversions.Either_OptionB()); } /** @@ -879,7 +879,7 @@ public static F, LinkedHashSet> Either_LinkedHashSetB() { * @return A function that converts eithers to linked lists. */ public static F, LinkedList> Either_LinkedListA() { - return Function.compose(Java.Option_LinkedList(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_LinkedList(), Conversions.Either_OptionA()); } /** @@ -888,7 +888,7 @@ public static F, LinkedList> Either_LinkedListA() { * @return A function that eithers options to priority queues. */ public static F, PriorityQueue> Option_PriorityQueueA() { - return Function.compose(Java.Option_PriorityQueue(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_PriorityQueue(), Conversions.Either_OptionA()); } /** @@ -897,7 +897,7 @@ public static F, PriorityQueue> Option_PriorityQueueA() { * @return A function that eithers options to priority queues. */ public static F, PriorityQueue> Option_PriorityQueueB() { - return Function.compose(Java.Option_PriorityQueue(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_PriorityQueue(), Conversions.Either_OptionB()); } /** @@ -906,7 +906,7 @@ public static F, PriorityQueue> Option_PriorityQueueB() { * @return A function that converts eithers to linked lists. */ public static F, LinkedList> Either_LinkedListB() { - return Function.compose(Java.Option_LinkedList(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_LinkedList(), Conversions.Either_OptionB()); } /** @@ -915,7 +915,7 @@ public static F, LinkedList> Either_LinkedListB() { * @return A function that converts eithers to stacks. */ public static F, Stack> Either_StackA() { - return Function.compose(Java.Option_Stack(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_Stack(), Conversions.Either_OptionA()); } /** @@ -924,7 +924,7 @@ public static F, Stack> Either_StackA() { * @return A function that converts eithers to stacks. */ public static F, Stack> Either_StackB() { - return Function.compose(Java.Option_Stack(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_Stack(), Conversions.Either_OptionB()); } /** @@ -933,7 +933,7 @@ public static F, Stack> Either_StackB() { * @return A function that converts eithers to tree sets. */ public static F, TreeSet> Either_TreeSetA() { - return Function.compose(Java.Option_TreeSet(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_TreeSet(), Conversions.Either_OptionA()); } /** @@ -942,7 +942,7 @@ public static F, TreeSet> Either_TreeSetA() { * @return A function that converts eithers to tree sets. */ public static F, TreeSet> Either_TreeSetB() { - return Function.compose(Java.Option_TreeSet(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_TreeSet(), Conversions.Either_OptionB()); } /** @@ -951,7 +951,7 @@ public static F, TreeSet> Either_TreeSetB() { * @return A function that converts eithers to vectors. */ public static F, Vector> Either_VectorA() { - return Function.compose(Java.Option_Vector(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_Vector(), Conversions.Either_OptionA()); } /** @@ -960,7 +960,7 @@ public static F, Vector> Either_VectorA() { * @return A function that converts eithers to vectors. */ public static F, Vector> Either_VectorB() { - return Function.compose(Java.Option_Vector(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_Vector(), Conversions.Either_OptionB()); } /** @@ -970,7 +970,7 @@ public static F, Vector> Either_VectorB() { * @return A function that converts eithers to array blocking queues. */ public static F, ArrayBlockingQueue> Either_ArrayBlockingQueueA(final boolean fair) { - return Function.compose(Java.Option_ArrayBlockingQueue(fair), Conversions.Either_OptionA()); + return Function.compose(Java.Option_ArrayBlockingQueue(fair), Conversions.Either_OptionA()); } /** @@ -980,7 +980,7 @@ public static F, ArrayBlockingQueue> Either_ArrayBlocking * @return A function that converts eithers to array blocking queues. */ public static F, ArrayBlockingQueue> Either_ArrayBlockingQueueB(final boolean fair) { - return Function.compose(Java.Option_ArrayBlockingQueue(fair), Conversions.Either_OptionB()); + return Function.compose(Java.Option_ArrayBlockingQueue(fair), Conversions.Either_OptionB()); } /** @@ -989,7 +989,7 @@ public static F, ArrayBlockingQueue> Either_ArrayBlocking * @return A function that converts eithers to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Either_ConcurrentLinkedQueueA() { - return Function.compose(Java.Option_ConcurrentLinkedQueue(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_ConcurrentLinkedQueue(), Conversions.Either_OptionA()); } /** @@ -998,7 +998,7 @@ public static F, ConcurrentLinkedQueue> Either_Concurrent * @return A function that converts eithers to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Either_ConcurrentLinkedQueueB() { - return Function.compose(Java.Option_ConcurrentLinkedQueue(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_ConcurrentLinkedQueue(), Conversions.Either_OptionB()); } /** @@ -1007,7 +1007,7 @@ public static F, ConcurrentLinkedQueue> Either_Concurrent * @return A function that converts eithers to copy on write array lists. */ public static F, CopyOnWriteArrayList> Either_CopyOnWriteArrayListA() { - return Function.compose(Java.Option_CopyOnWriteArrayList(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_CopyOnWriteArrayList(), Conversions.Either_OptionA()); } /** @@ -1016,7 +1016,7 @@ public static F, CopyOnWriteArrayList> Either_CopyOnWrite * @return A function that converts eithers to copy on write array lists. */ public static F, CopyOnWriteArrayList> Either_CopyOnWriteArrayListB() { - return Function.compose(Java.Option_CopyOnWriteArrayList(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_CopyOnWriteArrayList(), Conversions.Either_OptionB()); } /** @@ -1025,7 +1025,7 @@ public static F, CopyOnWriteArrayList> Either_CopyOnWrite * @return A function that converts eithers to copy on write array sets. */ public static F, CopyOnWriteArraySet> Either_CopyOnWriteArraySetA() { - return Function.compose(Java.Option_CopyOnWriteArraySet(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_CopyOnWriteArraySet(), Conversions.Either_OptionA()); } /** @@ -1034,7 +1034,7 @@ public static F, CopyOnWriteArraySet> Either_CopyOnWriteA * @return A function that converts eithers to copy on write array sets. */ public static F, CopyOnWriteArraySet> Either_CopyOnWriteArraySetB() { - return Function.compose(Java.Option_CopyOnWriteArraySet(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_CopyOnWriteArraySet(), Conversions.Either_OptionB()); } /** @@ -1043,7 +1043,7 @@ public static F, CopyOnWriteArraySet> Either_CopyOnWriteA * @return A function that converts eithers to delay queues. */ public static F, DelayQueue> Either_DelayQueueA() { - return Function.compose(Java.Option_DelayQueue(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_DelayQueue(), Conversions.Either_OptionA()); } /** @@ -1052,7 +1052,7 @@ public static F, DelayQueue> Either_Delay * @return A function that converts eithers to delay queues. */ public static F, DelayQueue> Either_DelayQueueB() { - return Function.compose(Java.Option_DelayQueue(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_DelayQueue(), Conversions.Either_OptionB()); } /** @@ -1061,7 +1061,7 @@ public static F, DelayQueue> Either_Delay * @return A function that converts eithers to linked blocking queues. */ public static F, LinkedBlockingQueue> Either_LinkedBlockingQueueA() { - return Function.compose(Java.Option_LinkedBlockingQueue(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_LinkedBlockingQueue(), Conversions.Either_OptionA()); } /** @@ -1070,7 +1070,7 @@ public static F, LinkedBlockingQueue> Either_LinkedBlocki * @return A function that converts eithers to linked blocking queues. */ public static F, LinkedBlockingQueue> Either_LinkedBlockingQueueB() { - return Function.compose(Java.Option_LinkedBlockingQueue(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_LinkedBlockingQueue(), Conversions.Either_OptionB()); } /** @@ -1079,7 +1079,7 @@ public static F, LinkedBlockingQueue> Either_LinkedBlocki * @return A function that converts eithers to priority blocking queues. */ public static F, PriorityBlockingQueue> Either_PriorityBlockingQueueA() { - return Function.compose(Java.Option_PriorityBlockingQueue(), Conversions.Either_OptionA()); + return Function.compose(Java.Option_PriorityBlockingQueue(), Conversions.Either_OptionA()); } /** @@ -1088,7 +1088,7 @@ public static F, PriorityBlockingQueue> Either_PriorityBl * @return A function that converts eithers to priority blocking queues. */ public static F, PriorityBlockingQueue> Either_PriorityBlockingQueueB() { - return Function.compose(Java.Option_PriorityBlockingQueue(), Conversions.Either_OptionB()); + return Function.compose(Java.Option_PriorityBlockingQueue(), Conversions.Either_OptionB()); } /** @@ -1098,7 +1098,7 @@ public static F, PriorityBlockingQueue> Either_PriorityBl * @return A function that converts eithers to synchronous queues. */ public static F, SynchronousQueue> Either_SynchronousQueueA(final boolean fair) { - return Function.compose(Java.Option_SynchronousQueue(fair), Conversions.Either_OptionA()); + return Function.compose(Java.Option_SynchronousQueue(fair), Conversions.Either_OptionA()); } /** @@ -1108,7 +1108,7 @@ public static F, SynchronousQueue> Either_SynchronousQueu * @return A function that converts eithers to synchronous queues. */ public static F, SynchronousQueue> Either_SynchronousQueueB(final boolean fair) { - return Function.compose(Java.Option_SynchronousQueue(fair), Conversions.Either_OptionB()); + return Function.compose(Java.Option_SynchronousQueue(fair), Conversions.Either_OptionB()); } // END Either -> @@ -1119,49 +1119,49 @@ public static F, SynchronousQueue> Either_SynchronousQueu * A function that converts strings to array lists. */ public static final F> String_ArrayList = - Function.compose(Java.List_ArrayList(), Conversions.String_List); + Function.compose(Java.List_ArrayList(), Conversions.String_List); /** * A function that converts strings to hash sets. */ public static final F> String_HashSet = - Function.compose(Java.List_HashSet(), Conversions.String_List); + Function.compose(Java.List_HashSet(), Conversions.String_List); /** * A function that converts strings to linked hash sets. */ public static final F> String_LinkedHashSet = - Function.compose(Java.List_LinkedHashSet(), Conversions.String_List); + Function.compose(Java.List_LinkedHashSet(), Conversions.String_List); /** * A function that converts strings to linked lists. */ public static final F> String_LinkedList = - Function.compose(Java.List_LinkedList(), Conversions.String_List); + Function.compose(Java.List_LinkedList(), Conversions.String_List); /** * A function that converts strings to priority queues. */ public static final F> String_PriorityQueue = - Function.compose(Java.List_PriorityQueue(), Conversions.String_List); + Function.compose(Java.List_PriorityQueue(), Conversions.String_List); /** * A function that converts strings to stacks. */ public static final F> String_Stack = - Function.compose(Java.List_Stack(), Conversions.String_List); + Function.compose(Java.List_Stack(), Conversions.String_List); /** * A function that converts strings to tree sets. */ public static final F> String_TreeSet = - Function.compose(Java.List_TreeSet(), Conversions.String_List); + Function.compose(Java.List_TreeSet(), Conversions.String_List); /** * A function that converts strings to vectors. */ public static final F> String_Vector = - Function.compose(Java.List_Vector(), Conversions.String_List); + Function.compose(Java.List_Vector(), Conversions.String_List); /** * A function that converts strings to array blocking queues. @@ -1170,38 +1170,38 @@ public static F, SynchronousQueue> Either_SynchronousQueu * @return A function that converts strings to array blocking queues. */ public static F> String_ArrayBlockingQueue(final boolean fair) { - return Function.compose(Java.List_ArrayBlockingQueue(fair), Conversions.String_List); + return Function.compose(Java.List_ArrayBlockingQueue(fair), Conversions.String_List); } /** * A function that converts strings to concurrent linked queues. */ public static final F> String_ConcurrentLinkedQueue = - Function.compose(Java.List_ConcurrentLinkedQueue(), Conversions.String_List); + Function.compose(Java.List_ConcurrentLinkedQueue(), Conversions.String_List); /** * A function that converts strings to copy on write array lists. */ public static final F> String_CopyOnWriteArrayList = - Function.compose(Java.List_CopyOnWriteArrayList(), Conversions.String_List); + Function.compose(Java.List_CopyOnWriteArrayList(), Conversions.String_List); /** * A function that converts strings to copy on write array sets. */ public static final F> String_CopyOnWriteArraySet = - Function.compose(Java.List_CopyOnWriteArraySet(), Conversions.String_List); + Function.compose(Java.List_CopyOnWriteArraySet(), Conversions.String_List); /** * A function that converts strings to linked blocking queues. */ public static final F> String_LinkedBlockingQueue = - Function.compose(Java.List_LinkedBlockingQueue(), Conversions.String_List); + Function.compose(Java.List_LinkedBlockingQueue(), Conversions.String_List); /** * A function that converts strings to priority blocking queues. */ public static final F> String_PriorityBlockingQueue = - Function.compose(Java.List_PriorityBlockingQueue(), Conversions.String_List); + Function.compose(Java.List_PriorityBlockingQueue(), Conversions.String_List); /** * A function that converts strings to synchronous queues. @@ -1210,7 +1210,7 @@ public static F> String_ArrayBlockingQueue * @return A function that converts strings to synchronous queues. */ public static F> String_SynchronousQueue(final boolean fair) { - return Function.compose(Java.List_SynchronousQueue(fair), Conversions.String_List); + return Function.compose(Java.List_SynchronousQueue(fair), Conversions.String_List); } // END String -> @@ -1221,49 +1221,49 @@ public static F> String_SynchronousQueue(fin * A function that converts string buffers to array lists. */ public static final F> StringBuffer_ArrayList = - Function.compose(Java.List_ArrayList(), Conversions.StringBuffer_List); + Function.compose(Java.List_ArrayList(), Conversions.StringBuffer_List); /** * A function that converts string buffers to hash sets. */ public static final F> StringBuffer_HashSet = - Function.compose(Java.List_HashSet(), Conversions.StringBuffer_List); + Function.compose(Java.List_HashSet(), Conversions.StringBuffer_List); /** * A function that converts string buffers to linked hash sets. */ public static final F> StringBuffer_LinkedHashSet = - Function.compose(Java.List_LinkedHashSet(), Conversions.StringBuffer_List); + Function.compose(Java.List_LinkedHashSet(), Conversions.StringBuffer_List); /** * A function that converts string buffers to linked lists. */ public static final F> StringBuffer_LinkedList = - Function.compose(Java.List_LinkedList(), Conversions.StringBuffer_List); + Function.compose(Java.List_LinkedList(), Conversions.StringBuffer_List); /** * A function that converts string buffers to priority queues. */ public static final F> StringBuffer_PriorityQueue = - Function.compose(Java.List_PriorityQueue(), Conversions.StringBuffer_List); + Function.compose(Java.List_PriorityQueue(), Conversions.StringBuffer_List); /** * A function that converts string buffers to stacks. */ public static final F> StringBuffer_Stack = - Function.compose(Java.List_Stack(), Conversions.StringBuffer_List); + Function.compose(Java.List_Stack(), Conversions.StringBuffer_List); /** * A function that converts string buffers to tree sets. */ public static final F> StringBuffer_TreeSet = - Function.compose(Java.List_TreeSet(), Conversions.StringBuffer_List); + Function.compose(Java.List_TreeSet(), Conversions.StringBuffer_List); /** * A function that converts string buffers to vectors. */ public static final F> StringBuffer_Vector = - Function.compose(Java.List_Vector(), Conversions.StringBuffer_List); + Function.compose(Java.List_Vector(), Conversions.StringBuffer_List); /** * A function that converts string buffers to array blocking queues. @@ -1272,38 +1272,38 @@ public static F> String_SynchronousQueue(fin * @return A function that converts string buffers to array blocking queues. */ public static F> StringBuffer_ArrayBlockingQueue(final boolean fair) { - return Function.compose(Java.List_ArrayBlockingQueue(fair), Conversions.StringBuffer_List); + return Function.compose(Java.List_ArrayBlockingQueue(fair), Conversions.StringBuffer_List); } /** * A function that converts string buffers to concurrent linked queues. */ public static final F> StringBuffer_ConcurrentLinkedQueue = - Function.compose(Java.List_ConcurrentLinkedQueue(), Conversions.StringBuffer_List); + Function.compose(Java.List_ConcurrentLinkedQueue(), Conversions.StringBuffer_List); /** * A function that converts string buffers to copy on write array lists. */ public static final F> StringBuffer_CopyOnWriteArrayList = - Function.compose(Java.List_CopyOnWriteArrayList(), Conversions.StringBuffer_List); + Function.compose(Java.List_CopyOnWriteArrayList(), Conversions.StringBuffer_List); /** * A function that converts string buffers to copy on write array sets. */ public static final F> StringBuffer_CopyOnWriteArraySet = - Function.compose(Java.List_CopyOnWriteArraySet(), Conversions.StringBuffer_List); + Function.compose(Java.List_CopyOnWriteArraySet(), Conversions.StringBuffer_List); /** * A function that converts string buffers to linked blocking queues. */ public static final F> StringBuffer_LinkedBlockingQueue = - Function.compose(Java.List_LinkedBlockingQueue(), Conversions.StringBuffer_List); + Function.compose(Java.List_LinkedBlockingQueue(), Conversions.StringBuffer_List); /** * A function that converts string buffers to priority blocking queues. */ public static final F> StringBuffer_PriorityBlockingQueue = - Function.compose(Java.List_PriorityBlockingQueue(), Conversions.StringBuffer_List); + Function.compose(Java.List_PriorityBlockingQueue(), Conversions.StringBuffer_List); /** * A function that converts string buffers to synchronous queues. @@ -1312,7 +1312,7 @@ public static F> StringBuffer_ArrayB * @return A function that converts string buffers to synchronous queues. */ public static F> StringBuffer_SynchronousQueue(final boolean fair) { - return Function.compose(Java.List_SynchronousQueue(fair), Conversions.StringBuffer_List); + return Function.compose(Java.List_SynchronousQueue(fair), Conversions.StringBuffer_List); } // END StringBuffer -> @@ -1323,49 +1323,49 @@ public static F> StringBuffer_Synchron * A function that converts string builders to array lists. */ public static final F> StringBuilder_ArrayList = - Function.compose(Java.List_ArrayList(), Conversions.StringBuilder_List); + Function.compose(Java.List_ArrayList(), Conversions.StringBuilder_List); /** * A function that converts string builders to hash sets. */ public static final F> StringBuilder_HashSet = - Function.compose(Java.List_HashSet(), Conversions.StringBuilder_List); + Function.compose(Java.List_HashSet(), Conversions.StringBuilder_List); /** * A function that converts string builders to linked hash sets. */ public static final F> StringBuilder_LinkedHashSet = - Function.compose(Java.List_LinkedHashSet(), Conversions.StringBuilder_List); + Function.compose(Java.List_LinkedHashSet(), Conversions.StringBuilder_List); /** * A function that converts string builders to linked lists. */ public static final F> StringBuilder_LinkedList = - Function.compose(Java.List_LinkedList(), Conversions.StringBuilder_List); + Function.compose(Java.List_LinkedList(), Conversions.StringBuilder_List); /** * A function that converts string builders to priority queues. */ public static final F> StringBuilder_PriorityQueue = - Function.compose(Java.List_PriorityQueue(), Conversions.StringBuilder_List); + Function.compose(Java.List_PriorityQueue(), Conversions.StringBuilder_List); /** * A function that converts string builders to stacks. */ public static final F> StringBuilder_Stack = - Function.compose(Java.List_Stack(), Conversions.StringBuilder_List); + Function.compose(Java.List_Stack(), Conversions.StringBuilder_List); /** * A function that converts string builders to tree sets. */ public static final F> StringBuilder_TreeSet = - Function.compose(Java.List_TreeSet(), Conversions.StringBuilder_List); + Function.compose(Java.List_TreeSet(), Conversions.StringBuilder_List); /** * A function that converts string builders to vectors. */ public static final F> StringBuilder_Vector = - Function.compose(Java.List_Vector(), Conversions.StringBuilder_List); + Function.compose(Java.List_Vector(), Conversions.StringBuilder_List); /** * A function that converts string builders to array blocking queues. @@ -1374,38 +1374,38 @@ public static F> StringBuffer_Synchron * @return A function that converts string builders to array blocking queues. */ public static F> StringBuilder_ArrayBlockingQueue(final boolean fair) { - return Function.compose(Java.List_ArrayBlockingQueue(fair), Conversions.StringBuilder_List); + return Function.compose(Java.List_ArrayBlockingQueue(fair), Conversions.StringBuilder_List); } /** * A function that converts string builders to concurrent linked queues. */ public static final F> StringBuilder_ConcurrentLinkedQueue = - Function.compose(Java.List_ConcurrentLinkedQueue(), Conversions.StringBuilder_List); + Function.compose(Java.List_ConcurrentLinkedQueue(), Conversions.StringBuilder_List); /** * A function that converts string builders to copy on write array lists. */ public static final F> StringBuilder_CopyOnWriteArrayList = - Function.compose(Java.List_CopyOnWriteArrayList(), Conversions.StringBuilder_List); + Function.compose(Java.List_CopyOnWriteArrayList(), Conversions.StringBuilder_List); /** * A function that converts string builders to copy on write array sets. */ public static final F> StringBuilder_CopyOnWriteArraySet = - Function.compose(Java.List_CopyOnWriteArraySet(), Conversions.StringBuilder_List); + Function.compose(Java.List_CopyOnWriteArraySet(), Conversions.StringBuilder_List); /** * A function that converts string builders to linked blocking queues. */ public static final F> StringBuilder_LinkedBlockingQueue = - Function.compose(Java.List_LinkedBlockingQueue(), Conversions.StringBuilder_List); + Function.compose(Java.List_LinkedBlockingQueue(), Conversions.StringBuilder_List); /** * A function that converts string builders to priority blocking queues. */ public static final F> StringBuilder_PriorityBlockingQueue = - Function.compose(Java.List_PriorityBlockingQueue(), Conversions.StringBuilder_List); + Function.compose(Java.List_PriorityBlockingQueue(), Conversions.StringBuilder_List); /** * A function that converts string builders to synchronous queues. @@ -1414,7 +1414,7 @@ public static F> StringBuilder_Arra * @return A function that converts string builders to synchronous queues. */ public static F> StringBuilder_SynchronousQueue(final boolean fair) { - return Function.compose(Java.List_SynchronousQueue(fair), Conversions.StringBuilder_List); + return Function.compose(Java.List_SynchronousQueue(fair), Conversions.StringBuilder_List); } // END StringBuffer -> @@ -1458,7 +1458,7 @@ public static List JavaList_List(java.util.List list) { * A function that converts bit sets to lists. */ public static final F> BitSet_List = s -> List.unfold(i -> i == s.length() ? - Option.>none() : + Option.none() : some(p(s.get(i), i + 1)), 0); // todo @@ -1481,7 +1481,7 @@ public static List Collection_List(Collection c) { } public static F, List> Collection_List() { - return c -> List.list(c.toArray(array(c.size()))); + return c -> List.list(c.toArray(array(c.size()))); } @SafeVarargs diff --git a/core/src/main/java/fj/data/LazyString.java b/core/src/main/java/fj/data/LazyString.java index 2583621f..3e393cf8 100644 --- a/core/src/main/java/fj/data/LazyString.java +++ b/core/src/main/java/fj/data/LazyString.java @@ -256,7 +256,7 @@ public boolean matches(final String regex) { public Stream split(final F p) { final Stream findIt = s.dropWhile(p); final P2, Stream> ws = findIt.split(p); - return findIt.isEmpty() ? Stream.nil() + return findIt.isEmpty() ? Stream.nil() : Stream.cons(fromStream(ws._1()), () -> fromStream(ws._2()).split(p)); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 5a2e2504..399cc016 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -167,7 +167,7 @@ public final Option toOption() { * @return The optional head of the list. */ public Option headOption() { - return isEmpty() ? Option.none() : some(head()); + return isEmpty() ? Option.none() : some(head()); } /** @@ -178,7 +178,7 @@ public Option headOption() { * @return An either projection of this list. */ public final Either toEither(final F0 x) { - return isEmpty() ? Either.left(x.f()) : Either.right(head()); + return isEmpty() ? Either.left(x.f()) : Either.right(head()); } /** @@ -258,7 +258,7 @@ public final A[] array(final Class c) { * @return A new list with the given element at the head. */ public final List cons(final A a) { - return new Cons(a, this); + return new Cons<>(a, this); } /** @@ -269,7 +269,7 @@ public final List cons(final A a) { * @return A new list with the given element at the head. */ public final List conss(final A a) { - return new Cons(a, this); + return new Cons<>(a, this); } /** @@ -412,7 +412,7 @@ public final P2, List> span(final F p) { else return p(b.toList(), xs); } - return p(b.toList(), List.nil()); + return p(b.toList(), List.nil()); } /** @@ -614,7 +614,7 @@ public final List sequence(final List bs) { public Option> traverseOption(final F> f) { return foldRight( (a, obs) -> f.f(a).bind(o -> obs.map(os -> os.cons(o))), - some(List.nil()) + some(List.nil()) ); } @@ -627,67 +627,67 @@ public Option> traverseOption(final F> f) { public Either> traverseEither(final F> f) { return foldRight( (a, acc) -> f.f(a).right().bind(e -> acc.right().map(es -> es.cons(e))), - Either.>right(List.nil()) + Either.right(List.nil()) ); } public Stream> traverseStream(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(s -> acc.map(ss -> ss.cons(s))), - Stream.>nil() + Stream.nil() ); } public P1> traverseP1(final F> f){ return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - p(List.nil()) + p(List.nil()) ); } public IO> traverseIO(F> f) { return this.foldRight( (a, acc) -> IOFunctions.bind(f.f(a), b -> IOFunctions.map(acc, bs -> bs.cons(b))), - IOFunctions.unit(List.nil()) + IOFunctions.unit(List.nil()) ); } public F> traverseF(F> f) { return this.foldRight( (a, acc) -> Function.bind(acc, - (bs) -> Function.> compose(bs::cons, f.f(a))), - constant(List. nil()) + (bs) -> Function.compose(bs::cons, f.f(a))), + constant(List.nil()) ); } public Trampoline> traverseTrampoline(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - Trampoline.pure(List. nil())); + Trampoline.pure(List.nil())); } public Promise> traversePromise(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.fmap(bs -> bs.cons(b))), - Promise.promise(Strategy.idStrategy(), p(List. nil()))); + Promise.promise(Strategy.idStrategy(), p(List.nil()))); } public List> traverseList(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - single(List. nil())); + single(List.nil())); } public Validation> traverseValidation(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - Validation.success(List. nil())); + Validation.success(List.nil())); } public V2> traverseV2(final F> f) { return foldRight( (a, acc) -> acc.apply(f.f(a)., List>> map(e -> es -> es.cons(e))), - v(List. nil(), List. nil())); + v(List.nil(), List.nil())); } /** @@ -800,7 +800,7 @@ public final A foldLeft1(final F> f) { * @return A new list that is the reverse of this one. */ public final List reverse() { - return foldLeft(as -> a -> cons(a, as), List.nil()); + return foldLeft(as -> a -> cons(a, as), List.nil()); } /** @@ -865,7 +865,7 @@ public final List drop(final int i) { */ public final P2, List> splitAt(final int i) { int c = 0; - List first = List.nil(); + List first = List.nil(); List second = nil(); for (List xs = this; xs.isNotEmpty(); xs = xs.tail()) { final A h = xs.head(); @@ -891,7 +891,7 @@ public final List> partition(final int n) { throw error("Can't create list partitions shorter than 1 element long."); if (isEmpty()) throw error("Partition on empty list."); - return unfold(as -> as.isEmpty() ? Option., List>>none() : some(as.splitAt(n)), this); + return unfold(as -> as.isEmpty() ? Option.none() : some(as.splitAt(n)), this); } /** @@ -916,7 +916,7 @@ public P2, List> partition(F f) { * @return The list of initial segments of this list, shortest first. */ public final List> inits() { - List> s = single(List.nil()); + List> s = single(List.nil()); if (isNotEmpty()) s = s.append(tail().inits().map(List.cons().f(head()))); return s; @@ -928,7 +928,7 @@ public final List> inits() { * @return The list of final segments of this list, longest first. */ public final List> tails() { - return isEmpty() ? single(List.nil()) : cons(this, tail().tails()); + return isEmpty() ? single(List.nil()) : cons(this, tail().tails()); } /** @@ -1133,7 +1133,7 @@ public final List intercalate(final List> as) { * @return A list without duplicates according to object equality. */ public final List nub() { - return nub(Equal.anyEqual()); + return nub(Equal.anyEqual()); } /** @@ -1154,7 +1154,7 @@ public final List nub(final Equal eq) { */ @SuppressWarnings("unchecked") public final List nub(final Ord o) { - return sort(o).group(o.equal()).map(List.head_()); + return sort(o).group(o.equal()).map(List.head_()); } @@ -1227,7 +1227,7 @@ public final Option> mapMOption(final F> f) { * @return A list of values in the Trampoline monad. */ public final Trampoline> mapMTrampoline(final F> f) { - return foldRight((a, bs) -> f.f(a).bind(b -> bs.map(bbs -> bbs.cons(b))), Trampoline.>pure(List.nil())); + return foldRight((a, bs) -> f.f(a).bind(b -> bs.map(bbs -> bbs.cons(b))), Trampoline.pure(List.nil())); } /** @@ -1296,7 +1296,7 @@ public final List insertBy(final F> f, final A x) { * @return The most common element in this list. */ public final A mode(final Ord o) { - return sort(o).group(o.equal()).maximum(intOrd.contramap(List.length_())).head(); + return sort(o).group(o.equal()).maximum(intOrd.contramap(List.length_())).head(); } /** @@ -1350,7 +1350,7 @@ public final TreeMap> groupBy( final F keyFunction, final F valueFunction, final Ord keyOrd) { - return this.>groupBy(keyFunction, valueFunction, List.nil(), List::cons, keyOrd); + return this.groupBy(keyFunction, valueFunction, List.nil(), List::cons, keyOrd); } /** @@ -1398,7 +1398,7 @@ public final TreeMap groupBy( return map.set(key, map.get(key) .map(existing -> groupingAcc.f(value, existing)) .orSome(groupingAcc.f(value, groupingIdentity))); - }, TreeMap.empty(keyOrd) + }, TreeMap.empty(keyOrd) ); } @@ -1470,7 +1470,7 @@ public final A minimum(final Ord o) { } public final java.util.List toJavaList() { - return new java.util.LinkedList(toCollection()); + return new java.util.LinkedList<>(toCollection()); } /** @@ -1511,7 +1511,7 @@ public int size() { } private static final class Nil extends List { - public static final Nil INSTANCE = new Nil(); + public static final Nil INSTANCE = new Nil<>(); public A head() { throw error("head on empty list"); @@ -1638,7 +1638,7 @@ public static F, List> cons_(final A a) { * @return The list with the given element prepended. */ public static List cons(final A head, final List tail) { - return new Cons(head, tail); + return new Cons<>(head, tail); } /** @@ -1798,7 +1798,7 @@ public static F, String> asString() { * @return A list of one element containing the given value. */ public static List single(final A a) { - return cons(a, List.nil()); + return cons(a, List.nil()); } /** @@ -1826,7 +1826,7 @@ public static List iterateWhile(final F f, final F p, f * @return An associated value with the given key in the list of pairs. */ public static Option lookup(final Equal e, final List> x, final A a) { - return x.find(p -> e.eq(p._1(), a)).map(P2.__2()); + return x.find(p -> e.eq(p._1(), a)).map(P2.__2()); } /** @@ -1865,8 +1865,8 @@ public static F, F, List>> map_() { * and returns a list of the results. */ public static F> sequence_(final List> fs) { - return fs.foldRight(Function., List, B>lift(List.cons()), Function - .>constant(List.nil())); + return fs.foldRight(Function.lift(List.cons()), Function + .constant(List.nil())); } /** @@ -1936,7 +1936,7 @@ public Buffer snoc(final A a) { if (exported) copy(); - final Cons t = new Cons(a, List.nil()); + final Cons t = new Cons<>(a, List.nil()); if (tail == null) start = t; @@ -2009,7 +2009,7 @@ public Collection toCollection() { * @return An empty buffer. */ public static Buffer empty() { - return new Buffer(); + return new Buffer<>(); } /** @@ -2019,7 +2019,7 @@ public static Buffer empty() { * @return A buffer from the given list. */ public static Buffer fromList(final List as) { - final Buffer b = new Buffer(); + final Buffer b = new Buffer<>(); for (List xs = as; xs.isNotEmpty(); xs = xs.tail()) b.snoc(xs.head()); @@ -2067,7 +2067,7 @@ private void copy() { * @return true if this list is equal to the provided argument */ @Override public boolean equals( final Object obj ) { - return Equal.equals0(List.class, this, obj, () -> Equal.listEqual(Equal.anyEqual())); + return Equal.equals0(List.class, this, obj, () -> Equal.listEqual(Equal.anyEqual())); } /** diff --git a/core/src/main/java/fj/data/Natural.java b/core/src/main/java/fj/data/Natural.java index 1779d8c7..23080a49 100644 --- a/core/src/main/java/fj/data/Natural.java +++ b/core/src/main/java/fj/data/Natural.java @@ -32,7 +32,7 @@ private Natural(final BigInteger i) { */ public static Option natural(final BigInteger i) { return i.compareTo(BigInteger.ZERO) < 0 - ? Option.none() + ? Option.none() : Option.some(new Natural(i)); } diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index c8dd4cca..013b287c 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -79,7 +79,7 @@ public NonEmptyList snoc(final A a) { * @return A new list with the given list appended. */ public NonEmptyList append(final NonEmptyList as) { - final List.Buffer b = new List.Buffer(); + final List.Buffer b = new List.Buffer<>(); b.append(tail); b.snoc(as.head); b.append(as.tail); @@ -104,7 +104,7 @@ public NonEmptyList map(final F f) { * @return A new list after performing the map, then final join. */ public NonEmptyList bind(final F> f) { - final List.Buffer b = new List.Buffer(); + final List.Buffer b = new List.Buffer<>(); final NonEmptyList p = f.f(head); b.snoc(p.head); b.append(p.tail); @@ -125,7 +125,7 @@ public NonEmptyList bind(final F> f) { public NonEmptyList> sublists() { return fromList( somes(toList().toStream().substreams() - .map(F1Functions.o(NonEmptyList::fromList, Conversions.Stream_List())).toList())).some(); + .map(F1Functions.o(NonEmptyList::fromList, Conversions.Stream_List())).toList())).some(); } /** @@ -277,7 +277,7 @@ public static F, List> toList_() { * @return A non-empty list with the given head and tail. */ public static NonEmptyList nel(final A head, final List tail) { - return new NonEmptyList(head, tail); + return new NonEmptyList<>(head, tail); } /** @@ -308,7 +308,7 @@ public static F> nel() { */ public static Option> fromList(final List as) { return as.isEmpty() ? - Option.>none() : + Option.none() : some(nel(as.head(), as.tail())); } @@ -328,7 +328,7 @@ public static Option> fromList(final List as) { * @return true if this list is equal to the provided argument */ @Override public boolean equals( final Object obj ) { - return Equal.equals0(NonEmptyList.class, this, obj, () -> Equal.nonEmptyListEqual(Equal.anyEqual())); + return Equal.equals0(NonEmptyList.class, this, obj, () -> Equal.nonEmptyListEqual(Equal.anyEqual())); } @Override public int hashCode() { diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 5c8dca74..1ec77980 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -191,7 +191,7 @@ public final A valueE(final String message) { * @return A new optional value after the given function has been applied to its element. */ public final Option map(final F f) { - return isSome() ? some(f.f(some())) : Option.none(); + return isSome() ? some(f.f(some())) : Option.none(); } /** @@ -231,7 +231,7 @@ public final void foreachDoEffect(final Effect1 f) { * @return A new optional value whose value matches the given predicate if it has one. */ public final Option filter(final F f) { - return isSome() ? f.f(some()) ? this : Option.none() : Option.none(); + return isSome() ? f.f(some()) ? this : Option.none() : Option.none(); } /** @@ -241,7 +241,7 @@ public final Option filter(final F f) { * @return A new optional value after performing the map, then final join. */ public final Option bind(final F> f) { - return isSome() ? f.f(some()) : Option.none(); + return isSome() ? f.f(some()) : Option.none(); } /** @@ -366,38 +366,38 @@ public final Option bind(final Option ob, final Option oc, } public final Option> bindProduct(final Option ob) { - return bind(ob, P.p2()); + return bind(ob, P.p2()); } public final Option> bindProduct(final Option ob, final Option oc) { - return bind(ob, oc, P.p3()); + return bind(ob, oc, P.p3()); } public final Option> bindProduct(final Option ob, final Option oc, final Option od) { - return bind(ob, oc, od, P.p4()); + return bind(ob, oc, od, P.p4()); } public final Option> bindProduct(final Option ob, final Option oc, final Option od, final Option oe) { - return bind(ob, oc, od, oe, P.p5()); + return bind(ob, oc, od, oe, P.p5()); } public final Option> bindProduct(final Option ob, final Option oc, final Option od, final Option oe, final Option of) { - return bind(ob, oc, od, oe, of, P.p6()); + return bind(ob, oc, od, oe, of, P.p6()); } public final Option> bindProduct(final Option ob, final Option oc, final Option od, final Option oe, final Option of, final Option og) { - return bind(ob, oc, od, oe, of, og, P.p7()); + return bind(ob, oc, od, oe, of, og, P.p7()); } public final Option> bindProduct(final Option ob, final Option oc, final Option od, final Option oe, final Option of, final Option og, final Option oh) { - return bind(ob, oc, od, oe, of, og, oh, P.p8()); + return bind(ob, oc, od, oe, of, og, oh, P.p8()); } /** @@ -491,7 +491,7 @@ public final Option orElse(final Option o) { * @return An either projection of this optional value. */ public final Either toEither(final F0 x) { - return isSome() ? Either.right(some()) : Either.left(x.f()); + return isSome() ? Either.right(some()) : Either.left(x.f()); } /** @@ -502,7 +502,7 @@ public final Either toEither(final F0 x) { * @return An either projection of this optional value. */ public final Either toEither(final X x) { - return isSome() ? Either.right(some()) : Either.left(x); + return isSome() ? Either.right(some()) : Either.left(x); } public final Validation toValidation(final X x) { @@ -525,7 +525,7 @@ public static F, F>> toEither() { * @return A list projection of this optional value. */ public final List toList() { - return isSome() ? cons(some(), List.nil()) : List.nil(); + return isSome() ? cons(some(), List.nil()) : List.nil(); } /** @@ -534,7 +534,7 @@ public final List toList() { * @return A stream projection of this optional value. */ public final Stream toStream() { - return isSome() ? Stream.nil().cons(some()) : Stream.nil(); + return isSome() ? Stream.nil().cons(some()) : Stream.nil(); } /** @@ -544,7 +544,7 @@ public final Stream toStream() { */ @SuppressWarnings("unchecked") public final Array toArray() { - return isSome() ? Array.array(some()) : Array.empty(); + return isSome() ? Array.array(some()) : Array.empty(); } /** @@ -609,7 +609,7 @@ public final boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.equals0(Option.class, this, other, () -> Equal.optionEqual(Equal.anyEqual())); + return Equal.equals0(Option.class, this, other, () -> Equal.optionEqual(Equal.anyEqual())); } /** @@ -651,7 +651,7 @@ public static F> some_() { * @return An optional value that has a value of the given argument. */ public static Option some(final T t) { - return new Some(t); + return new Some<>(t); } public static F> none_() { @@ -664,7 +664,7 @@ public static F> none_() { * @return An optional value that has no value. */ public static Option none() { - return new None(); + return new None<>(); } /** @@ -675,7 +675,7 @@ public static Option none() { * @return If t == null then return none, otherwise, return it in some. */ public static Option fromNull(final T t) { - return t == null ? Option.none() : some(t); + return t == null ? Option.none() : some(t); } /** @@ -707,7 +707,7 @@ public static Option join(final Option> o) { */ public static Option> sequence(final List> a) { return a.isEmpty() ? - some(List.nil()) : + some(List.nil()) : a.head().bind(aa -> sequence(a.tail()).map(cons_(aa))); } @@ -722,7 +722,7 @@ public static Option> sequence(final List> a) { * on that argument, otherwise, returns no value. */ public static Option iif(final F f, final A a) { - return f.f(a) ? some(a) : Option.none(); + return f.f(a) ? some(a) : Option.none(); } /** @@ -735,7 +735,7 @@ public static Option iif(final F f, final A a) { * no value. */ public static Option iif(final boolean p, final F0 a) { - return p ? some(a.f()) : Option.none(); + return p ? some(a.f()) : Option.none(); } /** @@ -768,7 +768,7 @@ public static F2, A, Option> iif() { * @return All the values in the given list. */ public static List somes(final List> as) { - return as.filter(Option.isSome_()).map(o -> o.some()); + return as.filter(Option.isSome_()).map(o -> o.some()); } @@ -779,7 +779,7 @@ public static List somes(final List> as) { * @return All the values in the given stream. */ public static Stream somes(final Stream> as) { - return as.filter(Option.isSome_()).map(o -> o.some()); + return as.filter(Option.isSome_()).map(o -> o.some()); } /** diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index 749f4c9b..042db624 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -20,7 +20,7 @@ public F getFunction() { } public static Reader unit(F f) { - return new Reader(f); + return new Reader<>(f); } public static Reader constant(B b) { diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 84b26d6e..c6eb98be 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -22,7 +22,7 @@ public final class Seq implements Iterable { private static final Measured ELEM_MEASURED = measured(intAdditionMonoid, Function.constant(1)); private static final MakeTree MK_TREE = FingerTree.mkTree(ELEM_MEASURED); - private static final Seq EMPTY = new Seq(MK_TREE.empty()); + private static final Seq EMPTY = new Seq<>(MK_TREE.empty()); @SuppressWarnings("unchecked") private static MakeTree mkTree() { @@ -52,7 +52,7 @@ public static Seq empty() { @Override public boolean equals(Object other) { - return Equal.equals0(Seq.class, this, other, () -> Equal.seqEqual(Equal.anyEqual())); + return Equal.equals0(Seq.class, this, other, () -> Equal.seqEqual(Equal.anyEqual())); } /** @@ -62,7 +62,7 @@ public boolean equals(Object other) { * @return A new sequence with the given element in it. */ public static Seq single(final A a) { - return new Seq(Seq.mkTree().single(a)); + return new Seq<>(Seq.mkTree().single(a)); } /** @@ -146,7 +146,7 @@ public static Seq fromJavaList(final java.util.List list) { * @return A new sequence with the given element at the front. */ public Seq cons(final A a) { - return new Seq(ftree.cons(a)); + return new Seq<>(ftree.cons(a)); } /** @@ -156,7 +156,7 @@ public Seq cons(final A a) { * @return A new sequence with the given element at the end. */ public Seq snoc(final A a) { - return new Seq(ftree.snoc(a)); + return new Seq<>(ftree.snoc(a)); } /** @@ -263,7 +263,7 @@ public String toString() { * @return A new sequence with the given sequence appended to this one. */ public Seq append(final Seq as) { - return new Seq(ftree.append(as.ftree)); + return new Seq<>(ftree.append(as.ftree)); } /** @@ -312,7 +312,7 @@ public P2, Seq> split(final int i) { */ public A index(final int i) { checkBounds(i); - return ftree.lookup(Function.identity(), i)._2(); + return ftree.lookup(Function.identity(), i)._2(); } /** @@ -376,7 +376,7 @@ public int hashCode() { } public Seq map(F f) { - return new Seq(ftree.map(f, Seq.elemMeasured())); + return new Seq<>(ftree.map(f, Seq.elemMeasured())); } } diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 4dcd10de..5bb902d6 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -115,20 +115,20 @@ public Set r() { public final P2> update(final A a, final F f) { return isEmpty() ? P.p(false, this) - : tryUpdate(a, f).either(a2 -> P.p(true, delete(a).insert(a2)), Function.>>identity()); + : tryUpdate(a, f).either(a2 -> P.p(true, delete(a).insert(a2)), Function.identity()); } private Either>> tryUpdate(final A a, final F f) { if (isEmpty()) return right(P.p(false, this)); else if (ord.isLessThan(a, head())) - return l().tryUpdate(a, f).right().map(set -> set._1() ? P.p(true, (Set) new Tree(ord, color(), set._2(), head(), r())) : set); + return l().tryUpdate(a, f).right().map(set -> set._1() ? P.p(true, (Set) new Tree<>(ord, color(), set._2(), head(), r())) : set); else if (ord.eq(a, head())) { final A h = f.f(head()); return ord.eq(head(), h) ? Either - .>>right(P.p(true, (Set) new Tree(ord, color(), l(), h, r()))) - : Either.>>left(h); - } else return r().tryUpdate(a, f).right().map(set -> set._1() ? P.p(true, (Set) new Tree(ord, color(), l(), head(), set._2())) : set); + .right(P.p(true, (Set) new Tree<>(ord, color(), l(), h, r()))) + : Either.left(h); + } else return r().tryUpdate(a, f).right().map(set -> set._1() ? P.p(true, (Set) new Tree<>(ord, color(), l(), head(), set._2())) : set); } /** @@ -138,12 +138,12 @@ else if (ord.eq(a, head())) { * @return the empty set. */ public static Set empty(final Ord ord) { - return new Empty(ord); + return new Empty<>(ord); } @Override public boolean equals(Object other) { - return Equal.equals0(Set.class, this, other, () -> Equal.setEqual(Equal.anyEqual())); + return Equal.equals0(Set.class, this, other, () -> Equal.setEqual(Equal.anyEqual())); } @Override @@ -197,16 +197,16 @@ public static F, Set>> insert() { private Set ins(final A x) { return isEmpty() - ? new Tree(ord, Color.R, empty(ord), x, empty(ord)) + ? new Tree<>(ord, Color.R, empty(ord), x, empty(ord)) : ord.isLessThan(x, head()) ? balance(ord, color(), l().ins(x), head(), r()) : ord.eq(x, head()) - ? new Tree(ord, color(), l(), x, r()) + ? new Tree<>(ord, color(), l(), x, r()) : balance(ord, color(), l(), head(), r().ins(x)); } private Set makeBlack() { - return new Tree(ord, Color.B, l(), head(), r()); + return new Tree<>(ord, Color.B, l(), head(), r()); } @SuppressWarnings("SuspiciousNameCombination") @@ -214,11 +214,11 @@ private static Tree tr(final Ord o, final Set a, final A x, final Set b, final A y, final Set c, final A z, final Set d) { - return new Tree(o, Color.R, new Tree(o, Color.B, a, x, b), y, new Tree(o, Color.B, c, z, d)); + return new Tree<>(o, Color.R, new Tree<>(o, Color.B, a, x, b), y, new Tree<>(o, Color.B, c, z, d)); } private static Set balance(final Ord ord, final Color c, final Set l, final A h, final Set r) { - return c == Color.B && l.isTR() && l.l().isTR() ? tr(ord, l.l().l(), l.l().head(), l.l().r(), l.head(), l.r(), h, r) : c == Color.B && l.isTR() && l.r().isTR() ? tr(ord, l.l(), l.head(), l.r().l(), l.r().head(), l.r().r(), h, r) : c == Color.B && r.isTR() && r.l().isTR() ? tr(ord, l, h, r.l().l(), r.l().head(), r.l().r(), r.head(), r.r()) : c == Color.B && r.isTR() && r.r().isTR() ? tr(ord, l, h, r.l(), r.head(), r.r().l(), r.r().head(), r.r().r()) : new Tree(ord, c, l, h, r); + return c == Color.B && l.isTR() && l.l().isTR() ? tr(ord, l.l().l(), l.l().head(), l.l().r(), l.head(), l.r(), h, r) : c == Color.B && l.isTR() && l.r().isTR() ? tr(ord, l.l(), l.head(), l.r().l(), l.r().head(), l.r().r(), h, r) : c == Color.B && r.isTR() && r.l().isTR() ? tr(ord, l, h, r.l().l(), r.l().head(), r.l().r(), r.head(), r.r()) : c == Color.B && r.isTR() && r.r().isTR() ? tr(ord, l, h, r.l(), r.head(), r.r().l(), r.r().head(), r.r().r()) : new Tree<>(ord, c, l, h, r); } private boolean isTR() { @@ -288,7 +288,7 @@ public final B foldMapRight(final F f, final Monoid m) { * @return a list representation of this set. */ public final List toList() { - return foldMap(List.cons(List.nil()), Monoid.listMonoid()); + return foldMap(List.cons(List.nil()), Monoid.listMonoid()); } /** @@ -306,7 +306,7 @@ public final java.util.Set toJavaSet() { * @return a java.util.HashSet representation of this set. */ public final java.util.HashSet toJavaHashSet() { - return new java.util.HashSet(toStream().toCollection()); + return new java.util.HashSet<>(toStream().toCollection()); } /** @@ -315,7 +315,7 @@ public final java.util.HashSet toJavaHashSet() { * @return a java.util.TreeSet representation of this set. */ public final java.util.TreeSet toJavaTreeSet() { - return new java.util.TreeSet(toStream().toCollection()); + return new java.util.TreeSet<>(toStream().toCollection()); } /** @@ -324,7 +324,7 @@ public final java.util.TreeSet toJavaTreeSet() { * @return a java.util.List representation of this set. */ public final java.util.List toJavaList() { - return new java.util.ArrayList(toStream().toCollection()); + return new java.util.ArrayList<>(toStream().toCollection()); } /** @@ -333,7 +333,7 @@ public final java.util.List toJavaList() { * @return a list representation of this set in reverse order. */ public final List toListReverse() { - return foldMapRight(List.cons(List.nil()), Monoid.listMonoid()); + return foldMapRight(List.cons(List.nil()), Monoid.listMonoid()); } /** @@ -500,7 +500,7 @@ public final int size() { */ public final P3, Option, Set> split(final A a) { if (isEmpty()) - return P.p(empty(ord), Option.none(), empty(ord)); + return P.p(empty(ord), Option.none(), empty(ord)); else { final A h = head(); final Ordering i = ord.compare(a, h); @@ -539,7 +539,7 @@ public final boolean subsetOf(final Set s) { */ public static Set join(final Ord o, final Set> s) { final F, Set> id = identity(); - return s.foldMap(id, Monoid.setMonoid(o)); + return s.foldMap(id, Monoid.setMonoid(o)); } /** diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 47703e7b..e0724373 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -20,7 +20,7 @@ public P2 run(S s) { } public static State unit(F> f) { - return new State(f); + return new State<>(f); } public static State units(F f) { @@ -102,7 +102,7 @@ public static State gets(F f) { public static State> sequence(List> list) { return list.foldLeft((State> acc, State ma) -> acc.flatMap((List xs) -> ma.map(xs::snoc) - ), constant(List.nil())); + ), constant(List.nil())); } /** @@ -112,7 +112,7 @@ public static State> sequence(List> list) { public static State> traverse(List list, F> f) { return list.foldLeft((State> acc, A a) -> acc.flatMap(bs -> f.f(a).map(bs::snoc) - ), constant(List.nil())); + ), constant(List.nil())); } } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 8e04e499..4abde573 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -145,7 +145,7 @@ public final B foldRight(final F2, B> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight1(final F> f, final B b) { - return foldRight(compose(Function., B, B>andThen().f(P1.__1()), f), b); + return foldRight(compose(Function., B, B>andThen().f(P1.__1()), f), b); } /** @@ -255,7 +255,7 @@ public Stream prefix(final A x, final Stream xs) { * @return A new stream after the given function has been applied to each element. */ public final Stream map(final F f) { - return isEmpty() ? Stream.nil() : cons(f.f(head()), () -> tail()._1().map(f)); + return isEmpty() ? Stream.nil() : cons(f.f(head()), () -> tail()._1().map(f)); } /** @@ -353,7 +353,7 @@ public final Stream removeAll(final F f) { */ public static F> sequence_(final Stream> fs) { return fs.foldRight((baf, p1) -> Function.bind(baf, p1._1(), curry((a, stream) -> cons(a, p(stream)))), Function - .>constant(Stream.nil())); + .constant(Stream.nil())); } /** @@ -580,7 +580,7 @@ public static Stream enumerationStream(Enumeration e) { * @return A new stream with the elements of this stream sorted according to the given ordering. */ public final Stream sort(final Ord o) { - return mergesort(o, map(flip(Stream.cons()).f(p(Stream.nil())))); + return mergesort(o, map(flip(Stream.cons()).f(p(Stream.nil())))); } // Merges a stream of individually sorted streams into a single sorted stream. @@ -700,7 +700,7 @@ public int size() { * to value (exclusive). */ public static Stream range(final int from, final long to) { - return from >= to ? Stream.nil() : cons(from, () -> range(from + 1, to)); + return from >= to ? Stream.nil() : cons(from, () -> range(from + 1, to)); } /** @@ -768,7 +768,7 @@ public static Stream forever(final Enumerator e, final A from) { * given value and stepping at the given increment. */ public static Stream forever(final Enumerator e, final A from, final long step) { - return cons(from, () -> e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil())); + return cons(from, () -> e.plus(from, step).map(a -> forever(e, a, step)).orSome(Stream.nil())); } /** @@ -830,7 +830,7 @@ public static F, F, Stream>> filter() { * @return A new stream with a length the same as the shortest of this stream and the given stream. */ public final Stream zapp(final Stream> fs) { - return fs.isEmpty() || isEmpty() ? Stream.nil() : + return fs.isEmpty() || isEmpty() ? Stream.nil() : cons(fs.head().f(head()), () -> tail()._1().zapp(fs.tail()._1())); } @@ -904,7 +904,7 @@ public final Stream> zipIndex() { * @return An either projection of this stream. */ public final Either toEither(final F0 x) { - return isEmpty() ? Either.left(x.f()) : Either.right(head()); + return isEmpty() ? Either.left(x.f()) : Either.right(head()); } /** @@ -914,7 +914,7 @@ public final Either toEither(final F0 x) { * @return An option projection of this stream. */ public final Option toOption() { - return isEmpty() ? Option.none() : some(head()); + return isEmpty() ? Option.none() : some(head()); } /** @@ -950,7 +950,7 @@ public final List toList() { * Returns a java.util.List projection of this stream. */ public final java.util.List toJavaList() { - return new java.util.LinkedList(toCollection()); + return new java.util.LinkedList<>(toCollection()); } /** @@ -1007,7 +1007,7 @@ public final A[] array(final Class c) { * @return A new stream with the given element at the head. */ public final Stream cons(final A a) { - return new Cons(a, () -> Stream.this); + return new Cons<>(a, () -> Stream.this); } /** @@ -1062,8 +1062,8 @@ public final Stream snoc(final F0 a) { */ public final Stream take(final int n) { return n <= 0 || isEmpty() ? - Stream.nil() : - cons(head(), () -> n <= 1 ? Stream.nil() : tail()._1().take(n - 1)); + Stream.nil() : + cons(head(), () -> n <= 1 ? Stream.nil() : tail()._1().take(n - 1)); } /** @@ -1093,7 +1093,7 @@ public final Stream takeWhile(final F f) { this : f.f(head()) ? cons(head(), () -> tail()._1().takeWhile(f)) : - Stream.nil(); + Stream.nil(); } /** @@ -1104,7 +1104,7 @@ public final Stream takeWhile(final F f) { public final IO> traverseIO(F> f) { return this.foldRight1((a, acc) -> IOFunctions.bind(acc, (Stream bs) -> - IOFunctions.map(f.f(a), bs::cons)), IOFunctions.unit(Stream.nil())); + IOFunctions.map(f.f(a), bs::cons)), IOFunctions.unit(Stream.nil())); } @@ -1114,7 +1114,7 @@ public final IO> traverseIO(F> f) { * @return traversed value */ public final Option> traverseOption(F> f) { - return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(bs::cons)), some(Stream.nil())); + return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(bs::cons)), some(Stream.nil())); } /** @@ -1146,11 +1146,11 @@ public final P2, Stream> span(final F p) { else if (p.f(head())) { final P1, Stream>> yszs = P.lazy(() -> tail()._1().span(p)); return P.lazy( - () -> cons(head(), yszs.map(P2., Stream>__1())), + () -> cons(head(), yszs.map(P2.__1())), () -> yszs._1()._2() ); } else - return p(Stream.nil(), this); + return p(Stream.nil(), this); } /** @@ -1187,7 +1187,7 @@ public final P2, Stream> split(final F p) { * @return A new stream that is the reverse of this one. */ public final Stream reverse() { - return foldLeft(as -> a -> cons(a, () -> as), Stream.nil()); + return foldLeft(as -> a -> cons(a, () -> as), Stream.nil()); } /** @@ -1259,7 +1259,7 @@ public final boolean forall(final F f) { @Override public boolean equals(Object other) { - return Equal.equals0(Stream.class, this, other, () -> Equal.streamEqual(Equal.anyEqual())); + return Equal.equals0(Stream.class, this, other, () -> Equal.streamEqual(Equal.anyEqual())); } @Override @@ -1325,7 +1325,7 @@ public final Stream cobind(final F, B> k) { * @return a stream of the suffixes of this stream, starting with the stream itself. */ public final Stream> tails() { - return isEmpty() ? Stream.>nil() : cons(this, () -> tail()._1().tails()); + return isEmpty() ? Stream.nil() : cons(this, () -> tail()._1().tails()); } /** @@ -1334,7 +1334,7 @@ public final Stream> tails() { * @return a stream of the prefixes of this stream, starting with the stream itself. */ public final Stream> inits() { - final Stream> nil = cons(Stream.nil(), Stream::nil); + final Stream> nil = cons(Stream.nil(), Stream::nil); return isEmpty() ? nil : nil.append(() -> tail()._1().inits().map(Stream.cons_().f(head()))); } @@ -1354,7 +1354,7 @@ public final Stream> substreams() { * @return the position of the first element matching the given predicate, if any. */ public final Option indexOf(final F p) { - return zipIndex().find(p2 -> p.f(p2._1())).map(P2.__2()); + return zipIndex().find(p2 -> p.f(p2._1())).map(P2.__2()); } /** @@ -1365,7 +1365,7 @@ public final Option indexOf(final F p) { */ public final Stream sequenceW(final Stream, B>> fs) { return fs.isEmpty() - ? Stream.nil() + ? Stream.nil() : cons(fs.head().f(this), () -> sequenceW(fs.tail()._1())); } @@ -1403,7 +1403,7 @@ public static Stream fromFunction(final Enumerator e, final F final Option s = e.successor(i); return s.isSome() ? fromFunction(e, f, s.some()) - : Stream.nil(); + : Stream.nil(); }); } @@ -1417,7 +1417,7 @@ public static P2, Stream> unzip(final Stream> xs) { return xs.foldRight((p, ps) -> { final P2, Stream> pp = ps._1(); return p(cons(p._1(), p(pp._1())), cons(p._2(), p(pp._2()))); - }, p(Stream.nil(), Stream.nil())); + }, p(Stream.nil(), Stream.nil())); } /** @@ -1482,7 +1482,7 @@ public static F, Stream>> cons_() { * @return An empty stream. */ public static Stream nil() { - return new Nil(); + return new Nil<>(); } /** @@ -1539,7 +1539,7 @@ public static F> single() { * @return The stream with the given element prepended. */ public static Stream cons(final A head, final F0> tail) { - return new Cons(head, tail); + return new Cons<>(head, tail); } /** @@ -1605,8 +1605,8 @@ public static Stream iterableStream(final Iterable i) { @SafeVarargs public static Stream arrayStream(final A...as) { - return as.length == 0 ? Stream.nil() - : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.>>none() + return as.length == 0 ? Stream.nil() + : unfold(P2.tuple((as1, i) -> i >= as.length ? Option.none() : some(p(as[i], p(as, i + 1)))), p(as, 0)); } diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 82e682bc..4b0ce7eb 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -38,7 +38,7 @@ private Tree(final A root, final P1>> subForest) { * @return A nullary tree with the root element in it. */ public static Tree leaf(final A root) { - return node(root, Stream.>nil()); + return node(root, Stream.nil()); } /** @@ -49,7 +49,7 @@ public static Tree leaf(final A root) { * @return A newly sprouted tree. */ public static Tree node(final A root, final P1>> forest) { - return new Tree(root, forest); + return new Tree<>(root, forest); } /** @@ -60,7 +60,7 @@ public static Tree node(final A root, final P1>> forest) { * @return A newly sprouted tree. */ public static Tree node(final A root, final Stream> forest) { - return new Tree(root, P.p(forest)); + return new Tree<>(root, P.p(forest)); } /** @@ -130,7 +130,7 @@ public Stream f(final Tree t, final P1> xs) { return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); } }; - return squish.f(this, P.p(Stream.nil())); + return squish.f(this, P.p(Stream.nil())); } /** @@ -152,9 +152,9 @@ public static F, Stream> flatten_() { */ public Stream> levels() { final F>, Stream>> flatSubForests = - Stream., Tree>bind_().f(compose(P1.>>__1(), Tree.subForest_())); - final F>, Stream> roots = Stream., A>map_().f(Tree.root_()); - return iterateWhile(flatSubForests, Stream.>isNotEmpty_(), single(this)).map(roots); + Stream., Tree>bind_().f(compose(P1.__1(), Tree.subForest_())); + final F>, Stream> roots = Stream., A>map_().f(Tree.root_()); + return iterateWhile(flatSubForests, Stream.isNotEmpty_(), single(this)).map(roots); } /** @@ -245,7 +245,7 @@ public Tree> cojoin() { } private static Stream drawSubTrees(final Show s, final Stream> ts) { - return ts.isEmpty() ? Stream.nil() + return ts.isEmpty() ? Stream.nil() : ts.tail()._1().isEmpty() ? shift("`- ", " ", ts.head().drawTree(s)).cons("|") : shift("+- ", "| ", ts.head().drawTree(s)) .append(drawSubTrees(s, ts.tail()._1())); @@ -261,7 +261,7 @@ private Stream drawTree(final Show s) { @Override public boolean equals(Object other) { - return Equal.equals0(Tree.class, this, other, () -> Equal.treeEqual(Equal.anyEqual())); + return Equal.equals0(Tree.class, this, other, () -> Equal.treeEqual(Equal.anyEqual())); } @Override @@ -328,7 +328,7 @@ public Tree zipWith(final Tree bs, final F> f) { public static Tree bottomUp(Tree t, final F>, B> f) { final F, Tree> recursiveCall = a -> bottomUp(a, f); final Stream> tbs = t.subForest()._1().map(recursiveCall); - return node(f.f(P.p(t.root(), tbs.map(Tree. getRoot()))), tbs); + return node(f.f(P.p(t.root(), tbs.map(Tree.getRoot()))), tbs); } /** diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index de4876ec..f663ab09 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -31,7 +31,7 @@ private TreeMap(final Set>> tree) { } private static Ord> ord(final Ord keyOrd) { - return keyOrd.contramap(P2.__1()); + return keyOrd.contramap(P2.__1()); } /** @@ -41,12 +41,12 @@ private static Ord> ord(final Ord keyOrd) { * @return an empty TreeMap with the given key order. */ public static TreeMap empty(final Ord keyOrd) { - return new TreeMap(Set.empty(TreeMap.>ord(keyOrd))); + return new TreeMap<>(Set.empty(TreeMap.ord(keyOrd))); } @Override public boolean equals(Object other) { - return Equal.equals0(TreeMap.class, this, other, () -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(TreeMap.class, this, other, () -> Equal.treeMapEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override @@ -129,8 +129,8 @@ public static TreeMap arrayTreeMap(final Ord keyOrd, final P2 get(final K k) { - final Option>> x = tree.split(p(k, Option.none()))._2(); - return x.bind(P2.>__2()); + final Option>> x = tree.split(p(k, Option.none()))._2(); + return x.bind(P2.__2()); } /** @@ -142,7 +142,7 @@ public Option get(final K k) { * @return A new tree map with the given value mapped to the given key. */ public TreeMap set(final K k, final V v) { - return new TreeMap(tree.insert(p(k, Option.some(v)))); + return new TreeMap<>(tree.insert(p(k, Option.some(v)))); } /** @@ -152,7 +152,7 @@ public TreeMap set(final K k, final V v) { * @return A new tree map with the entry corresponding to the given key removed. */ public TreeMap delete(final K k) { - return new TreeMap(tree.delete(p(k, Option.none()))); + return new TreeMap<>(tree.delete(p(k, Option.none()))); } /** @@ -179,7 +179,7 @@ public boolean isEmpty() { * @return All values in this tree map. */ public List values() { - return iterableList(join(tree.toList().map(compose(IterableW.>wrap(), P2.>__2())))); + return iterableList(join(tree.toList().map(compose(IterableW.wrap(), P2.__2())))); } /** @@ -188,7 +188,7 @@ public List values() { * @return All keys in this tree map. */ public List keys() { - return tree.toList().map(P2.>__1()); + return tree.toList().map(P2.__1()); } /** @@ -198,7 +198,7 @@ public List keys() { * @return true if this tree map contains the given key, false otherwise. */ public boolean contains(final K k) { - return tree.member(p(k, Option.none())); + return tree.member(p(k, Option.none())); } /** @@ -208,8 +208,8 @@ public boolean contains(final K k) { * @return A iterator for this map's key-value pairs. */ public Iterator> iterator() { - return join(tree.toStream().map(P2., IterableW>map2_(IterableW.>wrap()) - ).map(P2.tuple(compose(IterableW.>map(), P.p2())))).iterator(); + return join(tree.toStream().map(P2.map2_(IterableW.wrap()) + ).map(P2.tuple(compose(IterableW.map(), P.p2())))).iterator(); } /** @@ -220,7 +220,7 @@ public Iterator> iterator() { public Map toMutableMap() { final F>> fakePair = k -> p(k, Option.none()); final Comparator comparator = tree.ord().contramap(fakePair).toComparator(); - final Map m = new java.util.TreeMap(comparator); + final Map m = new java.util.TreeMap<>(comparator); for (final P2 e : this) { m.put(e._1(), e._2()); } @@ -277,8 +277,8 @@ public F> get() { */ public P2> update(final K k, final F f) { final P2>>> up = - tree.update(p(k, Option.none()), compose(P2.tuple(P.p2()), P2., Option>map2_(Option.map().f(f)))); - return p(up._1(), new TreeMap(up._2())); + tree.update(p(k, Option.none()), compose(P2.tuple(P.p2()), P2.map2_(Option.map().f(f)))); + return p(up._1(), new TreeMap<>(up._2())); } /** @@ -309,9 +309,9 @@ public TreeMap update(final K k, final F f, final V v) { * and the optional value is the value associated with the given key if present, otherwise None. */ public P3, Option, Set> split(Ord ord, final K k) { - final F>>, Set> getSome = F1Functions.mapSet(F1Functions.o(Option.fromSome(), P2.>__2()), ord); - return tree.split(p(k, Option.none())).map1(getSome).map3(getSome) - .map2(F1Functions.o(Option.join(), F1Functions.mapOption(P2.>__2()))); + final F>>, Set> getSome = F1Functions.mapSet(F1Functions.o(Option.fromSome(), P2.__2()), ord); + return tree.split(p(k, Option.none())).map1(getSome).map3(getSome) + .map2(F1Functions.o(Option.join(), F1Functions.mapOption(P2.__2()))); } /** @@ -321,7 +321,7 @@ public P3, Option, Set> split(Ord ord, final K k) { * @return a TreeMap with the given elements. */ private static TreeMap treeMap(Ord ord, Set>> s) { - TreeMap empty = TreeMap.empty(ord); + TreeMap empty = TreeMap.empty(ord); TreeMap tree = s.toList().foldLeft((tm, p2) -> { Option opt = p2._2(); if (opt.isSome()) { @@ -348,7 +348,7 @@ private static TreeMap treeMap(Ord ord, Set>> s) */ public P3, Option, TreeMap> splitLookup(final K k) { P3>>, Option>>, Set>>> p3 = tree.split(p(k, get(k))); - Ord o = tree.ord().contramap(k2 -> p(k2, Option.none())); + Ord o = tree.ord().contramap(k2 -> p(k2, Option.none())); return p(treeMap(o, p3._1()), get(k), treeMap(o, p3._3())); } @@ -361,9 +361,9 @@ public P3, Option, TreeMap> splitLookup(final K k) { @SuppressWarnings("unchecked") public TreeMap map(final F f) { final F>, P2>> g = P2.map2_(F1Functions.mapOption(f)); - final F>> coord = flip(P.>p2()).f(Option.none()); + final F>> coord = flip(P.>p2()).f(Option.none()); final Ord o = tree.ord().contramap(coord); - return new TreeMap(tree.map(TreeMap.>ord(o), g)); + return new TreeMap<>(tree.map(TreeMap.ord(o), g)); } /** diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index a9d92b5a..c94287cf 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -68,7 +68,7 @@ public static TreeZipper treeZipper(final Tree tree, final Stream> lefts, final Stream> rights, final Stream>, A, Stream>>> parents) { - return new TreeZipper(tree, lefts, rights, parents); + return new TreeZipper<>(tree, lefts, rights, parents); } /** @@ -114,7 +114,7 @@ public static Equal> eq(final Equal e) { treeEqual(e), streamEqual(treeEqual(e)), streamEqual(treeEqual(e)), - streamEqual(p3Equal(streamEqual(treeEqual(e)), e, streamEqual(treeEqual(e))))).contramap(TreeZipper.p_()); + streamEqual(p3Equal(streamEqual(treeEqual(e)), e, streamEqual(treeEqual(e))))).contramap(TreeZipper.p_()); } /** @@ -128,13 +128,13 @@ public static Show> show(final Show s) { treeShow(s), streamShow(treeShow(s)), streamShow(treeShow(s)), - streamShow(p3Show(streamShow(treeShow(s)), s, streamShow(treeShow(s))))).contramap(TreeZipper.p_()); + streamShow(p3Show(streamShow(treeShow(s)), s, streamShow(treeShow(s))))).contramap(TreeZipper.p_()); } private static Stream> combChildren(final Stream> ls, final Tree t, final Stream> rs) { - return ls.foldLeft(compose(flip(Stream.>cons()), P.>>p1()), Stream.cons(t, P.p(rs))); + return ls.foldLeft(compose(flip(Stream.cons()), P.p1()), Stream.cons(t, P.p(rs))); } /** @@ -158,7 +158,7 @@ public Option> parent() { * @return A new tree zipper focused on the top-most parent of the current node. */ public TreeZipper root() { - return parent().option(this, TreeZipper.root_()); + return parent().option(this, TreeZipper.root_()); } /** @@ -177,7 +177,7 @@ public static F, TreeZipper> root_() { * or none if there are no siblings on the left. */ public Option> left() { - return lefts.isEmpty() ? Option.>none() + return lefts.isEmpty() ? Option.none() : some(treeZipper(lefts.head(), lefts.tail()._1(), rights.cons(tree), parents)); } @@ -188,7 +188,7 @@ public Option> left() { * or none if there are no siblings on the right. */ public Option> right() { - return rights.isEmpty() ? Option.>none() + return rights.isEmpty() ? Option.none() : some(treeZipper(rights.head(), lefts.cons(tree), rights.tail()._1(), parents)); } @@ -199,8 +199,8 @@ public Option> right() { */ public Option> firstChild() { final Stream> ts = tree.subForest()._1(); - return ts.isEmpty() ? Option.>none() - : some(treeZipper(ts.head(), Stream.>nil(), ts.tail()._1(), downParents())); + return ts.isEmpty() ? Option.none() + : some(treeZipper(ts.head(), Stream.nil(), ts.tail()._1(), downParents())); } /** @@ -210,8 +210,8 @@ public Option> firstChild() { */ public Option> lastChild() { final Stream> ts = tree.subForest()._1().reverse(); - return ts.isEmpty() ? Option.>none() - : some(treeZipper(ts.head(), ts.tail()._1(), Stream.>nil(), downParents())); + return ts.isEmpty() ? Option.none() + : some(treeZipper(ts.head(), ts.tail()._1(), Stream.nil(), downParents())); } /** @@ -223,7 +223,7 @@ public Option> lastChild() { public Option> getChild(final int n) { Option> r = none(); for (final P2>, Stream>> lr - : splitChildren(Stream.>nil(), tree.subForest()._1(), n)) { + : splitChildren(Stream.nil(), tree.subForest()._1(), n)) { r = some(treeZipper(lr._1().head(), lr._1().tail()._1(), lr._2(), downParents())); } return r; @@ -246,14 +246,14 @@ public Option>, Tree, Stream>>> f(final Stream>, Tree, Stream>>>none(); + : Option.none(); } }; Stream> subforest = tree.subForest()._1(); if (subforest.isNotEmpty()) { for (final P3>, Tree, Stream>> ltr - : split.f(Stream.>nil(), subforest)) { + : split.f(Stream.nil(), subforest)) { r = some(treeZipper(ltr._2(), ltr._1(), ltr._3(), downParents())); } } @@ -269,7 +269,7 @@ private static Option, Stream>> splitChildren(final Stream, Stream>>none(); + : Option.none(); } private static Stream>, A, Stream>>> lp3nil() { @@ -283,7 +283,7 @@ private static Stream>, A, Stream>>> lp3nil() { * @return a new tree zipper focused on the root of the given tree. */ public static TreeZipper fromTree(final Tree t) { - return treeZipper(t, Stream.>nil(), Stream.>nil(), TreeZipper.lp3nil()); + return treeZipper(t, Stream.nil(), Stream.nil(), TreeZipper.lp3nil()); } /** @@ -294,8 +294,8 @@ public static TreeZipper fromTree(final Tree t) { */ public static Option> fromForest(final Stream> ts) { return ts.isNotEmpty() - ? some(treeZipper(ts.head(), Stream.>nil(), ts.tail()._1(), TreeZipper.lp3nil())) - : Option.>none(); + ? some(treeZipper(ts.head(), Stream.nil(), ts.tail()._1(), TreeZipper.lp3nil())) + : Option.none(); } /** @@ -474,7 +474,7 @@ public TreeZipper insertRight(final Tree t) { * @return A new tree zipper with the given tree in focus, as the first child of the current node. */ public TreeZipper insertDownFirst(final Tree t) { - return treeZipper(t, Stream.>nil(), tree.subForest()._1(), downParents()); + return treeZipper(t, Stream.nil(), tree.subForest()._1(), downParents()); } /** @@ -484,7 +484,7 @@ public TreeZipper insertDownFirst(final Tree t) { * @return A new tree zipper with the given tree in focus, as the last child of the current node. */ public TreeZipper insertDownLast(final Tree t) { - return treeZipper(t, tree.subForest()._1().reverse(), Stream.>nil(), downParents()); + return treeZipper(t, tree.subForest()._1().reverse(), Stream.nil(), downParents()); } /** @@ -499,7 +499,7 @@ public TreeZipper insertDownLast(final Tree t) { public Option> insertDownAt(final int n, final Tree t) { Option> r = none(); for (final P2>, Stream>> lr - : splitChildren(Stream.>nil(), tree.subForest()._1(), n)) { + : splitChildren(Stream.nil(), tree.subForest()._1(), n)) { r = some(treeZipper(t, lr._1(), lr._2(), downParents())); } return r; @@ -518,7 +518,7 @@ public Option> delete() { else if (lefts.isNotEmpty()) r = some(treeZipper(lefts.head(), lefts.tail()._1(), rights, parents)); else for (final TreeZipper loc : parent()) - r = some(loc.modifyTree(t -> node(t.root(), Stream.>nil()))); + r = some(loc.modifyTree(t -> node(t.root(), Stream.nil()))); return r; } @@ -531,7 +531,7 @@ else for (final TreeZipper loc : parent()) */ public TreeZipper> zipWithFocus() { final F> f = flip(P.p2()).f(false); - return map(f).modifyLabel(P2.map2_(Booleans.not)); + return map(f).modifyLabel(P2.map2_(Booleans.not)); } /** @@ -582,15 +582,15 @@ public static F, Option>> right_() { */ public TreeZipper> positions() { final Tree> t = unfoldTree(TreeZipper.dwn()).f(this); - final Stream>> l = uf(TreeZipper.left_()); - final Stream>> r = uf(TreeZipper.right_()); + final Stream>> l = uf(TreeZipper.left_()); + final Stream>> r = uf(TreeZipper.right_()); final Stream>>, TreeZipper, Stream>>>> p = unfold( o -> { Option>>, TreeZipper, Stream>>>, Option>>> r1 = none(); for (final TreeZipper z : o) { - r1 = some(P.p(P.p(z.uf(TreeZipper.left_()), z, z.uf(TreeZipper.right_())), z.parent())); + r1 = some(P.p(P.p(z.uf(TreeZipper.left_()), z, z.uf(TreeZipper.right_())), z.parent())); } return r1; }, parent()); @@ -609,7 +609,7 @@ private Stream>> uf(final F, Option F, P2, P1>>>> dwn() { - return tz -> P., P1>>>p(tz, new P1>>() { + return tz -> P.p(tz, new P1>>() { private F>, Option, Option>>>> fwd() { return o -> { Option, Option>>> r = none(); diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 8328590f..9d82596b 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -175,8 +175,8 @@ public void foreachDoEffect(final Effect1 f) { @SuppressWarnings("unchecked") public Validation map(final F f) { return isFail() ? - Validation.fail(fail()) : - Validation.success(f.f(success())); + Validation.fail(fail()) : + Validation.success(f.f(success())); } /** @@ -187,7 +187,7 @@ public Validation map(final F f) { */ @SuppressWarnings("unchecked") public Validation bind(final F> f) { - return isSuccess() ? f.f(success()) : Validation.fail(fail()); + return isSuccess() ? f.f(success()) : Validation.fail(fail()); } /** @@ -197,7 +197,7 @@ public Validation bind(final F> f) { * @return A validation after binding. */ public Validation sequence(final Validation v) { - return bind(Function.>constant(v)); + return bind(Function.constant(v)); } /** @@ -206,7 +206,7 @@ public Validation sequence(final Validation v) { */ public static Validation> sequence(final Semigroup s, final List> list) { if (list.exists(Validation::isFail)) { - return Validation.>fail(list.filter(Validation::isFail).map(v -> v.fail()).foldLeft1((F2) s::sum)); + return Validation.fail(list.filter(Validation::isFail).map(v -> v.fail()).foldLeft1((F2) s::sum)); } else { return success(list.foldLeft((List acc, Validation v) -> acc.cons(v.success()), List.nil()).reverse()); } @@ -221,7 +221,7 @@ public static Validation> sequence(final Semigroup s, final * success value, otherwise, returns a success in Some. */ public Option> filter(final F f) { - return e.right().filter(f).map(Validation.validation()); + return e.right().filter(f).map(Validation.validation()); } /** @@ -260,7 +260,7 @@ public boolean exists(final F f) { @Override public boolean equals(Object other) { - return Equal.equals0(Validation.class, this, other, () -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual())); + return Equal.equals0(Validation.class, this, other, () -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override @@ -316,12 +316,12 @@ public Stream toStream() { @SuppressWarnings("unchecked") public Validation accumapply(final Semigroup s, final Validation> v) { return isFail() ? - Validation.fail(v.isFail() ? + Validation.fail(v.isFail() ? s.sum(v.fail(), fail()) : fail()) : v.isFail() ? - Validation.fail(v.fail()) : - Validation.success(v.success().f(success())); + Validation.fail(v.fail()) : + Validation.success(v.success().f(success())); } /** @@ -722,7 +722,7 @@ public Iterator iterator() { public Validation, T> accumulate() { if (isFail()) { - return fail(List.single(fail())); + return fail(List.single(fail())); } else { return success(success()); } @@ -730,7 +730,7 @@ public Validation, T> accumulate() { public Validation, B> accumulate(F f) { if (isFail()) { - return fail(List.single(fail())); + return fail(List.single(fail())); } else { return success(f.f(success())); } @@ -969,7 +969,7 @@ public Validation map(final F f) { * @return A new validation value after binding. */ public Validation bind(final F> f) { - return v.isFail() ? f.f(v.fail()) : Validation.success(v.success()); + return v.isFail() ? f.f(v.fail()) : Validation.success(v.success()); } /** @@ -992,7 +992,7 @@ public Validation sequence(final Validation v) { * failing value, otherwise, returns a fail in Some. */ public Option> filter(final F f) { - return v.toEither().left().filter(f).map(Validation.validation()); + return v.toEither().left().filter(f).map(Validation.validation()); } /** @@ -1083,8 +1083,8 @@ public Iterator iterator() { @SuppressWarnings("unchecked") public Validation, T> nel() { return isSuccess() ? - Validation., T>success(success()) : - Validation., T>fail(NonEmptyList.nel(fail())); + Validation.success(success()) : + Validation.fail(NonEmptyList.nel(fail())); } /** @@ -1122,7 +1122,7 @@ public static F, Either> either() { * @return A succeeding validation containing the given value. */ public static Validation success(final T t) { - return validation(Either.right(t)); + return validation(Either.right(t)); } /** @@ -1132,7 +1132,7 @@ public static Validation success(final T t) { * @return A failing validation containing the given value. */ public static Validation fail(final E e) { - return validation(Either.left(e)); + return validation(Either.left(e)); } /** @@ -1155,7 +1155,7 @@ public static Validation, T> failNEL(final E e) { * @return A validation based on a boolean condition. */ public static Validation condition(final boolean c, final E e, final T t) { - return c ? Validation.success(t) : Validation.fail(e); + return c ? Validation.success(t) : Validation.fail(e); } /** diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index b384e259..b6b4579b 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -34,11 +34,11 @@ public Monoid monoid() { } public static Writer unit(A a, W w, Monoid m) { - return new Writer(a, w, m); + return new Writer<>(a, w, m); } public static Writer unit(A a, Monoid m) { - return new Writer(a, m.zero(), m); + return new Writer<>(a, m.zero(), m); } public Writer tell(W w) { diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index f24ecf01..24414ed2 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -54,7 +54,7 @@ private Zipper(final Stream left, final A focus, final Stream right) { * @return a new Zipper with the given streams before and after the focus, and the given focused item. */ public static Zipper zipper(final Stream left, final A focus, final Stream right) { - return new Zipper(left, focus, right); + return new Zipper<>(left, focus, right); } /** @@ -65,7 +65,7 @@ public static Zipper zipper(final Stream left, final A focus, final St * @return a new Zipper created from the given triple. */ public static Zipper zipper(final P3, A, Stream> p) { - return new Zipper(p._1(), p._2(), p._3()); + return new Zipper<>(p._1(), p._2(), p._3()); } /** @@ -103,7 +103,7 @@ public static F, P3, A, Stream>> p_() { */ public static Ord> ord(final Ord o) { final Ord> so = Ord.streamOrd(o); - return Ord.p3Ord(so, o, so).contramap(Zipper.p_()); + return Ord.p3Ord(so, o, so).contramap(Zipper.p_()); } /** @@ -114,7 +114,7 @@ public static Ord> ord(final Ord o) { */ public static Equal> eq(final Equal e) { final Equal> se = Equal.streamEqual(e); - return Equal.p3Equal(se, e, se).contramap(Zipper.p_()); + return Equal.p3Equal(se, e, se).contramap(Zipper.p_()); } /** @@ -125,7 +125,7 @@ public static Equal> eq(final Equal e) { */ public static Show> show(final Show s) { final Show> ss = Show.streamShow(s); - return Show.p3Show(ss, s, ss).contramap(Zipper.p_()); + return Show.p3Show(ss, s, ss).contramap(Zipper.p_()); } /** @@ -148,7 +148,7 @@ public Zipper map(final F f) { public B foldRight(final F> f, final B z) { return left.foldLeft(flip(f), right.cons(focus).foldRight(compose( - Function., B, B>andThen().f(P1.__1()), f), z)); + Function., B, B>andThen().f(P1.__1()), f), z)); } /** @@ -158,7 +158,7 @@ public B foldRight(final F> f, final B z) { * @return a new zipper with a single element which is in focus. */ public static Zipper single(final A a) { - return zipper(Stream.nil(), a, Stream.nil()); + return zipper(Stream.nil(), a, Stream.nil()); } /** @@ -174,7 +174,7 @@ public static Option> fromStream(final Stream a) { if (a.isEmpty()) return none(); else - return some(zipper(Stream.nil(), a.head(), a.tail()._1())); + return some(zipper(Stream.nil(), a.head(), a.tail()._1())); } /** @@ -190,7 +190,7 @@ public static Option> fromStreamEnd(final Stream a) { return none(); else { final Stream xs = a.reverse(); - return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); + return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); } } @@ -210,7 +210,7 @@ public A focus() { * focus, otherwise None. */ public Option> next() { - return right.isEmpty() ? Option.>none() : some(tryNext()); + return right.isEmpty() ? Option.none() : some(tryNext()); } /** @@ -233,7 +233,7 @@ public Zipper tryNext() { * focus, otherwise None. */ public Option> previous() { - return left.isEmpty() ? Option.>none() : some(tryPrevious()); + return left.isEmpty() ? Option.none() : some(tryPrevious()); } /** @@ -297,7 +297,7 @@ public Zipper insertRight(final A a) { */ public Option> deleteLeft() { return left.isEmpty() && right.isEmpty() - ? Option.>none() + ? Option.none() : some(zipper(left.isEmpty() ? left : left.tail()._1(), left.isEmpty() ? right.head() : left.head(), left.isEmpty() ? right.tail()._1() : right)); @@ -313,7 +313,7 @@ public Option> deleteLeft() { */ public Option> deleteRight() { return left.isEmpty() && right.isEmpty() - ? Option.>none() + ? Option.none() : some(zipper(right.isEmpty() ? left.tail()._1() : left, right.isEmpty() ? left.head() : right.head(), right.isEmpty() ? right : right.tail()._1())); @@ -335,7 +335,7 @@ public Zipper deleteOthers() { * @return the length of this zipper. */ public int length() { - return foldRight(Function.>constant(Integers.add.f(1)), 0); + return foldRight(Function.constant(Integers.add.f(1)), 0); } /** @@ -365,9 +365,9 @@ public boolean atEnd() { */ public Zipper> positions() { final Stream> left = Stream.unfold( - p -> p.previous().map(join(P., Zipper>p2())), this); + p -> p.previous().map(join(P.p2())), this); final Stream> right = Stream.unfold( - p -> p.next().map(join(P., Zipper>p2())), this); + p -> p.next().map(join(P.p2())), this); return zipper(left, this, right); } @@ -407,10 +407,10 @@ public Option> move(final int n) { return none(); else if (ll >= n) for (int i = ll - n; i > 0; i--) - p = p.bind(Zipper.previous_()); + p = p.bind(Zipper.previous_()); else if (rl >= n) for (int i = rl - n; i > 0; i--) - p = p.bind(Zipper.next_()); + p = p.bind(Zipper.next_()); return p; } @@ -458,7 +458,7 @@ public Zipper cycleNext() { return this; else if (right.isEmpty()) { final Stream xs = left.reverse(); - return zipper(Stream.nil(), xs.head(), xs.tail()._1().snoc(P.p(focus))); + return zipper(Stream.nil(), xs.head(), xs.tail()._1().snoc(P.p(focus))); } else return tryNext(); } @@ -474,7 +474,7 @@ public Zipper cyclePrevious() { return this; else if (left.isEmpty()) { final Stream xs = right.reverse(); - return zipper(xs.tail()._1().snoc(P.p(focus)), xs.head(), Stream.nil()); + return zipper(xs.tail()._1().snoc(P.p(focus)), xs.head(), Stream.nil()); } else return tryPrevious(); } @@ -493,7 +493,7 @@ else if (left.isNotEmpty()) return some(zipper(left.tail()._1(), left.head(), right)); else { final Stream xs = right.reverse(); - return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); + return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); } } @@ -511,7 +511,7 @@ else if (right.isNotEmpty()) return some(zipper(left, right.head(), right.tail()._1())); else { final Stream xs = left.reverse(); - return some(zipper(Stream.nil(), xs.head(), xs.tail()._1())); + return some(zipper(Stream.nil(), xs.head(), xs.tail()._1())); } } diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index 17e775e6..ea906507 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -57,24 +57,24 @@ public Digit suffix() { } @Override public B foldRight(final F> aff, final B z) { - return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.foldRight(aff, z))); + return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.foldRight(aff, z))); } @Override public A reduceRight(final F> aff) { - return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.reduceRight(aff))); + return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.reduceRight(aff))); } @Override public B foldLeft(final F> bff, final B z) { - return suffix.foldLeft(bff, middle.foldLeft(Node.foldLeft_(bff), prefix.foldLeft(bff, z))); + return suffix.foldLeft(bff, middle.foldLeft(Node.foldLeft_(bff), prefix.foldLeft(bff, z))); } @Override public A reduceLeft(final F> aff) { - return suffix.foldLeft(aff, middle.foldLeft(Node.foldLeft_(aff), prefix.reduceLeft(aff))); + return suffix.foldLeft(aff, middle.foldLeft(Node.foldLeft_(aff), prefix.reduceLeft(aff))); } @Override public FingerTree map(final F abf, final Measured m) { - return new Deep(m, v, prefix.map(abf, m), middle.map(Node.liftM(abf, m), m.nodeMeasured()), - suffix.map(abf, m)); + return new Deep<>(m, v, prefix.map(abf, m), middle.map(Node.liftM(abf, m), m.nodeMeasured()), + suffix.map(abf, m)); } /** @@ -281,9 +281,9 @@ private static FingerTree> append1(final Measured m, final Node a, final FingerTree> ys) { return xs.match(empty -> ys.cons(a), single -> ys.cons(a).cons(single.value()), deep1 -> ys.match(empty -> xs.snoc(a), single -> xs.snoc(a).snoc(single.value()), deep2 -> { final Measured> nm = m.nodeMeasured(); - return new Deep>(nm, m.sum(m.sum(deep1.v, nm.measure(a)), deep2.v), deep1.prefix, - addDigits1(nm, deep1.middle, deep1.suffix, a, deep2.prefix, deep2.middle), - deep2.suffix); + return new Deep<>(nm, m.sum(m.sum(deep1.v, nm.measure(a)), deep2.v), deep1.prefix, + addDigits1(nm, deep1.middle, deep1.suffix, a, deep2.prefix, deep2.middle), + deep2.suffix); })); } @@ -336,11 +336,11 @@ private static FingerTree>> addDigits1(final Measur private static FingerTree> append2(final Measured m, final FingerTree> t1, final Node n1, final Node n2, final FingerTree> t2) { - return t1.match(empty -> t2.cons(n2).cons(n1), single -> t2.cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2), single -> deep.snoc(n1).snoc(n2).snoc(single.value()), deep2 -> new Deep>(m.nodeMeasured(), - m.sum(m.sum(m.sum(deep.measure(), n1.measure()), n2.measure()), - deep2.measure()), deep.prefix, - addDigits2(m.nodeMeasured(), deep.middle, deep.suffix, n1, n2, deep2.prefix, - deep2.middle), deep2.suffix))); + return t1.match(empty -> t2.cons(n2).cons(n1), single -> t2.cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2), single -> deep.snoc(n1).snoc(n2).snoc(single.value()), deep2 -> new Deep<>(m.nodeMeasured(), + m.sum(m.sum(m.sum(deep.measure(), n1.measure()), n2.measure()), + deep2.measure()), deep.prefix, + addDigits2(m.nodeMeasured(), deep.middle, deep.suffix, n1, n2, deep2.prefix, + deep2.middle), deep2.suffix))); } private static FingerTree>> addDigits2(final Measured> m, @@ -395,10 +395,10 @@ private static FingerTree> append3(final Measured m, final Node n1, final Node n2, final Node n3, final FingerTree> t2) { final Measured> nm = m.nodeMeasured(); - return t1.match(empty -> t2.cons(n3).cons(n2).cons(n1), single -> t2.cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2).snoc(n3), single -> deep.snoc(n1).snoc(n2).snoc(n3).snoc(single.value()), deep2 -> new Deep>(nm, nm.monoid().sumLeft( + return t1.match(empty -> t2.cons(n3).cons(n2).cons(n1), single -> t2.cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2).snoc(n3), single -> deep.snoc(n1).snoc(n2).snoc(n3).snoc(single.value()), deep2 -> new Deep<>(nm, nm.monoid().sumLeft( list(deep.v, n1.measure(), n2.measure(), n3.measure(), deep2.v)), deep.prefix, - addDigits3(nm, deep.middle, deep.suffix, n1, n2, n3, deep2.prefix, - deep2.middle), deep2.suffix))); + addDigits3(nm, deep.middle, deep.suffix, n1, n2, n3, deep2.prefix, + deep2.middle), deep2.suffix))); } private static FingerTree>> addDigits3(final Measured> m, @@ -462,10 +462,10 @@ private static FingerTree> append4(final Measured m, final Node n4, final FingerTree> t2) { final Measured> nm = m.nodeMeasured(); - return t1.match(empty -> t2.cons(n4).cons(n3).cons(n2).cons(n1), single -> t2.cons(n4).cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4), single -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4).snoc(single.value()), deep2 -> new Deep>(nm, m.monoid().sumLeft( + return t1.match(empty -> t2.cons(n4).cons(n3).cons(n2).cons(n1), single -> t2.cons(n4).cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4), single -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4).snoc(single.value()), deep2 -> new Deep<>(nm, m.monoid().sumLeft( list(deep.v, n1.measure(), n2.measure(), n3.measure(), n4.measure(), deep2.v)), deep.prefix, - addDigits4(nm, deep.middle, deep.suffix, n1, n2, n3, n4, deep2.prefix, - deep2.middle), deep2.suffix))); + addDigits4(nm, deep.middle, deep.suffix, n1, n2, n3, n4, deep2.prefix, + deep2.middle), deep2.suffix))); } private static FingerTree>> addDigits4(final Measured> m, diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index 2b51f7a7..415f08c2 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -88,10 +88,10 @@ public final A reduceLeft(final F> f) { */ public final Digit map(final F f, final Measured m) { return match( - one -> new One(m, f.f(one.value())), - two -> new Two(m, two.values().map(f)), - three -> new Three(m, three.values().map(f)), - four -> new Four(m, four.values().map(f)) + one -> new One<>(m, f.f(one.value())), + two -> new Two<>(m, two.values().map(f)), + three -> new Three<>(m, three.values().map(f)), + four -> new Four<>(m, four.values().map(f)) ); } @@ -132,27 +132,27 @@ public final FingerTree toTree() { final MakeTree mk = mkTree(m); return match( one -> mk.single(one.value()), - two -> mk.deep(mk.one(two.values()._1()), new Empty>(m.nodeMeasured()), mk.one(two.values()._2())), - three -> mk.deep(mk.two(three.values()._1(), three.values()._2()), new Empty>(m.nodeMeasured()), mk.one(three.values()._3())), - four -> mk.deep(mk.two(four.values()._1(), four.values()._2()), new Empty>(m.nodeMeasured()), mk.two(four.values()._3(), four.values()._4())) + two -> mk.deep(mk.one(two.values()._1()), new Empty<>(m.nodeMeasured()), mk.one(two.values()._2())), + three -> mk.deep(mk.two(three.values()._1(), three.values()._2()), new Empty<>(m.nodeMeasured()), mk.one(three.values()._3())), + four -> mk.deep(mk.two(four.values()._1(), four.values()._2()), new Empty<>(m.nodeMeasured()), mk.two(four.values()._3(), four.values()._4())) ); } Option> tail() { return match( - one -> Option.> none(), - two -> Option.> some(mkTree(m).one(two.values()._2())), - three -> Option.> some(mkTree(m).two(three.values()._2(), three.values()._3())), - four -> Option.> some(mkTree(m).three(four.values()._2(), four.values()._3(), four.values()._4())) + one -> Option.none(), + two -> Option.some(mkTree(m).one(two.values()._2())), + three -> Option.some(mkTree(m).two(three.values()._2(), three.values()._3())), + four -> Option.some(mkTree(m).three(four.values()._2(), four.values()._3(), four.values()._4())) ); } Option> init() { return match( - one -> Option.> none(), - two -> Option.> some(mkTree(m).one(two.values()._1())), - three -> Option.> some(mkTree(m).two(three.values()._1(), three.values()._2())), - four -> Option.> some(mkTree(m).three(four.values()._1(), four.values()._2(), four.values()._3())) + one -> Option.none(), + two -> Option.some(mkTree(m).one(two.values()._1())), + three -> Option.some(mkTree(m).two(three.values()._1(), three.values()._2())), + four -> Option.some(mkTree(m).three(four.values()._1(), four.values()._2(), four.values()._3())) ); } diff --git a/core/src/main/java/fj/data/fingertrees/Empty.java b/core/src/main/java/fj/data/fingertrees/Empty.java index 9f2b9bd2..95065aef 100644 --- a/core/src/main/java/fj/data/fingertrees/Empty.java +++ b/core/src/main/java/fj/data/fingertrees/Empty.java @@ -15,7 +15,7 @@ public final class Empty extends FingerTree { } @Override public FingerTree cons(final A a) { - return new Single(measured(), a); + return new Single<>(measured(), a); } @Override public FingerTree snoc(final A a) { @@ -58,7 +58,7 @@ public A reduceRight(final F> aff) { } @Override public FingerTree map(final F abf, final Measured m) { - return new Empty(m); + return new Empty<>(m); } /** diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index 1078374b..060e976f 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -77,7 +77,7 @@ public B foldLeft(final F2 f, final B z) { public abstract FingerTree map(final F f, final Measured m); public FingerTree filter(final F f) { - FingerTree tree = new Empty(m); + FingerTree tree = new Empty<>(m); return foldLeft((acc, a) -> f.f(a) ? acc.snoc(a) : acc, tree); } @@ -134,7 +134,7 @@ public static Measured measured(final Monoid monoid, final F MakeTree mkTree(final Measured m) { - return new MakeTree(m); + return new MakeTree<>(m); } /** @@ -161,7 +161,7 @@ public static MakeTree mkTree(final Measured m) { public abstract A head(); public Option headOption() { - return isEmpty() ? Option.none() : Option.some(head()); + return isEmpty() ? Option.none() : Option.some(head()); } /** diff --git a/core/src/main/java/fj/data/fingertrees/MakeTree.java b/core/src/main/java/fj/data/fingertrees/MakeTree.java index b435d955..b2a3da84 100644 --- a/core/src/main/java/fj/data/fingertrees/MakeTree.java +++ b/core/src/main/java/fj/data/fingertrees/MakeTree.java @@ -14,7 +14,7 @@ public final class MakeTree { MakeTree(final Measured m) { this.m = m; - this.empty = new Empty(m); + this.empty = new Empty<>(m); } // Tree constructors @@ -35,7 +35,7 @@ public FingerTree empty() { * @return A tree with the given value as the single element. */ public FingerTree single(final A a) { - return new Single(m, a); + return new Single<>(m, a); } /** @@ -63,7 +63,7 @@ public FingerTree deep(final Digit prefix, final FingerTree deep(final V v, final Digit prefix, final FingerTree> middle, final Digit suffix) { - return new Deep(m, v, prefix, middle, suffix); + return new Deep<>(m, v, prefix, middle, suffix); } // Digit constructors @@ -75,7 +75,7 @@ public FingerTree deep(final V v, final Digit prefix, final FingerTr * @return A digit of the given element. */ public One one(final A a) { - return new One(m, a); + return new One<>(m, a); } /** @@ -86,7 +86,7 @@ public One one(final A a) { * @return A digit of the given elements. */ public Two two(final A a, final A b) { - return new Two(m, v(a, b)); + return new Two<>(m, v(a, b)); } /** @@ -98,7 +98,7 @@ public Two two(final A a, final A b) { * @return A digit of the given elements. */ public Three three(final A a, final A b, final A c) { - return new Three(m, v(a, b, c)); + return new Three<>(m, v(a, b, c)); } /** @@ -111,7 +111,7 @@ public Three three(final A a, final A b, final A c) { * @return A digit of the given elements. */ public Four four(final A a, final A b, final A c, final A d) { - return new Four(m, v(a, b, c, d)); + return new Four<>(m, v(a, b, c, d)); } // Node constructors @@ -124,7 +124,7 @@ public Four four(final A a, final A b, final A c, final A d) { * @return A new binary tree node. */ public Node2 node2(final A a, final A b) { - return new Node2(m, v(a, b)); + return new Node2<>(m, v(a, b)); } /** @@ -136,7 +136,7 @@ public Node2 node2(final A a, final A b) { * @return A new trinary tree node. */ public Node3 node3(final A a, final A b, final A c) { - return new Node3(m, v(a, b, c)); + return new Node3<>(m, v(a, b, c)); } /** @@ -146,7 +146,7 @@ public Node3 node3(final A a, final A b, final A c) { * @return A new binary tree node. */ public Node2 node2(final V2 v) { - return new Node2(m, v); + return new Node2<>(m, v); } /** @@ -156,7 +156,7 @@ public Node2 node2(final V2 v) { * @return A new trinary tree node. */ public Node3 node3(final V3 v) { - return new Node3(m, v); + return new Node3<>(m, v); } } diff --git a/core/src/main/java/fj/data/fingertrees/Measured.java b/core/src/main/java/fj/data/fingertrees/Measured.java index d33b5726..28c94abe 100644 --- a/core/src/main/java/fj/data/fingertrees/Measured.java +++ b/core/src/main/java/fj/data/fingertrees/Measured.java @@ -17,7 +17,7 @@ private Measured(final Monoid m, final F measure) { } public static Measured measured(final Monoid m, final F measure) { - return new Measured(m, measure); + return new Measured<>(m, measure); } /** @@ -74,7 +74,7 @@ public V zero() { * @return A measured instance for nodes. */ public Measured> nodeMeasured() { - return new Measured>(m, Node::measure); + return new Measured<>(m, Node::measure); } /** @@ -83,7 +83,7 @@ public Measured> nodeMeasured() { * @return A measured instance for digits. */ public Measured> digitMeasured() { - return new Measured>(m, Digit::measure); + return new Measured<>(m, Digit::measure); } } diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index d107c8d4..674195d7 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -28,8 +28,8 @@ public static F, B>> foldRight_(final F> af public final Node map(final F f, final Measured m) { return match( - node2 -> new Node2(m, node2.toVector().map(f)), - node3 -> new Node3(m, node3.toVector().map(f)) + node2 -> new Node2<>(m, node2.toVector().map(f)), + node3 -> new Node3<>(m, node3.toVector().map(f)) ); } diff --git a/core/src/main/java/fj/data/fingertrees/Node2.java b/core/src/main/java/fj/data/fingertrees/Node2.java index 5fc979be..5af121c2 100644 --- a/core/src/main/java/fj/data/fingertrees/Node2.java +++ b/core/src/main/java/fj/data/fingertrees/Node2.java @@ -31,7 +31,7 @@ public final class Node2 extends Node { } public Digit toDigit() { - return new Two(measured(), as); + return new Two<>(measured(), as); } P3>, A, Option>> split1(final F predicate, final V acc) { diff --git a/core/src/main/java/fj/data/fingertrees/Node3.java b/core/src/main/java/fj/data/fingertrees/Node3.java index 233fcda7..5eb9bf58 100644 --- a/core/src/main/java/fj/data/fingertrees/Node3.java +++ b/core/src/main/java/fj/data/fingertrees/Node3.java @@ -40,7 +40,7 @@ public int length() { } public Digit toDigit() { - return new Three(measured(), as); + return new Three<>(measured(), as); } P3>, A, Option>> split1(final F predicate, final V acc) { diff --git a/core/src/main/java/fj/data/fingertrees/Single.java b/core/src/main/java/fj/data/fingertrees/Single.java index 1bbe7884..d322dcaa 100644 --- a/core/src/main/java/fj/data/fingertrees/Single.java +++ b/core/src/main/java/fj/data/fingertrees/Single.java @@ -37,7 +37,7 @@ public final class Single extends FingerTree { } @Override public FingerTree map(final F abf, final Measured m) { - return new Single(m, abf.f(a)); + return new Single<>(m, abf.f(a)); } /** @@ -59,12 +59,12 @@ public V measure() { @Override public FingerTree cons(final A b) { final MakeTree mk = mkTree(measured()); - return mk.deep(mk.one(b), new Empty>(measured().nodeMeasured()), mk.one(a)); + return mk.deep(mk.one(b), new Empty<>(measured().nodeMeasured()), mk.one(a)); } @Override public FingerTree snoc(final A b) { final MakeTree mk = mkTree(measured()); - return mk.deep(mk.one(a), new Empty>(measured().nodeMeasured()), mk.one(b)); + return mk.deep(mk.one(a), new Empty<>(measured().nodeMeasured()), mk.one(b)); } @Override public A head() { return a; } diff --git a/core/src/main/java/fj/data/hlist/HList.java b/core/src/main/java/fj/data/hlist/HList.java index b02d9504..639c9e64 100644 --- a/core/src/main/java/fj/data/hlist/HList.java +++ b/core/src/main/java/fj/data/hlist/HList.java @@ -47,7 +47,7 @@ public static HNil nil() { * @return a heterogeneous list consisting of an element and another list. */ public static > HCons cons(final E e, final L l) { - return new HCons(e, l); + return new HCons<>(e, l); } /** @@ -91,7 +91,7 @@ public C append(final A a, final B b) { * @return a method for concatenating lists to the empty list. */ public static > HAppend append() { - return new HAppend((hNil, l) -> l); + return new HAppend<>((hNil, l) -> l); } /** @@ -102,7 +102,7 @@ public static > HAppend append() { */ public static , B, C extends HList, H extends HAppend> HAppend, B, HCons> append(final H h) { - return new HAppend, B, HCons>((c, l) -> cons(c.head(), h.append(c.tail(), l))); + return new HAppend<>((c, l) -> cons(c.head(), h.append(c.tail(), l))); } } @@ -212,7 +212,7 @@ private HFoldr(final F3 foldRight) { * @return a fold instance for the empty list. */ public static HFoldr hFoldr() { - return new HFoldr((f, v, hNil) -> v); + return new HFoldr<>((f, v, hNil) -> v); } /** @@ -234,7 +234,7 @@ public static HFoldr hFoldr() { H extends HFoldr, PP extends Apply, RR>> HFoldr, RR> hFoldr(final PP p, final H h) { - return new HFoldr, RR>((f, v, c) -> p.apply(f, P.p(c.head(), h.foldRight(f, v, c.tail())))); + return new HFoldr<>((f, v, c) -> p.apply(f, P.p(c.head(), h.foldRight(f, v, c.tail())))); } /** diff --git a/core/src/main/java/fj/data/optic/Fold.java b/core/src/main/java/fj/data/optic/Fold.java index 21aca09f..af6b5739 100644 --- a/core/src/main/java/fj/data/optic/Fold.java +++ b/core/src/main/java/fj/data/optic/Fold.java @@ -76,7 +76,7 @@ public final Fold composeFold(final Fold other) { return new Fold() { @Override public F foldMap(final Monoid m, final F f) { - return Fold.this. foldMap(m, other. foldMap(m, f)); + return Fold.this.foldMap(m, other. foldMap(m, f)); } }; } diff --git a/core/src/main/java/fj/data/optic/Optional.java b/core/src/main/java/fj/data/optic/Optional.java index 200a952d..b2106cae 100644 --- a/core/src/main/java/fj/data/optic/Optional.java +++ b/core/src/main/java/fj/data/optic/Optional.java @@ -180,7 +180,7 @@ public static final Optional optional(final F> getOpti @Override public Either getOrModify(final S s) { - return getOption.f(s).option(Either.left(s), Either. right_()); + return getOption.f(s).option(Either.left(s), Either.right_()); } @Override @@ -213,7 +213,7 @@ public F> modifyEitherF(final F> f) { public F> modifyIOF(final F> f) { return s -> getOption.f(s).option( IOFunctions.unit(s), - a -> IOFunctions. map(f.f(a), b -> set.f(b).f(s)) + a -> IOFunctions.map(f.f(a), b -> set.f(b).f(s)) ); } diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java index 5c0bdd8c..73cc6fe9 100644 --- a/core/src/main/java/fj/data/optic/POptional.java +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -403,7 +403,7 @@ public F> modifyEitherF(final F> f) { public F> modifyIOF(final F> f) { return s -> getOrModify.f(s).either( IOFunctions::unit, - t -> IOFunctions. map(f.f(t), b -> set.f(b).f(s)) + t -> IOFunctions.map(f.f(t), b -> set.f(b).f(s)) ); } diff --git a/core/src/main/java/fj/data/optic/Prism.java b/core/src/main/java/fj/data/optic/Prism.java index 42decaaf..c2160b1f 100644 --- a/core/src/main/java/fj/data/optic/Prism.java +++ b/core/src/main/java/fj/data/optic/Prism.java @@ -95,7 +95,7 @@ public static Prism prism(final F> getOption, final F< @Override public Either getOrModify(final S s) { - return getOption.f(s).option(Either.left(s), Either. right_()); + return getOption.f(s).option(Either.left(s), Either.right_()); } @Override diff --git a/core/src/main/java/fj/data/vector/V2.java b/core/src/main/java/fj/data/vector/V2.java index 700a8409..fdab115c 100644 --- a/core/src/main/java/fj/data/vector/V2.java +++ b/core/src/main/java/fj/data/vector/V2.java @@ -30,7 +30,7 @@ private V2(final P2 inner) { * @return A new vector-2. */ public static V2 p(final P2 p) { - return new V2(p); + return new V2<>(p); } /** diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index ceb492bc..9b25258f 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -30,7 +30,7 @@ private V3(final P1 head, final V2 tail) { * @return A new vector-3. */ public static V3 p(final P3 p) { - return new V3( + return new V3<>( P.lazy(p::_1), V2.p(P.lazy(p::_2, p::_3)) ); @@ -44,7 +44,7 @@ public static V3 p(final P3 p) { * @return The new vector. */ public static V3 cons(final P1 head, final V2 tail) { - return new V3(head, tail); + return new V3<>(head, tail); } /** @@ -131,7 +131,7 @@ public Array toArray() { * @return A new vector after zipping the given vector of functions over this vector. */ public V3 apply(final V3> vf) { - return new V3(head.apply(vf.head()), tail.apply(vf.tail())); + return new V3<>(head.apply(vf.head()), tail.apply(vf.tail())); } /** @@ -202,7 +202,7 @@ public Stream toStream() { * @return A new vector after the given function has been applied to each element. */ public V3 map(final F f) { - return new V3(head().map(f), tail().map(f)); + return new V3<>(head().map(f), tail().map(f)); } /** diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 8e142023..1f39346b 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -30,20 +30,20 @@ private V4(final P1 head, final V3 tail) { * @return A new vector-4. */ public static V4 p(final P4 p) { - return new V4(P.lazy(p::_1), - V3.p(new P3() { - public A _1() { - return p._2(); - } - - public A _2() { - return p._3(); - } - - public A _3() { - return p._4(); - } - })); + return new V4<>(P.lazy(p::_1), + V3.p(new P3() { + public A _1() { + return p._2(); + } + + public A _2() { + return p._3(); + } + + public A _3() { + return p._4(); + } + })); } /** @@ -54,7 +54,7 @@ public A _3() { * @return The new vector. */ public static V4 cons(final P1 head, final V3 tail) { - return new V4(head, tail); + return new V4<>(head, tail); } /** @@ -180,7 +180,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V4 map(final F f) { - return new V4(head.map(f), tail.map(f)); + return new V4<>(head.map(f), tail.map(f)); } /** @@ -190,7 +190,7 @@ public V4 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V4 apply(final V4> vf) { - return new V4(head.apply(vf.head()), tail.apply(vf.tail())); + return new V4<>(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index d386cb32..0119dcf9 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -30,24 +30,24 @@ private V5(final P1 head, final V4 tail) { * @return A new vector-5. */ public static V5 p(final P5 p) { - return new V5(P.lazy(p::_1), - V4.p(new P4() { - public A _1() { - return p._2(); - } - - public A _2() { - return p._3(); - } - - public A _3() { - return p._4(); - } - - public A _4() { - return p._5(); - } - })); + return new V5<>(P.lazy(p::_1), + V4.p(new P4() { + public A _1() { + return p._2(); + } + + public A _2() { + return p._3(); + } + + public A _3() { + return p._4(); + } + + public A _4() { + return p._5(); + } + })); } /** @@ -58,7 +58,7 @@ public A _4() { * @return The new vector. */ public static V5 cons(final P1 head, final V4 tail) { - return new V5(head, tail); + return new V5<>(head, tail); } /** @@ -197,7 +197,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V5 map(final F f) { - return new V5(head.map(f), tail.map(f)); + return new V5<>(head.map(f), tail.map(f)); } /** @@ -207,7 +207,7 @@ public V5 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V5 apply(final V5> vf) { - return new V5(head.apply(vf.head()), tail.apply(vf.tail())); + return new V5<>(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 107c01a5..47a0c4e7 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -30,28 +30,28 @@ private V6(final P1 head, final V5 tail) { * @return A new vector-6. */ public static V6 p(final P6 p) { - return new V6(P.lazy(p::_1), - V5.p(new P5() { - public A _1() { - return p._2(); - } - - public A _2() { - return p._3(); - } - - public A _3() { - return p._4(); - } - - public A _4() { - return p._5(); - } - - public A _5() { - return p._6(); - } - })); + return new V6<>(P.lazy(p::_1), + V5.p(new P5() { + public A _1() { + return p._2(); + } + + public A _2() { + return p._3(); + } + + public A _3() { + return p._4(); + } + + public A _4() { + return p._5(); + } + + public A _5() { + return p._6(); + } + })); } /** @@ -62,7 +62,7 @@ public A _5() { * @return The new vector. */ public static V6 cons(final P1 head, final V5 tail) { - return new V6(head, tail); + return new V6<>(head, tail); } /** @@ -214,7 +214,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V6 map(final F f) { - return new V6(head.map(f), tail.map(f)); + return new V6<>(head.map(f), tail.map(f)); } /** @@ -224,7 +224,7 @@ public V6 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V6 apply(final V6> vf) { - return new V6(head.apply(vf.head()), tail.apply(vf.tail())); + return new V6<>(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index 52699481..c0dfa4b6 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -30,32 +30,32 @@ private V7(final P1 head, final V6 tail) { * @return A new vector-7. */ public static V7 p(final P7 p) { - return new V7(P.lazy(p::_1), - V6.p(new P6() { - public A _1() { - return p._2(); - } - - public A _2() { - return p._3(); - } - - public A _3() { - return p._4(); - } - - public A _4() { - return p._5(); - } - - public A _5() { - return p._6(); - } - - public A _6() { - return p._7(); - } - })); + return new V7<>(P.lazy(p::_1), + V6.p(new P6() { + public A _1() { + return p._2(); + } + + public A _2() { + return p._3(); + } + + public A _3() { + return p._4(); + } + + public A _4() { + return p._5(); + } + + public A _5() { + return p._6(); + } + + public A _6() { + return p._7(); + } + })); } /** @@ -66,7 +66,7 @@ public A _6() { * @return The new vector. */ public static V7 cons(final P1 head, final V6 tail) { - return new V7(head, tail); + return new V7<>(head, tail); } /** @@ -231,7 +231,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V7 map(final F f) { - return new V7(head.map(f), tail.map(f)); + return new V7<>(head.map(f), tail.map(f)); } /** @@ -241,7 +241,7 @@ public V7 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V7 apply(final V7> vf) { - return new V7(head.apply(vf.head()), tail.apply(vf.tail())); + return new V7<>(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index 8ad96cdd..f01dc2fe 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -30,36 +30,36 @@ private V8(final P1 head, final V7 tail) { * @return A new vector-8. */ public static V8 p(final P8 p) { - return new V8(P.lazy(p::_1), - V7.p(new P7() { - public A _1() { - return p._2(); - } + return new V8<>(P.lazy(p::_1), + V7.p(new P7() { + public A _1() { + return p._2(); + } - public A _2() { - return p._3(); - } + public A _2() { + return p._3(); + } - public A _3() { - return p._4(); - } + public A _3() { + return p._4(); + } - public A _4() { - return p._5(); - } + public A _4() { + return p._5(); + } - public A _5() { - return p._6(); - } + public A _5() { + return p._6(); + } - public A _6() { - return p._7(); - } + public A _6() { + return p._7(); + } - public A _7() { - return p._8(); - } - })); + public A _7() { + return p._8(); + } + })); } /** @@ -70,7 +70,7 @@ public A _7() { * @return The new vector. */ public static V8 cons(final P1 head, final V7 tail) { - return new V8(head, tail); + return new V8<>(head, tail); } /** @@ -248,7 +248,7 @@ public Array toArray() { * @return A new vector after the given function has been applied to each element. */ public V8 map(final F f) { - return new V8(head.map(f), tail.map(f)); + return new V8<>(head.map(f), tail.map(f)); } /** @@ -258,7 +258,7 @@ public V8 map(final F f) { * @return A new vector after zipping the given vector of functions over this vector. */ public V8 apply(final V8> vf) { - return new V8(head.apply(vf.head()), tail.apply(vf.tail())); + return new V8<>(head.apply(vf.head()), tail.apply(vf.tail())); } /** diff --git a/core/src/main/java/fj/function/Visitor.java b/core/src/main/java/fj/function/Visitor.java index 0f8c3846..bdca3b5e 100644 --- a/core/src/main/java/fj/function/Visitor.java +++ b/core/src/main/java/fj/function/Visitor.java @@ -42,7 +42,7 @@ public static X findFirst(final List> values, final F0 def) { * @return The first non-null value in the given list of optional values. If none is found return the given default value. */ public static X nullablefindFirst(final List values, final F0 def) { - return findFirst(values.map(Option.fromNull()), def); + return findFirst(values.map(Option.fromNull()), def); } /** @@ -56,7 +56,7 @@ public static X nullablefindFirst(final List values, final F0 def) { * given default. */ public static B visitor(final List>> visitors, final F0 def, final A value) { - return findFirst(visitors.map(Function.>apply(value)), def); + return findFirst(visitors.map(Function.apply(value)), def); } /** @@ -70,7 +70,7 @@ public static B visitor(final List>> visitors, final F0 * given default. */ public static B nullableVisitor(final List> visitors, final F0 def, final A value) { - return visitor(visitors.map(k -> compose(Option.fromNull(), k)), def, value); + return visitor(visitors.map(k -> compose(Option.fromNull(), k)), def, value); } /** diff --git a/core/src/main/java/fj/parser/Parser.java b/core/src/main/java/fj/parser/Parser.java index 605125f0..3ea6dd15 100644 --- a/core/src/main/java/fj/parser/Parser.java +++ b/core/src/main/java/fj/parser/Parser.java @@ -210,7 +210,7 @@ public Parser sequence(final Parser p) { * @return A new parser after function application. */ public Parser apply(final Parser, E> p) { - return p.bind((F, Parser>) this::map); + return p.bind(this::map); } /** @@ -265,8 +265,8 @@ public Parser or(final Parser alt, final Semigroup s) { */ public Parser not(final F0 e) { return parser(i -> parse(i).isFail() ? - Validation.>success(result(i, unit())) : - Validation.>fail(e.f())); + Validation.success(result(i, unit())) : + Validation.fail(e.f())); } /** @@ -285,7 +285,7 @@ public Parser not(final E e) { * @return A parser that repeats application of this parser zero or many times. */ public Parser, E> repeat() { - return repeat1().or(() -> value(Stream.nil())); + return repeat1().or(() -> value(Stream.nil())); } /** @@ -345,7 +345,7 @@ public static Parser fail(final E e) { */ public static Parser, E> sequence(final List> ps) { return ps.isEmpty() ? - Parser., E>value(List.nil()) : + Parser.value(List.nil()) : ps.head().bind(a -> sequence(ps.tail()).map(cons_(a))); } @@ -365,8 +365,8 @@ private StreamParser() { */ public static Parser, I, E> element(final F0 e) { return parser(is -> is.isEmpty() ? - Validation., I>>fail(e.f()) : - Validation., I>>success(result(is.tail()._1(), is.head()))); + Validation.fail(e.f()) : + Validation.success(result(is.tail()._1(), is.head()))); } /** @@ -390,8 +390,8 @@ public static Parser, I, E> element(final E e) { public static Parser, I, E> satisfy(final F0 missing, final F sat, final F f) { return StreamParser.element(missing).bind(x -> f.f(x) ? - Parser., I, E>value(x) : - Parser., I, E>fail(sat.f(x))); + Parser.value(x) : + Parser.fail(sat.f(x))); } /** @@ -470,8 +470,8 @@ public static Parser, Character, E> character(final E miss */ public static Parser, Stream, E> characters(final F0 missing, final int n) { return n <= 0 ? - Parser., Stream, E>value(Stream.nil()) : - character(missing).bind(characters(missing, n - 1), Stream.cons_()); + Parser.value(Stream.nil()) : + character(missing).bind(characters(missing, n - 1), Stream.cons_()); } /** @@ -497,8 +497,8 @@ public static Parser, Stream, E> characters(fin final F sat, final Stream cs) { return cs.isEmpty() ? - Parser., Stream, E>value(Stream.nil()) : - character(missing, sat, cs.head()).bind(characters(missing, sat, cs.tail()._1()), Stream.cons_()); + Parser.value(Stream.nil()) : + character(missing, sat, cs.head()).bind(characters(missing, sat, cs.tail()._1()), Stream.cons_()); } /** diff --git a/core/src/main/java/fj/parser/Result.java b/core/src/main/java/fj/parser/Result.java index 8f5a4b78..51e115f6 100644 --- a/core/src/main/java/fj/parser/Result.java +++ b/core/src/main/java/fj/parser/Result.java @@ -133,7 +133,7 @@ public void remove() { * @return A result with the given remainder of the parse input and parse value. */ public static Result result(final I i, final A a) { - return new Result(i, a); + return new Result<>(i, a); } /** diff --git a/demo/src/main/java/fj/demo/ChequeWrite.java b/demo/src/main/java/fj/demo/ChequeWrite.java index ee958fc9..6e28153c 100644 --- a/demo/src/main/java/fj/demo/ChequeWrite.java +++ b/demo/src/main/java/fj/demo/ChequeWrite.java @@ -24,7 +24,7 @@ public final class ChequeWrite { private ChequeWrite() {} static List toZero(final int from) { - return unfold(i -> i < 0 ? Option.>none() : some(p(i, i - 1)), from); + return unfold(i -> i < 0 ? Option.none() : some(p(i, i - 1)), from); } static int signum(final int i) { @@ -60,9 +60,9 @@ static List show(final List cs) { : stringShow.showl( list("twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety").index( d1 - '0' - 2)) - .append(d2 == '0' ? List.nil() : show(d2).cons('-')) + .append(d2 == '0' ? List.nil() : show(d2).cons('-')) : d1 == '0' && d2 == '0' && d2r.head() == '0' - ? List.nil() + ? List.nil() : d1 == '0' ? show(list(d2, d2r.head())) : d2 == '0' && d2r.head() == '0' @@ -76,7 +76,7 @@ static List, Integer>> split(final List as) { final int len = as.length(); final List> ds = as.zip(toZero(len - 1)).foldRight((ki, z) -> - ki._2() % 3 == 0 ? z.conss(single(ki._1())) : z.tail().conss(z.head().cons(ki._1())), List.>nil() + ki._2() % 3 == 0 ? z.conss(single(ki._1())) : z.tail().conss(z.head().cons(ki._1())), List.nil() ); return ds.zip(toZero(len / 3 + signum(len % 3) - 1)); } @@ -106,7 +106,7 @@ static boolean eq(final List a, final List b) { if (cs.isEmpty()) return fromString("zero dollars"); else { - final List.Buffer> x = new List.Buffer>(); + final List.Buffer> x = new List.Buffer<>(); final List, Integer>> k = split(cs); final int c = k.head()._2(); diff --git a/demo/src/main/java/fj/demo/Comonad_example.java b/demo/src/main/java/fj/demo/Comonad_example.java index 9a64c34e..8d5bc683 100644 --- a/demo/src/main/java/fj/demo/Comonad_example.java +++ b/demo/src/main/java/fj/demo/Comonad_example.java @@ -22,11 +22,11 @@ public static void main(final String[] args) { } public static Stream> perms(final Stream s) { - Stream> r = single(Stream.nil()); + Stream> r = single(Stream.nil()); for (final Zipper z : fromStream(s)) r = join(z.cobind(zp -> perms(zp.lefts().reverse().append(zp.rights())).map( - F1Functions.o(Stream.cons().f(zp.focus()), P.>p1()) + F1Functions.o(Stream.cons().f(zp.focus()), P.p1()) ) ).toStream()); return r; diff --git a/demo/src/main/java/fj/demo/Option_bind.java b/demo/src/main/java/fj/demo/Option_bind.java index d02a1493..edf3dd83 100644 --- a/demo/src/main/java/fj/demo/Option_bind.java +++ b/demo/src/main/java/fj/demo/Option_bind.java @@ -18,9 +18,9 @@ public static void main(final String[] args) { final Option o5 = o2.bind(f); final Option o6 = o3.bind(f); - final Option p1 = o1.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); - final Option p2 = o2.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); - final Option p3 = o3.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p1 = o1.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p2 = o2.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); + final Option p3 = o3.bind(i -> i % 2 == 0 ? some(i * 3) : Option.none()); optionShow(intShow).println(o4); // None optionShow(intShow).println(o5); // Some(24) diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index 167a08f5..56763ce5 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -75,7 +75,7 @@ VendingMachine next(Input i) { } static State simulate(List list) { - return list.foldLeft((s, i) -> s.map(m -> m.next(i)), State.init()); + return list.foldLeft((s, i) -> s.map(m -> m.next(i)), State.init()); } static void test() { diff --git a/demo/src/main/java/fj/demo/concurrent/Fibs.java b/demo/src/main/java/fj/demo/concurrent/Fibs.java index 5e95e597..e2e94fc8 100644 --- a/demo/src/main/java/fj/demo/concurrent/Fibs.java +++ b/demo/src/main/java/fj/demo/concurrent/Fibs.java @@ -52,7 +52,7 @@ public static void main(final String[] args) {return n < CUTOFF ? promise(su, P.p(seqFib(n))) : f(n - 1).bind(f(n - 2), add);}}; System.out.println("Calculating Fibonacci sequence in parallel..."); - join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} + join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} // The sequential version of the recursive Fibonacci function public static int seqFib(final int n) diff --git a/demo/src/main/java/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java index 57a59d9e..3cb2d761 100644 --- a/demo/src/main/java/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -64,7 +64,7 @@ public Stream f(final BufferedReader reader) { })); final ExecutorService pool = newFixedThreadPool(16); - final ParModule m = parModule(Strategy.executorStrategy(pool)); + final ParModule m = parModule(Strategy.executorStrategy(pool)); System.out.println("Word Count: " + countWords(documents, m).claim()); diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index dbbd035c..203b8feb 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -56,7 +56,7 @@ private static Map update(Map map, K key, F valueFuncti private static final F> fileNameToWordsAndCountsWithCharChunkIteratee = fileName -> { try { - return IOFunctions.enumFileCharChunks(new File(fileName), Option.none(), wordCountsFromCharChunks()).run().run(); + return IOFunctions.enumFileCharChunks(new File(fileName), Option.none(), wordCountsFromCharChunks()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } @@ -64,7 +64,7 @@ private static Map update(Map map, K key, F valueFuncti private static final F> fileNameToWordsAndCountsWithCharChunk2Iteratee = fileName -> { try { - return IOFunctions.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); + return IOFunctions.enumFileChars(new File(fileName), Option.none(), wordCountsFromChars()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } @@ -72,7 +72,7 @@ private static Map update(Map map, K key, F valueFuncti private static final F> fileNameToWordsAndCountsWithCharIteratee = fileName -> { try { - return IOFunctions.enumFileChars(new File(fileName), Option. none(), wordCountsFromChars()).run().run(); + return IOFunctions.enumFileChars(new File(fileName), Option.none(), wordCountsFromChars()).run().run(); } catch (final IOException e) { throw new RuntimeException(e); } @@ -115,9 +115,9 @@ public F>> _1() { final StringBuilder sb = acc._1(); if(sb.length() > 0) { final Map map = update(acc._2(), sb.toString(), addOne, Integer.valueOf(0)); - return IterV.done(map, Input.eof()); + return IterV.done(map, Input.eof()); } - return IterV.done(acc._2(), Input.eof()); + return IterV.done(acc._2(), Input.eof()); }); return s -> s.apply(empty, el, eof); @@ -157,9 +157,9 @@ public F, IterV>> f(final P2 0) { final Map map = update(acc._2(), sb.toString(), addOne, Integer.valueOf(0)); - return IterV.done(map, Input.eof()); + return IterV.done(map, Input.eof()); } - return IterV.done(acc._2(), Input.eof()); + return IterV.done(acc._2(), Input.eof()); } ); return s -> s.apply(empty, el, eof); @@ -268,7 +268,7 @@ private static void print(Map wordsAndCountsFromFiles) { private static P2, Map> writeSampleFiles( int numFiles, int numSharedWords) throws IOException { - final Map expectedWordsAndCounts = new HashMap(); + final Map expectedWordsAndCounts = new HashMap<>(); List fileNames = nil(); for(int i = 0; i < numFiles; i++) { final File file = File.createTempFile("wordcount-"+ i + "-", ".txt"); @@ -294,7 +294,7 @@ public static Map getWordsAndCountsFromFilesWithIteratee(final public static Map getWordsAndCountsFromFilesInParallel( final List fileNames, final F> fileNameToWordsAndCounts, int numThreads) { final ExecutorService pool = newFixedThreadPool(numThreads); - final ParModule m = parModule(Strategy. executorStrategy(pool)); + final ParModule m = parModule(Strategy.executorStrategy(pool)); // Long wordCount = countWords(fileNames.map(readFile), m).claim(); final Map result = getWordsAndCountsFromFiles(fileNames, fileNameToWordsAndCounts, m).claim(); @@ -315,7 +315,7 @@ public static Promise> getWordsAndCountsFromFiles( } private static Map plus(Map a, Map b) { - final Map result = new HashMap(a); + final Map result = new HashMap<>(a); for(Map.Entry entry : b.entrySet()) { final Integer num = result.get(entry.getKey()); result.put(entry.getKey(), num != null ? num.intValue() + entry.getValue() : entry.getValue()); diff --git a/demo/src/main/java/fj/demo/test/JavaLinkedList.java b/demo/src/main/java/fj/demo/test/JavaLinkedList.java index 5ce11fba..ba8ec1f1 100644 --- a/demo/src/main/java/fj/demo/test/JavaLinkedList.java +++ b/demo/src/main/java/fj/demo/test/JavaLinkedList.java @@ -17,7 +17,7 @@ public final class JavaLinkedList { public static void main(final String[] args) { final Property p = property(arbLinkedList(arbInteger), arbLinkedList(arbInteger), (x, y) -> { - final LinkedList xy = new LinkedList(x); + final LinkedList xy = new LinkedList<>(x); xy.addAll(y); return prop(xy.size() == x.size() + y.size()); }); diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index 8ed7a306..6f17f827 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -40,7 +40,7 @@ For any list, mapping the identity function (\x -> x) produces the same list. @SuppressWarnings("PackageVisibleField") @CheckParams(minSuccessful = 1000) public final class ListFunctorLaws { - final Property identity = property(arbList(arbString), x -> prop(listEqual(stringEqual).eq(x, x.map(Function.identity())))); + final Property identity = property(arbList(arbString), x -> prop(listEqual(stringEqual).eq(x, x.map(Function.identity())))); final Property composition = property(arbF(coarbInteger, arbString), arbF(coarbLong, arbInteger), arbList(arbLong), (f, g, x) -> { final List s1 = x.map(compose(f, g)); diff --git a/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java index 18d1b5d7..5e5550a3 100644 --- a/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java +++ b/demo/src/main/java/fj/demo/test/OptionMonadFunctorLaw.java @@ -19,7 +19,7 @@ For any Option (o) and any function (f), then calling flatMap on o with a */ public final class OptionMonadFunctorLaw { public static void main(final String[] args) { - final Property unitMap = property(arbOption(arbInteger), Arbitrary.arbFInvariant(arbString), (o, f) -> prop(optionEqual(stringEqual).eq(o.bind(andThen(f, Option.some_())), o.map(f)))); + final Property unitMap = property(arbOption(arbInteger), Arbitrary.arbFInvariant(arbString), (o, f) -> prop(optionEqual(stringEqual).eq(o.bind(andThen(f, Option.some_())), o.map(f)))); summary.println(unitMap.minSuccessful(500)); // OK, passed 500 tests. } } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index a9f05549..848585aa 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -97,7 +97,7 @@ private Arbitrary(final Gen gen) { * @return A new arbitrary that uses the given generator. */ public static Arbitrary arbitrary(final Gen g) { - return new Arbitrary(g); + return new Arbitrary<>(g); } /** @@ -140,7 +140,7 @@ public static Arbitrary arbLcgRng() { * @return An arbitrary for functions. */ public static Arbitrary> arbFInvariant(final Arbitrary a) { - return arbitrary(a.gen.map(Function.constant())); + return arbitrary(a.gen.map(Function.constant())); } /** @@ -153,7 +153,7 @@ public static Arbitrary> arbFInvariant(final Arbitrary a) { */ public static Arbitrary> arbF2(final Coarbitrary ca, final Coarbitrary cb, final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, a)).gen.map(Function.uncurryF2())); + return arbitrary(arbF(ca, arbF(cb, a)).gen.map(Function.uncurryF2())); } /** @@ -164,7 +164,7 @@ public static Arbitrary> arbF2(final Coarbitrary ca, fi */ public static Arbitrary> arbF2Invariant(final Arbitrary a) { return arbitrary(a.gen.map( - compose(Function.uncurryF2(), compose(Function.>constant(), Function.constant())))); + compose(Function.uncurryF2(), compose(Function.constant(), Function.constant())))); } /** @@ -178,7 +178,7 @@ public static Arbitrary> arbF2Invariant(final Arbitrary */ public static Arbitrary> arbF3(final Coarbitrary ca, final Coarbitrary cb, final Coarbitrary cc, final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, a))).gen.map(Function.uncurryF3())); + return arbitrary(arbF(ca, arbF(cb, arbF(cc, a))).gen.map(Function.uncurryF3())); } /** @@ -188,10 +188,10 @@ public static Arbitrary> arbF3(final Coarbitrary * @return An arbitrary for function-3. */ public static Arbitrary> arbF3Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF3(), compose(Function.>>constant(), + return arbitrary(a.gen.map(compose(Function.uncurryF3(), compose(Function.constant(), compose( - Function.>constant(), - Function.constant()))))); + Function.constant(), + Function.constant()))))); } /** @@ -207,7 +207,7 @@ public static Arbitrary> arbF3Invariant(final Arbitr public static Arbitrary> arbF4(final Coarbitrary ca, final Coarbitrary cb, final Coarbitrary cc, final Coarbitrary cd, final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, a)))).gen.map(Function.uncurryF4())); + return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, a)))).gen.map(Function.uncurryF4())); } /** @@ -217,11 +217,11 @@ public static Arbitrary> arbF4(final Coarbitra * @return An arbitrary for function-4. */ public static Arbitrary> arbF4Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF4(), - compose(Function.>>>constant(), - compose(Function.>>constant(), - compose(Function.>constant(), - Function.constant())))))); + return arbitrary(a.gen.map(compose(Function.uncurryF4(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + Function.constant())))))); } /** @@ -242,7 +242,7 @@ public static Arbitrary> arbF4Invariant(final final Coarbitrary ce, final Arbitrary a) { return arbitrary( - arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, a))))).gen.map(Function.uncurryF5())); + arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, a))))).gen.map(Function.uncurryF5())); } /** @@ -252,12 +252,12 @@ public static Arbitrary> arbF4Invariant(final * @return An arbitrary for function-5. */ public static Arbitrary> arbF5Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF5(), - compose(Function.>>>>constant(), - compose(Function.>>>constant(), - compose(Function.>>constant(), - compose(Function.>constant(), - Function.constant()))))))); + return arbitrary(a.gen.map(compose(Function.uncurryF5(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + Function.constant()))))))); } /** @@ -280,7 +280,7 @@ public static Arbitrary> arbF4Invariant(final final Coarbitrary cf, final Arbitrary a) { return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, a)))))).gen.map( - Function.uncurryF6())); + Function.uncurryF6())); } /** @@ -291,12 +291,12 @@ public static Arbitrary> arbF4Invariant(final */ public static Arbitrary> arbF6Invariant(final Arbitrary a) { return arbitrary(a.gen.map(compose(Function.uncurryF6(), - compose(Function.>>>>>constant(), - compose(Function.>>>>constant(), - compose(Function.>>>constant(), - compose(Function.>>constant(), - compose(Function.>constant(), - Function.constant())))))))); + compose(Function.>>>>>constant(), + compose(Function.>>>>constant(), + compose(Function.>>>constant(), + compose(Function.>>constant(), + compose(Function.>constant(), + Function.constant())))))))); } /** @@ -321,7 +321,7 @@ public static Arbitrary> arbF4Invariant(final final Coarbitrary cg, final Arbitrary a) { return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, a))))))).gen.map( - Function.uncurryF7())); + Function.uncurryF7())); } /** @@ -332,13 +332,13 @@ public static Arbitrary> arbF4Invariant(final */ public static Arbitrary> arbF7Invariant(final Arbitrary a) { return arbitrary(a.gen.map(compose(Function.uncurryF7(), - compose(Function.>>>>>>constant(), - compose(Function.>>>>>constant(), - compose(Function.>>>>constant(), - compose(Function.>>>constant(), - compose(Function.>>constant(), - compose(Function.>constant(), - Function.constant()))))))))); + compose(Function.>>>>>>constant(), + compose(Function.>>>>>constant(), + compose(Function.>>>>constant(), + compose(Function.>>>constant(), + compose(Function.>>constant(), + compose(Function.>constant(), + Function.constant()))))))))); } /** @@ -365,7 +365,7 @@ public static Arbitrary> arbF4Invariant(final final Coarbitrary ch, final Arbitrary a) { return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, arbF(ch, a)))))))).gen.map( - Function.uncurryF8())); + Function.uncurryF8())); } /** @@ -377,16 +377,16 @@ public static Arbitrary> arbF4Invariant(final public static Arbitrary> arbF8Invariant( final Arbitrary a) { return arbitrary(a.gen.map(compose(Function.uncurryF8(), - compose(Function.>>>>>>>constant(), - compose(Function.>>>>>>constant(), - compose(Function.>>>>>constant(), - compose( - Function.>>>>constant(), - compose(Function.>>>constant(), - compose( - Function.>>constant(), - compose(Function.>constant(), - Function.constant())))))))))); + compose(Function.>>>>>>>constant(), + compose(Function.>>>>>>constant(), + compose(Function.>>>>>constant(), + compose( + Function.>>>>constant(), + compose(Function.>>>constant(), + compose( + Function.>>constant(), + compose(Function.>constant(), + Function.constant())))))))))); } /** @@ -619,7 +619,7 @@ public static Arbitrary> arbGen(final Arbitrary aa) { */ public static Arbitrary> arbOption(final Arbitrary aa) { return arbitrary(sized(i -> i == 0 ? - value(Option.none()) : + value(Option.none()) : aa.gen.map(Option::some).resize(i - 1))); } @@ -695,7 +695,7 @@ public static Arbitrary> arbValidation(final Arbitrary Arbitrary> arbStream(final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(List::toStream)); + return arbitrary(arbList(aa).gen.map(List::toStream)); } /** @@ -753,7 +753,7 @@ public static Arbitrary arbThrowable(final Arbitrary as) { * @return An arbitrary implementation for array lists. */ public static Arbitrary> arbArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new ArrayList(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new ArrayList<>(a.toCollection()))); } /** @@ -842,7 +842,7 @@ public static Arbitrary> arbHashMap(final Arbitrary ak, * @return An arbitrary implementation for hash sets. */ public static Arbitrary> arbHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new HashSet(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new HashSet<>(a.toCollection()))); } /** @@ -856,7 +856,7 @@ public static Arbitrary> arbHashSet(final Arbitrary aa) { */ public static Arbitrary> arbHashtable(final Arbitrary ak, final Arbitrary av) { return arbitrary(arbList(ak).gen.bind(arbList(av).gen, ks -> vs -> { - final Hashtable t = new Hashtable(); + final Hashtable t = new Hashtable<>(); ks.zip(vs).foreachDoEffect(kv -> t.put(kv._1(), kv._2())); @@ -898,7 +898,7 @@ public static Arbitrary> arbLinkedHashMap(final Arbit * @return An arbitrary implementation for hash sets. */ public static Arbitrary> arbLinkedHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedHashSet(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedHashSet<>(a.toCollection()))); } /** @@ -908,7 +908,7 @@ public static Arbitrary> arbLinkedHashSet(final Arbitrary Arbitrary> arbLinkedList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedList(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedList<>(a.toCollection()))); } /** @@ -918,7 +918,7 @@ public static Arbitrary> arbLinkedList(final Arbitrary aa) * @return An arbitrary implementation for priority queues. */ public static Arbitrary> arbPriorityQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new PriorityQueue(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new PriorityQueue<>(a.toCollection()))); } /** @@ -943,7 +943,7 @@ public static Arbitrary> arbPriorityQueue(final Arbitrary Arbitrary> arbStack(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.map(a -> { - final Stack s = new Stack(); + final Stack s = new Stack<>(); s.addAll(a.toCollection()); return s; })); @@ -1005,7 +1005,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb * @return An arbitrary implementation for tree sets. */ public static Arbitrary> arbTreeSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new TreeSet(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new TreeSet<>(a.toCollection()))); } /** @@ -1016,7 +1016,7 @@ public static Arbitrary> arbTreeSet(final Arbitrary aa) { */ @SuppressWarnings("UseOfObsoleteCollectionType") public static Arbitrary> arbVector(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new Vector(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new Vector<>(a.toCollection()))); } /** @@ -1071,7 +1071,7 @@ public static Arbitrary> arbConcurrentHashMap(fin * @return An arbitrary implementation for concurrent linked queues. */ public static Arbitrary> arbConcurrentLinkedQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new ConcurrentLinkedQueue(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new ConcurrentLinkedQueue<>(a.toCollection()))); } /** @@ -1082,7 +1082,7 @@ public static Arbitrary> arbConcurrentLinkedQueue(f * @return An arbitrary implementation for copy-on-write array lists. */ public static Arbitrary> arbCopyOnWriteArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArrayList(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArrayList<>(a.toCollection()))); } /** @@ -1093,7 +1093,7 @@ public static Arbitrary> arbCopyOnWriteArrayList(fin * @return An arbitrary implementation for copy-on-write array sets. */ public static Arbitrary> arbCopyOnWriteArraySet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArraySet(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArraySet<>(a.toCollection()))); } /** @@ -1103,7 +1103,7 @@ public static Arbitrary> arbCopyOnWriteArraySet(final * @return An arbitrary implementation for delay queues. */ public static Arbitrary> arbDelayQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new DelayQueue(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new DelayQueue<>(a.toCollection()))); } /** @@ -1114,7 +1114,7 @@ public static Arbitrary> arbDelayQueue(final A * @return An arbitrary implementation for linked blocking queues. */ public static Arbitrary> arbLinkedBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedBlockingQueue(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedBlockingQueue<>(a.toCollection()))); } /** @@ -1125,7 +1125,7 @@ public static Arbitrary> arbLinkedBlockingQueue(final * @return An arbitrary implementation for priority blocking queues. */ public static Arbitrary> arbPriorityBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new PriorityBlockingQueue(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new PriorityBlockingQueue<>(a.toCollection()))); } /** @@ -1137,7 +1137,7 @@ public static Arbitrary> arbPriorityBlockingQueue(f */ public static Arbitrary> arbSynchronousQueue(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.bind(arbBoolean.gen, a -> fair -> { - final SynchronousQueue q = new SynchronousQueue(fair); + final SynchronousQueue q = new SynchronousQueue<>(fair); q.addAll(a.toCollection()); return q; })); diff --git a/quickcheck/src/main/java/fj/test/Arg.java b/quickcheck/src/main/java/fj/test/Arg.java index 337f8027..4187c15d 100644 --- a/quickcheck/src/main/java/fj/test/Arg.java +++ b/quickcheck/src/main/java/fj/test/Arg.java @@ -28,7 +28,7 @@ private Arg(final T value, final int shrinks) { * @return A new argument. */ public static Arg arg(final T value, final int shrinks) { - return new Arg(value, shrinks); + return new Arg<>(value, shrinks); } /** diff --git a/quickcheck/src/main/java/fj/test/CheckResult.java b/quickcheck/src/main/java/fj/test/CheckResult.java index dc0195d7..718daf03 100644 --- a/quickcheck/src/main/java/fj/test/CheckResult.java +++ b/quickcheck/src/main/java/fj/test/CheckResult.java @@ -55,7 +55,7 @@ private CheckResult(final R r, final Option>> args, final Option>>none(), Option.none(), succeeded, discarded); + return new CheckResult(R.Passed, Option.none(), Option.none(), succeeded, discarded); } /** @@ -67,7 +67,7 @@ public static CheckResult passed(final int succeeded, final int discarded) { * @return A result that the property has been proven. */ public static CheckResult proven(final List> args, final int succeeded, final int discarded) { - return new CheckResult(R.Proven, some(args), Option.none(), succeeded, discarded); + return new CheckResult(R.Proven, some(args), Option.none(), succeeded, discarded); } /** @@ -79,7 +79,7 @@ public static CheckResult proven(final List> args, final int succeeded, f * @return A result that the property has been falsified. */ public static CheckResult falsified(final List> args, final int succeeded, final int discarded) { - return new CheckResult(R.Falsified, some(args), Option.none(), succeeded, discarded); + return new CheckResult(R.Falsified, some(args), Option.none(), succeeded, discarded); } /** @@ -90,7 +90,7 @@ public static CheckResult falsified(final List> args, final int succeeded * @return A result that the property has been exhausted in checking. */ public static CheckResult exhausted(final int succeeded, final int discarded) { - return new CheckResult(R.Exhausted, Option.>>none(), Option.none(), succeeded, discarded); + return new CheckResult(R.Exhausted, Option.none(), Option.none(), succeeded, discarded); } /** @@ -117,7 +117,7 @@ public static CheckResult propException(final List> args, final Throwable * @return A result that generating values to check the property threw an exception. */ public static CheckResult genException(final Throwable ex, final int succeeded, final int discarded) { - return new CheckResult(R.GenException, Option.>>none(), some(ex), succeeded, discarded); + return new CheckResult(R.GenException, Option.none(), some(ex), succeeded, discarded); } /** diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index 9655aec2..cd519513 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -574,7 +574,7 @@ public static , V> Coarbitrary> coarbEnumMap(fin return new Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final EnumMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } @@ -589,7 +589,7 @@ public static > Coarbitrary> coarbEnumSet(final Coa return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final EnumSet as, final Gen g) { - return coarbHashSet(c).coarbitrary(new HashSet(as), g); + return coarbHashSet(c).coarbitrary(new HashSet<>(as), g); } }; } @@ -614,7 +614,7 @@ public static Coarbitrary> coarbHashMap(final Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final HashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } @@ -668,7 +668,7 @@ public static Coarbitrary> coarbIdentityHashMap(fin return new Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final IdentityHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } @@ -685,7 +685,7 @@ public static Coarbitrary> coarbLinkedHashMap(final C return new Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final LinkedHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } @@ -700,7 +700,7 @@ public static Coarbitrary> coarbLinkedHashSet(final Coarbit return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final LinkedHashSet as, final Gen g) { - return coarbHashSet(c).coarbitrary(new HashSet(as), g); + return coarbHashSet(c).coarbitrary(new HashSet<>(as), g); } }; } @@ -741,7 +741,7 @@ public Gen coarbitrary(final PriorityQueue as, final Gen g) { public static final Coarbitrary coarbProperties = new Coarbitrary() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final Properties p, final Gen g) { - final Hashtable t = new Hashtable(); + final Hashtable t = new Hashtable<>(); for (final Object s : p.keySet()) { t.put((String) s, p.getProperty((String) s)); @@ -777,7 +777,7 @@ public static Coarbitrary> coarbTreeMap(final Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final TreeMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } @@ -792,7 +792,7 @@ public static Coarbitrary> coarbTreeSet(final Coarbitrary c) { return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final TreeSet as, final Gen g) { - return coarbHashSet(c).coarbitrary(new HashSet(as), g); + return coarbHashSet(c).coarbitrary(new HashSet<>(as), g); } }; } @@ -824,7 +824,7 @@ public static Coarbitrary> coarbWeakHashMap(final Coarb return new Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final WeakHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } @@ -860,7 +860,7 @@ public static Coarbitrary> coarbConcurrentHashMap return new Coarbitrary>() { @SuppressWarnings("UseOfObsoleteCollectionType") public Gen coarbitrary(final ConcurrentHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable(m), g); + return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); } }; } diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 45a4429a..0ffed76a 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -110,7 +110,7 @@ public A gen(final int i, final Rand r) { * @return A new generator after applying the mapping function. */ public Gen map(final F f) { - return new Gen(i -> r -> f.f(gen(i, r))); + return new Gen<>(i -> r -> f.f(gen(i, r))); } /** @@ -161,7 +161,7 @@ public void foreachDoEffect(final Integer i, final Rand r, final Effect1 f) { * @return A new generator after binding the given function. */ public Gen bind(final F> f) { - return new Gen(i -> r -> f.f(gen(i, r)).f.f(i).f(r)); + return new Gen<>(i -> r -> f.f(gen(i, r)).f.f(i).f(r)); } /** @@ -286,7 +286,7 @@ public Gen apply(final Gen> gf) { * @return A new generator that uses the given size. */ public Gen resize(final int s) { - return new Gen(i -> r -> f.f(s).f(r)); + return new Gen<>(i -> r -> f.f(s).f(r)); } /** @@ -296,7 +296,7 @@ public Gen resize(final int s) { * @return A new generator that uses the given function. */ public static Gen gen(final F> f) { - return new Gen(f); + return new Gen<>(f); } /** @@ -328,7 +328,7 @@ public static Gen> sequenceN(final int n, final Gen g) { * @return A new generator. */ public static Gen parameterised(final F>> f) { - return new Gen(curry((i, r) -> f.f(i).f(r).gen(i, r))); + return new Gen<>(curry((i, r) -> f.f(i).f(r).gen(i, r))); } /** @@ -338,7 +338,7 @@ public static Gen parameterised(final F>> f) { * @return A new generator. */ public static Gen sized(final F> f) { - return parameterised(flip(Function.>>constant(f))); + return parameterised(flip(Function.constant(f))); } /** @@ -348,7 +348,7 @@ public static Gen sized(final F> f) { * @return A generator that always produces the given value. */ public static Gen value(final A a) { - return new Gen(i -> r -> a); + return new Gen<>(i -> r -> a); } /** @@ -383,7 +383,7 @@ public static Gen choose(final double from, final double to) { * @return A generator that never returns a value. */ public static Gen fail() { - return new Gen(i -> r -> { + return new Gen<>(i -> r -> { throw error("Failing generator"); }); } @@ -395,7 +395,7 @@ public static Gen fail() { * @return A new generator after joining the given generator. */ public static Gen join(final Gen> g) { - return g.bind(Function.>identity()); + return g.bind(Function.identity()); } /** @@ -443,7 +443,7 @@ public static Gen elemFrequency(final List> as) { */ @SafeVarargs public static Gen elements(final A... as) { - return array(as).isEmpty() ? Gen.fail() : choose(0, as.length - 1).map(i -> as[i]); + return array(as).isEmpty() ? Gen.fail() : choose(0, as.length - 1).map(i -> as[i]); } /** @@ -455,7 +455,7 @@ public static Gen elements(final A... as) { * requests. */ public static Gen oneOf(final List> gs) { - return gs.isEmpty() ? Gen.fail() : choose(0, gs.length() - 1).bind(gs::index); + return gs.isEmpty() ? Gen.fail() : choose(0, gs.length() - 1).bind(gs::index); } /** @@ -723,6 +723,6 @@ public static Gen> someWordOf(int maxLength, List as) { * @return A generator for functions. */ public static Gen> promote(final F> f) { - return new Gen>(i -> r -> a -> f.f(a).f.f(i).f(r)); + return new Gen<>(i -> r -> a -> f.f(a).f.f(i).f(r)); } } diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index d69d0c65..274a7453 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -368,7 +368,7 @@ public static Property prop(final Result r) { * otherwise. */ public static Property prop(final boolean b) { - return b ? prop(Result.proven(List.>nil())) : prop(Result.falsified(List.>nil())); + return b ? prop(Result.proven(List.nil())) : prop(Result.falsified(List.nil())); } /** @@ -471,7 +471,7 @@ public static Property property(final Arbitrary aa, final Shrink sa, f * application of its arguments. */ public static Property propertyP(final Arbitrary aa, final F> f) { - return propertyP(aa, Shrink.empty(), f); + return propertyP(aa, Shrink.empty(), f); } /** @@ -521,7 +521,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F> f) { - return propertyP(aa, ab, sa, sb, compose2(P.p1(), f)); + return propertyP(aa, ab, sa, sb, compose2(P.p1(), f)); } /** @@ -549,7 +549,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final F> f) { - return propertyP(aa, ab, compose2(P.p1(), f)); + return propertyP(aa, ab, compose2(P.p1(), f)); } /** @@ -581,7 +581,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F2 f) { - return propertyP(aa, ab, sa, sb, compose2(P.p1(), curry(f))); + return propertyP(aa, ab, sa, sb, compose2(P.p1(), curry(f))); } /** @@ -609,7 +609,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final F2 f) { - return propertyP(aa, ab, compose2(P.p1(), curry(f))); + return propertyP(aa, ab, compose2(P.p1(), curry(f))); } /** @@ -1320,7 +1320,7 @@ public static Property exception(final F0 p) { try { return p.f(); } catch (final Throwable t) { - return new Property(i -> r -> Result.exception(List.>nil(), t)); + return new Property(i -> r -> Result.exception(List.nil(), t)); } } diff --git a/quickcheck/src/main/java/fj/test/Rand.java b/quickcheck/src/main/java/fj/test/Rand.java index 567dba77..97f94596 100644 --- a/quickcheck/src/main/java/fj/test/Rand.java +++ b/quickcheck/src/main/java/fj/test/Rand.java @@ -52,7 +52,7 @@ public int choose(final long seed, final int from, final int to) { * @return A random value in the given range. */ public int choose(final int from, final int to) { - return f.f(Option.none()).f(from).f(to); + return f.f(Option.none()).f(from).f(to); } /** @@ -75,7 +75,7 @@ public double choose(final long seed, final double from, final double to) { * @return A random value in the given range. */ public double choose(final double from, final double to) { - return g.f(Option.none()).f(from).f(to); + return g.f(Option.none()).f(from).f(to); } /** diff --git a/quickcheck/src/main/java/fj/test/Result.java b/quickcheck/src/main/java/fj/test/Result.java index 467e2ae2..8ad743bb 100644 --- a/quickcheck/src/main/java/fj/test/Result.java +++ b/quickcheck/src/main/java/fj/test/Result.java @@ -165,7 +165,7 @@ public static Result noResult(final Option r) { * @return A result representing no result. */ public static Result noResult() { - return new Result(Option.>>none(), R.NoResult, Option.none()); + return new Result(Option.none(), R.NoResult, Option.none()); } /** @@ -175,7 +175,7 @@ public static Result noResult() { * @return An unfalsified result. */ public static Result unfalsified(final List> args) { - return new Result(some(args), R.Unfalsified, Option.none()); + return new Result(some(args), R.Unfalsified, Option.none()); } /** @@ -185,7 +185,7 @@ public static Result unfalsified(final List> args) { * @return A falsified result. */ public static Result falsified(final List> args) { - return new Result(some(args), R.Falsified, Option.none()); + return new Result(some(args), R.Falsified, Option.none()); } /** @@ -195,7 +195,7 @@ public static Result falsified(final List> args) { * @return A proven result. */ public static Result proven(final List> args) { - return new Result(some(args), R.Proven, Option.none()); + return new Result(some(args), R.Proven, Option.none()); } /** diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 751a1307..46ca3380 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -119,7 +119,7 @@ public Shrink map(final F f, final F g) { * value. */ public static Shrink shrink(final F> f) { - return new Shrink(f); + return new Shrink<>(f); } /** @@ -148,7 +148,7 @@ public static Shrink empty() { * A shrink strategy for booleans using false as the bottom of the shrink. */ public static final Shrink shrinkBoolean = - shrink(Function.>constant(Stream.single(false))); + shrink(Function.constant(Stream.single(false))); /** * A shrink strategy for integers using 0 as the bottom of the shrink. @@ -189,8 +189,8 @@ public static Shrink empty() { */ public static Shrink> shrinkOption(final Shrink sa) { return shrink(o -> o.isNone() ? - Stream.>nil() : - cons(Option.none(), () -> sa.shrink(o.some()).map(Option.some_()))); + Stream.nil() : + cons(Option.none(), () -> sa.shrink(o.some()).map(Option.some_()))); } /** @@ -202,8 +202,8 @@ public static Shrink> shrinkOption(final Shrink sa) { */ public static Shrink> shrinkEither(final Shrink sa, final Shrink sb) { return shrink(e -> e.isLeft() ? - sa.shrink(e.left().value()).map(Either.left_()) : - sb.shrink(e.right().value()).map(Either.right_())); + sa.shrink(e.left().value()).map(Either.left_()) : + sb.shrink(e.right().value()).map(Either.right_())); } /** @@ -218,7 +218,7 @@ Stream> removeChunks(final int n, final List as) { if (as.isEmpty()) return nil(); else if (as.tail().isEmpty()) - return cons(List.nil(), Stream.>nil_()); + return cons(List.nil(), Stream.nil_()); else { final int n1 = n / 2; final int n2 = n - n1; @@ -263,7 +263,7 @@ Stream> shrinkOne(final List as) { * @return A shrink strategy for arrays. */ public static Shrink> shrinkArray(final Shrink sa) { - return shrinkList(sa).map(Conversions.List_Array(), Conversions.Array_List()); + return shrinkList(sa).map(Conversions.List_Array(), Conversions.Array_List()); } /** @@ -273,7 +273,7 @@ public static Shrink> shrinkArray(final Shrink sa) { * @return A shrink strategy for streams. */ public static Shrink> shrinkStream(final Shrink sa) { - return shrinkList(sa).map(Conversions.List_Stream(), Conversions.Stream_List()); + return shrinkList(sa).map(Conversions.List_Stream(), Conversions.Stream_List()); } /** @@ -318,7 +318,7 @@ public static Shrink shrinkThrowable(final Shrink ss) { * @return A shrink strategy for array lists. */ public static Shrink> shrinkArrayList(final Shrink sa) { - return shrinkList(sa).map(Java.List_ArrayList(), Java.ArrayList_List()); + return shrinkList(sa).map(Java.List_ArrayList(), Java.ArrayList_List()); } /** @@ -361,7 +361,7 @@ public static , V> Shrink> shrinkEnumMap(final S * @return A shrink strategy for enum sets. */ public static > Shrink> shrinkEnumSet(final Shrink sa) { - return shrinkList(sa).map(Java.List_EnumSet(), Java.EnumSet_List()); + return shrinkList(sa).map(Java.List_EnumSet(), Java.EnumSet_List()); } /** @@ -392,7 +392,7 @@ public static Shrink> shrinkHashMap(final Shrink sk, fin * @return A shrink strategy for hash sets. */ public static Shrink> shrinkHashSet(final Shrink sa) { - return shrinkList(sa).map(Java.List_HashSet(), Java.HashSet_List()); + return shrinkList(sa).map(Java.List_HashSet(), Java.HashSet_List()); } /** @@ -405,7 +405,7 @@ public static Shrink> shrinkHashSet(final Shrink sa) { @SuppressWarnings("UseOfObsoleteCollectionType") public static Shrink> shrinkHashtable(final Shrink sk, final Shrink sv) { return shrinkList(shrinkP2(sk, sv)).map(kvs -> { - final Hashtable h = new Hashtable(); + final Hashtable h = new Hashtable<>(); kvs.foreachDoEffect(kv -> h.put(kv._1(), kv._2())); return h; }, h -> { @@ -448,7 +448,7 @@ public static Shrink> shrinkLinkedHashMap(final Shrin * @return A shrink strategy for linked hash sets. */ public static Shrink> shrinkLinkedHashSet(final Shrink sa) { - return shrinkList(sa).map(Java.List_LinkedHashSet(), Java.LinkedHashSet_List()); + return shrinkList(sa).map(Java.List_LinkedHashSet(), Java.LinkedHashSet_List()); } /** @@ -458,7 +458,7 @@ public static Shrink> shrinkLinkedHashSet(final Shrink s * @return A shrink strategy for linked lists. */ public static Shrink> shrinkLinkedList(final Shrink sa) { - return shrinkList(sa).map(Java.List_LinkedList(), Java.LinkedList_List()); + return shrinkList(sa).map(Java.List_LinkedList(), Java.LinkedList_List()); } /** @@ -468,7 +468,7 @@ public static Shrink> shrinkLinkedList(final Shrink sa) { * @return A shrink strategy for priority queues. */ public static Shrink> shrinkPriorityQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_PriorityQueue(), Java.PriorityQueue_List()); + return shrinkList(sa).map(Java.List_PriorityQueue(), Java.PriorityQueue_List()); } /** @@ -484,7 +484,7 @@ public static Shrink> shrinkPriorityQueue(final Shrink s return p; }, p -> { - final Hashtable t = new Hashtable(); + final Hashtable t = new Hashtable<>(); for (final Object s : p.keySet()) { t.put((String) s, p.getProperty((String) s)); @@ -500,7 +500,7 @@ public static Shrink> shrinkPriorityQueue(final Shrink s * @return A shrink strategy for stacks. */ public static Shrink> shrinkStack(final Shrink sa) { - return shrinkList(sa).map(Java.List_Stack(), Java.Stack_List()); + return shrinkList(sa).map(Java.List_Stack(), Java.Stack_List()); } /** @@ -521,7 +521,7 @@ public static Shrink> shrinkTreeMap(final Shrink sk, fin * @return A shrink strategy for tree sets. */ public static Shrink> shrinkTreeSet(final Shrink sa) { - return shrinkList(sa).map(Java.List_TreeSet(), Java.TreeSet_List()); + return shrinkList(sa).map(Java.List_TreeSet(), Java.TreeSet_List()); } /** @@ -531,7 +531,7 @@ public static Shrink> shrinkTreeSet(final Shrink sa) { * @return A shrink strategy for vectors. */ public static Shrink> shrinkVector(final Shrink sa) { - return shrinkList(sa).map(Java.List_Vector(), Java.Vector_List()); + return shrinkList(sa).map(Java.List_Vector(), Java.Vector_List()); } /** @@ -556,7 +556,7 @@ public static Shrink> shrinkWeakHashMap(final Shrink * @return A shrink strategy for array blocking queues. */ public static Shrink> shrinkArrayBlockingQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_ArrayBlockingQueue(false), Java.ArrayBlockingQueue_List()); + return shrinkList(sa).map(Java.List_ArrayBlockingQueue(false), Java.ArrayBlockingQueue_List()); } /** @@ -577,7 +577,7 @@ public static Shrink> shrinkConcurrentHashMap(fin * @return A shrink strategy for concurrent linked queues. */ public static Shrink> shrinkConcurrentLinkedQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_ConcurrentLinkedQueue(), Java.ConcurrentLinkedQueue_List()); + return shrinkList(sa).map(Java.List_ConcurrentLinkedQueue(), Java.ConcurrentLinkedQueue_List()); } /** @@ -587,7 +587,7 @@ public static Shrink> shrinkConcurrentLinkedQueue(f * @return A shrink strategy for copy on write array lists. */ public static Shrink> shrinkCopyOnWriteArrayList(final Shrink sa) { - return shrinkList(sa).map(Java.List_CopyOnWriteArrayList(), Java.CopyOnWriteArrayList_List()); + return shrinkList(sa).map(Java.List_CopyOnWriteArrayList(), Java.CopyOnWriteArrayList_List()); } /** @@ -597,7 +597,7 @@ public static Shrink> shrinkCopyOnWriteArrayList(fin * @return A shrink strategy for copy on write array sets. */ public static Shrink> shrinkCopyOnWriteArraySet(final Shrink sa) { - return shrinkList(sa).map(Java.List_CopyOnWriteArraySet(), Java.CopyOnWriteArraySet_List()); + return shrinkList(sa).map(Java.List_CopyOnWriteArraySet(), Java.CopyOnWriteArraySet_List()); } /** @@ -607,7 +607,7 @@ public static Shrink> shrinkCopyOnWriteArraySet(final * @return A shrink strategy for delay queues. */ public static Shrink> shrinkDelayQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_DelayQueue(), Java.DelayQueue_List()); + return shrinkList(sa).map(Java.List_DelayQueue(), Java.DelayQueue_List()); } /** @@ -617,7 +617,7 @@ public static Shrink> shrinkDelayQueue(final S * @return A shrink strategy for linked blocking queues. */ public static Shrink> shrinkLinkedBlockingQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_LinkedBlockingQueue(), Java.LinkedBlockingQueue_List()); + return shrinkList(sa).map(Java.List_LinkedBlockingQueue(), Java.LinkedBlockingQueue_List()); } /** @@ -627,7 +627,7 @@ public static Shrink> shrinkLinkedBlockingQueue(final * @return A shrink strategy for priority blocking queues. */ public static Shrink> shrinkPriorityBlockingQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_PriorityBlockingQueue(), Java.PriorityBlockingQueue_List()); + return shrinkList(sa).map(Java.List_PriorityBlockingQueue(), Java.PriorityBlockingQueue_List()); } /** @@ -637,7 +637,7 @@ public static Shrink> shrinkPriorityBlockingQueue(f * @return A shrink strategy for synchronous queues. */ public static Shrink> shrinkSynchronousQueue(final Shrink sa) { - return shrinkList(sa).map(Java.List_SynchronousQueue(false), Java.SynchronousQueue_List()); + return shrinkList(sa).map(Java.List_SynchronousQueue(false), Java.SynchronousQueue_List()); } // END java.util.concurrent diff --git a/quickcheck/src/main/java/fj/test/Variant.java b/quickcheck/src/main/java/fj/test/Variant.java index f50bf923..a0ef3276 100644 --- a/quickcheck/src/main/java/fj/test/Variant.java +++ b/quickcheck/src/main/java/fj/test/Variant.java @@ -11,7 +11,7 @@ * @version %build.number% */ public final class Variant { - private static final HashMap> variantMemo = new HashMap>(); + private static final HashMap> variantMemo = new HashMap<>(); private static final class LongGen { private final long n; diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index f4da2459..eb865e04 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -264,7 +264,7 @@ private static Array>> properties(f @SuppressWarnings("unchecked") final List bss = somes(list(fromNull(e.getAnnotation(Category.class)).map(p1), fromNull(declaringClass.getAnnotation(Category.class)).map(p1))); - return bss.exists(Function.identity()); + return bss.exists(Function.identity()); }; final F nameS = Name::value; @@ -281,7 +281,7 @@ private static Array>> properties(f try { final Option params = fromNull(m.element().getAnnotation(CheckParams.class)).orElse(fromNull(declaringClass.getAnnotation(CheckParams.class))); final String name = fromNull(m.element().getAnnotation(Name.class)).map(nameS).orSome(m.name()); - return p(m.invoke(t.orSome(P.p(null))), name, params); + return p(m.invoke(t.orSome(P.p(null))), name, params); } catch(Exception e) { throw new Error(e.getMessage(), e); } From 1830edcf4a29bf4f5a55397c7ae9f660ed33ec48 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 08:16:39 +0100 Subject: [PATCH 521/811] Use simpler foreach instead of for loop --- core/src/main/java/fj/data/IOFunctions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index cfe5eba2..1440b692 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -283,10 +283,10 @@ public IO> f(final IterV it) { if (numRead < buffer.length) { buffer = Arrays.copyOfRange(buffer, 0, numRead); } - for (int c = 0; c < buffer.length; c++) { - final Input input = Input.el(buffer[c]); + for (char c : buffer) { + final Input input = Input.el(c); final F, IterV>, IterV> cont = - Function.apply(input); + Function.apply(input); i = i.fold(done, cont); } } From 06d0257b3fda740c28284f41fe8985ca2e2fc437 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 08:29:26 +0100 Subject: [PATCH 522/811] Add missing type parameter --- core/src/main/java/fj/data/DList.java | 2 +- core/src/main/java/fj/data/Set.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index cf2f0af5..af9d68b0 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -75,7 +75,7 @@ public List run() { /** * Converts the DList to a standard java.util.List. */ - public java.util.List toJavaList() { + public java.util.List toJavaList() { return run().toJavaList(); } diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 5bb902d6..42ce0bac 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -323,7 +323,7 @@ public final java.util.TreeSet toJavaTreeSet() { * * @return a java.util.List representation of this set. */ - public final java.util.List toJavaList() { + public final java.util.List toJavaList() { return new java.util.ArrayList<>(toStream().toCollection()); } From bf1d634f012f7014ee8813d1522b3373821f3b91 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 08:49:51 +0100 Subject: [PATCH 523/811] Improve HashMap.Key and HashMap#values --- core/src/main/java/fj/data/HashMap.java | 35 ++++++++++--------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 9a145b37..cf112b94 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -8,6 +8,7 @@ import java.util.Map; import static fj.P.p; +import static fj.data.List.iterableList; import static fj.data.Option.fromNull; /** @@ -17,24 +18,16 @@ * @see java.util.HashMap */ public final class HashMap implements Iterable { - private final class Key { - private final K k; - private final Equal e; - private final Hash h; + private final class Key { + final K k; - Key(final K k, final Equal e, final Hash h) { + Key(final K k) { this.k = k; - this.e = e; - this.h = h; - } - - K k() { - return k; } @SuppressWarnings("unchecked") public boolean equals(final Object o) { - return o instanceof Key && e.eq(k, (K) ((Key) o).k()); + return o instanceof HashMap.Key && e.eq(k, ((Key) o).k); } public int hashCode() { @@ -51,7 +44,7 @@ public Iterator iterator() { return keys().iterator(); } - private final java.util.HashMap, V> m; + private final java.util.HashMap m; private final Equal e; private final Hash h; @@ -152,7 +145,7 @@ public int hash(final K k) { * @return A potential value for the given key. */ public Option get(final K k) { - return fromNull(m.get(new Key<>(k, e, h))); + return fromNull(m.get(new Key(k))); } /** @@ -178,7 +171,7 @@ public void clear() { * @return true if this hash map contains the given key, false otherwise. */ public boolean contains(final K k) { - return m.containsKey(new Key<>(k, e, h)); + return m.containsKey(new Key(k)); } /** @@ -189,8 +182,8 @@ public boolean contains(final K k) { public List keys() { final List.Buffer b = new List.Buffer<>(); - for (final Key k : m.keySet()) { - b.snoc(k.k()); + for (final Key k : m.keySet()) { + b.snoc(k.k); } return b.toList(); @@ -202,7 +195,7 @@ public List keys() { * @return All values in this hash map. */ public List values() { - return keys().map(k -> m.get(new Key<>(k, e, h))); + return iterableList(m.values()); } /** @@ -231,7 +224,7 @@ public int size() { */ public void set(final K k, final V v) { if (v != null) { - m.put(new Key<>(k, e, h), v); + m.put(new Key(k), v); } } @@ -241,7 +234,7 @@ public void set(final K k, final V v) { * @param k The key to delete from this hash map. */ public void delete(final K k) { - m.remove(new Key<>(k, e, h)); + m.remove(new Key(k)); } /** @@ -251,7 +244,7 @@ public void delete(final K k) { * @return The value that was associated with the given key, if there was one. */ public Option getDelete(final K k) { - return fromNull(m.remove(new Key<>(k, e, h))); + return fromNull(m.remove(new Key(k))); } public HashMap map(F keyFunction, From e76812f402df2feece7ca9bc10890ed1e2783abe Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 14:20:05 +0100 Subject: [PATCH 524/811] Precompile regex --- core/src/main/java/fj/function/Strings.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index c64db043..dadbfd22 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -3,6 +3,9 @@ import fj.F; import fj.data.List; import fj.data.Stream; + +import java.util.regex.Pattern; + import static fj.Function.curry; import static fj.function.Booleans.not; import static fj.function.Characters.isWhitespace; @@ -17,6 +20,8 @@ private Strings() { throw new UnsupportedOperationException(); } + private static final Pattern lineSeparatorPattern = Pattern.compile("\\r?\\n"); + public static final String lineSeparator = System.getProperty("line.separator"); /** @@ -76,7 +81,7 @@ private Strings() { public static final F> matches = curry((s1, s2) -> s2.matches(s1)); public static List lines(String s) { - return List.list(s.split("\\r?\\n")); + return List.list(lineSeparatorPattern.split(s)); } public static F> lines() { From 7790a18a976cdb659ca972ebc6892986a981d19b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 14:23:59 +0100 Subject: [PATCH 525/811] Iterate over entrySet of j.u.Map instead of keySet + get --- core/src/main/java/fj/data/HashMap.java | 4 ++-- quickcheck/src/main/java/fj/test/Arbitrary.java | 4 ++-- quickcheck/src/main/java/fj/test/Coarbitrary.java | 5 +++-- quickcheck/src/main/java/fj/test/Shrink.java | 9 +++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index cf112b94..400cf415 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -63,8 +63,8 @@ public HashMap(final Equal e, final Hash h) { public HashMap(java.util.Map map, final Equal e, final Hash h) { this(e, h); - for (K key : map.keySet()) { - set(key, map.get(key)); + for (Map.Entry entry : map.entrySet()) { + set(entry.getKey(), entry.getValue()); } } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 848585aa..c675120c 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -928,8 +928,8 @@ public static Arbitrary> arbPriorityQueue(final Arbitrary { final Properties p = new Properties(); - for (final String k : ht.keySet()) { - p.setProperty(k, ht.get(k)); + for (final Map.Entry entry : ht.entrySet()) { + p.setProperty(entry.getKey(), entry.getValue()); } return p; diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index cd519513..b0f6be6d 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -33,6 +33,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; +import java.util.Map; import java.util.PriorityQueue; import java.util.Properties; import java.util.Stack; @@ -647,8 +648,8 @@ public static Coarbitrary> coarbHashtable(final Coarbitra public Gen coarbitrary(final Hashtable h, final Gen g) { List> x = nil(); - for (final K k : h.keySet()) { - x = x.snoc(p(k, h.get(k))); + for (final Map.Entry entry : h.entrySet()) { + x = x.snoc(p(entry.getKey(), entry.getValue())); } return coarbList(coarbP2(ck, cv)).coarbitrary(x, g); diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 46ca3380..2a2f0061 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -56,6 +56,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; +import java.util.Map; import java.util.PriorityQueue; import java.util.Properties; import java.util.Stack; @@ -411,8 +412,8 @@ public static Shrink> shrinkHashtable(final Shrink sk, }, h -> { List> x = List.nil(); - for (final K k : h.keySet()) { - x = x.snoc(p(k, h.get(k))); + for (final Map.Entry entry : h.entrySet()) { + x = x.snoc(p(entry.getKey(), entry.getValue())); } return x; @@ -478,8 +479,8 @@ public static Shrink> shrinkPriorityQueue(final Shrink s .map(h -> { final Properties p = new Properties(); - for (final String k : h.keySet()) { - p.setProperty(k, h.get(k)); + for (final Map.Entry entry : h.entrySet()) { + p.setProperty(entry.getKey(), entry.getValue()); } return p; From 4d800f8a2cf45443bace99355839824cd245c6af Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 14:25:52 +0100 Subject: [PATCH 526/811] IOW#getContents and IOW#interact should be static --- core/src/main/java/fj/data/IOW.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java index adb0c7af..859c9cdb 100644 --- a/core/src/main/java/fj/data/IOW.java +++ b/core/src/main/java/fj/data/IOW.java @@ -35,11 +35,11 @@ public SafeIO> safe() { public IOW append(IO iob) { return lift(IOFunctions.append(io, iob)); } - public IOW getContents() { + public static IOW getContents() { return lift(() -> IOFunctions.getContents().run()); } - public IOW interact(F f) { + public static IOW interact(F f) { return lift(() -> IOFunctions.interact(f).run()); } } From 344c9de7c888145bf6a932839bce9df8691ee3e4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 14:28:30 +0100 Subject: [PATCH 527/811] Presize StringBuilder when possible --- core/src/main/java/fj/data/Conversions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Conversions.java b/core/src/main/java/fj/data/Conversions.java index 35cf68be..403ca6d1 100644 --- a/core/src/main/java/fj/data/Conversions.java +++ b/core/src/main/java/fj/data/Conversions.java @@ -125,7 +125,7 @@ public static F, F, Either>> Array_Either() { * A function that converts arrays to strings. */ public static final F, String> Array_String = cs -> { - final StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(cs.length()); cs.foreachDoEffect(sb::append); return sb.toString(); }; @@ -134,7 +134,7 @@ public static F, F, Either>> Array_Either() { * A function that converts arrays to string buffers. */ public static final F, StringBuffer> Array_StringBuffer = cs -> { - final StringBuffer sb = new StringBuffer(); + final StringBuffer sb = new StringBuffer(cs.length()); cs.foreachDoEffect(sb::append); return sb; }; @@ -143,7 +143,7 @@ public static F, F, Either>> Array_Either() { * A function that converts arrays to string builders. */ public static final F, StringBuilder> Array_StringBuilder = cs -> { - final StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(cs.length()); cs.foreachDoEffect(sb::append); return sb; }; From 93a003e9cdcb08cadfaed4e04fd5b7aef5e963a6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 14:36:10 +0100 Subject: [PATCH 528/811] Avoid unnecessary null check in Optional_Option --- java8/src/main/java/fj/data/Java8.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index d893a370..be776822 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -108,7 +108,7 @@ public static Option Optional_Option(final Optional o) { } public static F, Option> Optional_Option() { - return o -> o.isPresent() ? Option.fromNull(o.get()) : Option.none(); + return o -> o.isPresent() ? Option.some(o.get()) : Option.none(); } public static Optional Option_Optional(final Option o) { From 1e40671d37573a2ebb2aebdc0b5e717a2b6f5357 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:00:30 +0100 Subject: [PATCH 529/811] Array: simpler conversion to jdk collections --- core/src/main/java/fj/data/Array.java | 47 ++++++------------- core/src/main/java/fj/data/Java.java | 34 +++++++------- .../src/main/java/fj/test/Arbitrary.java | 34 +++++++------- 3 files changed, 49 insertions(+), 66 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 09b56f9a..75dd3c3a 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -13,7 +13,9 @@ import java.util.AbstractCollection; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.NoSuchElementException; @@ -775,44 +777,25 @@ public Array> zipIndex() { * * @return An immutable collection of this array. */ - @SuppressWarnings("unchecked") public Collection toCollection() { - return new AbstractCollection() { - public Iterator iterator() { - return new Iterator() { - private int i; - - public boolean hasNext() { - return i < a.length; - } - - public A next() { - if (i >= a.length) - throw new NoSuchElementException(); - else { - final A aa = (A) a[i]; - i++; - return aa; - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } + return asJavaList(); + } - public int size() { - return a.length; - } - }; + /** + * Projects an unmodifiable list view of this array. + * + * @return An unmodifiable list view of this array. + */ + @SuppressWarnings("unchecked") + public java.util.List asJavaList() { + return Collections.unmodifiableList(Arrays.asList((A[]) a)); } /** - * Returns a standard java.util.List projection of this array. + * Returns a java.util.ArrayList projection of this array. */ - java.util.List toJavaList() { - return new ArrayList<>(toCollection()); + public ArrayList toJavaList() { + return new ArrayList<>(asJavaList()); } /** diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index b4b6173a..487e9703 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -227,7 +227,7 @@ public static F, SynchronousQueue> List_SynchronousQueue(final bo * @return A function that converts arrays to array lists. */ public static F, ArrayList> Array_ArrayList() { - return as -> new ArrayList<>(as.toCollection()); + return Array::toJavaList; } /** @@ -246,7 +246,7 @@ public static F, ArrayList> Array_ArrayList() { * @return A function that converts arrays to enum sets. */ public static > F, EnumSet> Array_EnumSet() { - return as -> copyOf(as.toCollection()); + return as -> copyOf(as.asJavaList()); } /** @@ -255,7 +255,7 @@ public static > F, EnumSet> Array_EnumSet() { * @return A function that converts arrays to hash sets. */ public static F, HashSet> Array_HashSet() { - return as -> new HashSet<>(as.toCollection()); + return as -> new HashSet<>(as.asJavaList()); } /** @@ -264,7 +264,7 @@ public static F, HashSet> Array_HashSet() { * @return A function that converts arrays to linked hash sets. */ public static F, LinkedHashSet> Array_LinkedHashSet() { - return as -> new LinkedHashSet<>(as.toCollection()); + return as -> new LinkedHashSet<>(as.asJavaList()); } /** @@ -273,7 +273,7 @@ public static F, LinkedHashSet> Array_LinkedHashSet() { * @return A function that converts arrays to linked lists. */ public static F, LinkedList> Array_LinkedList() { - return as -> new LinkedList<>(as.toCollection()); + return as -> new LinkedList<>(as.asJavaList()); } /** @@ -282,7 +282,7 @@ public static F, LinkedList> Array_LinkedList() { * @return A function that converts arrays to priority queues. */ public static F, PriorityQueue> Array_PriorityQueue() { - return as -> new PriorityQueue<>(as.toCollection()); + return as -> new PriorityQueue<>(as.asJavaList()); } /** @@ -293,7 +293,7 @@ public static F, PriorityQueue> Array_PriorityQueue() { public static F, Stack> Array_Stack() { return as -> { final Stack s = new Stack<>(); - s.addAll(as.toCollection()); + s.addAll(as.asJavaList()); return s; }; } @@ -304,7 +304,7 @@ public static F, Stack> Array_Stack() { * @return A function that converts arrays to tree sets. */ public static F, TreeSet> Array_TreeSet() { - return as -> new TreeSet<>(as.toCollection()); + return as -> new TreeSet<>(as.asJavaList()); } /** @@ -313,7 +313,7 @@ public static F, TreeSet> Array_TreeSet() { * @return A function that converts arrays to vectors. */ public static F, Vector> Array_Vector() { - return as -> new Vector<>(as.toCollection()); + return as -> new Vector<>(as.asJavaList()); } /** @@ -323,7 +323,7 @@ public static F, Vector> Array_Vector() { * @return A function that converts arrays to array blocking queues. */ public static F, ArrayBlockingQueue> Array_ArrayBlockingQueue(final boolean fair) { - return as -> new ArrayBlockingQueue<>(as.length(), fair, as.toCollection()); + return as -> new ArrayBlockingQueue<>(as.length(), fair, as.asJavaList()); } /** @@ -332,7 +332,7 @@ public static F, ArrayBlockingQueue> Array_ArrayBlockingQueue(fi * @return A function that converts arrays to concurrent linked queues. */ public static F, ConcurrentLinkedQueue> Array_ConcurrentLinkedQueue() { - return as -> new ConcurrentLinkedQueue<>(as.toCollection()); + return as -> new ConcurrentLinkedQueue<>(as.asJavaList()); } /** @@ -341,7 +341,7 @@ public static F, ConcurrentLinkedQueue> Array_ConcurrentLinkedQu * @return A function that converts arrays to copy on write array lists. */ public static F, CopyOnWriteArrayList> Array_CopyOnWriteArrayList() { - return as -> new CopyOnWriteArrayList<>(as.toCollection()); + return as -> new CopyOnWriteArrayList<>(as.asJavaList()); } /** @@ -350,7 +350,7 @@ public static F, CopyOnWriteArrayList> Array_CopyOnWriteArrayLis * @return A function that converts arrays to copy on write array sets. */ public static F, CopyOnWriteArraySet> Array_CopyOnWriteArraySet() { - return as -> new CopyOnWriteArraySet<>(as.toCollection()); + return as -> new CopyOnWriteArraySet<>(as.asJavaList()); } /** @@ -359,7 +359,7 @@ public static F, CopyOnWriteArraySet> Array_CopyOnWriteArraySet( * @return A function that converts arrays to delay queues. */ public static F, DelayQueue> Array_DelayQueue() { - return as -> new DelayQueue<>(as.toCollection()); + return as -> new DelayQueue<>(as.asJavaList()); } /** @@ -368,7 +368,7 @@ public static F, DelayQueue> Array_DelayQueue() * @return A function that converts arrays to linked blocking queues. */ public static F, LinkedBlockingQueue> Array_LinkedBlockingQueue() { - return as -> new LinkedBlockingQueue<>(as.toCollection()); + return as -> new LinkedBlockingQueue<>(as.asJavaList()); } /** @@ -377,7 +377,7 @@ public static F, LinkedBlockingQueue> Array_LinkedBlockingQueue( * @return A function that converts arrays to priority blocking queues. */ public static F, PriorityBlockingQueue> Array_PriorityBlockingQueue() { - return as -> new PriorityBlockingQueue<>(as.toCollection()); + return as -> new PriorityBlockingQueue<>(as.asJavaList()); } /** @@ -389,7 +389,7 @@ public static F, PriorityBlockingQueue> Array_PriorityBlockingQu public static F, SynchronousQueue> Array_SynchronousQueue(final boolean fair) { return as -> { final SynchronousQueue q = new SynchronousQueue<>(fair); - q.addAll(as.toCollection()); + q.addAll(as.asJavaList()); return q; }; } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index c675120c..20e6e2f0 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -753,7 +753,7 @@ public static Arbitrary arbThrowable(final Arbitrary as) { * @return An arbitrary implementation for array lists. */ public static Arbitrary> arbArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new ArrayList<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(Array::toJavaList)); } /** @@ -810,7 +810,7 @@ public static , V> Arbitrary> arbEnumMap(final A * @return An arbitrary implementation for enum sets. */ public static > Arbitrary> arbEnumSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> copyOf(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> copyOf(a.asJavaList()))); } /** @@ -842,7 +842,7 @@ public static Arbitrary> arbHashMap(final Arbitrary ak, * @return An arbitrary implementation for hash sets. */ public static Arbitrary> arbHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new HashSet<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new HashSet<>(a.asJavaList()))); } /** @@ -898,7 +898,7 @@ public static Arbitrary> arbLinkedHashMap(final Arbit * @return An arbitrary implementation for hash sets. */ public static Arbitrary> arbLinkedHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedHashSet<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedHashSet<>(a.asJavaList()))); } /** @@ -908,7 +908,7 @@ public static Arbitrary> arbLinkedHashSet(final Arbitrary Arbitrary> arbLinkedList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedList<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedList<>(a.asJavaList()))); } /** @@ -918,7 +918,7 @@ public static Arbitrary> arbLinkedList(final Arbitrary aa) * @return An arbitrary implementation for priority queues. */ public static Arbitrary> arbPriorityQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new PriorityQueue<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new PriorityQueue<>(a.asJavaList()))); } /** @@ -944,7 +944,7 @@ public static Arbitrary> arbPriorityQueue(final Arbitrary Arbitrary> arbStack(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.map(a -> { final Stack s = new Stack<>(); - s.addAll(a.toCollection()); + s.addAll(a.asJavaList()); return s; })); } @@ -1005,7 +1005,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb * @return An arbitrary implementation for tree sets. */ public static Arbitrary> arbTreeSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new TreeSet<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new TreeSet<>(a.asJavaList()))); } /** @@ -1016,7 +1016,7 @@ public static Arbitrary> arbTreeSet(final Arbitrary aa) { */ @SuppressWarnings("UseOfObsoleteCollectionType") public static Arbitrary> arbVector(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new Vector<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new Vector<>(a.asJavaList()))); } /** @@ -1046,7 +1046,7 @@ public static Arbitrary> arbWeakHashMap(final Arbitrary public static Arbitrary> arbArrayBlockingQueue(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.bind(arbInteger.gen, arbBoolean.gen, a -> capacity -> fair -> new ArrayBlockingQueue(a.length() + abs(capacity), - fair, a.toCollection()))); + fair, a.asJavaList()))); } /** @@ -1071,7 +1071,7 @@ public static Arbitrary> arbConcurrentHashMap(fin * @return An arbitrary implementation for concurrent linked queues. */ public static Arbitrary> arbConcurrentLinkedQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new ConcurrentLinkedQueue<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new ConcurrentLinkedQueue<>(a.asJavaList()))); } /** @@ -1082,7 +1082,7 @@ public static Arbitrary> arbConcurrentLinkedQueue(f * @return An arbitrary implementation for copy-on-write array lists. */ public static Arbitrary> arbCopyOnWriteArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArrayList<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArrayList<>(a.asJavaList()))); } /** @@ -1093,7 +1093,7 @@ public static Arbitrary> arbCopyOnWriteArrayList(fin * @return An arbitrary implementation for copy-on-write array sets. */ public static Arbitrary> arbCopyOnWriteArraySet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArraySet<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArraySet<>(a.asJavaList()))); } /** @@ -1103,7 +1103,7 @@ public static Arbitrary> arbCopyOnWriteArraySet(final * @return An arbitrary implementation for delay queues. */ public static Arbitrary> arbDelayQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new DelayQueue<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new DelayQueue<>(a.asJavaList()))); } /** @@ -1114,7 +1114,7 @@ public static Arbitrary> arbDelayQueue(final A * @return An arbitrary implementation for linked blocking queues. */ public static Arbitrary> arbLinkedBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedBlockingQueue<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new LinkedBlockingQueue<>(a.asJavaList()))); } /** @@ -1125,7 +1125,7 @@ public static Arbitrary> arbLinkedBlockingQueue(final * @return An arbitrary implementation for priority blocking queues. */ public static Arbitrary> arbPriorityBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new PriorityBlockingQueue<>(a.toCollection()))); + return arbitrary(arbArray(aa).gen.map(a -> new PriorityBlockingQueue<>(a.asJavaList()))); } /** @@ -1138,7 +1138,7 @@ public static Arbitrary> arbPriorityBlockingQueue(f public static Arbitrary> arbSynchronousQueue(final Arbitrary aa) { return arbitrary(arbArray(aa).gen.bind(arbBoolean.gen, a -> fair -> { final SynchronousQueue q = new SynchronousQueue<>(fair); - q.addAll(a.toCollection()); + q.addAll(a.asJavaList()); return q; })); } From cdd8fbe647a06d54cd6b708ef2d4bd90b3daffce Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:05:11 +0100 Subject: [PATCH 530/811] Avoid unecessary array type cast. --- .../src/main/java/fj/test/Arbitrary.java | 2 +- .../src/main/java/fj/test/Coarbitrary.java | 29 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 20e6e2f0..a776e15b 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -716,7 +716,7 @@ public static Arbitrary> arbArray(final Arbitrary aa) { */ @SuppressWarnings("unchecked") public static Arbitrary> arbSeq(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(array -> Seq.seq((A[]) array.array()))); + return arbitrary(arbArray(aa).gen.map(Seq::iterableSeq)); } public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index b0f6be6d..d158a90f 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -8,6 +8,7 @@ import fj.data.*; import static fj.data.Array.array; +import static fj.data.Array.iterableArray; import static fj.data.List.fromString; import static fj.data.List.nil; @@ -525,7 +526,7 @@ public static Coarbitrary> coarbArrayList(final Coarbitrary return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final ArrayList as, final Gen g) { - return coarbArray(ca).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(ca).coarbitrary(iterableArray(as), g); } }; } @@ -630,7 +631,7 @@ public static Coarbitrary> coarbHashSet(final Coarbitrary c) { return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final HashSet as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -716,7 +717,7 @@ public static Coarbitrary> coarbLinkedList(final Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final LinkedList as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -731,7 +732,7 @@ public static Coarbitrary> coarbPriorityQueue(final Coarbit return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final PriorityQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -762,7 +763,7 @@ public static Coarbitrary> coarbStack(final Coarbitrary c) { return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final Stack as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -808,7 +809,7 @@ public static Coarbitrary> coarbVector(final Coarbitrary c) { return new Coarbitrary>() { @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"}) public Gen coarbitrary(final Vector as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -844,7 +845,7 @@ public static Coarbitrary> coarbArrayBlockingQueue(fin return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final ArrayBlockingQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -876,7 +877,7 @@ public static Coarbitrary> coarbConcurrentLinkedQue return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final ConcurrentLinkedQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -891,7 +892,7 @@ public static Coarbitrary> coarbCopyOnWriteArrayList return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final CopyOnWriteArrayList as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -906,7 +907,7 @@ public static Coarbitrary> coarbCopyOnWriteArraySet(f return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final CopyOnWriteArraySet as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -921,7 +922,7 @@ public static Coarbitrary> coarbDelayQueue(fin return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final DelayQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -936,7 +937,7 @@ public static Coarbitrary> coarbLinkedBlockingQueue(f return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final LinkedBlockingQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -951,7 +952,7 @@ public static Coarbitrary> coarbPriorityBlockingQue return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final PriorityBlockingQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } @@ -966,7 +967,7 @@ public static Coarbitrary> coarbSynchronousQueue(final C return new Coarbitrary>() { @SuppressWarnings("unchecked") public Gen coarbitrary(final SynchronousQueue as, final Gen g) { - return coarbArray(c).coarbitrary(array(as.toArray((A[]) new Object[as.size()])), g); + return coarbArray(c).coarbitrary(iterableArray(as), g); } }; } From dd14dd4f9f0b1de69913d6e86736ffe47625fa27 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:06:27 +0100 Subject: [PATCH 531/811] make implicit throw explicit for readability --- quickcheck/src/main/java/fj/test/Arbitrary.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index a776e15b..e2a00b29 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -981,7 +981,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av, Arbitrary ai) { Gen>> gl2 = ai.gen.bind(i -> { if (i < 0) { - Bottom.error("Undefined: arbitrary natural is negative (" + i + ")"); + throw Bottom.error("Undefined: arbitrary natural is negative (" + i + ")"); } return Gen.sequenceN(Math.max(i, 0), arbP2(ak, av).gen); }); @@ -993,7 +993,7 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb */ public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av, int maxSize) { if (maxSize < 0) { - Bottom.error("Undefined: arbitrary natural is negative (" + maxSize + ")"); + throw Bottom.error("Undefined: arbitrary natural is negative (" + maxSize + ")"); } return arbTreeMap(ord, ak, av, arbitrary(choose(0, maxSize))); } From d33454285e734a8c4654e06d7c8e4771e440bbf2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:09:29 +0100 Subject: [PATCH 532/811] use Strings#lineSeparator instead of System.getProperty("line.separator") --- quickcheck/src/main/java/fj/test/CheckResult.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/CheckResult.java b/quickcheck/src/main/java/fj/test/CheckResult.java index 718daf03..c9c0a2fe 100644 --- a/quickcheck/src/main/java/fj/test/CheckResult.java +++ b/quickcheck/src/main/java/fj/test/CheckResult.java @@ -5,6 +5,8 @@ import fj.Show; import fj.data.List; import fj.data.Option; +import fj.function.Strings; + import static fj.data.Option.some; import static fj.Show.listShow; import static fj.Show.showS; @@ -252,12 +254,12 @@ else if (r.isPropException()) { final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); r.exception().some().printStackTrace(pw); - return "Exception on property evaluation with " + arguments(r) + System.getProperty("line.separator") + sw; + return "Exception on property evaluation with " + arguments(r) + Strings.lineSeparator + sw; } else if (r.isGenException()) { final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw); r.exception().some().printStackTrace(pw); - return "Exception on argument generation " + System.getProperty("line.separator") + sw; + return "Exception on argument generation " + Strings.lineSeparator + sw; } else throw decons(r.getClass()); } From 99fe9fdb93fa0bab9c1adc1930b5284a4570e423 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:38:10 +0100 Subject: [PATCH 533/811] Make methods that are not meant to be overriden final. --- core/src/main/java/fj/F1W.java | 138 +++++------ core/src/main/java/fj/F2W.java | 54 ++--- core/src/main/java/fj/LcgRng.java | 6 +- core/src/main/java/fj/Ord.java | 2 +- core/src/main/java/fj/P1.java | 48 ++-- core/src/main/java/fj/P2.java | 6 +- core/src/main/java/fj/P3.java | 6 +- core/src/main/java/fj/P4.java | 6 +- core/src/main/java/fj/P5.java | 6 +- core/src/main/java/fj/P6.java | 6 +- core/src/main/java/fj/P7.java | 6 +- core/src/main/java/fj/P8.java | 6 +- core/src/main/java/fj/Rng.java | 4 +- core/src/main/java/fj/control/Trampoline.java | 6 +- core/src/main/java/fj/data/Either.java | 22 +- core/src/main/java/fj/data/List.java | 38 +-- core/src/main/java/fj/data/Option.java | 28 +-- core/src/main/java/fj/data/Reader.java | 12 +- core/src/main/java/fj/data/Set.java | 10 +- core/src/main/java/fj/data/Stream.java | 10 +- core/src/main/java/fj/data/Validation.java | 218 +++++++++--------- .../main/java/fj/data/fingertrees/Digit.java | 4 +- .../java/fj/data/fingertrees/FingerTree.java | 10 +- .../main/java/fj/data/fingertrees/Node.java | 2 +- core/src/main/java/fj/data/optic/PIso.java | 2 +- demo/src/main/java/fj/demo/IODemo.java | 8 +- .../fj/demo/StateDemo_VendingMachine.java | 8 +- .../main/java/fj/demo/concurrent/Ping.java | 4 +- .../java/fj/demo/concurrent/PingPong.java | 2 +- .../main/java/fj/demo/concurrent/Pong.java | 2 +- .../main/java/fj/demo/optic/LensPerson.java | 8 +- .../fj/test/runner/PropertyTestRunner.java | 6 +- 32 files changed, 348 insertions(+), 346 deletions(-) diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java index 19a978dc..611c9e01 100644 --- a/core/src/main/java/fj/F1W.java +++ b/core/src/main/java/fj/F1W.java @@ -22,7 +22,7 @@ public abstract class F1W implements F { * @param g A function to compose with this one. * @return The composed function such that this function is applied last. */ - public F1W o(final F g) { + public final F1W o(final F g) { return lift(F1Functions.o(this, g)); } @@ -31,7 +31,7 @@ public F1W o(final F g) { * * @return A function that composes this function with another. */ - public F1W, F> o() { + public final F1W, F> o() { return lift(F1Functions.o(this)); } @@ -42,7 +42,7 @@ public F1W, F> o() { * @return The composed function such that this function is applied first. */ @SuppressWarnings("unchecked") - public F1W andThen(final F g) { + public final F1W andThen(final F g) { return lift(F1Functions.andThen(this, g)); } @@ -51,7 +51,7 @@ public F1W andThen(final F g) { * * @return A function that invokes this function and then a given function on the result. */ - public F1W, F> andThen() { + public final F1W, F> andThen() { return lift( F1Functions.andThen(this)); } @@ -61,7 +61,7 @@ public F1W, F> andThen() { * @param g A function that takes the return value of this function as an argument, yielding a new function. * @return A function that invokes this function on its argument and then the given function on the result. */ - public F1W bind(final F> g) { + public final F1W bind(final F> g) { return lift(F1Functions.bind(this, g)); } @@ -71,7 +71,7 @@ public F1W bind(final F> g) { * * @return A function that binds another function across this function. */ - public F1W>, F> bind() { + public final F1W>, F> bind() { return lift(F1Functions.bind(this)); } @@ -83,7 +83,7 @@ public F1W>, F> bind() { * @return A new function that invokes the given function on its argument, yielding a new function that is then * applied to the result of applying this function to the argument. */ - public F1W apply(final F> g) { + public final F1W apply(final F> g) { return lift(F1Functions.apply(this, g)); } @@ -93,7 +93,7 @@ public F1W apply(final F> g) { * * @return A function that applies a given function within the environment of this function. */ - public F1W>, F> apply() { + public final F1W>, F> apply() { return lift(F1Functions.apply(this)); } @@ -103,7 +103,7 @@ public F1W>, F> apply() { * @param g The function over whose arguments to apply this function. * @return A new function that invokes this function on its arguments before invoking the given function. */ - public F1W> on(final F> g) { + public final F1W> on(final F> g) { return lift(F1Functions.on(this, g)); } @@ -113,7 +113,7 @@ public F1W> on(final F> g) { * * @return A function that applies this function over the arguments of another function. */ - public F1W>, F>> on() { + public final F1W>, F>> on() { return lift(F1Functions.on(this)); } @@ -122,7 +122,7 @@ public F1W>, F>> on() { * * @return This function promoted to return its result in a product-1. */ - public F1W> lazy() { + public final F1W> lazy() { return lift(F1Functions.lazy(this)); } @@ -133,7 +133,7 @@ public F1W> lazy() { * @param a The A to which to apply this function. * @return The function partially applied to the given argument to return a lazy value. */ - public P1 lazy(final A a) { + public final P1 lazy(final A a) { return F1Functions.f(this, a); } @@ -142,7 +142,7 @@ public P1 lazy(final A a) { * * @return This function promoted to map over a product-1. */ - public F1W, P1> mapP1() { + public final F1W, P1> mapP1() { return lift(F1Functions.mapP1(this)); } @@ -151,7 +151,7 @@ public F1W, P1> mapP1() { * * @return This function promoted to return its result in an Option. */ - public F1W> optionK() { + public final F1W> optionK() { return lift(F1Functions.optionK(this)); } @@ -161,7 +161,7 @@ public F1W> optionK() { * * @return This function promoted to map over an optional value. */ - public F1W, Option> mapOption() { + public final F1W, Option> mapOption() { return lift(F1Functions.mapOption(this)); } @@ -170,7 +170,7 @@ public F1W, Option> mapOption() { * * @return This function promoted to return its result in a List. */ - public F1W> listK() { + public final F1W> listK() { return lift( F1Functions.listK(this)); } @@ -179,7 +179,7 @@ public F1W> listK() { * * @return This function promoted to map over a List. */ - public F1W, List> mapList() { + public final F1W, List> mapList() { return lift(F1Functions.mapList(this)); } @@ -188,7 +188,7 @@ public F1W, List> mapList() { * * @return This function promoted to return its result in a Stream. */ - public F1W> streamK() { + public final F1W> streamK() { return lift(F1Functions.streamK(this)); } @@ -197,7 +197,7 @@ public F1W> streamK() { * * @return This function promoted to map over a Stream. */ - public F1W, Stream> mapStream() { + public final F1W, Stream> mapStream() { return lift(F1Functions.mapStream(this)); } @@ -206,7 +206,7 @@ public F1W, Stream> mapStream() { * * @return This function promoted to return its result in a Array. */ - public F1W> arrayK() { + public final F1W> arrayK() { return lift(F1Functions.arrayK(this)); } @@ -216,7 +216,7 @@ public F1W> arrayK() { * * @return This function promoted to map over a Array. */ - public F1W, Array> mapArray() { + public final F1W, Array> mapArray() { return lift(F1Functions.mapArray(this)); } @@ -225,7 +225,7 @@ public F1W, Array> mapArray() { * * @return A function that contramaps over a given actor. */ - public F1W, Actor> contramapActor() { + public final F1W, Actor> contramapActor() { return lift(F1Functions.contramapActor(this)); } @@ -235,7 +235,7 @@ public F1W, Actor> contramapActor() { * @param s A parallel strategy for concurrent execution. * @return A concurrent function that returns a Promise of a value. */ - public F1W> promiseK(final Strategy s) { + public final F1W> promiseK(final Strategy s) { return lift(F1Functions.promiseK(this, s)); } @@ -244,7 +244,7 @@ public F1W> promiseK(final Strategy s) { * * @return This function promoted to map over Promises. */ - public F1W, Promise> mapPromise() { + public final F1W, Promise> mapPromise() { return lift(F1Functions.mapPromise(this)); } @@ -255,7 +255,7 @@ public F1W, Promise> mapPromise() { * @return This function promoted to return its result on the left side of an Either. */ @SuppressWarnings("unchecked") - public F1W> eitherLeftK() { + public final F1W> eitherLeftK() { return lift(F1Functions.eitherLeftK(this)); } @@ -266,7 +266,7 @@ public F1W> eitherLeftK() { * @return This function promoted to return its result on the right side of an Either. */ @SuppressWarnings("unchecked") - public F1W> eitherRightK() { + public final F1W> eitherRightK() { return lift(F1Functions.eitherRightK(this)); } @@ -276,7 +276,7 @@ public F1W> eitherRightK() { * @return This function promoted to map over the left side of an Either. */ @SuppressWarnings("unchecked") - public F1W, Either> mapLeft() { + public final F1W, Either> mapLeft() { return lift(F1Functions.mapLeft(this)); } @@ -286,7 +286,7 @@ public F1W, Either> mapLeft() { * @return This function promoted to map over the right side of an Either. */ @SuppressWarnings("unchecked") - public F1W, Either> mapRight() { + public final F1W, Either> mapRight() { return lift(F1Functions.mapRight(this)); } @@ -295,7 +295,7 @@ public F1W, Either> mapRight() { * * @return a function that returns the left side of a given Either, or this function applied to the right side. */ - public F1W, B> onLeft() { + public final F1W, B> onLeft() { return lift(F1Functions.onLeft(this)); } @@ -304,7 +304,7 @@ public F1W, B> onLeft() { * * @return a function that returns the right side of a given Either, or this function applied to the left side. */ - public F1W, B> onRight() { + public final F1W, B> onRight() { return lift(F1Functions.onRight(this)); } @@ -314,7 +314,7 @@ public F1W, B> onRight() { * @return This function promoted to return its value in an Iterable. */ @SuppressWarnings("unchecked") - public F1W> iterableK() { + public final F1W> iterableK() { return lift( F1Functions.iterableK(this)); } @@ -324,7 +324,7 @@ public F1W> iterableK() { * @return This function promoted to map over Iterables. */ @SuppressWarnings("unchecked") - public F1W, IterableW> mapIterable() { + public final F1W, IterableW> mapIterable() { return lift( F1Functions.mapIterable(this)); } @@ -334,7 +334,7 @@ public F1W, IterableW> mapIterable() { * @return This function promoted to return its value in a NonEmptyList. */ @SuppressWarnings("unchecked") - public F1W> nelK() { + public final F1W> nelK() { return lift(F1Functions.nelK(this)); } @@ -343,7 +343,7 @@ public F1W> nelK() { * * @return This function promoted to map over a NonEmptyList. */ - public F1W, NonEmptyList> mapNel() { + public final F1W, NonEmptyList> mapNel() { return lift(F1Functions.mapNel(this)); } @@ -353,7 +353,7 @@ public F1W, NonEmptyList> mapNel() { * @param o An order for the set. * @return This function promoted to return its value in a Set. */ - public F1W> setK(final Ord o) { + public final F1W> setK(final Ord o) { return lift(F1Functions.setK(this, o)); } @@ -363,7 +363,7 @@ public F1W> setK(final Ord o) { * @param o An order for the resulting set. * @return This function promoted to map over a Set. */ - public F1W, Set> mapSet(final Ord o) { + public final F1W, Set> mapSet(final Ord o) { return lift(F1Functions.mapSet(this, o)); } @@ -372,7 +372,7 @@ public F1W, Set> mapSet(final Ord o) { * * @return This function promoted to return its value in a Tree. */ - public F1W> treeK() { + public final F1W> treeK() { return lift(F1Functions.treeK(this)); } @@ -382,7 +382,7 @@ public F1W> treeK() { * @return This function promoted to map over a Tree. */ @SuppressWarnings("unchecked") - public F1W, Tree> mapTree() { + public final F1W, Tree> mapTree() { return lift(F1Functions.mapTree(this)); } @@ -392,7 +392,7 @@ public F1W, Tree> mapTree() { * @param m The monoid with which to fold the mapped tree. * @return a function that maps this function over a tree and folds it with the given monoid. */ - public F1W, B> foldMapTree(final Monoid m) { + public final F1W, B> foldMapTree(final Monoid m) { return lift(F1Functions.foldMapTree(this, m)); } @@ -401,7 +401,7 @@ public F1W, B> foldMapTree(final Monoid m) { * * @return This function promoted to return its value in a TreeZipper. */ - public F1W> treeZipperK() { + public final F1W> treeZipperK() { return lift(F1Functions.treeZipperK(this)); } @@ -410,7 +410,7 @@ public F1W> treeZipperK() { * * @return This function promoted to map over a TreeZipper. */ - public F1W, TreeZipper> mapTreeZipper() { + public final F1W, TreeZipper> mapTreeZipper() { return lift(F1Functions.mapTreeZipper(this)); } @@ -420,7 +420,7 @@ public F1W, TreeZipper> mapTreeZipper() { * * @return This function promoted to return its result on the failure side of a Validation. */ - public F1W> failK() { + public final F1W> failK() { return lift(F1Functions.failK(this)); } @@ -430,7 +430,7 @@ public F1W> failK() { * * @return This function promoted to return its result on the success side of an Validation. */ - public F1W> successK() { + public final F1W> successK() { return lift( F1Functions.successK(this)); } @@ -439,7 +439,7 @@ public F1W> successK() { * * @return This function promoted to map over the failure side of a Validation. */ - public F1W, Validation> mapFail() { + public final F1W, Validation> mapFail() { return lift(F1Functions.mapFail(this)); } @@ -448,7 +448,7 @@ public F1W, Validation> mapFail() { * * @return This function promoted to map over the success side of a Validation. */ - public F1W, Validation> mapSuccess() { + public final F1W, Validation> mapSuccess() { return lift(F1Functions.mapSuccess(this)); } @@ -459,7 +459,7 @@ public F1W, Validation> mapSuccess() { * @return a function that returns the failure side of a given Validation, * or this function applied to the success side. */ - public F1W, B> onFail() { + public final F1W, B> onFail() { return lift(F1Functions.onFail(this)); } @@ -470,7 +470,7 @@ public F1W, B> onFail() { * @return a function that returns the success side of a given Validation, * or this function applied to the failure side. */ - public F1W, B> onSuccess() { + public final F1W, B> onSuccess() { return lift(F1Functions.onSuccess(this)); } @@ -479,7 +479,7 @@ public F1W, B> onSuccess() { * * @return This function promoted to return its value in a Zipper. */ - public F1W> zipperK() { + public final F1W> zipperK() { return lift(F1Functions.zipperK(this)); } @@ -488,7 +488,7 @@ public F1W> zipperK() { * * @return This function promoted to map over a Zipper. */ - public F1W, Zipper> mapZipper() { + public final F1W, Zipper> mapZipper() { return lift(F1Functions.mapZipper(this)); } @@ -497,7 +497,7 @@ public F1W, Zipper> mapZipper() { * * @return This function promoted to map over an Equal as a contravariant functor. */ - public F1W, Equal> contramapEqual() { + public final F1W, Equal> contramapEqual() { return lift(F1Functions.contramapEqual(this)); } @@ -506,7 +506,7 @@ public F1W, Equal> contramapEqual() { * * @return This function promoted to map over a Hash as a contravariant functor. */ - public F1W, Hash> contramapHash() { + public final F1W, Hash> contramapHash() { return lift(F1Functions.contramapHash(this)); } @@ -515,7 +515,7 @@ public F1W, Hash> contramapHash() { * * @return This function promoted to map over a Show as a contravariant functor. */ - public F1W, Show> contramapShow() { + public final F1W, Show> contramapShow() { return lift(F1Functions.contramapShow(this)); } @@ -524,7 +524,7 @@ public F1W, Show> contramapShow() { * * @return This function promoted to map over the first element of a pair. */ - public F1W, P2> mapFst() { + public final F1W, P2> mapFst() { return lift(F1Functions.mapFst(this)); } @@ -533,7 +533,7 @@ public F1W, P2> mapFst() { * * @return This function promoted to map over the second element of a pair. */ - public F1W, P2> mapSnd() { + public final F1W, P2> mapSnd() { return lift(F1Functions.mapSnd(this)); } @@ -542,7 +542,7 @@ public F1W, P2> mapSnd() { * * @return This function promoted to map over both elements of a pair. */ - public F1W, P2> mapBoth() { + public final F1W, P2> mapBoth() { return lift(F1Functions.mapBoth(this)); } @@ -552,7 +552,7 @@ public F1W, P2> mapBoth() { * @param as A SynchronousQueue to map this function over. * @return A new SynchronousQueue with this function applied to each element. */ - public SynchronousQueue mapJ(final SynchronousQueue as) { + public final SynchronousQueue mapJ(final SynchronousQueue as) { return F1Functions.mapJ(this, as); } @@ -563,7 +563,7 @@ public SynchronousQueue mapJ(final SynchronousQueue as) { * @param as A PriorityBlockingQueue to map this function over. * @return A new PriorityBlockingQueue with this function applied to each element. */ - public PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { + public final PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { return F1Functions.mapJ(this, as); } @@ -573,7 +573,7 @@ public PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { * @param as A LinkedBlockingQueue to map this function over. * @return A new LinkedBlockingQueue with this function applied to each element. */ - public LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { + public final LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { return F1Functions.mapJ(this, as); } @@ -583,7 +583,7 @@ public LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { * @param as A CopyOnWriteArraySet to map this function over. * @return A new CopyOnWriteArraySet with this function applied to each element. */ - public CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { + public final CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { return F1Functions.mapJ(this, as); } @@ -593,7 +593,7 @@ public CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { * @param as A CopyOnWriteArrayList to map this function over. * @return A new CopyOnWriteArrayList with this function applied to each element. */ - public CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { + public final CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { return F1Functions.mapJ(this, as); } @@ -603,7 +603,7 @@ public CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { * @param as A ConcurrentLinkedQueue to map this function over. * @return A new ConcurrentLinkedQueue with this function applied to each element. */ - public ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { + public final ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { return F1Functions.mapJ(this, as); } @@ -613,7 +613,7 @@ public ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { * @param as An ArrayBlockingQueue to map this function over. * @return A new ArrayBlockingQueue with this function applied to each element. */ - public ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { + public final ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { return F1Functions.mapJ(this, as); } @@ -624,7 +624,7 @@ public ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { * @param as A TreeSet to map this function over. * @return A new TreeSet with this function applied to each element. */ - public TreeSet mapJ(final TreeSet as) { + public final TreeSet mapJ(final TreeSet as) { return F1Functions.mapJ(this, as); } @@ -634,7 +634,7 @@ public TreeSet mapJ(final TreeSet as) { * @param as A PriorityQueue to map this function over. * @return A new PriorityQueue with this function applied to each element. */ - public PriorityQueue mapJ(final PriorityQueue as) { + public final PriorityQueue mapJ(final PriorityQueue as) { return F1Functions.mapJ(this, as); } @@ -644,7 +644,7 @@ public PriorityQueue mapJ(final PriorityQueue as) { * @param as A LinkedList to map this function over. * @return A new LinkedList with this function applied to each element. */ - public LinkedList mapJ(final LinkedList as) { + public final LinkedList mapJ(final LinkedList as) { return F1Functions.mapJ(this, as); } @@ -654,15 +654,15 @@ public LinkedList mapJ(final LinkedList as) { * @param as An ArrayList to map this function over. * @return A new ArrayList with this function applied to each element. */ - public ArrayList mapJ(final ArrayList as) { + public final ArrayList mapJ(final ArrayList as) { return F1Functions.mapJ(this, as); } - public F1W map(F f) { + public final F1W map(F f) { return lift(F1Functions.map(this, f)); } - public F1W contramap(F f) { + public final F1W contramap(F f) { return lift(F1Functions.contramap(this, f)); } @@ -673,7 +673,7 @@ public F1WFunc(F f) { } @Override - public B f(A a) { + public final B f(A a) { return func.f(a); } } diff --git a/core/src/main/java/fj/F2W.java b/core/src/main/java/fj/F2W.java index eb2fb590..1f35855a 100644 --- a/core/src/main/java/fj/F2W.java +++ b/core/src/main/java/fj/F2W.java @@ -14,7 +14,7 @@ public abstract class F2W implements F2 { * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ - public F1W f(final A a) { + public final F1W f(final A a) { return F1W.lift(F2Functions.f(this, a)); } @@ -23,7 +23,7 @@ public F1W f(final A a) { * * @return a wrapped function of arity-1 that returns another wrapped function. */ - public F1W> curry() { + public final F1W> curry() { return F1W.lift(F2Functions.curry(this)); } @@ -32,7 +32,7 @@ public F1W> curry() { * * @return A new function with the arguments of this function flipped. */ - public F2W flip() { + public final F2W flip() { return lift(F2Functions.flip(this)); } @@ -41,7 +41,7 @@ public F2W flip() { * * @return A new function that calls this function with the elements of a given tuple. */ - public F1W, C> tuple() { + public final F1W, C> tuple() { return F1W.lift(F2Functions.tuple(this)); } @@ -50,7 +50,7 @@ public F1W, C> tuple() { * * @return This function promoted to transform Arrays. */ - public F2W, Array, Array> arrayM() { + public final F2W, Array, Array> arrayM() { return lift(F2Functions.arrayM(this)); } @@ -59,7 +59,7 @@ public F2W, Array, Array> arrayM() { * * @return This function promoted to transform Promises. */ - public F2W, Promise, Promise> promiseM() { + public final F2W, Promise, Promise> promiseM() { return lift(F2Functions.promiseM(this)); } @@ -68,7 +68,7 @@ public F2W, Promise, Promise> promiseM() { * * @return This function promoted to transform Iterables. */ - public F2W, Iterable, IterableW> iterableM() { + public final F2W, Iterable, IterableW> iterableM() { return lift(F2Functions.iterableM(this)); } @@ -77,7 +77,7 @@ public F2W, Iterable, IterableW> iterableM() { * * @return This function promoted to transform Lists. */ - public F2W, List, List> listM() { + public final F2W, List, List> listM() { return lift(F2Functions.listM(this)); } @@ -86,7 +86,7 @@ public F2W, List, List> listM() { * * @return This function promoted to transform non-empty lists. */ - public F2W, NonEmptyList, NonEmptyList> nelM() { + public final F2W, NonEmptyList, NonEmptyList> nelM() { return lift(F2Functions.nelM(this)); } @@ -95,7 +95,7 @@ public F2W, NonEmptyList, NonEmptyList> nelM() { * * @return This function promoted to transform Options. */ - public F2W, Option, Option> optionM() { + public final F2W, Option, Option> optionM() { return lift(F2Functions.optionM(this)); } @@ -105,7 +105,7 @@ public F2W, Option, Option> optionM() { * @param o An ordering for the result of the promoted function. * @return This function promoted to transform Sets. */ - public F2W, Set, Set> setM(final Ord o) { + public final F2W, Set, Set> setM(final Ord o) { return lift(F2Functions.setM(this, o)); } @@ -114,7 +114,7 @@ public F2W, Set, Set> setM(final Ord o) { * * @return This function promoted to transform Streams. */ - public F2W, Stream, Stream> streamM() { + public final F2W, Stream, Stream> streamM() { return lift(F2Functions.streamM(this)); } @@ -123,7 +123,7 @@ public F2W, Stream, Stream> streamM() { * * @return This function promoted to transform Trees. */ - public F2W, Tree, Tree> treeM() { + public final F2W, Tree, Tree> treeM() { return lift(F2Functions.treeM(this)); } @@ -132,7 +132,7 @@ public F2W, Tree, Tree> treeM() { * * @return A function that zips two arrays with this function. */ - public F2W, Array, Array> zipArrayM() { + public final F2W, Array, Array> zipArrayM() { return lift(F2Functions.zipArrayM(this)); } @@ -141,7 +141,7 @@ public F2W, Array, Array> zipArrayM() { * * @return A function that zips two iterables with this function. */ - public F2W, Iterable, Iterable> zipIterableM() { + public final F2W, Iterable, Iterable> zipIterableM() { return lift(F2Functions.zipIterableM(this)); } @@ -150,7 +150,7 @@ public F2W, Iterable, Iterable> zipIterableM() { * * @return A function that zips two lists with this function. */ - public F2W, List, List> zipListM() { + public final F2W, List, List> zipListM() { return lift(F2Functions.zipListM(this)); } @@ -160,7 +160,7 @@ public F2W, List, List> zipListM() { * * @return A function that zips two streams with this function. */ - public F2W, Stream, Stream> zipStreamM() { + public final F2W, Stream, Stream> zipStreamM() { return lift(F2Functions.zipStreamM(this)); } @@ -169,7 +169,7 @@ public F2W, Stream, Stream> zipStreamM() { * * @return A function that zips two non-empty lists with this function. */ - public F2W, NonEmptyList, NonEmptyList> zipNelM() { + public final F2W, NonEmptyList, NonEmptyList> zipNelM() { return lift(F2Functions.zipNelM(this)); } @@ -179,7 +179,7 @@ public F2W, NonEmptyList, NonEmptyList> zipNelM() { * @param o An ordering for the resulting set. * @return A function that zips two sets with this function. */ - public F2W, Set, Set> zipSetM(final Ord o) { + public final F2W, Set, Set> zipSetM(final Ord o) { return lift(F2Functions.zipSetM(this, o)); } @@ -189,7 +189,7 @@ public F2W, Set, Set> zipSetM(final Ord o) { * * @return A function that zips two trees with this function. */ - public F2W, Tree, Tree> zipTreeM() { + public final F2W, Tree, Tree> zipTreeM() { return lift(F2Functions.zipTreeM(this)); } @@ -199,7 +199,7 @@ public F2W, Tree, Tree> zipTreeM() { * * @return A function that zips two zippers with this function. */ - public F2W, Zipper, Zipper> zipZipperM() { + public final F2W, Zipper, Zipper> zipZipperM() { return lift(F2Functions.zipZipperM(this)); } @@ -209,23 +209,23 @@ public F2W, Zipper, Zipper> zipZipperM() { * * @return A function that zips two TreeZippers with this function. */ - public F2W, TreeZipper, TreeZipper> zipTreeZipperM() { + public final F2W, TreeZipper, TreeZipper> zipTreeZipperM() { return lift(F2Functions.zipTreeZipperM(this)); } - public F2W contramapFirst(F f) { + public final F2W contramapFirst(F f) { return lift(F2Functions.contramapFirst(this, f)); } - public F2W contramapSecond(F f) { + public final F2W contramapSecond(F f) { return lift(F2Functions.contramapSecond(this, f)); } - public F2W contramap(F f, F g) { + public final F2W contramap(F f, F g) { return lift(F2Functions.contramap(this, f, g)); } - public F2W map(F f) { + public final F2W map(F f) { return lift(F2Functions.map(this, f)); } @@ -237,7 +237,7 @@ public F2WFunc(F2 f) { } @Override - public C f(A a, B b) { + public final C f(A a, B b) { return func.f(a, b); } } diff --git a/core/src/main/java/fj/LcgRng.java b/core/src/main/java/fj/LcgRng.java index 50ee9e03..215b3572 100644 --- a/core/src/main/java/fj/LcgRng.java +++ b/core/src/main/java/fj/LcgRng.java @@ -17,18 +17,18 @@ public LcgRng(long s) { seed = s; } - public long getSeed() { + public final long getSeed() { return seed; } - public P2 nextInt() { + public final P2 nextInt() { P2 p = nextLong(); int i = (int) p._2().longValue(); return P.p(p._1(), i); } - public P2 nextLong() { + public final P2 nextLong() { P2 p = nextLong(seed); return P.p(new LcgRng(p._1()), p._2()); } diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 471c110f..bb682ad8 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -527,7 +527,7 @@ public static Ord hashEqualsOrd() { class OrdComparator implements Comparator { @Override - public int compare(A o1, A o2) { + public final int compare(A o1, A o2) { return Ord.this.compare(o1, o2).toInt(); } } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 5a1d9b8a..d6809da9 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -63,7 +63,7 @@ public static F, P1> map_(final F f) { * @param f A function to apply to the value in a product-1. * @return The result of applying the given function to the value of given product-1. */ - public P1 bind(final F> f) { + public final P1 bind(final F> f) { P1 self = this; return P.lazy(() -> f.f(self._1())._1()); } @@ -84,7 +84,7 @@ public static F> curry(final F f) { * @param cf The P1 function to apply. * @return A new P1 after applying the given P1 function to the first argument. */ - public P1 apply(final P1> cf) { + public final P1 apply(final P1> cf) { P1 self = this; return cf.bind(f -> map_(f).f(self)); } @@ -96,14 +96,14 @@ public P1 apply(final P1> cf) { * @param f The function to apply to the values in the given P1s. * @return A new P1 after performing the map, then final join. */ - public P1 bind(final P1 cb, final F> f) { + public final P1 bind(final P1 cb, final F> f) { return cb.apply(map_(f).f(this)); } /** * Binds the given function to the values in the given P1s with a final join. */ - public P1 bind(final P1 cb, final F2 f) { + public final P1 bind(final P1 cb, final F2 f) { return bind(cb, F2W.lift(f).curry()); } @@ -127,7 +127,7 @@ public static F, F, P1>> liftM2(final F> f) return Function.curry((pa, pb) -> pa.bind(pb, f)); } - public P1 liftM2(P1 pb, F2 f) { + public final P1 liftM2(P1 pb, F2 f) { return P.lazy(() -> f.f(_1(), pb._1())); } @@ -183,7 +183,7 @@ public static P1> sequence(final Array> as) { * @param f The function that takes A and produces a List (non-deterministic result) * @return A List of P1 */ - public List> traverseList(final F> f){ + public final List> traverseList(final F> f){ return f.f(_1()).map(P::p); } @@ -193,7 +193,7 @@ public List> traverseList(final F> f){ * @param f The function produces Either * @return An Either of P1 */ - public Either> traverseEither(final F> f){ + public final Either> traverseEither(final F> f){ return f.f(_1()).right().map(P::p); } @@ -203,7 +203,7 @@ public Either> traverseEither(final F> f){ * @param f The function that produces Option * @return An Option of P1 */ - public Option> traverseOption(final F> f){ + public final Option> traverseOption(final F> f){ return f.f(_1()).map(P::p); } @@ -213,7 +213,7 @@ public Option> traverseOption(final F> f){ * @param f The function might produces Validation * @return An Validation of P1 */ - public Validation> traverseValidation(final F> f){ + public final Validation> traverseValidation(final F> f){ return f.f(_1()).map(P::p); } @@ -223,7 +223,7 @@ public Validation> traverseValidation(final F */ - public Stream> traverseStream(final F> f){ + public final Stream> traverseStream(final F> f){ return f.f(_1()).map(P::p); } @@ -233,7 +233,7 @@ public Stream> traverseStream(final F> f){ * @param f The function to map with. * @return A product with the given function applied. */ - public P1 map(final F f) { + public final P1 map(final F f) { final P1 self = this; return P.lazy(() -> f.f(self._1())); } @@ -247,7 +247,7 @@ public P1 memo() { * * @return A P1 that calls this P1 once and remembers the value for subsequent calls. */ - public P1 hardMemo() { return new Memo<>(this); } + public final P1 hardMemo() { return new Memo<>(this); } /** * Like memo, but the memoized value is wrapped into a WeakReference @@ -274,7 +274,7 @@ static class Memo extends P1 { Memo(P1 self) { this.self = self; } - @Override public A _1() { + @Override public final A _1() { if (!initialized) { synchronized (this) { if (!initialized) { @@ -288,7 +288,7 @@ static class Memo extends P1 { return value; } - @Override public P1 memo() { return this; } + @Override public final P1 memo() { return this; } } abstract static class ReferenceMemo extends P1 { @@ -298,7 +298,7 @@ abstract static class ReferenceMemo extends P1 { ReferenceMemo(final P1 self) { this.self = self; } - @Override public A _1() { + @Override public final A _1() { Option o = v != null ? v.get() : null; if (o == null) { synchronized (latch) { @@ -317,14 +317,16 @@ abstract static class ReferenceMemo extends P1 { static class WeakReferenceMemo extends ReferenceMemo { WeakReferenceMemo(P1 self) { super(self); } - @Override Reference> newReference(final Option o) { return new WeakReference<>(o); } - @Override public P1 weakMemo() { return this; } + @Override + final Reference> newReference(final Option o) { return new WeakReference<>(o); } + @Override public final P1 weakMemo() { return this; } } static class SoftReferenceMemo extends ReferenceMemo { SoftReferenceMemo(P1 self) { super(self); } - @Override Reference> newReference(final Option o) { return new SoftReference<>(o); } - @Override public P1 softMemo() { return this; } + @Override + final Reference> newReference(final Option o) { return new SoftReference<>(o); } + @Override public final P1 softMemo() { return this; } } /** @@ -332,20 +334,20 @@ static class SoftReferenceMemo extends ReferenceMemo { * * @return A constant function that always uses this value. */ - public F constant() { return Function.constant(_1()); } + public final F constant() { return Function.constant(_1()); } @Override - public String toString() { + public final String toString() { return Show.p1Show(Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P1.class, this, other, () -> Equal.p1Equal(Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p1Hash(Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index be3be69b..521fc14d 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -27,12 +27,12 @@ public abstract class P2 { public abstract B _2(); @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P2.class, this, other, () -> Equal.p2Equal(Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p2Hash(Hash.anyHash(), Hash.anyHash()).hash(this); } @@ -311,7 +311,7 @@ public static F2 untuple(final F, C> f) { @Override - public String toString() { + public final String toString() { return Show.p2Show(Show.anyShow(), Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index c6bc38a9..26c51b05 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -174,18 +174,18 @@ public static F, C> __3() { } @Override - public String toString() { + public final String toString() { return Show.p3Show(Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P3.class, this, other, () -> Equal.p3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p3Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 6181b75e..c2f94f8f 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -243,18 +243,18 @@ public static F, D> __4() { } @Override - public String toString() { + public final String toString() { return Show.p4Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P4.class, this, other, () -> Equal.p4Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p4Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 2fd74ebe..902da93c 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -318,18 +318,18 @@ public static F, E> __5() { } @Override - public String toString() { + public final String toString() { return Show.p5Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P5.class, this, other, () -> Equal.p5Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p5Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 5c679a2c..37f5fe6c 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -404,19 +404,19 @@ public F _6() { } @Override - public String toString() { + public final String toString() { return Show.p6Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P6.class, this, other, () -> Equal.p6Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p6Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index eb0cb913..e2673183 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -495,18 +495,18 @@ public G _7() { } @Override - public String toString() { + public final String toString() { return Show.p7Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P7.class, this, other, () -> Equal.p7Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p7Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index de13749b..cfa916eb 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -597,18 +597,18 @@ public H _8() { } @Override - public String toString() { + public final String toString() { return Show.p8Show(Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow(), Show.anyShow()).showS(this); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(P8.class, this, other, () -> Equal.p8Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.p8Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); } diff --git a/core/src/main/java/fj/Rng.java b/core/src/main/java/fj/Rng.java index 45f03c06..20b3358f 100644 --- a/core/src/main/java/fj/Rng.java +++ b/core/src/main/java/fj/Rng.java @@ -10,12 +10,12 @@ public abstract class Rng { public abstract P2 nextLong(); // [low, high] inclusive - public P2 range(int low, int high) { + public final P2 range(int low, int high) { return nextNatural().map2(x -> (x % (high - low + 1)) + low); } - public P2 nextNatural() { + public final P2 nextNatural() { return nextInt().map2(x -> x < 0 ? -(x + 1) : x); } diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index fa07df3c..bd69ae7a 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -18,7 +18,7 @@ public abstract class Trampoline { private abstract static class Normal extends Trampoline { public abstract R foldNormal(final F pure, final F>, R> k); - public Trampoline bind(final F> f) { + public final Trampoline bind(final F> f) { return codense(this, f); } } @@ -199,7 +199,7 @@ public static F, Either>, A>> resume_() { * @return The end result of this computation. */ @SuppressWarnings("LoopStatementThatDoesntLoop") - public A run() { + public final A run() { Trampoline current = this; while (true) { final Either>, A> x = current.resume(); @@ -252,7 +252,7 @@ public static F, F, Trampoline>> liftM2 * @return A new trampoline that runs this trampoline and the given trampoline simultaneously. */ @SuppressWarnings("LoopStatementThatDoesntLoop") - public Trampoline zipWith(final Trampoline b, final F2 f) { + public final Trampoline zipWith(final Trampoline b, final F2 f) { final Either>, A> ea = resume(); final Either>, B> eb = b.resume(); for (final P1> x : ea.left()) { diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 0d944415..77dea3c3 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -92,12 +92,12 @@ public final Either bimap(final F left, final F right) } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(Either.class, this, other, () -> Equal.eitherEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.eitherHash(Hash.anyHash(), Hash.anyHash()).hash(this); } @@ -802,7 +802,7 @@ public static Either> sequenceRight(final List> a * * @return traversed value */ - public List> traverseListRight(final F> f) { + public final List> traverseListRight(final F> f) { return right().traverseList(f); } @@ -811,7 +811,7 @@ public List> traverseListRight(final F> f) { * * @return traversed value */ - public List> traverseListLeft(final F> f) { + public final List> traverseListLeft(final F> f) { return left().traverseList(f); } @@ -820,7 +820,7 @@ public List> traverseListLeft(final F> f) { * * @return traversed value */ - public IO> traverseIORight(final F> f) { + public final IO> traverseIORight(final F> f) { return right().traverseIO(f); } @@ -829,7 +829,7 @@ public IO> traverseIORight(final F> f) { * * @return traversed value */ - public IO> traverseIOLeft(final F> f) { + public final IO> traverseIOLeft(final F> f) { return left().traverseIO(f); } @@ -838,7 +838,7 @@ public IO> traverseIOLeft(final F> f) { * * @return traversed value */ - public Option> traverseOptionRight(final F> f) { + public final Option> traverseOptionRight(final F> f) { return right().traverseOption(f); } @@ -847,7 +847,7 @@ public Option> traverseOptionRight(final F> f) { * * @return traversed value */ - public Option> traverseOptionLeft(final F> f) { + public final Option> traverseOptionLeft(final F> f) { return left().traverseOption(f); } @@ -856,7 +856,7 @@ public Option> traverseOptionLeft(final F> f) { * * @return traversed value */ - public Stream> traverseStreamRight(final F> f) { + public final Stream> traverseStreamRight(final F> f) { return right().traverseStream(f); } @@ -865,7 +865,7 @@ public Stream> traverseStreamRight(final F> f) { * * @return traversed value */ - public Stream> traverseStreamLeft(final F> f) { + public final Stream> traverseStreamLeft(final F> f) { return left().traverseStream(f); } @@ -913,7 +913,7 @@ public static List rights(final List> es) { return es.foldRight(e -> bs -> e.isRight() ? bs.cons(e.right().value()) : bs, List.nil()); } - public String toString() { + public final String toString() { return Show.eitherShow(Show.anyShow(), Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 399cc016..15171e43 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -166,7 +166,7 @@ public final Option toOption() { * * @return The optional head of the list. */ - public Option headOption() { + public final Option headOption() { return isEmpty() ? Option.none() : some(head()); } @@ -611,7 +611,7 @@ public final List sequence(final List bs) { * @param f The function that produces Option value * @return none if applying f returns none to any element of the list or f mapped list in some . */ - public Option> traverseOption(final F> f) { + public final Option> traverseOption(final F> f) { return foldRight( (a, obs) -> f.f(a).bind(o -> obs.map(os -> os.cons(o))), some(List.nil()) @@ -624,35 +624,35 @@ public Option> traverseOption(final F> f) { * @param f The function that produces Either value. * @return error in left or f mapped list in right. */ - public Either> traverseEither(final F> f) { + public final Either> traverseEither(final F> f) { return foldRight( (a, acc) -> f.f(a).right().bind(e -> acc.right().map(es -> es.cons(e))), Either.right(List.nil()) ); } - public Stream> traverseStream(final F> f) { + public final Stream> traverseStream(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(s -> acc.map(ss -> ss.cons(s))), Stream.nil() ); } - public P1> traverseP1(final F> f){ + public final P1> traverseP1(final F> f){ return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), p(List.nil()) ); } - public IO> traverseIO(F> f) { + public final IO> traverseIO(F> f) { return this.foldRight( (a, acc) -> IOFunctions.bind(f.f(a), b -> IOFunctions.map(acc, bs -> bs.cons(b))), IOFunctions.unit(List.nil()) ); } - public F> traverseF(F> f) { + public final F> traverseF(F> f) { return this.foldRight( (a, acc) -> Function.bind(acc, (bs) -> Function.compose(bs::cons, f.f(a))), @@ -660,31 +660,31 @@ public F> traverseF(F> f) { ); } - public Trampoline> traverseTrampoline(final F> f) { + public final Trampoline> traverseTrampoline(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), Trampoline.pure(List.nil())); } - public Promise> traversePromise(final F> f) { + public final Promise> traversePromise(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.fmap(bs -> bs.cons(b))), Promise.promise(Strategy.idStrategy(), p(List.nil()))); } - public List> traverseList(final F> f) { + public final List> traverseList(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), single(List.nil())); } - public Validation> traverseValidation(final F> f) { + public final Validation> traverseValidation(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), Validation.success(List.nil())); } - public V2> traverseV2(final F> f) { + public final V2> traverseV2(final F> f) { return foldRight( (a, acc) -> acc.apply(f.f(a)., List>> map(e -> es -> es.cons(e))), v(List.nil(), List.nil())); @@ -902,7 +902,7 @@ public final List> partition(final int n) { * * @param f Predicate function. */ - public P2, List> partition(F f) { + public final P2, List> partition(F f) { P2, List> p2 = foldLeft(acc -> a -> f.f(a) ? p(acc._1().cons(a), acc._2()) : p(acc._1(), acc._2().cons(a)), p(nil(), nil()) @@ -1172,7 +1172,7 @@ public static F, A> head_() { * Reutrns the tail of the list, if any. * @return The optional tail of the list. */ - public Option> tailOption() { + public final Option> tailOption() { return isEmpty() ? none() : some(tail()); } @@ -1410,7 +1410,7 @@ public final TreeMap groupBy( * @param eq The equality test. * @return Whether or not all elements in the list are equal according to the given equality test. */ - public boolean allEqual(final Equal eq) { + public final boolean allEqual(final Equal eq) { return isEmpty() || tail().isEmpty() || eq.eq(head(), tail().head()) && tail().allEqual(eq); } @@ -2066,7 +2066,7 @@ private void copy() { * @param obj the other object to check for equality against. * @return true if this list is equal to the provided argument */ - @Override public boolean equals( final Object obj ) { + @Override public final boolean equals(final Object obj) { return Equal.equals0(List.class, this, obj, () -> Equal.listEqual(Equal.anyEqual())); } @@ -2077,7 +2077,7 @@ private void copy() { * @return the hash code for this list. */ @Override - public int hashCode() { + public final int hashCode() { return Hash.listHash(Hash.anyHash()).hash(this); } @@ -2087,14 +2087,14 @@ public int hashCode() { * * @return a String representation of the list */ - @Override public String toString() { + @Override public final String toString() { return Show.listShow(Show.anyShow()).showS(this); } /** * True if and only if the list has one element. Runs in constant time. */ - public boolean isSingle() { + public final boolean isSingle() { return isNotEmpty() && tail().isEmpty(); } diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 1ec77980..a74d2495 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -51,7 +51,7 @@ private Option() { } @Override - public String toString() { + public final String toString() { return optionShow(Show.anyShow()).showS(this); } @@ -411,44 +411,44 @@ public final Option sequence(final Option o) { return bind(c); } - public Either> traverseEither(F> f) { + public final Either> traverseEither(F> f) { return map(a -> f.f(a).right().map(Option::some)).orSome(Either.right(none())); } - public IO> traverseIO(F> f) { + public final IO> traverseIO(F> f) { return map(a -> IOFunctions.map(f.f(a), Option::some)).orSome(IOFunctions.lazy(Option::none)); } - public List> traverseList(F> f) { + public final List> traverseList(F> f) { return map(a -> f.f(a).map(Option::some)).orSome(List.list()); } - public Option> traverseOption(F> f) { + public final Option> traverseOption(F> f) { return map(f); } - public Stream> traverseStream(F> f) { + public final Stream> traverseStream(F> f) { return map(a -> f.f(a).map(Option::some)).orSome(Stream.nil()); } - public P1> traverseP1(F> f) { + public final P1> traverseP1(F> f) { return map(a -> f.f(a).map(Option::some)).orSome(p(none())); } - public Seq> traverseSeq(F> f) { + public final Seq> traverseSeq(F> f) { return map(a -> f.f(a).map(Option::some)).orSome(Seq.empty()); } - public Set> traverseSet(Ord ord, F> f) { + public final Set> traverseSet(Ord ord, F> f) { Ord> optOrd = Ord.optionOrd(ord); return map(a -> f.f(a).map(optOrd, Option::some)).orSome(Set.empty(optOrd)); } - public F2, F>, Set>> traverseSet() { + public final F2, F>, Set>> traverseSet() { return this::traverseSet; } - public Validation> traverseValidation(F> f) { + public final Validation> traverseValidation(F> f) { return map(a -> f.f(a).map(Option::some)).orSome(Validation.success(none())); } @@ -608,7 +608,7 @@ public final boolean exists(final F f) { } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(Option.class, this, other, () -> Equal.optionEqual(Equal.anyEqual())); } @@ -796,7 +796,7 @@ public static Option fromString(final String s) { } @Override - public int hashCode() { + public final int hashCode() { return Hash.optionHash(Hash.anyHash()).hash(this); } @@ -836,7 +836,7 @@ public static F, F, Option>> liftM2(final F Option liftM2(final Option ob, final F2 f) { + public final Option liftM2(final Option ob, final F2 f) { return bind(a -> ob.map(b -> f.f(a, b))); } diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index 042db624..af66c87e 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -15,7 +15,7 @@ public Reader(F f) { function = f; } - public F getFunction() { + public final F getFunction() { return function; } @@ -27,23 +27,23 @@ public static Reader constant(B b) { return unit(a -> b); } - public B f(A a) { + public final B f(A a) { return function.f(a); } - public Reader map(F f) { + public final Reader map(F f) { return unit(F1Functions.andThen(function, f)); } - public Reader andThen(F f) { + public final Reader andThen(F f) { return map(f); } - public Reader flatMap(F> f) { + public final Reader flatMap(F> f) { return unit(a -> f.f(function.f(a)).f(a)); } - public Reader bind(F> f) { + public final Reader bind(F> f) { return flatMap(f); } diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 42ce0bac..35b3c683 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -142,17 +142,17 @@ public static Set empty(final Ord ord) { } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(Set.class, this, other, () -> Equal.setEqual(Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.setHash(Hash.anyHash()).hash(this); } @Override - public String toString() { + public final String toString() { return Show.setShow(Show.anyShow()).showS(this); } @@ -467,11 +467,11 @@ public static F, F, Set>> minus() { return curry(Set::minus); } - public Option min() { + public final Option min() { return isEmpty() ? none() : l().min().orElse(some(head())); } - public Option max() { + public final Option max() { return isEmpty() ? none() : r().max().orElse(some(head())); } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 4abde573..01e1756b 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -1258,25 +1258,25 @@ public final boolean forall(final F f) { } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(Stream.class, this, other, () -> Equal.streamEqual(Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.streamHash(Hash.anyHash()).hash(this); } @Override - public String toString() { + public final String toString() { return toStringLazy(); } - public String toStringLazy() { + public final String toStringLazy() { return isEmpty() ? "Nil()" : "Cons(" + Show.anyShow().showS(head()) + ", ?)"; } - public String toStringEager() { + public final String toStringEager() { return Show.streamShow(Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 9d82596b..58aa5e9c 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -31,7 +31,7 @@ protected Validation(final Either e) { * * @return true if this is a failure, false otherwise. */ - public boolean isFail() { + public final boolean isFail() { return e.isLeft(); } @@ -40,7 +40,7 @@ public boolean isFail() { * * @return true if this is a success, false otherwise. */ - public boolean isSuccess() { + public final boolean isSuccess() { return e.isRight(); } @@ -49,7 +49,7 @@ public boolean isSuccess() { * * @return the failing value, or throws an error if there is no failing value. */ - public E fail() { + public final E fail() { if (isFail()) return e.left().value(); else @@ -61,7 +61,7 @@ public E fail() { * * @return the success value, or throws an error if there is no success value. */ - public T success() { + public final T success() { if (isSuccess()) return e.right().value(); else @@ -75,7 +75,7 @@ public T success() { * @param success The function to call if this succeeded. * @return The reduced value. */ - public X validation(final F fail, final F success) { + public final X validation(final F fail, final F success) { return e.either(fail, success); } @@ -84,7 +84,7 @@ public X validation(final F fail, final F success) { * * @return a failing projection of this validation. */ - public FailProjection f() { + public final FailProjection f() { return new FailProjection<>(this); } @@ -93,7 +93,7 @@ public FailProjection f() { * * @return An either projection of this validation. */ - public Either toEither() { + public final Either toEither() { return e; } @@ -103,7 +103,7 @@ public Either toEither() { * @param err The error message to fail with. * @return The success value. */ - public T successE(final F0 err) { + public final T successE(final F0 err) { return e.right().valueE(err); } @@ -113,7 +113,7 @@ public T successE(final F0 err) { * @param err The error message to fail with. * @return The success value. */ - public T successE(final String err) { + public final T successE(final String err) { return e.right().valueE(p(err)); } @@ -123,7 +123,7 @@ public T successE(final String err) { * @param t The value to return if this is failure. * @return The success value or the given value. */ - public T orSuccess(final F0 t) { + public final T orSuccess(final F0 t) { return e.right().orValue(t); } @@ -133,7 +133,7 @@ public T orSuccess(final F0 t) { * @param t The value to return if this is failure. * @return The success value or the given value. */ - public T orSuccess(final T t) { + public final T orSuccess(final T t) { return e.right().orValue(p(t)); } @@ -143,7 +143,7 @@ public T orSuccess(final T t) { * @param f The function to execute on the failing value. * @return The success value or the application of the given function to the failing value. */ - public T on(final F f) { + public final T on(final F f) { return e.right().on(f); } @@ -153,7 +153,7 @@ public T on(final F f) { * @param f The side-effect to execute. * @return The unit value. */ - public Unit foreach(final F f) { + public final Unit foreach(final F f) { return e.right().foreach(f); } @@ -162,7 +162,7 @@ public Unit foreach(final F f) { * * @param f The side-effect to execute. */ - public void foreachDoEffect(final Effect1 f) { + public final void foreachDoEffect(final Effect1 f) { e.right().foreachDoEffect(f); } @@ -173,7 +173,7 @@ public void foreachDoEffect(final Effect1 f) { * @return A new validation with the function mapped. */ @SuppressWarnings("unchecked") - public Validation map(final F f) { + public final Validation map(final F f) { return isFail() ? Validation.fail(fail()) : Validation.success(f.f(success())); @@ -186,7 +186,7 @@ public Validation map(final F f) { * @return A new validation value after binding. */ @SuppressWarnings("unchecked") - public Validation bind(final F> f) { + public final Validation bind(final F> f) { return isSuccess() ? f.f(success()) : Validation.fail(fail()); } @@ -196,7 +196,7 @@ public Validation bind(final F> f) { * @param v The value to bind with. * @return A validation after binding. */ - public Validation sequence(final Validation v) { + public final Validation sequence(final Validation v) { return bind(Function.constant(v)); } @@ -220,7 +220,7 @@ public static Validation> sequence(final Semigroup s, final * @return None if this is a failure or if the given predicate p does not hold for the * success value, otherwise, returns a success in Some. */ - public Option> filter(final F f) { + public final Option> filter(final F f) { return e.right().filter(f).map(Validation.validation()); } @@ -230,7 +230,7 @@ public Option> filter(final F f) { * @param v The validation of the function to apply on the success value. * @return The result of function application in validation. */ - public Validation apply(final Validation> v) { + public final Validation apply(final Validation> v) { return v.bind(this::map); } @@ -242,7 +242,7 @@ public Validation apply(final Validation> v) { * @return true if this is a failure or returns the result of the application of the given * function to the success value. */ - public boolean forall(final F f) { + public final boolean forall(final F f) { return e.right().forall(f); } @@ -254,17 +254,17 @@ public boolean forall(final F f) { * @return false if this is a failure or returns the result of the application of the given * function to the success value. */ - public boolean exists(final F f) { + public final boolean exists(final F f) { return e.right().exists(f); } @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { return Equal.equals0(Validation.class, this, other, () -> Equal.validationEqual(Equal.anyEqual(), Equal.anyEqual())); } @Override - public int hashCode() { + public final int hashCode() { return Hash.validationHash(Hash.anyHash(), Hash.anyHash()).hash(this); } @@ -273,7 +273,7 @@ public int hashCode() { * * @return A single element list if this is a success value, otherwise an empty list. */ - public List toList() { + public final List toList() { return e.right().toList(); } @@ -282,7 +282,7 @@ public List toList() { * * @return The success value in Some if there is one, otherwise None. */ - public Option toOption() { + public final Option toOption() { return e.right().toOption(); } @@ -291,7 +291,7 @@ public Option toOption() { * * @return A single element array if this is a success value, otherwise an empty list. */ - public Array toArray() { + public final Array toArray() { return e.right().toArray(); } @@ -300,7 +300,7 @@ public Array toArray() { * * @return A single element stream if this is a success value, otherwise an empty list. */ - public Stream toStream() { + public final Stream toStream() { return e.right().toStream(); } @@ -314,7 +314,7 @@ public Stream toStream() { * succeeding validation if both succeeded. */ @SuppressWarnings("unchecked") - public Validation accumapply(final Semigroup s, final Validation> v) { + public final Validation accumapply(final Semigroup s, final Validation> v) { return isFail() ? Validation.fail(v.isFail() ? s.sum(v.fail(), fail()) : @@ -334,7 +334,7 @@ public Validation accumapply(final Semigroup s, final Validation Validation accumulate(final Semigroup s, final Validation va, final F> f) { + public final Validation accumulate(final Semigroup s, final Validation va, final F> f) { return va.accumapply(s, map(f)); } @@ -348,7 +348,7 @@ public Validation accumulate(final Semigroup s, final Validation * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, final F2 f) { + public final Validation accumulate(final Semigroup s, final Validation va, final F2 f) { return va.accumapply(s, map(curry(f))); } @@ -360,7 +360,7 @@ public Validation accumulate(final Semigroup s, final Validation * @return A Some if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va) { + public final Option accumulate(final Semigroup s, final Validation va) { return accumulate(s, va, (t, a) -> unit()).f().toOption(); } @@ -375,8 +375,8 @@ public Option accumulate(final Semigroup s, final Validation va) * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final F>> f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final F>> f) { return vb.accumapply(s, accumulate(s, va, f)); } @@ -391,8 +391,8 @@ public Validation accumulate(final Semigroup s, final Validat * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final F3 f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final F3 f) { return vb.accumapply(s, accumulate(s, va, curry(f))); } @@ -405,7 +405,7 @@ public Validation accumulate(final Semigroup s, final Validat * @return A Some if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va, final Validation vb) { + public final Option accumulate(final Semigroup s, final Validation va, final Validation vb) { return accumulate(s, va, vb, (t, a, b) -> unit()).f().toOption(); } @@ -421,9 +421,9 @@ public Option accumulate(final Semigroup s, final Validation * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final F>>> f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final F>>> f) { return vc.accumapply(s, accumulate(s, va, vb, f)); } @@ -439,9 +439,9 @@ public Validation accumulate(final Semigroup s, final Vali * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final F4 f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final F4 f) { return vc.accumapply(s, accumulate(s, va, vb, curry(f))); } @@ -455,8 +455,8 @@ public Validation accumulate(final Semigroup s, final Vali * @return A Some if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va, final Validation vb, - final Validation vc) { + public final Option accumulate(final Semigroup s, final Validation va, final Validation vb, + final Validation vc) { return accumulate(s, va, vb, vc, (t, a, b, c) -> unit()).f().toOption(); } @@ -473,10 +473,10 @@ public Option accumulate(final Semigroup s, final Validation Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, - final F>>>> f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, + final F>>>> f) { return vd.accumapply(s, accumulate(s, va, vb, vc, f)); } @@ -493,9 +493,9 @@ public Option accumulate(final Semigroup s, final Validation Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final F5 f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final F5 f) { return vd.accumapply(s, accumulate(s, va, vb, vc, curry(f))); } @@ -510,8 +510,8 @@ public Option accumulate(final Semigroup s, final ValidationSome if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va, final Validation vb, - final Validation vc, final Validation vd) { + public final Option accumulate(final Semigroup s, final Validation va, final Validation vb, + final Validation vc, final Validation vd) { return accumulate(s, va, vb, vc, vd, (t, a, b, c, d) -> unit()).f().toOption(); } @@ -529,10 +529,10 @@ public Option accumulate(final Semigroup s, final Validation< * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final F>>>>> f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final F>>>>> f) { return ve.accumapply(s, accumulate(s, va, vb, vc, vd, f)); } @@ -550,10 +550,10 @@ public Option accumulate(final Semigroup s, final Validation< * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final F6 f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final F6 f) { return ve.accumapply(s, accumulate(s, va, vb, vc, vd, curry(f))); } @@ -569,9 +569,9 @@ public Option accumulate(final Semigroup s, final Validation< * @return A Some if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve) { + public final Option accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve) { return accumulate(s, va, vb, vc, vd, ve, (t, a, b, c, d, e1) -> unit()).f().toOption(); } @@ -590,11 +590,11 @@ public Option accumulate(final Semigroup s, final Validation< * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final Validation vf, - final F>>>>>> f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final Validation vf, + final F>>>>>> f) { return vf.accumapply(s, accumulate(s, va, vb, vc, vd, ve, f)); } @@ -613,11 +613,11 @@ public Option accumulate(final Semigroup s, final Validation< * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final Validation vf, - final F7 f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final Validation vf, + final F7 f) { return vf.accumapply(s, accumulate(s, va, vb, vc, vd, ve, curry(f))); } @@ -634,10 +634,10 @@ public Option accumulate(final Semigroup s, final Validation< * @return A Some if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final Validation vf) { + public final Option accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final Validation vf) { return accumulate(s, va, vb, vc, vd, ve, vf, (t, a, b, c, d, e1, f) -> unit()).f().toOption(); } @@ -657,11 +657,11 @@ public Option accumulate(final Semigroup s, final Validation< * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final Validation vf, final Validation vg, - final F>>>>>>> f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final Validation vf, final Validation vg, + final F>>>>>>> f) { return vg.accumapply(s, accumulate(s, va, vb, vc, vd, ve, vf, f)); } @@ -681,11 +681,11 @@ public Option accumulate(final Semigroup s, final Validation< * @return A succeeding validation if all validations succeeded, or a failing validation with errors accumulated if * one or more failed. */ - public Validation accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final Validation vf, final Validation vg, - final F8 f) { + public final Validation accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final Validation vf, final Validation vg, + final F8 f) { return vg.accumapply(s, accumulate(s, va, vb, vc, vd, ve, vf, curry(f))); } @@ -703,10 +703,10 @@ public Option accumulate(final Semigroup s, final Validation< * @return A Some if one or more validations failed (accumulated with the semigroup), otherwise, * None. */ - public Option accumulate(final Semigroup s, final Validation va, - final Validation vb, final Validation vc, - final Validation vd, final Validation ve, - final Validation vf, final Validation vg) { + public final Option accumulate(final Semigroup s, final Validation va, + final Validation vb, final Validation vc, + final Validation vd, final Validation ve, + final Validation vf, final Validation vg) { return accumulate(s, va, vb, vc, vd, ve, vf, vg, (t, a, b, c, d, e1, f, g) -> unit()).f().toOption(); } @@ -715,12 +715,12 @@ public Option accumulate(final Semigroup s, final Validation< * * @return A iterator for this validation. */ - public Iterator iterator() { + public final Iterator iterator() { return toEither().right().iterator(); } - public Validation, T> accumulate() { + public final Validation, T> accumulate() { if (isFail()) { return fail(List.single(fail())); } else { @@ -728,7 +728,7 @@ public Validation, T> accumulate() { } } - public Validation, B> accumulate(F f) { + public final Validation, B> accumulate(F f) { if (isFail()) { return fail(List.single(fail())); } else { @@ -737,7 +737,7 @@ public Validation, B> accumulate(F f) { } - public Validation, C> accumulate(Validation v2, F2 f) { + public final Validation, C> accumulate(Validation v2, F2 f) { List list = List.nil(); if (isFail()) { list = list.cons(fail()); @@ -754,7 +754,7 @@ public Validation, C> accumulate(Validation v2, F2 - public Validation, D> accumulate(Validation v2, Validation v3, F3 f) { + public final Validation, D> accumulate(Validation v2, Validation v3, F3 f) { List list = fails(list(this, v2, v3)); if (!list.isEmpty()) { return fail(list); @@ -763,7 +763,7 @@ public Validation, D> accumulate(Validation v2, Validati } } - public Validation, $E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { + public final Validation, $E> accumulate(Validation v2, Validation v3, Validation v4, F4 f) { List list = fails(list(this, v2, v3, v4)); if (!list.isEmpty()) { return fail(list); @@ -772,7 +772,7 @@ public Validation, D> accumulate(Validation v2, Validati } } - public Validation, $F> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, F5 f) { + public final Validation, $F> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, F5 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return fail(list); @@ -782,7 +782,7 @@ public Validation, D> accumulate(Validation v2, Validati } - public Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { + public final Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return fail(list); @@ -791,7 +791,7 @@ public Validation, D> accumulate(Validation v2, Validati } } - public Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { + public final Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return fail(list); @@ -800,7 +800,7 @@ public Validation, D> accumulate(Validation v2, Validati } } - public Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { + public final Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { List list = fails(list(this, v2, v3, v4, v5)); if (!list.isEmpty()) { return fail(list); @@ -825,31 +825,31 @@ public static Validation, List> sequenceNonCumulative(List List> traverseList(F> f){ + public final List> traverseList(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : List.iterableList(fail(e.left().value())); } - public Stream> traverseStream(F> f){ + public final Stream> traverseStream(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : Stream.iterableStream(fail(e.left().value())); } - public Option> traverseOption(F> f){ + public final Option> traverseOption(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : Option.some(fail(e.left().value())); } - public IO> traverseIO(F> f){ + public final IO> traverseIO(F> f){ return isSuccess() ? IOFunctions.map(f.f(success()), Validation::success) : IOFunctions.unit(fail(e.left().value())); } - public P1> traverseP1(F> f){ + public final P1> traverseP1(F> f){ return isSuccess() ? f.f(success()).map(Validation::success) : p(fail(e.left().value())); @@ -1081,7 +1081,7 @@ public Iterator iterator() { * @return A validation with its failing value in a non-empty list if there is one. */ @SuppressWarnings("unchecked") - public Validation, T> nel() { + public final Validation, T> nel() { return isSuccess() ? Validation.success(success()) : Validation.fail(NonEmptyList.nel(fail())); @@ -1283,7 +1283,7 @@ public static P2, List> partition(List> list) } @Override - public String toString() { + public final String toString() { return Show.validationShow(Show.anyShow(), Show.anyShow()).showS(this); } diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index 415f08c2..fb552ce9 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -138,7 +138,7 @@ public final FingerTree toTree() { ); } - Option> tail() { + final Option> tail() { return match( one -> Option.none(), two -> Option.some(mkTree(m).one(two.values()._2())), @@ -147,7 +147,7 @@ Option> tail() { ); } - Option> init() { + final Option> init() { return match( one -> Option.none(), two -> Option.some(mkTree(m).one(two.values()._1())), diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index 060e976f..f361a76a 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -33,7 +33,7 @@ public abstract class FingerTree { */ public abstract B foldRight(final F> f, final B z); - public B foldRight(final F2 f, final B z) { + public final B foldRight(final F2 f, final B z) { return foldRight(F2Functions.curry(f), z); } @@ -54,7 +54,7 @@ public B foldRight(final F2 f, final B z) { */ public abstract B foldLeft(final F> f, final B z); - public B foldLeft(final F2 f, final B z) { + public final B foldLeft(final F2 f, final B z) { return foldLeft(F2Functions.curry(f), z); } @@ -76,7 +76,7 @@ public B foldLeft(final F2 f, final B z) { */ public abstract FingerTree map(final F f, final Measured m); - public FingerTree filter(final F f) { + public final FingerTree filter(final F f) { FingerTree tree = new Empty<>(m); return foldLeft((acc, a) -> f.f(a) ? acc.snoc(a) : acc, tree); } @@ -97,7 +97,7 @@ public final boolean isEmpty() { return this instanceof Empty; } - Measured measured() { + final Measured measured() { return m; } @@ -160,7 +160,7 @@ public static MakeTree mkTree(final Measured m) { */ public abstract A head(); - public Option headOption() { + public final Option headOption() { return isEmpty() ? Option.none() : Option.some(head()); } diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index 674195d7..c7e3e7a2 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -48,7 +48,7 @@ public final V measure() { return measure; } - Measured measured() { + final Measured measured() { return m; } diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java index 4ed45ca0..7dcd0888 100644 --- a/core/src/main/java/fj/data/optic/PIso.java +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -130,7 +130,7 @@ public final F set(final B b) { } /** pair two disjoint {@link PIso} */ - public PIso, P2, P2, P2> product(final PIso other) { + public final PIso, P2, P2, P2> product(final PIso other) { return pIso( ss1 -> P.p(get(ss1._1()), other.get(ss1._2())), bb1 -> P.p(reverseGet(bb1._1()), other.reverseGet(bb1._2()))); diff --git a/demo/src/main/java/fj/demo/IODemo.java b/demo/src/main/java/fj/demo/IODemo.java index 0bc7db12..6451a46b 100644 --- a/demo/src/main/java/fj/demo/IODemo.java +++ b/demo/src/main/java/fj/demo/IODemo.java @@ -28,7 +28,7 @@ public static void main(String[] args) { * Reads from standard input until the line length is less than three * and prints that last line. */ - public void readFirstShortLine() { + public final void readFirstShortLine() { F f = lift(lines_()).andThen(l -> l.filter(s -> s.length() < 3)).andThen(unlines_()); runSafe(interact(f)); } @@ -36,7 +36,7 @@ public void readFirstShortLine() { /** * Read a stream of input lazily using interact, in effect reading the first line */ - public void readFirstLine() { + public final void readFirstLine() { F f = lift(LazyString::lines).andThen(unlines_()); runSafe(interact(f)); } @@ -45,14 +45,14 @@ public void readFirstLine() { * Demonstrate use of interact, just echoing the lazy string. Reading lines is done * lazily, so just the first line is read. */ - public void simpleInteract() { + public final void simpleInteract() { runSafe(interact(s -> s)); } /** * Demonstrate that getContents returns a lazy string. */ - public void getContents() { + public final void getContents() { out.println(runSafe(IOFunctions.getContents())); } diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index 56763ce5..ef1a09cd 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -29,7 +29,7 @@ public VendingMachine(boolean lock, int things, int numCoins) { * Equals generated by Intellij */ @Override - public boolean equals(Object o) { + public final boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -46,18 +46,18 @@ public boolean equals(Object o) { * HashCode generated by Intellij */ @Override - public int hashCode() { + public final int hashCode() { int result = locked ? 1 : 0; result = 31 * result + items; result = 31 * result + coins; return result; } - public String toString() { + public final String toString() { return String.format("VendingMachine(locked=%b,items=%d,coins=%d)", locked, items, coins); } - VendingMachine next(Input i) { + final VendingMachine next(Input i) { if (items == 0) { return this; } else if (i == COIN && !locked) { diff --git a/demo/src/main/java/fj/demo/concurrent/Ping.java b/demo/src/main/java/fj/demo/concurrent/Ping.java index 3ba934fb..da2efd52 100644 --- a/demo/src/main/java/fj/demo/concurrent/Ping.java +++ b/demo/src/main/java/fj/demo/concurrent/Ping.java @@ -33,12 +33,12 @@ public void f(final Pong pong) { } // Commence pinging - public P1 start() { + public final P1 start() { return pong.act(this); } // Receive a pong - public P1 act(final Pong p) { + public final P1 act(final Pong p) { return ping.act(p); } } diff --git a/demo/src/main/java/fj/demo/concurrent/PingPong.java b/demo/src/main/java/fj/demo/concurrent/PingPong.java index a9109585..d845ab32 100644 --- a/demo/src/main/java/fj/demo/concurrent/PingPong.java +++ b/demo/src/main/java/fj/demo/concurrent/PingPong.java @@ -51,7 +51,7 @@ public static void main(final String[] args) { new PingPong(Executors.newFixedThreadPool(threads), actors, pings).start(); } - public void start() { + public final void start() { // We will use one Pong actor... final Pong pong = new Pong(s); diff --git a/demo/src/main/java/fj/demo/concurrent/Pong.java b/demo/src/main/java/fj/demo/concurrent/Pong.java index b0f0ad57..bc06a22d 100644 --- a/demo/src/main/java/fj/demo/concurrent/Pong.java +++ b/demo/src/main/java/fj/demo/concurrent/Pong.java @@ -23,7 +23,7 @@ public void f(final Ping m) { } // Receive a ping - public P1 act(final Ping ping) { + public final P1 act(final Ping ping) { return p.act(ping); } } \ No newline at end of file diff --git a/demo/src/main/java/fj/demo/optic/LensPerson.java b/demo/src/main/java/fj/demo/optic/LensPerson.java index 107ef659..51f5e103 100644 --- a/demo/src/main/java/fj/demo/optic/LensPerson.java +++ b/demo/src/main/java/fj/demo/optic/LensPerson.java @@ -48,14 +48,14 @@ public Address(int number, String street) { static final Person oldPerson = new Person(oldName, oldAddress); @Test - public void get() { + public final void get() { assertTrue(personNameLens.get(oldPerson).equals(oldName)); assertTrue(personNumberLens.get(oldPerson) == oldNumber); assertTrue(personStreetLens.get(oldPerson) == oldStreet); } @Test - public void setName() { + public final void setName() { String newName = "Bill"; Person p = personNameLens.set(newName).f(oldPerson); assertTrue(p.name.equals(newName)); @@ -63,7 +63,7 @@ public void setName() { } @Test - public void setNumber() { + public final void setNumber() { int newNumber = 20; Person p = personNumberLens.set(newNumber).f(oldPerson); assertTrue(p.name.equals(oldName)); @@ -72,7 +72,7 @@ public void setNumber() { } @Test - public void setStreet() { + public final void setStreet() { String newStreet = "First St"; Person p = personStreetLens.set(newStreet).f(oldPerson); assertTrue(p.name.equals(oldName)); diff --git a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java index 7f2b04ce..876dbff1 100644 --- a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java +++ b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java @@ -29,14 +29,14 @@ public PropertyTestRunner(Class clas) { } @Override - public Description getDescription() { + public final Description getDescription() { Description suite = Description.createSuiteDescription(clas); filteredTests.foreachDoEffect(p -> suite.addChild(p._3())); return suite; } @Override - public void run(RunNotifier notifier) { + public final void run(RunNotifier notifier) { filteredTests.foreachDoEffect(p -> { Description desc = p._3(); notifier.fireTestStarted(desc); @@ -66,7 +66,7 @@ private static CheckResult checkProperty(Property prop, Option para } @Override - public void filter(Filter filter) throws NoTestsRemainException { + public final void filter(Filter filter) throws NoTestsRemainException { filteredTests = allTests.filter(p -> filter.shouldRun(p._3())); if (filteredTests.isEmpty()) { throw new NoTestsRemainException(); } } From e47222746840562302f28d9e7eea788d8d6e23e9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:42:59 +0100 Subject: [PATCH 534/811] Avoid potential static initialization deadlock with HNil singleton --- core/src/main/java/fj/data/hlist/HList.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/data/hlist/HList.java b/core/src/main/java/fj/data/hlist/HList.java index 639c9e64..8e9b5389 100644 --- a/core/src/main/java/fj/data/hlist/HList.java +++ b/core/src/main/java/fj/data/hlist/HList.java @@ -28,15 +28,13 @@ public abstract class HList> { public abstract Apply, HCons> extender(); - private static final HNil nil = new HNil(); - /** * Returns the empty list. * * @return the empty list. */ public static HNil nil() { - return nil; + return HNil.nil; } /** @@ -285,7 +283,10 @@ public HCons> extend(final X e) { * The empty list */ public static final class HNil extends HList { - HNil() { + + private static final HNil nil = new HNil(); + + private HNil() { } public HCons extend(final E e) { From c0caae8e7fa5652c21a14a68bb1dc0b3efee3a59 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:46:58 +0100 Subject: [PATCH 535/811] Trampoline#codense should be private --- core/src/main/java/fj/control/Trampoline.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index bd69ae7a..b47a5ea7 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -107,7 +107,7 @@ public Either>, A> resume() { } @SuppressWarnings("unchecked") - protected static Codense codense(final Normal a, final F> k) { + private static Codense codense(final Normal a, final F> k) { return new Codense<>((Normal) a, (F>) k); } From 5345f6ffea3054f97ac9690bce57952d9da3fb27 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:53:33 +0100 Subject: [PATCH 536/811] Male Either projections _static_ inner classes. --- core/src/main/java/fj/data/Either.java | 90 +++++++++++++------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 77dea3c3..a4f0fc02 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -145,7 +145,7 @@ public boolean isRight() { /** * A left projection of an either value. */ - public final class LeftProjection implements Iterable { + public static final class LeftProjection implements Iterable { private final Either e; private LeftProjection(final Either e) { @@ -210,7 +210,7 @@ public A value() { * @return The value of this projection or the given argument. */ public A orValue(final F0 a) { - return isLeft() ? value() : a.f(); + return e.isLeft() ? value() : a.f(); } /** @@ -220,7 +220,7 @@ public A orValue(final F0 a) { * @return The value of this projection or the given argument. */ public A orValue(final A a) { - return isLeft() ? value() : a; + return e.isLeft() ? value() : a; } /** @@ -232,7 +232,7 @@ public A orValue(final A a) { * value. */ public A on(final F f) { - return isLeft() ? value() : f.f(e.right().value()); + return e.isLeft() ? value() : f.f(e.right().value()); } /** @@ -242,7 +242,7 @@ public A on(final F f) { * @return The unit value. */ public Unit foreach(final F f) { - if (isLeft()) + if (e.isLeft()) f.f(value()); return unit(); @@ -254,7 +254,7 @@ public Unit foreach(final F f) { * @param f The side-effect to execute. */ public void foreachDoEffect(final Effect1 f) { - if (isLeft()) + if (e.isLeft()) f.f(value()); } @@ -265,7 +265,7 @@ public void foreachDoEffect(final Effect1 f) { * @return A new either value after mapping. */ public Either map(final F f) { - return isLeft() ? new Left<>(f.f(value())) : new Right<>(e.right().value()); + return e.isLeft() ? new Left<>(f.f(value())) : new Right<>(e.right().value()); } /** @@ -275,7 +275,7 @@ public Either map(final F f) { * @return A new either value after binding. */ public Either bind(final F> f) { - return isLeft() ? f.f(value()) : new Right<>(e.right().value()); + return e.isLeft() ? f.f(value()) : new Right<>(e.right().value()); } /** @@ -295,9 +295,9 @@ public Either sequence(final Either e) { * @return An either after traversing through this projection. */ public List> traverseList(final F> f) { - return isLeft() ? + return e.isLeft() ? f.f(value()).map(Either::left) : - list(Either.right(e.right().value())); + list(right(e.right().value())); } /** @@ -307,7 +307,7 @@ public List> traverseList(final F> f) { * @return An either after traversing through this projection. */ public IO> traverseIO(final F> f) { - return isRight() ? + return e.isRight() ? IOFunctions.map(f.f(value()), Either::left) : IOFunctions.unit(Either.right(e.right().value())); } @@ -321,9 +321,9 @@ public IO> traverseIO(final F> f) { * p does not hold for the value, otherwise, returns a right in Some. */ public Option> filter(final F f) { - return isLeft() ? + return e.isLeft() ? f.f(value()) ? - Option.some(new Left<>(value())) : + some(new Left<>(value())) : Option.none() : Option.none(); } @@ -347,7 +347,7 @@ public Either apply(final Either, B> e) { * function to the value. */ public boolean forall(final F f) { - return isRight() || f.f(value()); + return e.isRight() || f.f(value()); } /** @@ -359,7 +359,7 @@ public boolean forall(final F f) { * function to the value. */ public boolean exists(final F f) { - return isLeft() && f.f(value()); + return e.isLeft() && f.f(value()); } /** @@ -368,7 +368,7 @@ public boolean exists(final F f) { * @return A single element list if this projection has a value, otherwise an empty list. */ public List toList() { - return isLeft() ? single(value()) : List.nil(); + return e.isLeft() ? single(value()) : List.nil(); } /** @@ -379,7 +379,7 @@ public List toList() { * None. */ public Option toOption() { - return isLeft() ? some(value()) : Option.none(); + return e.isLeft() ? some(value()) : Option.none(); } /** @@ -388,7 +388,7 @@ public Option toOption() { * @return A single element array if this projection has a value, otherwise an empty array. */ public Array toArray() { - if (isLeft()) { + if (e.isLeft()) { final Object[] a = new Object[1]; a[0] = value(); return mkArray(a); @@ -402,7 +402,7 @@ public Array toArray() { * @return A single element stream if this projection has a value, otherwise an empty stream. */ public Stream toStream() { - return isLeft() ? Stream.single(value()) : Stream.nil(); + return e.isLeft() ? Stream.single(value()) : Stream.nil(); } /** @@ -415,13 +415,13 @@ public Collection toCollection() { } public Option> traverseOption(F> f) { - return isLeft() ? + return e.isLeft() ? f.f(value()).map(Either::left) : some(Either.right(e.right().value())); } public Stream> traverseStream(F> f) { - return isLeft() ? + return e.isLeft() ? f.f(value()).map(Either::left) : Stream.single(Either.right(e.right().value())); } @@ -430,7 +430,7 @@ public Stream> traverseStream(F> f) { /** * A right projection of an either value. */ - public final class RightProjection implements Iterable { + public static final class RightProjection implements Iterable { private final Either e; private RightProjection(final Either e) { @@ -485,7 +485,7 @@ public B value() { * @return The value of this projection or the given argument. */ public B orValue(final F0 b) { - return isRight() ? value() : b.f(); + return e.isRight() ? value() : b.f(); } /** @@ -497,7 +497,7 @@ public B orValue(final F0 b) { * value. */ public B on(final F f) { - return isRight() ? value() : f.f(e.left().value()); + return e.isRight() ? value() : f.f(e.left().value()); } /** @@ -507,7 +507,7 @@ public B on(final F f) { * @return The unit value. */ public Unit foreach(final F f) { - if (isRight()) + if (e.isRight()) f.f(value()); return unit(); @@ -519,7 +519,7 @@ public Unit foreach(final F f) { * @param f The side-effect to execute. */ public void foreachDoEffect(final Effect1 f) { - if (isRight()) + if (e.isRight()) f.f(value()); } @@ -530,7 +530,7 @@ public void foreachDoEffect(final Effect1 f) { * @return A new either value after mapping. */ public Either map(final F f) { - return isRight() ? new Right<>(f.f(value())) : new Left<>(e.left().value()); + return e.isRight() ? new Right<>(f.f(value())) : new Left<>(e.left().value()); } /** @@ -540,7 +540,7 @@ public Either map(final F f) { * @return A new either value after binding. */ public Either bind(final F> f) { - return isRight() ? f.f(value()) : new Left<>(e.left().value()); + return e.isRight() ? f.f(value()) : new Left<>(e.left().value()); } @@ -560,9 +560,9 @@ public Either sequence(final Either e) { * @return An either after traversing through this projection. */ public List> traverseList(final F> f) { - return isRight() ? + return e.isRight() ? f.f(value()).map(Either::right) : - list(Either.left(e.left().value())); + list(left(e.left().value())); } /** @@ -572,21 +572,21 @@ public List> traverseList(final F> f) { * @return An either after traversing through this projection. */ public IO> traverseIO(final F> f) { - return isRight() ? + return e.isRight() ? IOFunctions.map(f.f(value()), Either::right) : - IOFunctions.lazy(() -> Either.left(e.left().value())); + IOFunctions.lazy(() -> left(e.left().value())); } public P1> traverseP1(final F> f) { - return isRight() ? + return e.isRight() ? f.f(value()).map(Either::right) : - p(Either.left(e.left().value())); + p(left(e.left().value())); } public Option> traverseOption(final F> f) { - return isRight() ? + return e.isRight() ? f.f(value()).map(Either::right) : - some(Either.left(e.left().value())); + some(left(e.left().value())); } /** @@ -598,9 +598,9 @@ public Option> traverseOption(final F> f) { * p does not hold for the value, otherwise, returns a left in Some. */ public Option> filter(final F f) { - return isRight() ? + return e.isRight() ? f.f(value()) ? - Option.some(new Right(value())) : + some(new Right(value())) : Option.none() : Option.none(); } @@ -624,7 +624,7 @@ public Either apply(final Either> e) { * function to the value. */ public boolean forall(final F f) { - return isLeft() || f.f(value()); + return e.isLeft() || f.f(value()); } /** @@ -636,7 +636,7 @@ public boolean forall(final F f) { * function to the value. */ public boolean exists(final F f) { - return isRight() && f.f(value()); + return e.isRight() && f.f(value()); } /** @@ -645,7 +645,7 @@ public boolean exists(final F f) { * @return A single element list if this projection has a value, otherwise an empty list. */ public List toList() { - return isRight() ? single(value()) : List.nil(); + return e.isRight() ? single(value()) : List.nil(); } /** @@ -656,7 +656,7 @@ public List toList() { * None. */ public Option toOption() { - return isRight() ? some(value()) : Option.none(); + return e.isRight() ? some(value()) : Option.none(); } /** @@ -665,7 +665,7 @@ public Option toOption() { * @return A single element array if this projection has a value, otherwise an empty array. */ public Array toArray() { - if (isRight()) { + if (e.isRight()) { final Object[] a = new Object[1]; a[0] = value(); return mkArray(a); @@ -679,7 +679,7 @@ public Array toArray() { * @return A single element stream if this projection has a value, otherwise an empty stream. */ public Stream toStream() { - return isRight() ? Stream.single(value()) : Stream.nil(); + return e.isRight() ? Stream.single(value()) : Stream.nil(); } /** @@ -692,7 +692,7 @@ public Collection toCollection() { } public Stream> traverseStream(F> f) { - return isRight() ? + return e.isRight() ? f.f(value()).map(Either::right) : Stream.single(left(e.left().value())); From 345fb6c8e1be735c288c7c1bef9127b2f35aae1f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 15:59:52 +0100 Subject: [PATCH 537/811] Remove confusing hiding of type parameter --- core/src/main/java/fj/data/List.java | 4 ++-- quickcheck/src/main/java/fj/test/Gen.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 15171e43..cfd95898 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -943,7 +943,7 @@ public final List sort(final Ord o) { else if (tail().isEmpty()) return this; else { - final class Merge { + final class Merge { List merge(List xs, List ys, final Ord o) { final Buffer buf = empty(); @@ -975,7 +975,7 @@ List merge(List xs, List ys, final Ord o) { } final P2, List> s = splitAt(length() / 2); - return new Merge().merge(s._1().sort(o), s._2().sort(o), o); + return new Merge().merge(s._1().sort(o), s._2().sort(o), o); } } diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 0ffed76a..24e855a8 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -409,7 +409,7 @@ public static Gen join(final Gen> g) { */ public static Gen frequency(final List>> gs) { final class Pick { - Gen pick(final int n, final List>> gs) { + Gen pick(final int n, final List>> gs) { if(gs.isEmpty()) return fail(); else { @@ -421,7 +421,7 @@ Gen pick(final int n, final List>> gs) { final F>, Integer> f = __1(); - return choose(1, intAdditionMonoid.sumLeft(gs.map(f))).bind(i -> new Pick().pick(i, gs)); + return choose(1, intAdditionMonoid.sumLeft(gs.map(f))).bind(i -> new Pick().pick(i, gs)); } /** From d784b7f7ee1e5068d934a36a7b211e9974d53e9a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Mar 2016 16:09:45 +0100 Subject: [PATCH 538/811] unwrap redondant function application --- core/src/main/java/fj/control/Trampoline.java | 2 +- core/src/main/java/fj/data/Array.java | 2 +- core/src/main/java/fj/data/IOFunctions.java | 2 +- core/src/main/java/fj/data/Option.java | 2 +- core/src/main/java/fj/data/State.java | 2 +- core/src/main/java/fj/data/vector/V.java | 2 +- quickcheck/src/main/java/fj/test/Gen.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index b47a5ea7..cd477dd0 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -56,7 +56,7 @@ public Either>, A> resume() { // WARNING: In JDK 8, update 25 (current version) the following code is a // workaround for an internal JDK compiler error, likely due to // https:bugs.openjdk.java.net/browse/JDK-8062253. - F, Trampoline> f = o -> o.foldNormal(cont::f, t -> t._1().bind(cont)); + F, Trampoline> f = o -> o.foldNormal(cont, t -> t._1().bind(cont)); F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); return ot.fold(f, g); }), o -> P.lazy(() -> cont.f(o)))); diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 75dd3c3a..b6538ba5 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -529,7 +529,7 @@ public Array bind(final Array sb, final F2 f) { * @return A new array after applying the given array of functions through this array. */ public Array apply(final Array> lf) { - return lf.bind(f -> map(f::f)); + return lf.bind(f -> map(f)); } /** diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 1440b692..92263d09 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -417,7 +417,7 @@ public static IO> sequenceWhile(final Stream> stream, final } public static IO apply(IO io, IO> iof) { - return bind(iof, f -> map(io, f::f)); + return bind(iof, f -> map(io, f)); } public static IO liftM2(IO ioa, IO iob, F2 f) { diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index a74d2495..4cdb411f 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -460,7 +460,7 @@ public final Validation> traverseValidation(F Option apply(final Option> of) { - return of.bind(f -> map(f::f)); + return of.bind(f -> map(f)); } /** diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index e0724373..3128ae6c 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -93,7 +93,7 @@ public State withs(F f) { } public static State gets(F f) { - return State.init().map(f::f); + return State.init().map(f); } /** diff --git a/core/src/main/java/fj/data/vector/V.java b/core/src/main/java/fj/data/vector/V.java index 57249ac8..70d60f58 100644 --- a/core/src/main/java/fj/data/vector/V.java +++ b/core/src/main/java/fj/data/vector/V.java @@ -35,7 +35,7 @@ public static V2 v(final A a1, final A a2) { * @return The vector-2. */ public static V2 v(final F0 a1, final F0 a2) { - return V2.p(P.lazy(a1::f, a2::f)); + return V2.p(P.lazy(a1, a2)); } /** diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 24e855a8..6db7b304 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -276,7 +276,7 @@ public Gen bind(final Gen gb, final Gen gc, final Gen g * @return A new generator after function application. */ public Gen apply(final Gen> gf) { - return gf.bind(f1 -> map(f1::f)); + return gf.bind(f1 -> map(f1)); } /** From 3107a2f11f59f5b0dbf8226604e513908c210fd1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 9 May 2016 23:19:30 +0200 Subject: [PATCH 539/811] add unit tests for IOFunctions#bracket --- .../test/java/fj/data/IOFunctionsTest.java | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 core/src/test/java/fj/data/IOFunctionsTest.java diff --git a/core/src/test/java/fj/data/IOFunctionsTest.java b/core/src/test/java/fj/data/IOFunctionsTest.java new file mode 100644 index 00000000..dcafc221 --- /dev/null +++ b/core/src/test/java/fj/data/IOFunctionsTest.java @@ -0,0 +1,64 @@ +package fj.data; + +import fj.Unit; +import org.hamcrest.core.Is; +import org.junit.Assert; +import org.junit.Test; + +import java.io.*; +import java.io.Reader; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.junit.Assert.*; + +public class IOFunctionsTest { + + @Test + public void bracket_happy_path() throws Exception { + AtomicBoolean closed = new AtomicBoolean(); + Reader reader = new StringReader("Read OK") { + @Override + public void close() { + super.close(); + closed.set(true); + } + }; + + IO bracketed = IOFunctions.bracket( + () -> reader, + IOFunctions.closeReader, + r -> () -> new BufferedReader(r).readLine() + ); + + Assert.assertThat(bracketed.run(), Is.is("Read OK")); + Assert.assertThat(closed.get(), Is.is(true)); + } + + @Test + public void bracket_exception_path() throws Exception { + AtomicBoolean closed = new AtomicBoolean(); + Reader reader = new StringReader("Read OK") { + @Override + public void close() { + super.close(); + closed.set(true); + throw new IllegalStateException("Should be suppressed"); + } + }; + + IO bracketed = IOFunctions.bracket( + () -> reader, + IOFunctions.closeReader, + r -> () -> {throw new IllegalArgumentException("OoO");} + ); + + try { + bracketed.run(); + fail("Exception expected"); + } catch (IllegalArgumentException e) { + Assert.assertThat(e.getMessage(), Is.is("OoO")); + } + Assert.assertThat(closed.get(), Is.is(true)); + } + +} \ No newline at end of file From 30da36c20aabfc09b2335f227683bc74d725bab4 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Fri, 13 May 2016 23:08:44 +1000 Subject: [PATCH 540/811] Add "dual" methods on Semigroup and Monoid --- core/src/main/java/fj/Monoid.java | 8 ++++++++ core/src/main/java/fj/Semigroup.java | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index af6d95f9..a7f3106f 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -11,6 +11,7 @@ import fj.data.Set; import fj.data.Stream; +import static fj.Function.flip; import static fj.Semigroup.multiply1p; import static fj.data.Stream.iterableStream; @@ -191,6 +192,13 @@ public A join(final Iterable as, final A a) { s.foldLeft1(Function.compose(sum, flip(sum).f(a))); } + /** + * Swaps the arguments when summing. + */ + public Monoid dual() { + return monoid(flip(sum), zero); + } + /** * Constructs a monoid from the given sum function and zero value, which must follow the monoidal * laws. diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 057596f5..0aa4e810 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -14,6 +14,7 @@ import java.math.BigInteger; import static fj.Function.curry; +import static fj.Function.flip; /** * Implementations must satisfy the law of associativity: @@ -97,6 +98,13 @@ static A multiply1p(F> sum, int n, A a) { } /** + /** + * Swaps the arguments when summing. + */ + public Semigroup dual() { + return semigroup(flip(sum)); + } + * Constructs a semigroup from the given function. * * @param sum The function to construct this semigroup with. From e3bf1253bfc7dc10bbd86b0dad9bcf24d5f7912f Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 16 May 2016 18:46:59 +1000 Subject: [PATCH 541/811] Add min and max Semigroup instances for Ords --- core/src/main/java/fj/Ord.java | 11 ++++++++++- core/src/main/java/fj/Semigroup.java | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index bb682ad8..41b87f94 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -15,6 +15,7 @@ import java.util.Comparator; import static fj.Function.curry; +import static fj.Semigroup.semigroup; /** * Tests for ordering between two objects. @@ -157,7 +158,15 @@ public A min(final A a1, final A a2) { */ public final F> min = curry(this::min); - public Ord reverse() { return ord(Function.flip(f)); } + public final Semigroup minSemigroup() { + return semigroup(this::min); + } + + public final Semigroup maxSemigroup() { + return semigroup(this::max); + } + + public final Ord reverse() { return ord(Function.flip(f)); } /** * Returns an order instance that uses the given equality test and ordering function. diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 0aa4e810..8557c02b 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -147,12 +147,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that yields the maximum of integers. */ - public static final Semigroup intMaximumSemigroup = semigroup(Ord.intOrd.max); + public static final Semigroup intMaximumSemigroup = Ord.intOrd.maxSemigroup(); /** * A semigroup that yields the minimum of integers. */ - public static final Semigroup intMinimumSemigroup = semigroup(Ord.intOrd.min); + public static final Semigroup intMinimumSemigroup = Ord.intOrd.minSemigroup(); /** * A semigroup that adds big integers. @@ -169,12 +169,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that yields the maximum of big integers. */ - public static final Semigroup bigintMaximumSemigroup = semigroup(Ord.bigintOrd.max); + public static final Semigroup bigintMaximumSemigroup = Ord.bigintOrd.maxSemigroup(); /** * A semigroup that yields the minimum of big integers. */ - public static final Semigroup bigintMinimumSemigroup = semigroup(Ord.bigintOrd.min); + public static final Semigroup bigintMinimumSemigroup = Ord.bigintOrd.minSemigroup(); /** * A semigroup that adds big decimals. @@ -191,12 +191,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that yields the maximum of big decimals. */ - public static final Semigroup bigDecimalMaximumSemigroup = semigroup(Ord.bigdecimalOrd.max); + public static final Semigroup bigDecimalMaximumSemigroup = Ord.bigdecimalOrd.maxSemigroup(); /** * A semigroup that yields the minimum of big decimals. */ - public static final Semigroup bigDecimalMinimumSemigroup = semigroup(Ord.bigdecimalOrd.min); + public static final Semigroup bigDecimalMinimumSemigroup = Ord.bigdecimalOrd.minSemigroup(); /** * A semigroup that multiplies natural numbers. @@ -213,12 +213,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that yields the maximum of natural numbers. */ - public static final Semigroup naturalMaximumSemigroup = semigroup(Ord.naturalOrd.max); + public static final Semigroup naturalMaximumSemigroup = Ord.naturalOrd.maxSemigroup(); /** * A semigroup that yields the minimum of natural numbers. */ - public static final Semigroup naturalMinimumSemigroup = semigroup(Ord.naturalOrd.min); + public static final Semigroup naturalMinimumSemigroup = Ord.naturalOrd.minSemigroup(); /** * A semigroup that adds longs. @@ -233,12 +233,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that yields the maximum of longs. */ - public static final Semigroup longMaximumSemigroup = semigroup(Ord.longOrd.max); + public static final Semigroup longMaximumSemigroup = Ord.longOrd.maxSemigroup(); /** * A semigroup that yields the minimum of longs. */ - public static final Semigroup longMinimumSemigroup = semigroup(Ord.longOrd.min); + public static final Semigroup longMinimumSemigroup = Ord.longOrd.minSemigroup(); /** * A semigroup that ORs booleans. From 158aabf0d73fab255cb3420f25edc513102a13cd Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 16 May 2016 20:11:41 +1000 Subject: [PATCH 542/811] Add "lift" from Semigroup into an Option Monoid --- core/src/main/java/fj/Semigroup.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 8557c02b..6377ceae 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -105,6 +105,14 @@ public Semigroup dual() { return semigroup(flip(sum)); } + /** + * Lifts the semigroup to obtain a trivial monoid. + */ + public Monoid> lift() { + return Monoid.monoid(a -> b -> Option.liftM2(sum).f(a).f(b).orElse(a).orElse(b), Option.none()); + } + + /** * Constructs a semigroup from the given function. * * @param sum The function to construct this semigroup with. From 0386eb7abd644e8017aa30b1a36a1bcb5f503a68 Mon Sep 17 00:00:00 2001 From: Brian McKenna Date: Mon, 16 May 2016 20:13:06 +1000 Subject: [PATCH 543/811] Add sumNel for Semigroup using a NonEmptyList --- core/src/main/java/fj/Semigroup.java | 6 ++++++ core/src/main/java/fj/data/NonEmptyList.java | 21 ++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 6377ceae..1427f0e5 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -98,6 +98,12 @@ static A multiply1p(F> sum, int n, A a) { } /** + * Sums the given values with left-fold. + */ + public A sumNel(final NonEmptyList as) { + return as.foldLeft1(sum); + } + /** * Swaps the arguments when summing. */ diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 013b287c..db994dc0 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -6,6 +6,7 @@ import java.util.Collection; import java.util.Iterator; +import static fj.Function.flip; import static fj.Function.identity; import static fj.data.Option.some; import static fj.data.Option.somes; @@ -87,6 +88,26 @@ public NonEmptyList append(final NonEmptyList as) { return nel(head, bb); } + /** + * Performs a right-fold reduction across this list. This function uses O(length) stack space. + */ + public final A foldRight1(final F> f) { + return reverse().foldLeft1(flip(f)); + } + + /** + * Performs a left-fold reduction across this list. This function runs in constant space. + */ + public final A foldLeft1(final F> f) { + A x = head; + + for (List xs = tail; !xs.isEmpty(); xs = xs.tail()) { + x = f.f(x).f(xs.head()); + } + + return x; + } + /** * Maps the given function across this list. * From 97b767e89e6db089c5f763971c3224b302eeb5db Mon Sep 17 00:00:00 2001 From: Clinton Selke Date: Thu, 26 May 2016 23:29:11 +1000 Subject: [PATCH 544/811] Hard memo memory reduction (#258) * hard memo memory reduction. Dereferences the computation allowing it to become garbage collected once the value has been memorised. * removed initialized --- core/src/main/java/fj/P1.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index d6809da9..1b36e0a7 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -268,19 +268,18 @@ public static P1 memo(F0 f) { } static class Memo extends P1 { - private final P1 self; - private volatile boolean initialized; + private volatile P1 self; private A value; Memo(P1 self) { this.self = self; } @Override public final A _1() { - if (!initialized) { + if (self != null) { synchronized (this) { - if (!initialized) { + if (self != null) { A a = self._1(); value = a; - initialized = true; + self = null; return a; } } From b947a4fbd033c3d8b826d666396bf88520e4cf94 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 2 Jun 2016 22:44:40 +1000 Subject: [PATCH 545/811] Added int min, int max and ord monoid. Added FingerTree empty and int max for pqueue's --- core/src/main/java/fj/Monoid.java | 8 ++++++++ .../main/java/fj/data/fingertrees/FingerTree.java | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index a7f3106f..d9bf40b5 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -401,6 +401,10 @@ public static Monoid> ioMonoid(final Monoid ma) { return monoid(Semigroup.ioSemigroup(ma.semigroup()), IOFunctions.unit(ma.zero())); } + public static final Monoid intMaxMonoid = monoid(Semigroup.intMaximumSemigroup, Integer.MIN_VALUE); + + public static final Monoid intMinMonoid = monoid(Semigroup.intMinimumSemigroup, Integer.MAX_VALUE); + /** * A monoid for the Unit value. */ @@ -416,4 +420,8 @@ public static Monoid> setMonoid(final Ord o) { return monoid(Semigroup.setSemigroup(), Set.empty(o)); } + public static Monoid ordMonoid(Ord o, A zero) { + return monoid(o.max, zero); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index f361a76a..c3dfbed9 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -5,6 +5,7 @@ import fj.data.Seq; import static fj.Monoid.intAdditionMonoid; +import static fj.Monoid.intMaxMonoid; /** * Provides 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in @@ -96,8 +97,8 @@ public final FingerTree filter(final F f) { public final boolean isEmpty() { return this instanceof Empty; } - - final Measured measured() { + + public final Measured measured() { return m; } @@ -225,7 +226,15 @@ public final P3, A, FingerTree> split1(final F FingerTree emptyIntAddition() { - return mkTree(FingerTree.measured(intAdditionMonoid, Function.constant(1))).empty(); + return empty(intAdditionMonoid, Function.constant(1)); } + public static FingerTree empty(Monoid m, F f) { + return FingerTree.mkTree(measured(m, f)).empty(); + } + + public static FingerTree> emptyIntMax() { + return empty(intMaxMonoid, (P2 p) -> p._1()); + } + } From 6e5c822d64879ba2277d3808ecf4a7b6cb90b951 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 2 Jun 2016 22:47:03 +1000 Subject: [PATCH 546/811] Added show instances and toString implementations for finger trees --- core/src/main/java/fj/Show.java | 40 +++++++++++++++++++ .../main/java/fj/data/fingertrees/Deep.java | 5 +++ .../main/java/fj/data/fingertrees/Digit.java | 3 ++ .../main/java/fj/data/fingertrees/Empty.java | 6 +++ .../main/java/fj/data/fingertrees/Four.java | 6 +++ .../main/java/fj/data/fingertrees/Node2.java | 6 +++ .../main/java/fj/data/fingertrees/Node3.java | 6 +++ .../main/java/fj/data/fingertrees/One.java | 5 +++ .../main/java/fj/data/fingertrees/Single.java | 7 ++++ .../main/java/fj/data/fingertrees/Three.java | 6 +++ .../main/java/fj/data/fingertrees/Two.java | 5 +++ .../src/main/java/fj/test/Arbitrary.java | 1 + 12 files changed, 96 insertions(+) diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 4d599693..b8bed494 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -1,6 +1,8 @@ package fj; import fj.data.*; +import fj.data.fingertrees.FingerTree; +import fj.data.fingertrees.Node; import fj.data.hlist.HList; import fj.data.vector.V2; import fj.data.vector.V3; @@ -301,6 +303,44 @@ public static Show> treeShow(final Show sa) { }); } + public static Show> digitShow(final Show sv, final Show sa) { + return show(d -> { + String s = d.match( + o -> "One(" + o.measure() + " -> " + o.value() + ")", + two -> "Two(" + two.measure() + " -> " + v2Show(sa).showS(two.values()) + ")", + three -> "Three(" + three.measure() + " -> " + v3Show(sa).showS(three.values()) + ")", + four -> "Four(" + four.measure() + " -> " + v4Show(sa).showS(four.values()) + ")" + ); + return Stream.fromString(s); + }); + } + + public static Show> nodeShow(final Show sv, final Show sa) { + return show(n -> { + final String s = n.match( + n2 -> "Node2(" + n2.measure() + " -> " + v2Show(sa).showS(n2.toVector()) + ")", + n3 -> "Node3(" + n3.measure() + " -> " + v3Show(sa).showS(n3.toVector()) + ")"); + return Stream.fromString(s); + }); + } + + public static Show> fingerTreeShow(final Show sv, final Show sa) { + + return show(ft -> { + String sep = ", "; + String str = ft.match(e -> "Empty()", + s -> "Single(" + sv.showS(ft.measure()) + " -> " + sa.showS(s.value()) + ")", + d -> "Deep(" + d.measure() + " -> " + + digitShow(sv, sa).showS(d.prefix()) + sep + + fingerTreeShow(sv, nodeShow(sv, sa)).showS(d.middle()) + sep + + digitShow(sv, sa).showS(d.suffix()) + + ")" + ); + return Stream.fromString(str); + }); + } + + public static Show> seqShow(final Show sa) { return show(s -> streamShow(sa, "Seq(", ",", ")").show(s.toStream())); } diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index ea906507..3a08c670 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -520,4 +520,9 @@ private static FingerTree>> addDigits4(final Measur }); }); } + + public String toString() { + return Show.fingerTreeShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index fb552ce9..31e7aa04 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -162,4 +162,7 @@ final Option> init() { public abstract int length(); + public String toString() { + return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); + } } diff --git a/core/src/main/java/fj/data/fingertrees/Empty.java b/core/src/main/java/fj/data/fingertrees/Empty.java index 95065aef..f4f79271 100644 --- a/core/src/main/java/fj/data/fingertrees/Empty.java +++ b/core/src/main/java/fj/data/fingertrees/Empty.java @@ -3,6 +3,7 @@ import fj.F; import fj.P2; import fj.P3; +import fj.Show; import static fj.Bottom.error; @@ -81,4 +82,9 @@ public V measure() { @Override P3, A, FingerTree> split1(final F predicate, final V acc) { throw error("Splitting an empty tree"); } + + public String toString() { + return Show.fingerTreeShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Four.java b/core/src/main/java/fj/data/fingertrees/Four.java index c66ddeca..635cb45f 100644 --- a/core/src/main/java/fj/data/fingertrees/Four.java +++ b/core/src/main/java/fj/data/fingertrees/Four.java @@ -3,6 +3,7 @@ import fj.P; import fj.P2; import fj.P3; +import fj.Show; import fj.data.Option; import fj.data.vector.V4; import fj.F; @@ -88,4 +89,9 @@ public V4 values() { public int length() { return 4; } + + public String toString() { + return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Node2.java b/core/src/main/java/fj/data/fingertrees/Node2.java index 5af121c2..4f47c7c5 100644 --- a/core/src/main/java/fj/data/fingertrees/Node2.java +++ b/core/src/main/java/fj/data/fingertrees/Node2.java @@ -2,6 +2,7 @@ import fj.P; import fj.P3; +import fj.Show; import fj.data.Option; import fj.data.vector.V2; import fj.F; @@ -66,4 +67,9 @@ public int length() { public V2 toVector() { return as; } + + public String toString() { + return Show.nodeShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Node3.java b/core/src/main/java/fj/data/fingertrees/Node3.java index 5eb9bf58..74a026c3 100644 --- a/core/src/main/java/fj/data/fingertrees/Node3.java +++ b/core/src/main/java/fj/data/fingertrees/Node3.java @@ -2,6 +2,7 @@ import fj.P; import fj.P3; +import fj.Show; import fj.data.Option; import fj.data.vector.V3; import fj.F; @@ -74,4 +75,9 @@ P3>, A, Option>> split1(final F predi public V3 toVector() { return as; } + + public String toString() { + return Show.nodeShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/One.java b/core/src/main/java/fj/data/fingertrees/One.java index d07cab60..098003d2 100644 --- a/core/src/main/java/fj/data/fingertrees/One.java +++ b/core/src/main/java/fj/data/fingertrees/One.java @@ -4,6 +4,7 @@ import fj.P; import fj.P2; import fj.P3; +import fj.Show; import fj.data.Option; import static fj.data.Option.none; @@ -54,4 +55,8 @@ public A value() { public int length() { return 1; } + + public String toString() { + return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); + } } diff --git a/core/src/main/java/fj/data/fingertrees/Single.java b/core/src/main/java/fj/data/fingertrees/Single.java index d322dcaa..951d9976 100644 --- a/core/src/main/java/fj/data/fingertrees/Single.java +++ b/core/src/main/java/fj/data/fingertrees/Single.java @@ -4,8 +4,10 @@ import fj.P; import fj.P2; import fj.P3; +import fj.Show; import static fj.P.p; +import static fj.Show.anyShow; /** * A tree with a single element. @@ -99,4 +101,9 @@ public int length() { public A value() { return a; } + + public String toString() { + return Show.fingerTreeShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Three.java b/core/src/main/java/fj/data/fingertrees/Three.java index da9f6a9e..21a2fd2c 100644 --- a/core/src/main/java/fj/data/fingertrees/Three.java +++ b/core/src/main/java/fj/data/fingertrees/Three.java @@ -3,6 +3,7 @@ import fj.P; import fj.P2; import fj.P3; +import fj.Show; import fj.data.Option; import fj.data.vector.V3; import fj.F; @@ -78,4 +79,9 @@ public V3 values() { public int length() { return 3; } + + public String toString() { + return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Two.java b/core/src/main/java/fj/data/fingertrees/Two.java index 3029fd9d..c88ff639 100644 --- a/core/src/main/java/fj/data/fingertrees/Two.java +++ b/core/src/main/java/fj/data/fingertrees/Two.java @@ -3,6 +3,7 @@ import fj.P; import fj.P2; import fj.P3; +import fj.Show; import fj.data.Option; import fj.data.vector.V2; import fj.F; @@ -70,4 +71,8 @@ public int length() { return 2; } + public String toString() { + return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index e2a00b29..19cae500 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -62,6 +62,7 @@ import java.util.HashMap; import java.util.HashSet; +import java.util.PriorityQueue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; From 45abb41b3788c0f054ecc32cd12eb1880bea9301 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 2 Jun 2016 23:15:41 +1000 Subject: [PATCH 547/811] Test show on finger trees to expose what is going on inside the finger tree --- .../fj/data/fingertrees/FingerTreeTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index 3d95d182..6ce46640 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -1,10 +1,19 @@ package fj.data.fingertrees; +import fj.Function; +import fj.P; +import fj.P2; import fj.data.List; +import fj.data.Seq; import org.junit.Test; +import static fj.Monoid.intAdditionMonoid; +import static fj.Monoid.intMaxMonoid; +import static fj.P.p; +import static fj.data.fingertrees.FingerTree.measured; import static fj.test.Property.prop; import static fj.test.Property.property; +import static java.lang.System.out; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; @@ -27,4 +36,33 @@ void validateSize(List list) { assertThat(ft.length(), equalTo(list.length())); } + @Test + public void testSeqString() { + FingerTree ft = FingerTree.emptyIntAddition(); +// out.println(ft.toString()); + String actual = List.range(1, 10).foldLeft(ft2 -> i -> { + FingerTree ft3 = ft2.snoc(i); +// out.println(ft3.toString()); + return ft3; + }, ft).toString(); + String expected = "Deep(9 -> One(1 -> 1), Deep(6 -> One(3 -> Node3(3 -> V3(2,3,4))), Empty(), One(3 -> Node3(3 -> V3(5,6,7)))), Two(2 -> V2(8,9)))"; + assertThat(actual, equalTo(expected)); + } + + @Test + public void testQueueString() { + FingerTree> ft = FingerTree.emptyIntMax(); +// out.println(ft.toString()); + String actual = List.range(1, 10).foldLeft(ft2 -> i -> { + int j = i % 2 == 0 ? 2 * i : i; + FingerTree> ft3 = ft2.snoc(P.p(j, j)); +// out.println(ft3.toString()); + return ft3; + }, ft).toString(); + String expected = "Deep(16 -> One(1 -> (1,1)), Deep(12 -> One(8 -> Node3(8 -> V3((4,4),(3,3),(8,8)))), Empty(), One(12 -> Node3(12 -> V3((5,5),(12,12),(7,7))))), Two(16 -> V2((16,16),(9,9))))"; + assertThat(actual, equalTo(expected)); + + } + + } From 8321b4f61053229fdcc84ae2e1939087b9890e0a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 3 Jun 2016 22:09:08 +1000 Subject: [PATCH 548/811] Added streaming of finger trees --- .../main/java/fj/data/fingertrees/Deep.java | 12 ++++ .../main/java/fj/data/fingertrees/Digit.java | 5 ++ .../main/java/fj/data/fingertrees/Empty.java | 5 ++ .../java/fj/data/fingertrees/FingerTree.java | 4 ++ .../main/java/fj/data/fingertrees/Four.java | 5 ++ .../main/java/fj/data/fingertrees/Node.java | 5 ++ .../main/java/fj/data/fingertrees/Node2.java | 5 ++ .../main/java/fj/data/fingertrees/Node3.java | 5 ++ .../main/java/fj/data/fingertrees/One.java | 6 ++ .../main/java/fj/data/fingertrees/Single.java | 5 ++ .../main/java/fj/data/fingertrees/Three.java | 4 ++ .../main/java/fj/data/fingertrees/Two.java | 5 ++ .../fj/data/fingertrees/FingerTreeTest.java | 64 +++++++++++++++---- 13 files changed, 116 insertions(+), 14 deletions(-) diff --git a/core/src/main/java/fj/data/fingertrees/Deep.java b/core/src/main/java/fj/data/fingertrees/Deep.java index 3a08c670..f9d6eb83 100644 --- a/core/src/main/java/fj/data/fingertrees/Deep.java +++ b/core/src/main/java/fj/data/fingertrees/Deep.java @@ -2,6 +2,7 @@ import fj.*; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; @@ -9,6 +10,7 @@ import static fj.Function.constant; import static fj.data.List.list; import static fj.Function.flip; +import static fj.data.Stream.nil; /** * A finger tree with 1-4-digits on the left and right, and a finger tree of 2-3-nodes in the middle. @@ -525,4 +527,14 @@ public String toString() { return Show.fingerTreeShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return prefix().toStream().append(() -> + middle().match( + e -> Stream.nil(), + s -> s.value().toStream(), + d -> d.toStream().bind(p -> p.toStream()) + ) + ).append(() -> suffix.toStream()); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Digit.java b/core/src/main/java/fj/data/fingertrees/Digit.java index 31e7aa04..fe76d1df 100644 --- a/core/src/main/java/fj/data/fingertrees/Digit.java +++ b/core/src/main/java/fj/data/fingertrees/Digit.java @@ -2,6 +2,7 @@ import fj.*; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; @@ -165,4 +166,8 @@ final Option> init() { public String toString() { return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); } + + public abstract Stream toStream(); + + } diff --git a/core/src/main/java/fj/data/fingertrees/Empty.java b/core/src/main/java/fj/data/fingertrees/Empty.java index f4f79271..275b1cec 100644 --- a/core/src/main/java/fj/data/fingertrees/Empty.java +++ b/core/src/main/java/fj/data/fingertrees/Empty.java @@ -4,6 +4,7 @@ import fj.P2; import fj.P3; import fj.Show; +import fj.data.Stream; import static fj.Bottom.error; @@ -87,4 +88,8 @@ public String toString() { return Show.fingerTreeShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return Stream.nil(); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index c3dfbed9..aa72f020 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -3,9 +3,11 @@ import fj.*; import fj.data.Option; import fj.data.Seq; +import fj.data.Stream; import static fj.Monoid.intAdditionMonoid; import static fj.Monoid.intMaxMonoid; +import static fj.data.Stream.nil; /** * Provides 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in @@ -237,4 +239,6 @@ public static FingerTree> emptyIntMax() { return empty(intMaxMonoid, (P2 p) -> p._1()); } + public abstract Stream toStream(); + } diff --git a/core/src/main/java/fj/data/fingertrees/Four.java b/core/src/main/java/fj/data/fingertrees/Four.java index 635cb45f..31a40d72 100644 --- a/core/src/main/java/fj/data/fingertrees/Four.java +++ b/core/src/main/java/fj/data/fingertrees/Four.java @@ -5,6 +5,7 @@ import fj.P3; import fj.Show; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V4; import fj.F; @@ -94,4 +95,8 @@ public String toString() { return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return values().toStream(); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Node.java b/core/src/main/java/fj/data/fingertrees/Node.java index c7e3e7a2..ff98b337 100644 --- a/core/src/main/java/fj/data/fingertrees/Node.java +++ b/core/src/main/java/fj/data/fingertrees/Node.java @@ -1,9 +1,11 @@ package fj.data.fingertrees; import fj.F; +import fj.P; import fj.P2; import fj.P3; import fj.data.Option; +import fj.data.Stream; import static fj.Function.curry; @@ -59,4 +61,7 @@ final Measured measured() { public abstract B match(final F, B> n2, final F, B> n3); public abstract int length(); + + public abstract Stream toStream(); + } diff --git a/core/src/main/java/fj/data/fingertrees/Node2.java b/core/src/main/java/fj/data/fingertrees/Node2.java index 4f47c7c5..56e668e7 100644 --- a/core/src/main/java/fj/data/fingertrees/Node2.java +++ b/core/src/main/java/fj/data/fingertrees/Node2.java @@ -4,6 +4,7 @@ import fj.P3; import fj.Show; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V2; import fj.F; import fj.P2; @@ -72,4 +73,8 @@ public String toString() { return Show.nodeShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return as.toStream(); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Node3.java b/core/src/main/java/fj/data/fingertrees/Node3.java index 74a026c3..c803239f 100644 --- a/core/src/main/java/fj/data/fingertrees/Node3.java +++ b/core/src/main/java/fj/data/fingertrees/Node3.java @@ -4,6 +4,7 @@ import fj.P3; import fj.Show; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V3; import fj.F; import fj.P2; @@ -80,4 +81,8 @@ public String toString() { return Show.nodeShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return as.toStream(); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/One.java b/core/src/main/java/fj/data/fingertrees/One.java index 098003d2..f3711ace 100644 --- a/core/src/main/java/fj/data/fingertrees/One.java +++ b/core/src/main/java/fj/data/fingertrees/One.java @@ -6,6 +6,7 @@ import fj.P3; import fj.Show; import fj.data.Option; +import fj.data.Stream; import static fj.data.Option.none; @@ -59,4 +60,9 @@ public int length() { public String toString() { return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); } + + public Stream toStream() { + return Stream.single(a); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Single.java b/core/src/main/java/fj/data/fingertrees/Single.java index 951d9976..57ea0897 100644 --- a/core/src/main/java/fj/data/fingertrees/Single.java +++ b/core/src/main/java/fj/data/fingertrees/Single.java @@ -5,6 +5,7 @@ import fj.P2; import fj.P3; import fj.Show; +import fj.data.Stream; import static fj.P.p; import static fj.Show.anyShow; @@ -106,4 +107,8 @@ public String toString() { return Show.fingerTreeShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return Stream.single(a); + } + } diff --git a/core/src/main/java/fj/data/fingertrees/Three.java b/core/src/main/java/fj/data/fingertrees/Three.java index 21a2fd2c..2db896b3 100644 --- a/core/src/main/java/fj/data/fingertrees/Three.java +++ b/core/src/main/java/fj/data/fingertrees/Three.java @@ -5,6 +5,7 @@ import fj.P3; import fj.Show; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V3; import fj.F; @@ -83,5 +84,8 @@ public int length() { public String toString() { return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return values().toStream(); + } } diff --git a/core/src/main/java/fj/data/fingertrees/Two.java b/core/src/main/java/fj/data/fingertrees/Two.java index c88ff639..cb8a2162 100644 --- a/core/src/main/java/fj/data/fingertrees/Two.java +++ b/core/src/main/java/fj/data/fingertrees/Two.java @@ -5,6 +5,7 @@ import fj.P3; import fj.Show; import fj.data.Option; +import fj.data.Stream; import fj.data.vector.V2; import fj.F; @@ -75,4 +76,8 @@ public String toString() { return Show.digitShow(Show.anyShow(), Show.anyShow()).showS(this); } + public Stream toStream() { + return values().toStream(); + } + } diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index 6ce46640..901c9c89 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -1,16 +1,14 @@ package fj.data.fingertrees; -import fj.Function; import fj.P; import fj.P2; +import fj.Show; import fj.data.List; -import fj.data.Seq; +import fj.data.Stream; import org.junit.Test; -import static fj.Monoid.intAdditionMonoid; -import static fj.Monoid.intMaxMonoid; import static fj.P.p; -import static fj.data.fingertrees.FingerTree.measured; +import static fj.Show.intShow; import static fj.test.Property.prop; import static fj.test.Property.property; import static java.lang.System.out; @@ -36,33 +34,71 @@ void validateSize(List list) { assertThat(ft.length(), equalTo(list.length())); } - @Test - public void testSeqString() { + public FingerTree midSeq() { FingerTree ft = FingerTree.emptyIntAddition(); -// out.println(ft.toString()); - String actual = List.range(1, 10).foldLeft(ft2 -> i -> { + // out.println(ft.toString()); + return List.range(1, 10).foldLeft(ft2 -> i -> { FingerTree ft3 = ft2.snoc(i); // out.println(ft3.toString()); return ft3; - }, ft).toString(); + }, ft); + } + + + + @Test + public void testSeqString() { +// FingerTree ft = FingerTree.emptyIntAddition(); +// out.println(ft.toString()); + String actual = midSeq().toString(); String expected = "Deep(9 -> One(1 -> 1), Deep(6 -> One(3 -> Node3(3 -> V3(2,3,4))), Empty(), One(3 -> Node3(3 -> V3(5,6,7)))), Two(2 -> V2(8,9)))"; assertThat(actual, equalTo(expected)); } - @Test - public void testQueueString() { + public FingerTree> midPriorityQueue() { FingerTree> ft = FingerTree.emptyIntMax(); // out.println(ft.toString()); - String actual = List.range(1, 10).foldLeft(ft2 -> i -> { + return List.range(1, 10).foldLeft(ft2 -> i -> { int j = i % 2 == 0 ? 2 * i : i; FingerTree> ft3 = ft2.snoc(P.p(j, j)); // out.println(ft3.toString()); return ft3; - }, ft).toString(); + }, ft); + } + + @Test + public void testQueueString() { +// FingerTree> ft = FingerTree.emptyIntMax(); +// out.println(ft.toString()); + String actual = midPriorityQueue().toString(); String expected = "Deep(16 -> One(1 -> (1,1)), Deep(12 -> One(8 -> Node3(8 -> V3((4,4),(3,3),(8,8)))), Empty(), One(12 -> Node3(12 -> V3((5,5),(12,12),(7,7))))), Two(16 -> V2((16,16),(9,9))))"; assertThat(actual, equalTo(expected)); } + @Test + public void stream() { + FingerTree ft = midSeq(); + out.println(ft); + Stream s = ft.toStream(); + System.out.println(s.toList()); + + out.println(midPriorityQueue()); + out.println(midPriorityQueue().toStream().toList()); + } + + @Test + public void split() { + + FingerTree ft = FingerTree.emptyIntAddition(); + FingerTree ft3 = List.range(1, 10).foldLeft(ft2 -> i -> ft2.snoc(i), ft); + P2, FingerTree> p = ft3.split(v -> v >= 3); + Show> fts = Show.fingerTreeShow(intShow, intShow); + Show, FingerTree>> s = Show.p2Show(fts, fts); + System.out.println(s.showS(p)); + System.out.println(p); + + + } } From a20a86ee841721b0e916d757e31a9c0409dad843 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 3 Jun 2016 22:25:57 +1000 Subject: [PATCH 549/811] Initial implementation of priority queue based on finger trees --- core/src/main/java/fj/data/PriorityQueue.java | 81 +++++++++++++++++++ .../test/java/fj/data/PriorityQueueTest.java | 30 +++++++ 2 files changed, 111 insertions(+) create mode 100644 core/src/main/java/fj/data/PriorityQueue.java create mode 100644 core/src/test/java/fj/data/PriorityQueueTest.java diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java new file mode 100644 index 00000000..35188120 --- /dev/null +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -0,0 +1,81 @@ +package fj.data; + +import fj.Equal; +import fj.F; +import fj.Monoid; +import fj.P; +import fj.P2; +import fj.P3; +import fj.data.fingertrees.FingerTree; + +/** + * Created by MarkPerry on 31 May 16. + */ +public class PriorityQueue { + + private final FingerTree> ftree; + private final Equal equal; + + private PriorityQueue(Equal e, FingerTree> ft) { + equal = e; + ftree = ft; + } + + public static PriorityQueue priorityQueue(Equal e, FingerTree> ft) { + return new PriorityQueue(e, ft); + } + + public static PriorityQueue empty(Monoid m, Equal e) { + return priorityQueue(e, FingerTree.empty(m, (P2 p) -> p._1())); + } + + public static PriorityQueue emptyInt() { + return priorityQueue(Equal.intEqual, FingerTree.empty(Monoid.intMaxMonoid, (P2 p) -> p._1())); + } + + public PriorityQueue map(F f) { + return priorityQueue(equal, + ftree.map(p2 -> p2.map2(a -> f.f(a)), + FingerTree.measured(ftree.measured().monoid(), (P2 p2) -> p2._1())) + ); + } + + public PriorityQueue filter(F f) { + return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._2()))); + } + + public boolean isEmpty() { + return ftree.isEmpty(); + } + + public Option> top() { + K top = ftree.measure(); + P2>, FingerTree>> p = ftree.split(k -> equal.eq(top, k)); + return p._2().headOption(); + } + + public PriorityQueue enqueue(K k, A a) { + return priorityQueue(equal, ftree.cons(P.p(k, a))); + } + + public PriorityQueue enqueue(List> list) { + return list.foldLeft(pq -> p -> pq.enqueue(p._1(), p._2()), this); + } + + public PriorityQueue dequeue() { + K top = ftree.measure(); + P3>, P2, FingerTree>> p = ftree.split1(k -> equal.eq(k, top)); + return priorityQueue(equal, p._1().append(p._3())); + } + + public PriorityQueue dequeue(int n) { + int i = n; + PriorityQueue result = this; + while (i > 0) { + i--; + result = result.dequeue(); + } + return result; + } + +} diff --git a/core/src/test/java/fj/data/PriorityQueueTest.java b/core/src/test/java/fj/data/PriorityQueueTest.java new file mode 100644 index 00000000..1943d2ca --- /dev/null +++ b/core/src/test/java/fj/data/PriorityQueueTest.java @@ -0,0 +1,30 @@ +package fj.data; + +import fj.Equal; +import fj.Monoid; +import org.junit.Assert; +import org.junit.Test; + +import static fj.P.p; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * Created by MarkPerry on 1 Jun 16. + */ +public class PriorityQueueTest { + + @Test + public void test1() { + PriorityQueue pq = PriorityQueue.emptyInt(); + PriorityQueue pq2 = pq.enqueue(List.list(p(1, 1))); + System.out.println(pq2.toString()); + } + + @Test + public void empty() { + PriorityQueue pq = PriorityQueue.emptyInt(); + assertThat(pq.isEmpty(), is(true)); + } + +} From d630f99b1e881aa1e511b0a7d9418d12c3fea154 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 4 Jun 2016 23:00:33 +1000 Subject: [PATCH 550/811] Added priority queue show, toStream, toString. Fixed enqueue and dequeue --- core/src/main/java/fj/Show.java | 8 ++++- core/src/main/java/fj/data/PriorityQueue.java | 16 +++++++-- .../test/java/fj/data/PriorityQueueTest.java | 33 ++++++++++++++++--- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index b8bed494..9e55a1d6 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -377,7 +377,7 @@ public static Show> treeMapShow(final Show sk, final Sho * @return A show instance for the {@link P2 tuple-2} type. */ public static Show> p2MapShow(final Show sa, final Show sb) { - return p2Show(sa, sb, "(", ":", ")"); + return p2Show(sa, sb, "(", ": ", ")"); } /** @@ -590,6 +590,12 @@ public static Show> p5Show(final Show sa, f .append(sg.show(p._7())).snoc(',').append(sh.show(p._8())).snoc(')')); } + public static Show> priorityQueueShow(Show sk, Show sv) { + return show(pq -> { + return streamShow(p2MapShow(sk, sv), "PriorityQueue(", ", ", ")").show(pq.toStream()); + }); + } + /** * A show instance for a vector-2. * diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 35188120..67abdb88 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -6,6 +6,7 @@ import fj.P; import fj.P2; import fj.P3; +import fj.Show; import fj.data.fingertrees.FingerTree; /** @@ -55,7 +56,7 @@ public Option> top() { } public PriorityQueue enqueue(K k, A a) { - return priorityQueue(equal, ftree.cons(P.p(k, a))); + return priorityQueue(equal, ftree.snoc(P.p(k, a))); } public PriorityQueue enqueue(List> list) { @@ -64,8 +65,9 @@ public PriorityQueue enqueue(List> list) { public PriorityQueue dequeue() { K top = ftree.measure(); - P3>, P2, FingerTree>> p = ftree.split1(k -> equal.eq(k, top)); - return priorityQueue(equal, p._1().append(p._3())); + P2>, FingerTree>> p = ftree.split(k -> equal.eq(k, top)); + FingerTree> right = p._2(); + return right.isEmpty() ? this : priorityQueue(equal, p._1().append(right.tail())); } public PriorityQueue dequeue(int n) { @@ -78,4 +80,12 @@ public PriorityQueue dequeue(int n) { return result; } + public Stream> toStream() { + return ftree.toStream(); + } + + public String toString() { + return Show.priorityQueueShow(Show.anyShow(), Show.anyShow()).showS(this); + } + } diff --git a/core/src/test/java/fj/data/PriorityQueueTest.java b/core/src/test/java/fj/data/PriorityQueueTest.java index 1943d2ca..7e30cfc5 100644 --- a/core/src/test/java/fj/data/PriorityQueueTest.java +++ b/core/src/test/java/fj/data/PriorityQueueTest.java @@ -1,11 +1,11 @@ package fj.data; -import fj.Equal; -import fj.Monoid; -import org.junit.Assert; +import fj.P2; import org.junit.Test; import static fj.P.p; +import static java.lang.System.out; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -18,7 +18,7 @@ public class PriorityQueueTest { public void test1() { PriorityQueue pq = PriorityQueue.emptyInt(); PriorityQueue pq2 = pq.enqueue(List.list(p(1, 1))); - System.out.println(pq2.toString()); + out.println(pq2.toString()); } @Test @@ -27,4 +27,29 @@ public void empty() { assertThat(pq.isEmpty(), is(true)); } + @Test + public void top() { + PriorityQueue pq1 = PriorityQueue.emptyInt(); + Option> o = pq1.top(); + assertThat(o, is(Option.none())); + } + + @Test + public void dequeue() { + PriorityQueue pq1 = PriorityQueue.emptyInt().enqueue(List.list( + p(3, 6), p(10, 20), p(4, 8), p(1, 2) + )); + out.println(pq1); + assertThat(pq1.toString(), equalTo("PriorityQueue((3: 6), (10: 20), (4: 8), (1: 2))")); + + PriorityQueue pq2 = PriorityQueue.emptyInt(); + PriorityQueue pq3 = pq2.dequeue(); + out.println(pq3); + assertThat(pq3.toString(), equalTo("PriorityQueue()")); + + PriorityQueue pq4 = pq1.dequeue(); + out.println(pq4); + assertThat(pq4.toString(), equalTo("PriorityQueue((3: 6), (4: 8), (1: 2))")); + } + } From 63667ffc4606be7ee33bd59b469f03ca09e4b662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 14 Feb 2016 20:14:36 -0500 Subject: [PATCH 551/811] Add JUnit for DbState --- core/build.gradle | 2 + .../test/java/fj/control/db/TestDbState.java | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 core/src/test/java/fj/control/db/TestDbState.java diff --git a/core/build.gradle b/core/build.gradle index 1a1763e7..b3e1756e 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -7,6 +7,8 @@ archivesBaseName = project.projectName dependencies { testCompile dependencyJunit + testCompile 'com.h2database:h2:1.4.191' + testCompile 'commons-dbutils:commons-dbutils:1.6' } performSigning(signingEnabled, signModule) diff --git a/core/src/test/java/fj/control/db/TestDbState.java b/core/src/test/java/fj/control/db/TestDbState.java new file mode 100644 index 00000000..00933921 --- /dev/null +++ b/core/src/test/java/fj/control/db/TestDbState.java @@ -0,0 +1,55 @@ +package fj.control.db; + +import fj.Unit; +import fj.data.Option; +import org.apache.commons.dbutils.DbUtils; +import org.junit.Test; + +import java.sql.*; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class TestDbState { + @Test + public void testWriter() throws SQLException { + final int TEN = 10; + DbState writer = DbState.writer(DbState.driverManager("jdbc:h2:mem:")); + + DB setup = new DB() { + @Override + public Unit run(Connection c) throws SQLException { + Statement s = null; + try { + s = c.createStatement(); + assertThat(s.executeUpdate("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))"), is(0)); + assertThat(s.executeUpdate("INSERT INTO TEST (ID, NAME) VALUES (" + TEN + ", 'FOO')"), is(1)); + } finally { + DbUtils.closeQuietly(s); + } + return Unit.unit(); + } + }; + DB> query = new DB>() { + @Override + public Option run(Connection c) throws SQLException { + PreparedStatement ps = null; + ResultSet rs = null; + try { + ps = c.prepareStatement("SELECT ID FROM TEST WHERE NAME = ?"); + ps.setString(1, "FOO"); + rs = ps.executeQuery(); + if (rs.next()) { + return Option.some(rs.getInt("ID")); + } else { + return Option.none(); + } + } finally { + DbUtils.closeQuietly(rs); + DbUtils.closeQuietly(ps); + } + } + }; + assertThat(writer.run(setup.bind(v -> query)).some(), is(TEN)); + } +} From b943873974c06794b61ae0ea1332d87a8da30b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 14 Feb 2016 16:04:49 -0500 Subject: [PATCH 552/811] Add JUnit for quickcheck Bool --- .../src/test/java/fj/test/TestBool.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 quickcheck/src/test/java/fj/test/TestBool.java diff --git a/quickcheck/src/test/java/fj/test/TestBool.java b/quickcheck/src/test/java/fj/test/TestBool.java new file mode 100644 index 00000000..2f29f69a --- /dev/null +++ b/quickcheck/src/test/java/fj/test/TestBool.java @@ -0,0 +1,20 @@ +package fj.test; + +import fj.data.test.PropertyAssert; +import org.junit.Test; + +import static fj.test.Arbitrary.arbBoolean; +import static fj.test.Arbitrary.arbitrary; +import static fj.test.Bool.bool; +import static fj.test.Property.property; + +public class TestBool { + + @Test + public void testBool() { + final Arbitrary arbBooleanR = arbitrary(arbBoolean.gen); + final Property p = property(arbBooleanR, arbBooleanR, (m1, m2) -> bool(m1.equals(m2)) + .implies(m1 == m2)); + PropertyAssert.assertResult(p); + } +} From e93d78a9d3116ab2f4f0a90a4174426ea858550a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 4 Jun 2016 14:44:03 -0400 Subject: [PATCH 553/811] Add tests for fj.Class --- core/src/test/java/fj/ClassTest.java | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 core/src/test/java/fj/ClassTest.java diff --git a/core/src/test/java/fj/ClassTest.java b/core/src/test/java/fj/ClassTest.java new file mode 100644 index 00000000..862c6fdd --- /dev/null +++ b/core/src/test/java/fj/ClassTest.java @@ -0,0 +1,53 @@ +package fj; + +import fj.data.List; +import fj.data.Natural; +import fj.data.Option; +import fj.data.Tree; +import org.junit.Test; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Iterator; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class ClassTest { + @Test + public void testInheritance() { + Class c = Class.clas(Natural.class); + List> l = c.inheritance(); + assertThat(l.length(), is(3)); + } + + @Test + public void testClassParameters() { + Class c = Class.clas(Option.none().getClass()); + Tree cp = c.classParameters(); + assertThat(cp.length(), is(1)); + } + + @Test + public void testSuperclassParameters() { + Class c = Class.clas(Option.none().getClass()); + Tree cp = c.superclassParameters(); + assertThat(cp.length(), is(2)); + } + + @Test + public void testInterfaceParameters() { + Class c = Class.clas(Option.none().getClass()); + List l =c.interfaceParameters(); + assertThat(l.length(), is(0)); + } + + @Test + public void testTypeParameterTree() { + Class c = Class.clas(Option.none().getClass()); + Collection coll = c.classParameters().toCollection(); + for (Type t: coll) { + assertThat(Class.typeParameterTree(t).toString(), is("Tree(class fj.data.Option$None)")); + } + } +} From 8ada2aeb55b7d8b9a3b5e1600ab164320e6b2fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 6 Jun 2016 19:31:57 -0400 Subject: [PATCH 554/811] Exclude demo subproject from Coveralls --- demo/build.gradle | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/demo/build.gradle b/demo/build.gradle index 0b83f4f8..41841cfa 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -8,7 +8,13 @@ archivesBaseName = "${project.projectName}-${project.name}" configureAllRetroLambda() dependencies { - compile project(":core") - compile project(":quickcheck") + compile project(":core") + compile project(":quickcheck") testCompile dependencyJunit } + +test { + jacoco { + enabled = false + } +} \ No newline at end of file From d011bf169667e6451e2796aef3a6df7190a70184 Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Tue, 7 Jun 2016 22:09:15 +1000 Subject: [PATCH 555/811] Remove use of Arbitrary wrapper --- .../java/fj/demo/test/EqualsHashCode.java | 9 +- .../src/test/java/fj/data/ReaderTest.java | 4 +- .../src/test/java/fj/data/TestRngState.java | 6 +- .../src/test/java/fj/data/WriterTest.java | 7 +- .../fj/data/properties/ArrayProperties.java | 5 +- .../fj/data/properties/ListProperties.java | 17 +- .../fj/data/properties/SeqProperties.java | 9 +- .../fj/data/properties/SetProperties.java | 3 +- .../fj/data/properties/StreamProperties.java | 5 +- .../fj/data/properties/TreeMapProperties.java | 5 +- .../data/properties/ValidationProperties.java | 6 +- .../src/main/java/fj/test/Arbitrary.java | 601 +++++++++--------- .../src/main/java/fj/test/Coarbitrary.java | 70 +- quickcheck/src/main/java/fj/test/Gen.java | 12 +- .../src/main/java/fj/test/Property.java | 290 ++++----- .../src/test/java/fj/data/test/TestCheck.java | 3 +- .../src/test/java/fj/data/test/TestNull.java | 3 +- .../src/test/java/fj/test/TestBool.java | 4 +- 18 files changed, 513 insertions(+), 546 deletions(-) diff --git a/demo/src/main/java/fj/demo/test/EqualsHashCode.java b/demo/src/main/java/fj/demo/test/EqualsHashCode.java index c5b0a898..a9f0ef2c 100644 --- a/demo/src/main/java/fj/demo/test/EqualsHashCode.java +++ b/demo/src/main/java/fj/demo/test/EqualsHashCode.java @@ -1,10 +1,9 @@ package fj.demo.test; import static fj.Function.curry; -import fj.test.Arbitrary; +import fj.test.Gen; import static fj.test.Arbitrary.arbByte; import static fj.test.Arbitrary.arbCharacter; -import static fj.test.Arbitrary.arbitrary; import static fj.test.Bool.bool; import static fj.test.CheckResult.summary; import fj.test.Property; @@ -55,14 +54,14 @@ public int hashCode() { public static void main(final String[] args) { // Restrictive arbitrary for Byte, produces from three possible values. - final Arbitrary arbByteR = arbitrary(arbByte.gen.map(b -> (byte)(b % 3))); + final Gen arbByteR = arbByte.map(b -> (byte)(b % 3)); // Restrictive arbitrary for String, produces from twelve (2 * 3 * 2) possible values. - final Arbitrary arbStringR = arbitrary(arbCharacter.gen.bind(arbCharacter.gen, arbCharacter.gen, curry((c1, c2, c3) -> new String(new char[]{(char)(c1 % 2 + 'a'), (char)(c2 % 3 + 'a'), (char)(c3 % 2 + 'a')})))); + final Gen arbStringR = arbCharacter.bind(arbCharacter, arbCharacter, curry((c1, c2, c3) -> new String(new char[]{(char)(c1 % 2 + 'a'), (char)(c2 % 3 + 'a'), (char)(c3 % 2 + 'a')}))); // Arbitrary for MyClass that uses the restrictive arbitraries above. // We are using the monad pattern (bind) to make this a trivial exercise. - final Arbitrary arbMyClass = arbitrary(arbByteR.gen.bind(arbStringR.gen, curry(MyClass::new))); + final Gen arbMyClass = arbByteR.bind(arbStringR, curry(MyClass::new)); // Finally the property. // if m1 equals m2, then this implies that m1's hashCode is equal to m2's hashCode. diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index 083716e9..05c858b8 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -52,7 +52,7 @@ public void testMapProp() { @Test public void testFlatMapProp() { - Arbitrary>> a = arbF(coarbInteger, arbReader()); + Gen>> a = arbF(coarbInteger, arbReader()); Property p = property( arbF(coarbInteger, arbInteger), a, @@ -108,7 +108,7 @@ public void testAssociativity() { PropertyAssert.assertResult(p); } - public Arbitrary> arbReader() { + public Gen> arbReader() { return Arbitrary.arbReader(coarbInteger, arbInteger); } diff --git a/props-core/src/test/java/fj/data/TestRngState.java b/props-core/src/test/java/fj/data/TestRngState.java index b8a17494..ddc319b9 100644 --- a/props-core/src/test/java/fj/data/TestRngState.java +++ b/props-core/src/test/java/fj/data/TestRngState.java @@ -79,11 +79,11 @@ public void testTraverse() { Assert.assertTrue(listIntEqual.eq(list, expected)); } - public static Arbitrary> arbState() { + public static Gen> arbState() { return Arbitrary.arbState(Arbitrary.arbLcgRng(), Coarbitrary.coarbLcgRng(), arbInteger); } - public static Arbitrary>> arbStateF() { + public static Gen>> arbStateF() { return arbF(Coarbitrary.coarbLcgRng(), arbP2(arbLcgRng(), arbInteger)); } @@ -91,7 +91,7 @@ public static Coarbitrary> coarbState() { return Coarbitrary.coarbState(Arbitrary.arbLcgRng(), (LcgRng s, Integer j) -> (long) (j >= 0 ? 2 * j : -2 * j + 1)); } - public static Arbitrary>> arbBindable() { + public static Gen>> arbBindable() { return arbF(coarbInteger, arbState()); } diff --git a/props-core/src/test/java/fj/data/WriterTest.java b/props-core/src/test/java/fj/data/WriterTest.java index 158a2314..a2af9952 100644 --- a/props-core/src/test/java/fj/data/WriterTest.java +++ b/props-core/src/test/java/fj/data/WriterTest.java @@ -4,6 +4,7 @@ import fj.F; import fj.data.test.PropertyAssert; import fj.test.Arbitrary; +import fj.test.Gen; import fj.test.Property; import org.junit.Assert; import org.junit.Test; @@ -62,12 +63,12 @@ public void testFlatMap() { } - public Arbitrary> arbWriterStringInt() { + public Gen> arbWriterStringInt() { return arbWriterString(arbInteger); } - public Arbitrary> arbWriterString(Arbitrary arb) { - return Arbitrary.arbitrary(arb.gen.map(a -> Writer.stringLogger().f(a))); + public Gen> arbWriterString(Gen arb) { + return arb.map(a -> Writer.stringLogger().f(a)); } // Left identity: return a >>= f == f a diff --git a/props-core/src/test/java/fj/data/properties/ArrayProperties.java b/props-core/src/test/java/fj/data/properties/ArrayProperties.java index c6aea391..feb5dcf4 100644 --- a/props-core/src/test/java/fj/data/properties/ArrayProperties.java +++ b/props-core/src/test/java/fj/data/properties/ArrayProperties.java @@ -3,7 +3,6 @@ import fj.*; import fj.data.Array; import fj.data.Either; -import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; @@ -31,9 +30,9 @@ public class ArrayProperties { private static final Equal> eq = arrayEqual(intEqual); - private static final Arbitrary, Integer>> arbArrayWithIndex = arbitrary(arbArray(arbInteger).gen + private static final Gen, Integer>> arbArrayWithIndex = arbArray(arbInteger) .filter(Array::isNotEmpty) - .bind(array -> Gen.choose(0, array.length() - 1).map(i -> P.p(array, i)))); + .bind(array -> Gen.choose(0, array.length() - 1).map(i -> P.p(array, i))); public Property isEmpty() { return property(arbArray(arbInteger), array -> prop(array.isEmpty() != array.isNotEmpty())); diff --git a/props-core/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java index 825a5f17..9724488f 100644 --- a/props-core/src/test/java/fj/data/properties/ListProperties.java +++ b/props-core/src/test/java/fj/data/properties/ListProperties.java @@ -4,7 +4,6 @@ import fj.data.List; import fj.data.Stream; import fj.data.TreeMap; -import fj.test.Arbitrary; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; import fj.test.Gen; @@ -36,9 +35,9 @@ public class ListProperties { private static final Equal> eq = listEqual(intEqual); - private static final Arbitrary, Integer>> arbListWithIndex = arbitrary(arbList(arbInteger).gen + private static final Gen, Integer>> arbListWithIndex = arbList(arbInteger) .filter(List::isNotEmpty) - .bind(list -> Gen.choose(0, list.length() - 1).map(i -> p(list, i)))); + .bind(list -> Gen.choose(0, list.length() - 1).map(i -> p(list, i))); public Property isEmpty() { return property(arbList(arbInteger), list -> prop(list.isEmpty() != list.isNotEmpty())); @@ -172,11 +171,11 @@ public Property appendLength() { @CheckParams(minSize = 2, maxSize = 10000) public Property indexTail() { - final Gen, Integer>> gen = arbList(arbInteger).gen + final Gen, Integer>> gen = arbList(arbInteger) .filter(list -> list.length() > 1) .bind(list -> Gen.choose(1, list.length() - 1).map(i -> p(list, i))); - return property(Arbitrary.arbitrary(gen), pair -> { + return property(gen, pair -> { final List list = pair._1(); final int i = pair._2(); return prop(intEqual.eq(list.index(i), list.tail().index(i - 1))); @@ -277,17 +276,17 @@ public Property groupByMonoid() { } public Property isPrefixOf() { - final Gen, Integer>> gen = arbList(arbInteger).gen.bind(list -> + final Gen, Integer>> gen = arbList(arbInteger).bind(list -> Gen.choose(0, list.length()).map(i -> p(list, i))); - return property(arbitrary(gen), pair -> prop(pair._1().take(pair._2()).isPrefixOf(intEqual, pair._1()))); + return property(gen, pair -> prop(pair._1().take(pair._2()).isPrefixOf(intEqual, pair._1()))); } public Property isSuffixOf() { - final Gen, Integer>> gen = arbList(arbInteger).gen.bind(list -> + final Gen, Integer>> gen = arbList(arbInteger).bind(list -> Gen.choose(0, list.length()).map(i -> p(list, i))); - return property(arbitrary(gen), pair -> prop(pair._1().drop(pair._2()).isSuffixOf(intEqual, pair._1()))); + return property(gen, pair -> prop(pair._1().drop(pair._2()).isSuffixOf(intEqual, pair._1()))); } public Property isPrefixOfShorter() { diff --git a/props-core/src/test/java/fj/data/properties/SeqProperties.java b/props-core/src/test/java/fj/data/properties/SeqProperties.java index 8e8076aa..eedbcc5c 100644 --- a/props-core/src/test/java/fj/data/properties/SeqProperties.java +++ b/props-core/src/test/java/fj/data/properties/SeqProperties.java @@ -6,7 +6,6 @@ import fj.data.Seq; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; -import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; import org.junit.runner.RunWith; @@ -21,9 +20,9 @@ @CheckParams(maxSize = 10000) public class SeqProperties { - private static final Arbitrary, Integer>> arbSeqWithIndex = arbitrary(arbSeq(arbInteger).gen + private static final Gen, Integer>> arbSeqWithIndex = arbSeq(arbInteger) .filter(Seq::isNotEmpty) - .bind(seq -> Gen.choose(0, seq.length() - 1).map(i -> P.p(seq, i)))); + .bind(seq -> Gen.choose(0, seq.length() - 1).map(i -> P.p(seq, i))); public Property consHead() { return property(arbSeq(arbInteger), arbInteger, (seq, n) -> prop(seq.cons(n).head().equals(n))); @@ -107,12 +106,12 @@ public Property delete() { } public Property foldLeft() { - return property(arbSeq(arbitrary(Gen.value(1))), seq -> + return property(arbSeq(Gen.value(1)), seq -> prop(seq.foldLeft((acc, i) -> acc + i, 0) == seq.length())); } public Property foldRight() { - return property(arbSeq(arbitrary(Gen.value(1))), seq -> + return property(arbSeq(Gen.value(1)), seq -> prop(seq.foldRight((i, acc) -> acc + i, 0) == seq.length())); } diff --git a/props-core/src/test/java/fj/data/properties/SetProperties.java b/props-core/src/test/java/fj/data/properties/SetProperties.java index 84c7e40c..5349b650 100644 --- a/props-core/src/test/java/fj/data/properties/SetProperties.java +++ b/props-core/src/test/java/fj/data/properties/SetProperties.java @@ -6,6 +6,7 @@ import fj.data.Set; import fj.data.Stream; import fj.test.Arbitrary; +import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; @@ -22,7 +23,7 @@ public class SetProperties { public final static int maxSize = 20; - public final static Arbitrary> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger, maxSize); + public final static Gen> as = Arbitrary.arbSet(Ord.intOrd, Arbitrary.arbInteger, maxSize); public final static Equal> eq = Equal.listEqual(Equal.intEqual); Property setToListIsSorted() { diff --git a/props-core/src/test/java/fj/data/properties/StreamProperties.java b/props-core/src/test/java/fj/data/properties/StreamProperties.java index f68df0bc..07bc7897 100644 --- a/props-core/src/test/java/fj/data/properties/StreamProperties.java +++ b/props-core/src/test/java/fj/data/properties/StreamProperties.java @@ -3,7 +3,6 @@ import fj.*; import fj.data.Either; import fj.data.Stream; -import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; @@ -170,11 +169,11 @@ public Property reverse() { @CheckParams(minSize = 2, maxSize = 10000) public Property indexTail() { - final Gen, Integer>> gen = arbStream(arbInteger).gen + final Gen, Integer>> gen = arbStream(arbInteger) .filter(stream -> stream.length() > 1) .bind(stream -> Gen.choose(1, stream.length() - 1).map(i -> P.p(stream, i))); - return property(Arbitrary.arbitrary(gen), pair -> { + return property(gen, pair -> { final Stream stream = pair._1(); final int i = pair._2(); return prop(intEqual.eq(stream.index(i), stream.tail()._1().index(i - 1))); diff --git a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java index 8dd718ee..eb71749b 100644 --- a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java +++ b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java @@ -6,7 +6,6 @@ import fj.data.List; import fj.data.Stream; import fj.data.TreeMap; -import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; @@ -33,8 +32,8 @@ public class TreeMapProperties { private static final int smallMax = 5; private static final int midMax = 20; - public static final Arbitrary> smallArbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, smallMax); - public static final Arbitrary> arbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, midMax); + public static final Gen> smallArbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, smallMax); + public static final Gen> arbTreeMapIS = arbTreeMap(intOrd, arbInteger, arbString, midMax); public static final Ord> p2Ord = Ord.p2Ord1(Ord.intOrd); Equal>> listEq = Equal.listEqual(p2Equal(intEqual, stringEqual)); diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java index d9580cc4..f5205d73 100644 --- a/props-core/src/test/java/fj/data/properties/ValidationProperties.java +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -4,7 +4,7 @@ import fj.Semigroup; import fj.data.List; import fj.data.Validation; -import fj.test.Arbitrary; +import fj.test.Gen; import fj.test.Property; import fj.test.runner.PropertyTestRunner; import org.junit.runner.RunWith; @@ -20,7 +20,7 @@ public class ValidationProperties { public Property partition() { - Arbitrary>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); + Gen>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); return Property.property(al, list -> { P2, List> p = Validation.partition(list); boolean b1 = p._1().length() + p._2().length() == list.length(); @@ -31,7 +31,7 @@ public Property partition() { } public Property sequenceNonCumulative() { - Arbitrary>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); + Gen>> al = arbList(arbValidation(arbUSASCIIString, arbInteger)); return Property.property(al, list -> { Validation, List> v = Validation.sequenceNonCumulative(list); Property p1 = implies( diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index e2a00b29..0b82108f 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -74,31 +74,11 @@ import java.util.concurrent.SynchronousQueue; /** - * The type used to generate arbitrary values of the given type parameter (A). Common - * arbitrary implementations are provided. + * Common Gen helper functions. * * @version %build.number% */ -public final class Arbitrary { - /** - * The generator associated with this arbitrary. - */ - @SuppressWarnings("PublicField") - public final Gen gen; - - private Arbitrary(final Gen gen) { - this.gen = gen; - } - - /** - * Constructs and arbitrary with the given generator. - * - * @param g The generator to construct an arbitrary with. - * @return A new arbitrary that uses the given generator. - */ - public static Arbitrary arbitrary(final Gen g) { - return new Arbitrary<>(g); - } +public final class Arbitrary { /** * An arbitrary for functions. @@ -107,30 +87,30 @@ public static Arbitrary arbitrary(final Gen g) { * @param a The arbitrary for the function codomain. * @return An arbitrary for functions. */ - public static Arbitrary> arbF(final Coarbitrary c, final Arbitrary a) { - return arbitrary(promote(new F>() { + public static Gen> arbF(final Coarbitrary c, final Gen a) { + return promote(new F>() { public Gen f(final A x) { - return c.coarbitrary(x, a.gen); + return c.coarbitrary(x, a); } - })); + }); } - public static Arbitrary> arbReader(Coarbitrary aa, Arbitrary ab) { - return arbitrary(arbF(aa, ab).gen.map(Reader::unit)); + public static Gen> arbReader(Coarbitrary aa, Gen ab) { + return arbF(aa, ab).map(Reader::unit); } /** * An arbitrary for state. */ - public static Arbitrary> arbState(Arbitrary as, Coarbitrary cs, Arbitrary aa) { - return arbitrary(arbF(cs, arbP2(as, aa)).gen.map(State::unit)); + public static Gen> arbState(Gen as, Coarbitrary cs, Gen aa) { + return arbF(cs, arbP2(as, aa)).map(State::unit); } /** * An arbitrary for the LcgRng. */ - public static Arbitrary arbLcgRng() { - return arbitrary(Arbitrary.arbLong.gen.map(LcgRng::new)); + public static Gen arbLcgRng() { + return Arbitrary.arbLong.map(LcgRng::new); } /** @@ -139,8 +119,8 @@ public static Arbitrary arbLcgRng() { * @param a The arbitrary for the function codomain. * @return An arbitrary for functions. */ - public static Arbitrary> arbFInvariant(final Arbitrary a) { - return arbitrary(a.gen.map(Function.constant())); + public static Gen> arbFInvariant(final Gen a) { + return a.map(Function.constant()); } /** @@ -151,9 +131,9 @@ public static Arbitrary> arbFInvariant(final Arbitrary a) { * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-2. */ - public static Arbitrary> arbF2(final Coarbitrary ca, final Coarbitrary cb, - final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, a)).gen.map(Function.uncurryF2())); + public static Gen> arbF2(final Coarbitrary ca, final Coarbitrary cb, + final Gen a) { + return arbF(ca, arbF(cb, a)).map(Function.uncurryF2()); } /** @@ -162,9 +142,8 @@ public static Arbitrary> arbF2(final Coarbitrary ca, fi * @param a The arbitrary for the function codomain. * @return An arbitrary for function-2. */ - public static Arbitrary> arbF2Invariant(final Arbitrary a) { - return arbitrary(a.gen.map( - compose(Function.uncurryF2(), compose(Function.constant(), Function.constant())))); + public static Gen> arbF2Invariant(final Gen a) { + return a.map(compose(Function.uncurryF2(), compose(Function.constant(), Function.constant()))); } /** @@ -176,9 +155,9 @@ public static Arbitrary> arbF2Invariant(final Arbitrary * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-3. */ - public static Arbitrary> arbF3(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc, final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, a))).gen.map(Function.uncurryF3())); + public static Gen> arbF3(final Coarbitrary ca, final Coarbitrary cb, + final Coarbitrary cc, final Gen a) { + return arbF(ca, arbF(cb, arbF(cc, a))).map(Function.uncurryF3()); } /** @@ -187,11 +166,11 @@ public static Arbitrary> arbF3(final Coarbitrary * @param a The arbitrary for the function codomain. * @return An arbitrary for function-3. */ - public static Arbitrary> arbF3Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF3(), compose(Function.constant(), + public static Gen> arbF3Invariant(final Gen a) { + return a.map(compose(Function.uncurryF3(), compose(Function.constant(), compose( Function.constant(), - Function.constant()))))); + Function.constant())))); } /** @@ -204,10 +183,10 @@ public static Arbitrary> arbF3Invariant(final Arbitr * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-4. */ - public static Arbitrary> arbF4(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc, final Coarbitrary cd, - final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, a)))).gen.map(Function.uncurryF4())); + public static Gen> arbF4(final Coarbitrary ca, final Coarbitrary cb, + final Coarbitrary cc, final Coarbitrary cd, + final Gen a) { + return arbF(ca, arbF(cb, arbF(cc, arbF(cd, a)))).map(Function.uncurryF4()); } /** @@ -216,12 +195,12 @@ public static Arbitrary> arbF4(final Coarbitra * @param a The arbitrary for the function codomain. * @return An arbitrary for function-4. */ - public static Arbitrary> arbF4Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF4(), + public static Gen> arbF4Invariant(final Gen a) { + return a.map(compose(Function.uncurryF4(), compose(Function.constant(), compose(Function.constant(), compose(Function.constant(), - Function.constant())))))); + Function.constant()))))); } /** @@ -235,14 +214,13 @@ public static Arbitrary> arbF4Invariant(final * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-5. */ - public static Arbitrary> arbF5(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Arbitrary a) { - return arbitrary( - arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, a))))).gen.map(Function.uncurryF5())); + public static Gen> arbF5(final Coarbitrary ca, + final Coarbitrary cb, + final Coarbitrary cc, + final Coarbitrary cd, + final Coarbitrary ce, + final Gen a) { + return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, a))))).map(Function.uncurryF5()); } /** @@ -251,13 +229,13 @@ public static Arbitrary> arbF4Invariant(final * @param a The arbitrary for the function codomain. * @return An arbitrary for function-5. */ - public static Arbitrary> arbF5Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF5(), + public static Gen> arbF5Invariant(final Gen a) { + return a.map(compose(Function.uncurryF5(), compose(Function.constant(), compose(Function.constant(), compose(Function.constant(), compose(Function.constant(), - Function.constant()))))))); + Function.constant())))))); } /** @@ -272,15 +250,15 @@ public static Arbitrary> arbF4Invariant(final * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-6. */ - public static Arbitrary> arbF6(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, a)))))).gen.map( - Function.uncurryF6())); + public static Gen> arbF6(final Coarbitrary ca, + final Coarbitrary cb, + final Coarbitrary cc, + final Coarbitrary cd, + final Coarbitrary ce, + final Coarbitrary cf, + final Gen a) { + return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, a)))))).map( + Function.uncurryF6()); } /** @@ -289,14 +267,14 @@ public static Arbitrary> arbF4Invariant(final * @param a The arbitrary for the function codomain. * @return An arbitrary for function-6. */ - public static Arbitrary> arbF6Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF6(), + public static Gen> arbF6Invariant(final Gen a) { + return a.map(compose(Function.uncurryF6(), compose(Function.>>>>>constant(), compose(Function.>>>>constant(), compose(Function.>>>constant(), compose(Function.>>constant(), compose(Function.>constant(), - Function.constant())))))))); + Function.constant()))))))); } /** @@ -312,16 +290,16 @@ public static Arbitrary> arbF4Invariant(final * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-7. */ - public static Arbitrary> arbF7(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Coarbitrary cg, - final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, a))))))).gen.map( - Function.uncurryF7())); + public static Gen> arbF7(final Coarbitrary ca, + final Coarbitrary cb, + final Coarbitrary cc, + final Coarbitrary cd, + final Coarbitrary ce, + final Coarbitrary cf, + final Coarbitrary cg, + final Gen a) { + return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, a))))))).map( + Function.uncurryF7()); } /** @@ -330,15 +308,15 @@ public static Arbitrary> arbF4Invariant(final * @param a The arbitrary for the function codomain. * @return An arbitrary for function-7. */ - public static Arbitrary> arbF7Invariant(final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF7(), + public static Gen> arbF7Invariant(final Gen a) { + return a.map(compose(Function.uncurryF7(), compose(Function.>>>>>>constant(), compose(Function.>>>>>constant(), compose(Function.>>>>constant(), compose(Function.>>>constant(), compose(Function.>>constant(), compose(Function.>constant(), - Function.constant()))))))))); + Function.constant())))))))); } /** @@ -355,17 +333,17 @@ public static Arbitrary> arbF4Invariant(final * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-8. */ - public static Arbitrary> arbF8(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Coarbitrary cg, - final Coarbitrary ch, - final Arbitrary a) { - return arbitrary(arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, arbF(ch, a)))))))).gen.map( - Function.uncurryF8())); + public static Gen> arbF8(final Coarbitrary ca, + final Coarbitrary cb, + final Coarbitrary cc, + final Coarbitrary cd, + final Coarbitrary ce, + final Coarbitrary cf, + final Coarbitrary cg, + final Coarbitrary ch, + final Gen a) { + return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, arbF(ch, a)))))))).map( + Function.uncurryF8()); } /** @@ -374,9 +352,9 @@ public static Arbitrary> arbF4Invariant(final * @param a The arbitrary for the function codomain. * @return An arbitrary for function-8. */ - public static Arbitrary> arbF8Invariant( - final Arbitrary a) { - return arbitrary(a.gen.map(compose(Function.uncurryF8(), + public static Gen> arbF8Invariant( + final Gen a) { + return a.map(compose(Function.uncurryF8(), compose(Function.>>>>>>>constant(), compose(Function.>>>>>>constant(), compose(Function.>>>>>constant(), @@ -386,25 +364,25 @@ public static Arbitrary> arbF4Invariant(final compose( Function.>>constant(), compose(Function.>constant(), - Function.constant())))))))))); + Function.constant()))))))))); } /** * An arbitrary implementation for boolean values. */ - public static final Arbitrary arbBoolean = arbitrary(elements(true, false)); + public static final Gen arbBoolean = elements(true, false); /** * An arbitrary implementation for integer values. */ - public static final Arbitrary arbInteger = arbitrary(sized(i -> choose(-i, i))); + public static final Gen arbInteger = sized(i -> choose(-i, i)); /** * An arbitrary implementation for integer values that checks boundary values (0, 1, -1, * max, min, max - 1, min + 1) with a frequency of 1% each then generates from {@link * #arbInteger} the remainder of the time (93%). */ - public static final Arbitrary arbIntegerBoundaries = arbitrary(sized(new F>() { + public static final Gen arbIntegerBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value(0)), @@ -414,22 +392,22 @@ public Gen f(final Integer i) { p(1, value(Integer.MIN_VALUE)), p(1, value(Integer.MAX_VALUE - 1)), p(1, value(Integer.MIN_VALUE + 1)), - p(93, arbInteger.gen))); + p(93, arbInteger))); } - })); + }); /** * An arbitrary implementation for long values. */ - public static final Arbitrary arbLong = - arbitrary(arbInteger.gen.bind(arbInteger.gen, i1 -> i2 -> (long) i1 << 32L & i2)); + public static final Gen arbLong = + arbInteger.bind(arbInteger, i1 -> i2 -> (long) i1 << 32L & i2); /** * An arbitrary implementation for long values that checks boundary values (0, 1, -1, max, * min, max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbLong} * the remainder of the time (93%). */ - public static final Arbitrary arbLongBoundaries = arbitrary(sized(new F>() { + public static final Gen arbLongBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value(0L)), @@ -439,21 +417,21 @@ public Gen f(final Integer i) { p(1, value(Long.MIN_VALUE)), p(1, value(Long.MAX_VALUE - 1L)), p(1, value(Long.MIN_VALUE + 1L)), - p(93, arbLong.gen))); + p(93, arbLong))); } - })); + }); /** * An arbitrary implementation for byte values. */ - public static final Arbitrary arbByte = arbitrary(arbInteger.gen.map(i -> (byte) i.intValue())); + public static final Gen arbByte = arbInteger.map(i -> (byte) i.intValue()); /** * An arbitrary implementation for byte values that checks boundary values (0, 1, -1, max, * min, max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbByte} * the remainder of the time (93%). */ - public static final Arbitrary arbByteBoundaries = arbitrary(sized(new F>() { + public static final Gen arbByteBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value((byte) 0)), @@ -463,21 +441,21 @@ public Gen f(final Integer i) { p(1, value(Byte.MIN_VALUE)), p(1, value((byte) (Byte.MAX_VALUE - 1))), p(1, value((byte) (Byte.MIN_VALUE + 1))), - p(93, arbByte.gen))); + p(93, arbByte))); } - })); + }); /** * An arbitrary implementation for short values. */ - public static final Arbitrary arbShort = arbitrary(arbInteger.gen.map(i -> (short) i.intValue())); + public static final Gen arbShort = arbInteger.map(i -> (short) i.intValue()); /** * An arbitrary implementation for short values that checks boundary values (0, 1, -1, max, * min, max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbShort} * the remainder of the time (93%). */ - public static final Arbitrary arbShortBoundaries = arbitrary(sized(new F>() { + public static final Gen arbShortBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value((short) 0)), @@ -487,42 +465,42 @@ public Gen f(final Integer i) { p(1, value(Short.MIN_VALUE)), p(1, value((short) (Short.MAX_VALUE - 1))), p(1, value((short) (Short.MIN_VALUE + 1))), - p(93, arbShort.gen))); + p(93, arbShort))); } - })); + }); /** * An arbitrary implementation for character values. */ - public static final Arbitrary arbCharacter = arbitrary(choose(0, 65536).map(i -> (char) i.intValue())); + public static final Gen arbCharacter = choose(0, 65536).map(i -> (char) i.intValue()); /** * An arbitrary implementation for character values that checks boundary values (max, min, * max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbCharacter} * the remainder of the time (96%). */ - public static final Arbitrary arbCharacterBoundaries = arbitrary(sized(new F>() { + public static final Gen arbCharacterBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value(Character.MIN_VALUE)), p(1, value((char) (Character.MIN_VALUE + 1))), p(1, value(Character.MAX_VALUE)), p(1, value((char) (Character.MAX_VALUE - 1))), - p(95, arbCharacter.gen))); + p(95, arbCharacter))); } - })); + }); /** * An arbitrary implementation for double values. */ - public static final Arbitrary arbDouble = arbitrary(sized(i -> choose((double) -i, i))); + public static final Gen arbDouble = sized(i -> choose((double) -i, i)); /** * An arbitrary implementation for double values that checks boundary values (0, 1, -1, max, * min, min (normal), NaN, -infinity, infinity, max - 1) with a frequency of 1% each then * generates from {@link #arbDouble} the remainder of the time (91%). */ - public static final Arbitrary arbDoubleBoundaries = arbitrary(sized(new F>() { + public static final Gen arbDoubleBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value(0D)), @@ -534,21 +512,21 @@ public Gen f(final Integer i) { p(1, value(Double.NEGATIVE_INFINITY)), p(1, value(Double.POSITIVE_INFINITY)), p(1, value(Double.MAX_VALUE - 1D)), - p(91, arbDouble.gen))); + p(91, arbDouble))); } - })); + }); /** * An arbitrary implementation for float values. */ - public static final Arbitrary arbFloat = arbitrary(arbDouble.gen.map(d -> (float) d.doubleValue())); + public static final Gen arbFloat = arbDouble.map(d -> (float) d.doubleValue()); /** * An arbitrary implementation for float values that checks boundary values (0, 1, -1, max, * min, NaN, -infinity, infinity, max - 1) with a frequency of 1% each then generates from * {@link #arbFloat} the remainder of the time (91%). */ - public static final Arbitrary arbFloatBoundaries = arbitrary(sized(new F>() { + public static final Gen arbFloatBoundaries = sized(new F>() { @SuppressWarnings("unchecked") public Gen f(final Integer i) { return frequency(list(p(1, value(0F)), @@ -560,41 +538,41 @@ public Gen f(final Integer i) { p(1, value(Float.NEGATIVE_INFINITY)), p(1, value(Float.POSITIVE_INFINITY)), p(1, value(Float.MAX_VALUE - 1F)), - p(91, arbFloat.gen))); + p(91, arbFloat))); } - })); + }); /** * An arbitrary implementation for string values. */ - public static final Arbitrary arbString = - arbitrary(arbList(arbCharacter).gen.map(List::asString)); + public static final Gen arbString = + arbList(arbCharacter).map(List::asString); /** * An arbitrary implementation for string values with characters in the US-ASCII range. */ - public static final Arbitrary arbUSASCIIString = - arbitrary(arbList(arbCharacter).gen.map(cs -> asString(cs.map(c -> (char) (c % 128))))); + public static final Gen arbUSASCIIString = + arbList(arbCharacter).map(cs -> asString(cs.map(c -> (char) (c % 128)))); /** * An arbitrary implementation for string values with alpha-numeric characters. */ - public static final Arbitrary arbAlphaNumString = - arbitrary(arbList(arbitrary(elements(range(charEnumerator, 'a', 'z').append( + public static final Gen arbAlphaNumString = + arbList(elements(range(charEnumerator, 'a', 'z').append( range(charEnumerator, 'A', 'Z')).append( - range(charEnumerator, '0', '9')).toArray().array(Character[].class)))).gen.map(asString())); + range(charEnumerator, '0', '9')).toArray().array(Character[].class))).map(asString()); /** * An arbitrary implementation for string buffer values. */ - public static final Arbitrary arbStringBuffer = - arbitrary(arbString.gen.map(StringBuffer::new)); + public static final Gen arbStringBuffer = + arbString.map(StringBuffer::new); /** * An arbitrary implementation for string builder values. */ - public static final Arbitrary arbStringBuilder = - arbitrary(arbString.gen.map(StringBuilder::new)); + public static final Gen arbStringBuilder = + arbString.map(StringBuilder::new); /** * Returns an arbitrary implementation for generators. @@ -602,13 +580,13 @@ public Gen f(final Integer i) { * @param aa an arbitrary implementation for the type over which the generator is defined. * @return An arbitrary implementation for generators. */ - public static Arbitrary> arbGen(final Arbitrary aa) { - return arbitrary(sized(i -> { + public static Gen> arbGen(final Gen aa) { + return sized(i -> { if (i == 0) return fail(); else - return aa.gen.map(Gen::value).resize(i - 1); - })); + return aa.map(Gen::value).resize(i - 1); + }); } /** @@ -617,10 +595,10 @@ public static Arbitrary> arbGen(final Arbitrary aa) { * @param aa an arbitrary implementation for the type over which the optional value is defined. * @return An arbitrary implementation for optional values. */ - public static Arbitrary> arbOption(final Arbitrary aa) { - return arbitrary(sized(i -> i == 0 ? + public static Gen> arbOption(final Gen aa) { + return sized(i -> i == 0 ? value(Option.none()) : - aa.gen.map(Option::some).resize(i - 1))); + aa.map(Option::some).resize(i - 1)); } /** @@ -633,10 +611,10 @@ public static Arbitrary> arbOption(final Arbitrary aa) { * @return An arbitrary implementation for the disjoint union. */ @SuppressWarnings("unchecked") - public static Arbitrary> arbEither(final Arbitrary aa, final Arbitrary ab) { - final Gen> left = aa.gen.map(Either::left); - final Gen> right = ab.gen.map(Either::right); - return arbitrary(oneOf(list(left, right))); + public static Gen> arbEither(final Gen aa, final Gen ab) { + final Gen> left = aa.map(Either::left); + final Gen> right = ab.map(Either::right); + return oneOf(list(left, right)); } /** @@ -645,47 +623,47 @@ public static Arbitrary> arbEither(final Arbitrary aa, fi * @param aa An arbitrary implementation for the type over which the list is defined. * @return An arbitrary implementation for lists. */ - public static Arbitrary> arbList(final Arbitrary aa) { - return arbitrary(listOf(aa.gen)); + public static Gen> arbList(final Gen aa) { + return listOf(aa); } /** * Returns an arbitrary list of integers. */ - public static Arbitrary> arbListInteger() { - return arbitrary(listOf(arbInteger.gen)); + public static Gen> arbListInteger() { + return listOf(arbInteger); } /** * Returns an arbitrary list of strings. */ - public static Arbitrary> arbListString() { - return arbitrary(listOf(arbString.gen)); + public static Gen> arbListString() { + return listOf(arbString); } /** * Returns an arbitrary list of booleans. */ - public static Arbitrary> arbListBoolean() { - return arbitrary(listOf(arbBoolean.gen)); + public static Gen> arbListBoolean() { + return listOf(arbBoolean); } /** * Returns an arbitrary list of doubles. */ - public static Arbitrary> arbListDouble() { - return arbitrary(listOf(arbDouble.gen)); + public static Gen> arbListDouble() { + return listOf(arbDouble); } - public static Arbitrary> arbNonEmptyList(final Arbitrary aa) { - return arbitrary(Gen.listOf1(aa.gen).map(list -> NonEmptyList.fromList(list).some())); + public static Gen> arbNonEmptyList(final Gen aa) { + return Gen.listOf1(aa).map(list -> NonEmptyList.fromList(list).some()); } /** * Returns an arbitrary Validation for the given arbitrary parameters. */ - public static Arbitrary> arbValidation(final Arbitrary aa, final Arbitrary ab) { - return arbitrary(arbBoolean.gen.bind(bool -> bool ? ab.gen.map(Validation::success) : aa.gen.map(Validation::fail))); + public static Gen> arbValidation(final Gen aa, final Gen ab) { + return arbBoolean.bind(bool -> bool ? ab.map(Validation::success) : aa.map(Validation::fail)); } /** @@ -694,8 +672,8 @@ public static Arbitrary> arbValidation(final Arbitrary Arbitrary> arbStream(final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(List::toStream)); + public static Gen> arbStream(final Gen aa) { + return arbList(aa).map(List::toStream); } /** @@ -704,8 +682,8 @@ public static Arbitrary> arbStream(final Arbitrary aa) { * @param aa An arbitrary implementation for the type over which the array is defined. * @return An arbitrary implementation for arrays. */ - public static Arbitrary> arbArray(final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(List::toArray)); + public static Gen> arbArray(final Gen aa) { + return arbList(aa).map(List::toArray); } /** @@ -715,17 +693,16 @@ public static Arbitrary> arbArray(final Arbitrary aa) { * @return An arbitrary implementation for sequences. */ @SuppressWarnings("unchecked") - public static Arbitrary> arbSeq(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(Seq::iterableSeq)); + public static Gen> arbSeq(final Gen aa) { + return arbArray(aa).map(Seq::iterableSeq); } - public static Arbitrary> arbSet(Ord ord, final Arbitrary aa) { - return arbitrary(arbList(aa).gen.map(list -> Set.iterableSet(ord, list))); + public static Gen> arbSet(Ord ord, final Gen aa) { + return arbList(aa).map(list -> Set.iterableSet(ord, list)); } - public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, int max) { - Gen> g = choose(0, max).bind(i -> Gen.sequenceN(i, aa.gen)).map(list -> Set.iterableSet(ord, list)); - return arbitrary(g); + public static Gen> arbSet(Ord ord, final Gen aa, int max) { + return choose(0, max).bind(i -> Gen.sequenceN(i, aa)).map(list -> Set.iterableSet(ord, list)); } @@ -735,14 +712,14 @@ public static Arbitrary> arbSet(Ord ord, final Arbitrary aa, in * @param as An arbitrary used for the throwable message. * @return An arbitrary implementation for throwables. */ - public static Arbitrary arbThrowable(final Arbitrary as) { - return arbitrary(as.gen.map(Throwable::new)); + public static Gen arbThrowable(final Gen as) { + return as.map(Throwable::new); } /** * An arbitrary implementation for throwables. */ - public static final Arbitrary arbThrowable = arbThrowable(arbString); + public static final Gen arbThrowable = arbThrowable(arbString); // BEGIN java.util @@ -752,33 +729,33 @@ public static Arbitrary arbThrowable(final Arbitrary as) { * @param aa An arbitrary implementation for the type over which the array list is defined. * @return An arbitrary implementation for array lists. */ - public static Arbitrary> arbArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(Array::toJavaList)); + public static Gen> arbArrayList(final Gen aa) { + return arbArray(aa).map(Array::toJavaList); } /** * An arbitrary implementation for bit sets. */ - public static final Arbitrary arbBitSet = - arbitrary(arbList(arbBoolean).gen.map(bs -> { + public static final Gen arbBitSet = + arbList(arbBoolean).map(bs -> { final BitSet s = new BitSet(bs.length()); bs.zipIndex().foreachDoEffect(bi -> s.set(bi._2(), bi._1())); return s; - })); + }); /** * An arbitrary implementation for calendars. */ - public static final Arbitrary arbCalendar = arbitrary(arbLong.gen.map(i -> { + public static final Gen arbCalendar = arbLong.map(i -> { final Calendar c = Calendar.getInstance(); c.setTimeInMillis(i); return c; - })); + }); /** * An arbitrary implementation for dates. */ - public static final Arbitrary arbDate = arbitrary(arbLong.gen.map(Date::new)); + public static final Gen arbDate = arbLong.map(Date::new); /** * Returns an arbitrary implementation for a Java enumeration. @@ -786,8 +763,8 @@ public static Arbitrary> arbArrayList(final Arbitrary aa) { * @param clazz The type of enum to return an arbtrary of. * @return An arbitrary for instances of the supplied enum type. */ - public static > Arbitrary arbEnumValue(final Class clazz) { - return arbitrary(elements(clazz.getEnumConstants())); + public static > Gen arbEnumValue(final Class clazz) { + return elements(clazz.getEnumConstants()); } /** @@ -798,9 +775,9 @@ public static > Arbitrary arbEnumValue(final Class clazz * defined. * @return An arbitrary implementation for enum maps. */ - public static , V> Arbitrary> arbEnumMap(final Arbitrary ak, - final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(EnumMap::new)); + public static , V> Gen> arbEnumMap(final Gen ak, + final Gen av) { + return arbHashtable(ak, av).map(EnumMap::new); } /** @@ -809,19 +786,19 @@ public static , V> Arbitrary> arbEnumMap(final A * @param aa An arbitrary implementation for the type over which the enum set is defined. * @return An arbitrary implementation for enum sets. */ - public static > Arbitrary> arbEnumSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> copyOf(a.asJavaList()))); + public static > Gen> arbEnumSet(final Gen aa) { + return arbArray(aa).map(a -> copyOf(a.asJavaList())); } /** * An arbitrary implementation for gregorian calendars. */ - public static final Arbitrary arbGregorianCalendar = - arbitrary(arbLong.gen.map(i -> { + public static final Gen arbGregorianCalendar = + arbLong.map(i -> { final GregorianCalendar c = new GregorianCalendar(); c.setTimeInMillis(i); return c; - })); + }); /** * Returns an arbitrary implementation for hash maps. @@ -831,8 +808,8 @@ public static > Arbitrary> arbEnumSet(final Arbitra * defined. * @return An arbitrary implementation for hash maps. */ - public static Arbitrary> arbHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(HashMap::new)); + public static Gen> arbHashMap(final Gen ak, final Gen av) { + return arbHashtable(ak, av).map(HashMap::new); } /** @@ -841,8 +818,8 @@ public static Arbitrary> arbHashMap(final Arbitrary ak, * @param aa An arbitrary implementation for the type over which the hash set is defined. * @return An arbitrary implementation for hash sets. */ - public static Arbitrary> arbHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new HashSet<>(a.asJavaList()))); + public static Gen> arbHashSet(final Gen aa) { + return arbArray(aa).map(a -> new HashSet<>(a.asJavaList())); } /** @@ -854,14 +831,14 @@ public static Arbitrary> arbHashSet(final Arbitrary aa) { * defined. * @return An arbitrary implementation for hash tables. */ - public static Arbitrary> arbHashtable(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbList(ak).gen.bind(arbList(av).gen, ks -> vs -> { + public static Gen> arbHashtable(final Gen ak, final Gen av) { + return arbList(ak).bind(arbList(av), ks -> vs -> { final Hashtable t = new Hashtable<>(); ks.zip(vs).foreachDoEffect(kv -> t.put(kv._1(), kv._2())); return t; - })); + }); } /** @@ -873,9 +850,9 @@ public static Arbitrary> arbHashtable(final Arbitrary * are defined. * @return An arbitrary implementation for identity hash maps. */ - public static Arbitrary> arbIdentityHashMap(final Arbitrary ak, - final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(IdentityHashMap::new)); + public static Gen> arbIdentityHashMap(final Gen ak, + final Gen av) { + return arbHashtable(ak, av).map(IdentityHashMap::new); } /** @@ -887,8 +864,8 @@ public static Arbitrary> arbIdentityHashMap(final A * defined. * @return An arbitrary implementation for linked hash maps. */ - public static Arbitrary> arbLinkedHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(LinkedHashMap::new)); + public static Gen> arbLinkedHashMap(final Gen ak, final Gen av) { + return arbHashtable(ak, av).map(LinkedHashMap::new); } /** @@ -897,8 +874,8 @@ public static Arbitrary> arbLinkedHashMap(final Arbit * @param aa An arbitrary implementation for the type over which the hash set is defined. * @return An arbitrary implementation for hash sets. */ - public static Arbitrary> arbLinkedHashSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedHashSet<>(a.asJavaList()))); + public static Gen> arbLinkedHashSet(final Gen aa) { + return arbArray(aa).map(a -> new LinkedHashSet<>(a.asJavaList())); } /** @@ -907,8 +884,8 @@ public static Arbitrary> arbLinkedHashSet(final Arbitrary Arbitrary> arbLinkedList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedList<>(a.asJavaList()))); + public static Gen> arbLinkedList(final Gen aa) { + return arbArray(aa).map(a -> new LinkedList<>(a.asJavaList())); } /** @@ -917,15 +894,15 @@ public static Arbitrary> arbLinkedList(final Arbitrary aa) * @param aa An arbitrary implementation for the type over which the priority queue is defined. * @return An arbitrary implementation for priority queues. */ - public static Arbitrary> arbPriorityQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new PriorityQueue<>(a.asJavaList()))); + public static Gen> arbPriorityQueue(final Gen aa) { + return arbArray(aa).map(a -> new PriorityQueue<>(a.asJavaList())); } /** * An arbitrary implementation for properties. */ - public static final Arbitrary arbProperties = - arbitrary(arbHashtable(arbString, arbString).gen.map(ht -> { + public static final Gen arbProperties = + arbHashtable(arbString, arbString).map(ht -> { final Properties p = new Properties(); for (final Map.Entry entry : ht.entrySet()) { @@ -933,7 +910,7 @@ public static Arbitrary> arbPriorityQueue(final Arbitrary Arbitrary> arbPriorityQueue(final Arbitrary Arbitrary> arbStack(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> { + public static Gen> arbStack(final Gen aa) { + return arbArray(aa).map(a -> { final Stack s = new Stack<>(); s.addAll(a.asJavaList()); return s; - })); + }); } /** @@ -957,45 +934,45 @@ public static Arbitrary> arbStack(final Arbitrary aa) { * defined. * @return An arbitrary implementation for tree maps. */ - public static Arbitrary> arbJavaTreeMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(java.util.TreeMap::new)); + public static Gen> arbJavaTreeMap(final Gen ak, final Gen av) { + return arbHashtable(ak, av).map(java.util.TreeMap::new); } /** * Returns an arbitrary implementation for tree maps. */ - public static Arbitrary> arbTreeMap(Ord ord, Arbitrary>> al) { - return arbitrary(al.gen.map(list -> fj.data.TreeMap.iterableTreeMap(ord, list))); + public static Gen> arbTreeMap(Ord ord, Gen>> al) { + return al.map(list -> fj.data.TreeMap.iterableTreeMap(ord, list)); } /** * Returns an arbitrary implementation for tree maps. */ - public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av) { + public static Gen> arbTreeMap(Ord ord, Gen ak, Gen av) { return arbTreeMap(ord, arbList(arbP2(ak, av))); } /** * Returns an arbitrary implementation for tree maps where the map size is the given arbitrary integer. */ - public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av, Arbitrary ai) { - Gen>> gl2 = ai.gen.bind(i -> { + public static Gen> arbTreeMap(Ord ord, Gen ak, Gen av, Gen ai) { + Gen>> gl2 = ai.bind(i -> { if (i < 0) { throw Bottom.error("Undefined: arbitrary natural is negative (" + i + ")"); } - return Gen.sequenceN(Math.max(i, 0), arbP2(ak, av).gen); + return Gen.sequenceN(Math.max(i, 0), arbP2(ak, av)); }); - return arbTreeMap(ord, arbitrary(gl2)); + return arbTreeMap(ord, gl2); } /** * Returns an arbitrary implementation for tree maps where the size is less than or equal to the max size. */ - public static Arbitrary> arbTreeMap(Ord ord, Arbitrary ak, Arbitrary av, int maxSize) { + public static Gen> arbTreeMap(Ord ord, Gen ak, Gen av, int maxSize) { if (maxSize < 0) { throw Bottom.error("Undefined: arbitrary natural is negative (" + maxSize + ")"); } - return arbTreeMap(ord, ak, av, arbitrary(choose(0, maxSize))); + return arbTreeMap(ord, ak, av, choose(0, maxSize)); } /** @@ -1004,8 +981,8 @@ public static Arbitrary> arbTreeMap(Ord ord, Arb * @param aa An arbitrary implementation for the type over which the tree set is defined. * @return An arbitrary implementation for tree sets. */ - public static Arbitrary> arbTreeSet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new TreeSet<>(a.asJavaList()))); + public static Gen> arbTreeSet(final Gen aa) { + return arbArray(aa).map(a -> new TreeSet<>(a.asJavaList())); } /** @@ -1015,8 +992,8 @@ public static Arbitrary> arbTreeSet(final Arbitrary aa) { * @return An arbitrary implementation for vectors. */ @SuppressWarnings("UseOfObsoleteCollectionType") - public static Arbitrary> arbVector(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new Vector<>(a.asJavaList()))); + public static Gen> arbVector(final Gen aa) { + return arbArray(aa).map(a -> new Vector<>(a.asJavaList())); } /** @@ -1028,8 +1005,8 @@ public static Arbitrary> arbVector(final Arbitrary aa) { * defined. * @return An arbitrary implementation for weak hash maps. */ - public static Arbitrary> arbWeakHashMap(final Arbitrary ak, final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(WeakHashMap::new)); + public static Gen> arbWeakHashMap(final Gen ak, final Gen av) { + return arbHashtable(ak, av).map(WeakHashMap::new); } // END java.util @@ -1043,10 +1020,10 @@ public static Arbitrary> arbWeakHashMap(final Arbitrary * defined. * @return An arbitrary implementation for array blocking queues. */ - public static Arbitrary> arbArrayBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.bind(arbInteger.gen, arbBoolean.gen, + public static Gen> arbArrayBlockingQueue(final Gen aa) { + return arbArray(aa).bind(arbInteger, arbBoolean, a -> capacity -> fair -> new ArrayBlockingQueue(a.length() + abs(capacity), - fair, a.asJavaList()))); + fair, a.asJavaList())); } /** @@ -1058,9 +1035,9 @@ public static Arbitrary> arbArrayBlockingQueue(final A * are defined. * @return An arbitrary implementation for concurrent hash maps. */ - public static Arbitrary> arbConcurrentHashMap(final Arbitrary ak, - final Arbitrary av) { - return arbitrary(arbHashtable(ak, av).gen.map(ConcurrentHashMap::new)); + public static Gen> arbConcurrentHashMap(final Gen ak, + final Gen av) { + return arbHashtable(ak, av).map(ConcurrentHashMap::new); } /** @@ -1070,8 +1047,8 @@ public static Arbitrary> arbConcurrentHashMap(fin * defined. * @return An arbitrary implementation for concurrent linked queues. */ - public static Arbitrary> arbConcurrentLinkedQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new ConcurrentLinkedQueue<>(a.asJavaList()))); + public static Gen> arbConcurrentLinkedQueue(final Gen aa) { + return arbArray(aa).map(a -> new ConcurrentLinkedQueue<>(a.asJavaList())); } /** @@ -1081,8 +1058,8 @@ public static Arbitrary> arbConcurrentLinkedQueue(f * defined. * @return An arbitrary implementation for copy-on-write array lists. */ - public static Arbitrary> arbCopyOnWriteArrayList(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArrayList<>(a.asJavaList()))); + public static Gen> arbCopyOnWriteArrayList(final Gen aa) { + return arbArray(aa).map(a -> new CopyOnWriteArrayList<>(a.asJavaList())); } /** @@ -1092,8 +1069,8 @@ public static Arbitrary> arbCopyOnWriteArrayList(fin * defined. * @return An arbitrary implementation for copy-on-write array sets. */ - public static Arbitrary> arbCopyOnWriteArraySet(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new CopyOnWriteArraySet<>(a.asJavaList()))); + public static Gen> arbCopyOnWriteArraySet(final Gen aa) { + return arbArray(aa).map(a -> new CopyOnWriteArraySet<>(a.asJavaList())); } /** @@ -1102,8 +1079,8 @@ public static Arbitrary> arbCopyOnWriteArraySet(final * @param aa An arbitrary implementation for the type over which the delay queue is defined. * @return An arbitrary implementation for delay queues. */ - public static Arbitrary> arbDelayQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new DelayQueue<>(a.asJavaList()))); + public static Gen> arbDelayQueue(final Gen aa) { + return arbArray(aa).map(a -> new DelayQueue<>(a.asJavaList())); } /** @@ -1113,8 +1090,8 @@ public static Arbitrary> arbDelayQueue(final A * defined. * @return An arbitrary implementation for linked blocking queues. */ - public static Arbitrary> arbLinkedBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new LinkedBlockingQueue<>(a.asJavaList()))); + public static Gen> arbLinkedBlockingQueue(final Gen aa) { + return arbArray(aa).map(a -> new LinkedBlockingQueue<>(a.asJavaList())); } /** @@ -1124,8 +1101,8 @@ public static Arbitrary> arbLinkedBlockingQueue(final * defined. * @return An arbitrary implementation for priority blocking queues. */ - public static Arbitrary> arbPriorityBlockingQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.map(a -> new PriorityBlockingQueue<>(a.asJavaList()))); + public static Gen> arbPriorityBlockingQueue(final Gen aa) { + return arbArray(aa).map(a -> new PriorityBlockingQueue<>(a.asJavaList())); } /** @@ -1135,12 +1112,12 @@ public static Arbitrary> arbPriorityBlockingQueue(f * defined. * @return An arbitrary implementation for priority blocking queues. */ - public static Arbitrary> arbSynchronousQueue(final Arbitrary aa) { - return arbitrary(arbArray(aa).gen.bind(arbBoolean.gen, a -> fair -> { + public static Gen> arbSynchronousQueue(final Gen aa) { + return arbArray(aa).bind(arbBoolean, a -> fair -> { final SynchronousQueue q = new SynchronousQueue<>(fair); q.addAll(a.asJavaList()); return q; - })); + }); } // END java.util.concurrent @@ -1150,17 +1127,17 @@ public static Arbitrary> arbSynchronousQueue(final Arbit /** * An arbitrary implementation for SQL dates. */ - public static final Arbitrary arbSQLDate = arbitrary(arbLong.gen.map(java.sql.Date::new)); + public static final Gen arbSQLDate = arbLong.map(java.sql.Date::new); /** * An arbitrary implementation for SQL times. */ - public static final Arbitrary Arbitrary> arbSynchronousQueue(final Arbit /** * An arbitrary implementation for big integers. */ - public static final Arbitrary arbBigInteger = - arbitrary(arbArray(arbByte).gen.bind(arbByte.gen, a -> b -> { + public static final Gen arbBigInteger = + arbArray(arbByte).bind(arbByte, a -> b -> { final byte[] x = new byte[a.length() + 1]; for (int i = 0; i < a.array().length; i++) { @@ -1180,20 +1157,20 @@ public static Arbitrary> arbSynchronousQueue(final Arbit x[a.length()] = b; return new BigInteger(x); - })); + }); /** * An arbitrary implementation for big decimals. */ - public static final Arbitrary arbBigDecimal = - arbitrary(arbBigInteger.gen.map(BigDecimal::new)); + public static final Gen arbBigDecimal = + arbBigInteger.map(BigDecimal::new); // END java.math /** * An arbitrary implementation for locales. */ - public static final Arbitrary arbLocale = arbitrary(elements(getAvailableLocales())); + public static final Gen arbLocale = elements(getAvailableLocales()); /** * Returns an arbitrary implementation for product-1 values. @@ -1201,8 +1178,8 @@ public static Arbitrary> arbSynchronousQueue(final Arbit * @param aa An arbitrary implementation for the type over which the product-1 is defined. * @return An arbitrary implementation for product-1 values. */ - public static Arbitrary> arbP1(final Arbitrary aa) { - return arbitrary(aa.gen.map(P::p)); + public static Gen> arbP1(final Gen aa) { + return aa.map(P::p); } /** @@ -1214,8 +1191,8 @@ public static Arbitrary> arbP1(final Arbitrary aa) { * defined. * @return An arbitrary implementation for product-2 values. */ - public static Arbitrary> arbP2(final Arbitrary aa, final Arbitrary ab) { - return arbitrary(aa.gen.bind(ab.gen, a -> b -> p(a, b))); + public static Gen> arbP2(final Gen aa, final Gen ab) { + return aa.bind(ab, a -> b -> p(a, b)); } /** @@ -1229,9 +1206,9 @@ public static Arbitrary> arbP2(final Arbitrary aa, final Arbi * defined. * @return An arbitrary implementation for product-3 values. */ - public static Arbitrary> arbP3(final Arbitrary aa, final Arbitrary ab, - final Arbitrary ac) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, a -> b -> c -> p(a, b, c))); + public static Gen> arbP3(final Gen aa, final Gen ab, + final Gen ac) { + return aa.bind(ab, ac, a -> b -> c -> p(a, b, c)); } /** @@ -1247,9 +1224,9 @@ public static Arbitrary> arbP3(final Arbitrary aa, fina * defined. * @return An arbitrary implementation for product-4 values. */ - public static Arbitrary> arbP4(final Arbitrary aa, final Arbitrary ab, - final Arbitrary ac, final Arbitrary ad) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, a -> b -> c -> d -> p(a, b, c, d))); + public static Gen> arbP4(final Gen aa, final Gen ab, + final Gen ac, final Gen ad) { + return aa.bind(ab, ac, ad, a -> b -> c -> d -> p(a, b, c, d)); } /** @@ -1267,10 +1244,10 @@ public static Arbitrary> arbP4(final Arbitrary aa * defined. * @return An arbitrary implementation for product-5 values. */ - public static Arbitrary> arbP5(final Arbitrary aa, final Arbitrary ab, - final Arbitrary ac, final Arbitrary ad, - final Arbitrary ae) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, a -> b -> c -> d -> e -> p(a, b, c, d, e))); + public static Gen> arbP5(final Gen aa, final Gen ab, + final Gen ac, final Gen ad, + final Gen ae) { + return aa.bind(ab, ac, ad, ae, a -> b -> c -> d -> e -> p(a, b, c, d, e)); } /** @@ -1290,12 +1267,12 @@ public static Arbitrary> arbP5(final Arbitrary * defined. * @return An arbitrary implementation for product-6 values. */ - public static Arbitrary> arbP6(final Arbitrary aa, final Arbitrary ab, - final Arbitrary ac, final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, af.gen, - a -> b -> c -> d -> e -> f -> p(a, b, c, d, e, f))); + public static Gen> arbP6(final Gen aa, final Gen ab, + final Gen ac, final Gen ad, + final Gen ae, + final Gen af) { + return aa.bind(ab, ac, ad, ae, af, + a -> b -> c -> d -> e -> f -> p(a, b, c, d, e, f)); } /** @@ -1317,15 +1294,15 @@ public static Arbitrary> arbP5(final Arbitrary * defined. * @return An arbitrary implementation for product-7 values. */ - public static Arbitrary> arbP7(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, af.gen, ag.gen, - a -> b -> c -> d -> e -> f -> g -> p(a, b, c, d, e, f, g))); + public static Gen> arbP7(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag) { + return aa.bind(ab, ac, ad, ae, af, ag, + a -> b -> c -> d -> e -> f -> g -> p(a, b, c, d, e, f, g)); } /** @@ -1349,15 +1326,15 @@ public static Arbitrary> arbP5(final Arbitrary * defined. * @return An arbitrary implementation for product-8 values. */ - public static Arbitrary> arbP8(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, - final Arbitrary ah) { - return arbitrary(aa.gen.bind(ab.gen, ac.gen, ad.gen, ae.gen, af.gen, ag.gen, ah.gen, - a -> b -> c -> d -> e -> f -> g -> h -> p(a, b, c, d, e, f, g, h))); + public static Gen> arbP8(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah) { + return aa.bind(ab, ac, ad, ae, af, ag, ah, + a -> b -> c -> d -> e -> f -> g -> h -> p(a, b, c, d, e, f, g, h)); } } diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java index d158a90f..14c7acb4 100644 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ b/quickcheck/src/main/java/fj/test/Coarbitrary.java @@ -116,10 +116,10 @@ public Gen coarbitrary(final B b, final Gen g) { * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function. */ - public static Coarbitrary> coarbF(final Arbitrary a, final Coarbitrary c) { + public static Coarbitrary> coarbF(final Gen a, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F f, final Gen g) { - return a.gen.bind(a1 -> c.coarbitrary(f.f(a1), g)); + return a.bind(a1 -> c.coarbitrary(f.f(a1), g)); } }; } @@ -132,7 +132,7 @@ public Gen coarbitrary(final F f, final Gen g) { * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-2. */ - public static Coarbitrary> coarbF2(final Arbitrary aa, final Arbitrary ab, + public static Coarbitrary> coarbF2(final Gen aa, final Gen ab, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F2 f, final Gen g) { @@ -150,8 +150,8 @@ public Gen coarbitrary(final F2 f, final Gen g) { * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-3. */ - public static Coarbitrary> coarbF3(final Arbitrary aa, final Arbitrary ab, - final Arbitrary ac, final Coarbitrary c) { + public static Coarbitrary> coarbF3(final Gen aa, final Gen ab, + final Gen ac, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F3 f, final Gen g) { return coarbF(aa, coarbF(ab, coarbF(ac, c))).coarbitrary(curry(f), g); @@ -169,8 +169,8 @@ public Gen coarbitrary(final F3 f, final Gen g) { * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-4. */ - public static Coarbitrary> coarbF4(final Arbitrary aa, final Arbitrary ab, - final Arbitrary ac, final Arbitrary ad, + public static Coarbitrary> coarbF4(final Gen aa, final Gen ab, + final Gen ac, final Gen ad, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F4 f, final Gen g) { @@ -190,11 +190,11 @@ public Gen coarbitrary(final F4 f, final Gen g) { * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-5. */ - public static Coarbitrary> coarbF5(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, + public static Coarbitrary> coarbF5(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F5 f, final Gen g) { @@ -215,12 +215,12 @@ public Gen coarbitrary(final F5 f, final Gen g) { * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-6. */ - public static Coarbitrary> coarbF6(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, + public static Coarbitrary> coarbF6(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F6 f, final Gen g) { @@ -242,13 +242,13 @@ public Gen coarbitrary(final F6 f, final Gen g) * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-7. */ - public static Coarbitrary> coarbF7(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, + public static Coarbitrary> coarbF7(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F7 f, final Gen g) { @@ -272,14 +272,14 @@ public Gen coarbitrary(final F7 f, final Gen * @param c A coarbitrary for the codomain of the function. * @return A coarbitrary for a function-8. */ - public static Coarbitrary> coarbF8(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, - final Arbitrary ah, + public static Coarbitrary> coarbF8(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah, final Coarbitrary c) { return new Coarbitrary>() { public Gen coarbitrary(final F8 f, final Gen g) { @@ -468,11 +468,11 @@ public Gen coarbitrary(LcgRng rng, Gen g) { /** * A coarbitrary for state. */ - public static Coarbitrary> coarbState(Arbitrary as, F2 f) { + public static Coarbitrary> coarbState(Gen as, F2 f) { return new Coarbitrary>() { @Override public Gen coarbitrary(State s1, Gen g) { - return as.gen.bind(r -> { + return as.bind(r -> { P2 p = s1.run(r); return variant(f.f(p._1(), p._2()), g); }); diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 6db7b304..1ea9be0a 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -50,21 +50,20 @@ class Person { * invoking the {@link #bind(F)} methods — in this case, {@link #bind(Gen , Gen , F)} the one * that takes two generator arguments}, since the class has one more than two fields (the bind * method is invoked on a generator adding the extra one to the count as they are composed). The - * class fields are of types for which there exist generators (on {@link Arbitrary} so those can be + * class fields are of types for which there exist generators (on {@link Gen} so those can be * used to compose a generator for Person:

-static Arbitrary<Person> personArbitrary() {
-  final Gen<Person> personGenerator = arbInteger.gen.bind(arbString().gen, arbBoolean().gen,
+static Gen<Person> personArbitrary() {
+  return arbInteger.bind(arbString(), arbBoolean(),
       // compose the generators
       {int age => {String name => {boolean male => new Person(age, name, male)}}};
-  return arbitrary(personGenerator);
 }
 
*

* The example above uses Java 7 closure syntax. Here is the same example using objects instead:

-static Arbitrary<Person> personArbitrary() {
-  final Gen<Person> personGenerator = arbInteger.gen.bind(arbString.gen, arbBoolean.gen,
+static Gen<Person> personArbitrary() {
+  return arbInteger.bind(arbString, arbBoolean,
       // compose the generators
       new F<Integer, F<String, F<Boolean, Person>>>() {
         public F<String, F<Boolean, Person>> f(final Integer age) {
@@ -79,7 +78,6 @@ public Person f(final Boolean male) {
           };
         }
       });
-  return arbitrary(personGenerator);
 }
 
* diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 274a7453..0f77f85e 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -443,8 +443,8 @@ public boolean failed(final Option> o) { * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static
Property propertyP(final Arbitrary aa, final Shrink sa, final F> f) { - return forall(aa.gen, sa, f); + public static Property propertyP(final Gen aa, final Shrink sa, final F> f) { + return forall(aa, sa, f); } /** @@ -457,7 +457,7 @@ public static Property propertyP(final Arbitrary aa, final Shrink sa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, final Shrink sa, final F f) { + public static Property property(final Gen aa, final Shrink sa, final F f) { return propertyP(aa, sa, P1.curry(f)); } @@ -470,7 +470,7 @@ public static Property property(final Arbitrary aa, final Shrink sa, f * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property propertyP(final Arbitrary aa, final F> f) { + public static Property propertyP(final Gen aa, final F> f) { return propertyP(aa, Shrink.empty(), f); } @@ -483,7 +483,7 @@ public static Property propertyP(final Arbitrary aa, final F Property property(final Arbitrary aa, final F f) { + public static Property property(final Gen aa, final F f) { return propertyP(aa, P1.curry(f)); } @@ -500,7 +500,7 @@ public static Property property(final Arbitrary aa, final F * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property propertyP(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F>> f) { + public static Property propertyP(final Gen aa, final Gen ab, final Shrink sa, final Shrink sb, final F>> f) { return property(aa, sa, a -> { return propertyP(ab, sb, b -> { return f.f(a).f(b); @@ -520,7 +520,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F> f) { + public static Property property(final Gen aa, final Gen ab, final Shrink sa, final Shrink sb, final F> f) { return propertyP(aa, ab, sa, sb, compose2(P.p1(), f)); } @@ -534,7 +534,7 @@ public static Property property(final Arbitrary aa, final Arbitrary * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property propertyP(final Arbitrary aa, final Arbitrary ab, final F>> f) { + public static Property propertyP(final Gen aa, final Gen ab, final F>> f) { return property(aa, a -> propertyP(ab, b -> f.f(a).f(b))); } @@ -548,7 +548,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final F> f) { + public static Property property(final Gen aa, final Gen ab, final F> f) { return propertyP(aa, ab, compose2(P.p1(), f)); } @@ -564,7 +564,7 @@ public static Property property(final Arbitrary aa, final Arbitrary * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property propertyP(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F2> f) { + public static Property propertyP(final Gen aa, final Gen ab, final Shrink sa, final Shrink sb, final F2> f) { return propertyP(aa, ab, sa, sb, curry(f)); } @@ -580,7 +580,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final Shrink sa, final Shrink sb, final F2 f) { + public static Property property(final Gen aa, final Gen ab, final Shrink sa, final Shrink sb, final F2 f) { return propertyP(aa, ab, sa, sb, compose2(P.p1(), curry(f))); } @@ -594,7 +594,7 @@ public static Property property(final Arbitrary aa, final Arbitrary * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property propertyP(final Arbitrary aa, final Arbitrary ab, final F2> f) { + public static Property propertyP(final Gen aa, final Gen ab, final F2> f) { return propertyP(aa, ab, curry(f)); } @@ -608,7 +608,7 @@ public static Property propertyP(final Arbitrary aa, final Arbitrary Property property(final Arbitrary aa, final Arbitrary ab, final F2 f) { + public static Property property(final Gen aa, final Gen ab, final F2 f) { return propertyP(aa, ab, compose2(P.p1(), curry(f))); } @@ -626,9 +626,9 @@ public static Property property(final Arbitrary aa, final Arbitrary * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, final Shrink sa, final Shrink sb, final Shrink sc, @@ -649,9 +649,9 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, final F>> f) { return property(aa, ab, a -> b -> property(ac, c -> f.f(a).f(b).f(c))); } @@ -670,9 +670,9 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, final Shrink sa, final Shrink sb, final Shrink sc, @@ -691,9 +691,9 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, final F3 f) { return property(aa, ab, ac, curry(f)); } @@ -714,10 +714,10 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, final Shrink sa, final Shrink sb, final Shrink sc, @@ -740,10 +740,10 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, final F>>> f) { return property(aa, ab, ac, a -> b -> c -> property(ad, d -> f.f(a).f(b).f(c).f(d))); } @@ -764,10 +764,10 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, final Shrink sa, final Shrink sb, final Shrink sc, @@ -788,10 +788,10 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, final F4 f) { return property(aa, ab, ac, ad, curry(f)); } @@ -814,11 +814,11 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, final Shrink sa, final Shrink sb, final Shrink sc, @@ -843,11 +843,11 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, final F>>>> f) { return property(aa, ab, ac, ad, a -> b -> c -> d -> property(ae, e -> f.f(a).f(b).f(c).f(d).f(e))); } @@ -870,11 +870,11 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, final Shrink sa, final Shrink sb, final Shrink sc, @@ -897,11 +897,11 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, final F5 f) { return property(aa, ab, ac, ad, ae, curry(f)); } @@ -926,12 +926,12 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, final Shrink sa, final Shrink sb, final Shrink sc, @@ -958,12 +958,12 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, final F>>>>> f) { return property(aa, ab, ac, ad, ae, a -> b -> c -> d -> e -> property(af, f$ -> f.f(a).f(b).f(c).f(d).f(e).f(f$))); } @@ -988,12 +988,12 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, final Shrink sa, final Shrink sb, final Shrink sc, @@ -1018,12 +1018,12 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, final F6 f) { return property(aa, ab, ac, ad, ae, af, curry(f)); } @@ -1050,13 +1050,13 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, final Shrink sa, final Shrink sb, final Shrink sc, @@ -1085,13 +1085,13 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, final F>>>>>> f) { return property(aa, ab, ac, ad, ae, af, a -> b -> c -> d -> e -> f$ -> property(ag, g -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g))); } @@ -1118,13 +1118,13 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, final Shrink sa, final Shrink sb, final Shrink sc, @@ -1151,13 +1151,13 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, final F7 f) { return property(aa, ab, ac, ad, ae, af, ag, curry(f)); } @@ -1186,14 +1186,14 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, - final Arbitrary ah, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah, final Shrink sa, final Shrink sb, final Shrink sc, @@ -1224,14 +1224,14 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, - final Arbitrary ah, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah, final F>>>>>>> f) { return property(aa, ab, ac, ad, ae, af, ag, a -> b -> c -> d -> e -> f$ -> g -> property(ah, h -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h))); } @@ -1260,14 +1260,14 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, - final Arbitrary ah, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah, final Shrink sa, final Shrink sb, final Shrink sc, @@ -1296,14 +1296,14 @@ public static Property property(final Arbitrary aa, * @return A property where its result is derived from universal quantification across the * application of its arguments. */ - public static Property property(final Arbitrary aa, - final Arbitrary ab, - final Arbitrary ac, - final Arbitrary ad, - final Arbitrary ae, - final Arbitrary af, - final Arbitrary ag, - final Arbitrary ah, + public static Property property(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah, final F8 f) { return property(aa, ab, ac, ad, ae, af, ag, ah, curry(f)); } diff --git a/quickcheck/src/test/java/fj/data/test/TestCheck.java b/quickcheck/src/test/java/fj/data/test/TestCheck.java index 10c59a1c..6bfaeaf7 100644 --- a/quickcheck/src/test/java/fj/data/test/TestCheck.java +++ b/quickcheck/src/test/java/fj/data/test/TestCheck.java @@ -10,7 +10,6 @@ import org.junit.*; import static fj.Function.compose; -import static fj.test.Arbitrary.*; import static fj.test.Arbitrary.arbLong; import static fj.test.Coarbitrary.coarbInteger; import static fj.test.Coarbitrary.coarbLong; @@ -26,7 +25,7 @@ public void testExceptionsThrownFromGeneratorsArePropagated() { throw new RuntimeException("test failure"); }); - Property p = property(arbitrary(failingGen), (Integer i) -> { + Property p = property(failingGen, (Integer i) -> { return prop(i == 0); }); diff --git a/quickcheck/src/test/java/fj/data/test/TestNull.java b/quickcheck/src/test/java/fj/data/test/TestNull.java index 6f7795aa..0346407d 100644 --- a/quickcheck/src/test/java/fj/data/test/TestNull.java +++ b/quickcheck/src/test/java/fj/data/test/TestNull.java @@ -10,7 +10,6 @@ import org.junit.Test; import static fj.Function.compose; -import static fj.test.Arbitrary.*; import static fj.test.Arbitrary.arbLong; import static fj.test.Coarbitrary.coarbInteger; import static fj.test.Coarbitrary.coarbLong; @@ -24,7 +23,7 @@ public class TestNull { @Test public void testShowNullParameters() { - Property p = property(arbitrary(Gen.value(null)), (Integer i) -> { + Property p = property(Gen.value(null), (Integer i) -> { return prop(i != null); }); CheckResult.summary.println(p.check()); diff --git a/quickcheck/src/test/java/fj/test/TestBool.java b/quickcheck/src/test/java/fj/test/TestBool.java index 2f29f69a..a2b9cae7 100644 --- a/quickcheck/src/test/java/fj/test/TestBool.java +++ b/quickcheck/src/test/java/fj/test/TestBool.java @@ -4,7 +4,6 @@ import org.junit.Test; import static fj.test.Arbitrary.arbBoolean; -import static fj.test.Arbitrary.arbitrary; import static fj.test.Bool.bool; import static fj.test.Property.property; @@ -12,8 +11,7 @@ public class TestBool { @Test public void testBool() { - final Arbitrary arbBooleanR = arbitrary(arbBoolean.gen); - final Property p = property(arbBooleanR, arbBooleanR, (m1, m2) -> bool(m1.equals(m2)) + final Property p = property(arbBoolean, arbBoolean, (m1, m2) -> bool(m1.equals(m2)) .implies(m1 == m2)); PropertyAssert.assertResult(p); } From 7f46d9df703c4ba4b8b28b0bc4c35273bf134b4b Mon Sep 17 00:00:00 2001 From: Charles O'Farrell Date: Wed, 8 Jun 2016 06:31:15 +1000 Subject: [PATCH 556/811] Rename Coarbitrary to Cogen --- .../java/fj/demo/test/ListFunctorLaws.java | 6 +- .../src/test/java/fj/data/ReaderTest.java | 18 +- .../src/test/java/fj/data/TestRngState.java | 14 +- .../src/test/java/fj/data/WriterTest.java | 12 +- .../src/main/java/fj/test/Arbitrary.java | 142 +- .../src/main/java/fj/test/Coarbitrary.java | 1184 ----------------- quickcheck/src/main/java/fj/test/Cogen.java | 1184 +++++++++++++++++ .../src/test/java/fj/data/test/TestCheck.java | 2 - .../src/test/java/fj/data/test/TestNull.java | 2 - 9 files changed, 1280 insertions(+), 1284 deletions(-) delete mode 100644 quickcheck/src/main/java/fj/test/Coarbitrary.java create mode 100644 quickcheck/src/main/java/fj/test/Cogen.java diff --git a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java index 6f17f827..46f7bdb0 100644 --- a/demo/src/main/java/fj/demo/test/ListFunctorLaws.java +++ b/demo/src/main/java/fj/demo/test/ListFunctorLaws.java @@ -15,8 +15,8 @@ import fj.function.Effect1; import fj.test.CheckResult; import static fj.test.CheckResult.summary; -import static fj.test.Coarbitrary.coarbInteger; -import static fj.test.Coarbitrary.coarbLong; +import static fj.test.Cogen.cogenInteger; +import static fj.test.Cogen.cogenLong; import fj.test.Property; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -42,7 +42,7 @@ For any list, mapping the identity function (\x -> x) produces the same list. public final class ListFunctorLaws { final Property identity = property(arbList(arbString), x -> prop(listEqual(stringEqual).eq(x, x.map(Function.identity())))); - final Property composition = property(arbF(coarbInteger, arbString), arbF(coarbLong, arbInteger), arbList(arbLong), (f, g, x) -> { + final Property composition = property(arbF(cogenInteger, arbString), arbF(cogenLong, arbInteger), arbList(arbLong), (f, g, x) -> { final List s1 = x.map(compose(f, g)); final List s2 = x.map(g).map(f); return prop(listEqual(stringEqual).eq(s1, s2)); diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index 05c858b8..8494336e 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -8,7 +8,7 @@ import static fj.F1Functions.bind; import static fj.F1Functions.map; import static fj.test.Arbitrary.*; -import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Cogen.cogenInteger; import static fj.test.Property.prop; import static fj.test.Property.property; import static org.junit.Assert.assertTrue; @@ -39,8 +39,8 @@ public void testFlatMap() { @Test public void testMapProp() { Property p = property( - arbF(coarbInteger, arbInteger), - arbF(coarbInteger, arbInteger), + arbF(cogenInteger, arbInteger), + arbF(cogenInteger, arbInteger), arbInteger, (f, g, i) -> { int expected = map(f, g).f(i); @@ -52,9 +52,9 @@ public void testMapProp() { @Test public void testFlatMapProp() { - Gen>> a = arbF(coarbInteger, arbReader()); + Gen>> a = arbF(cogenInteger, arbReader()); Property p = property( - arbF(coarbInteger, arbInteger), + arbF(cogenInteger, arbInteger), a, arbInteger, (f, g, i) -> { @@ -72,7 +72,7 @@ public void testLeftIdentity() { Property p = Property.property( arbInteger, arbInteger, - arbF(coarbInteger, arbReader()), + arbF(cogenInteger, arbReader()), (i, j, f) -> { int a = Reader.constant(i).flatMap(f).f(j); int b = f.f(i).f(j); @@ -99,8 +99,8 @@ public void testAssociativity() { Property p = Property.property( arbInteger, arbReader(), - arbF(coarbInteger, arbReader()), - arbF(coarbInteger, arbReader()), + arbF(cogenInteger, arbReader()), + arbF(cogenInteger, arbReader()), (i, r, f, g) -> { boolean b2 = r.flatMap(f).flatMap(g).f(i) == r.flatMap(x -> f.f(x).flatMap(g)).f(i); return prop(b2); @@ -109,7 +109,7 @@ public void testAssociativity() { } public Gen> arbReader() { - return Arbitrary.arbReader(coarbInteger, arbInteger); + return Arbitrary.arbReader(cogenInteger, arbInteger); } diff --git a/props-core/src/test/java/fj/data/TestRngState.java b/props-core/src/test/java/fj/data/TestRngState.java index ddc319b9..5f5f81bb 100644 --- a/props-core/src/test/java/fj/data/TestRngState.java +++ b/props-core/src/test/java/fj/data/TestRngState.java @@ -2,7 +2,7 @@ import fj.*; import fj.test.Arbitrary; -import fj.test.Coarbitrary; +import fj.test.Cogen; import fj.test.Gen; import fj.test.Property; import org.junit.Assert; @@ -12,7 +12,7 @@ import static fj.data.Stream.unfold; import static fj.data.test.PropertyAssert.assertResult; import static fj.test.Arbitrary.*; -import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Cogen.cogenInteger; import static fj.test.Property.prop; import static fj.test.Property.property; import static fj.test.Variant.variant; @@ -80,19 +80,19 @@ public void testTraverse() { } public static Gen> arbState() { - return Arbitrary.arbState(Arbitrary.arbLcgRng(), Coarbitrary.coarbLcgRng(), arbInteger); + return Arbitrary.arbState(Arbitrary.arbLcgRng(), Cogen.cogenLcgRng(), arbInteger); } public static Gen>> arbStateF() { - return arbF(Coarbitrary.coarbLcgRng(), arbP2(arbLcgRng(), arbInteger)); + return arbF(Cogen.cogenLcgRng(), arbP2(arbLcgRng(), arbInteger)); } - public static Coarbitrary> coarbState() { - return Coarbitrary.coarbState(Arbitrary.arbLcgRng(), (LcgRng s, Integer j) -> (long) (j >= 0 ? 2 * j : -2 * j + 1)); + public static Cogen> cogenState() { + return Cogen.cogenState(Arbitrary.arbLcgRng(), (LcgRng s, Integer j) -> (long) (j >= 0 ? 2 * j : -2 * j + 1)); } public static Gen>> arbBindable() { - return arbF(coarbInteger, arbState()); + return arbF(cogenInteger, arbState()); } // Left identity: return i >>= f == f i diff --git a/props-core/src/test/java/fj/data/WriterTest.java b/props-core/src/test/java/fj/data/WriterTest.java index a2af9952..5f0ac122 100644 --- a/props-core/src/test/java/fj/data/WriterTest.java +++ b/props-core/src/test/java/fj/data/WriterTest.java @@ -11,7 +11,7 @@ import static fj.data.test.PropertyAssert.assertResult; import static fj.test.Arbitrary.*; -import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Cogen.cogenInteger; import static fj.test.Property.prop; import static fj.test.Property.property; import static org.junit.Assert.assertTrue; @@ -46,7 +46,7 @@ public void testTellProp() { @Test public void testMap() { - Property p = property(arbInteger, arbF(coarbInteger, arbInteger), (i, f) -> { + Property p = property(arbInteger, arbF(cogenInteger, arbInteger), (i, f) -> { boolean b = eq.eq(defaultWriter.f(i).map(f), defaultWriter.f(f.f(i))); return prop(b); }); @@ -55,7 +55,7 @@ public void testMap() { @Test public void testFlatMap() { - Property p = property(arbInteger,arbF(coarbInteger, arbWriterStringInt()), (i, f) -> { + Property p = property(arbInteger,arbF(cogenInteger, arbWriterStringInt()), (i, f) -> { boolean b = eq.eq(Writer.stringLogger().f(i).flatMap(f), f.f(i)); return prop(b); }); @@ -76,7 +76,7 @@ public Gen> arbWriterString(Gen arb) { public void testLeftIdentity() { Property p = Property.property( arbInteger, - arbF(coarbInteger, arbWriterStringInt()), + arbF(cogenInteger, arbWriterStringInt()), (i, f) -> { return prop(eq.eq(defaultWriter.f(i).flatMap(f), f.f(i))); }); @@ -98,8 +98,8 @@ public void testRightIdentity() { public void testAssociativity() { Property p = Property.property( arbWriterStringInt(), - arbF(coarbInteger, arbWriterStringInt()), - arbF(coarbInteger, arbWriterStringInt()), + arbF(cogenInteger, arbWriterStringInt()), + arbF(cogenInteger, arbWriterStringInt()), (w, f, g) -> { boolean t = eq.eq(w.flatMap(f).flatMap(g), w.flatMap(x -> f.f(x).flatMap(g))); return prop(t); diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 0b82108f..d8f88bed 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -83,26 +83,26 @@ public final class Arbitrary { /** * An arbitrary for functions. * - * @param c The coarbitrary for the function domain. + * @param c The cogen for the function domain. * @param a The arbitrary for the function codomain. * @return An arbitrary for functions. */ - public static Gen> arbF(final Coarbitrary c, final Gen a) { + public static Gen> arbF(final Cogen c, final Gen a) { return promote(new F>() { public Gen f(final A x) { - return c.coarbitrary(x, a); + return c.cogen(x, a); } }); } - public static Gen> arbReader(Coarbitrary aa, Gen ab) { + public static Gen> arbReader(Cogen aa, Gen ab) { return arbF(aa, ab).map(Reader::unit); } /** * An arbitrary for state. */ - public static Gen> arbState(Gen as, Coarbitrary cs, Gen aa) { + public static Gen> arbState(Gen as, Cogen cs, Gen aa) { return arbF(cs, arbP2(as, aa)).map(State::unit); } @@ -126,12 +126,12 @@ public static Gen> arbFInvariant(final Gen a) { /** * An arbitrary for function-2. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-2. */ - public static Gen> arbF2(final Coarbitrary ca, final Coarbitrary cb, + public static Gen> arbF2(final Cogen ca, final Cogen cb, final Gen a) { return arbF(ca, arbF(cb, a)).map(Function.uncurryF2()); } @@ -149,14 +149,14 @@ public static Gen> arbF2Invariant(final Gen a) { /** * An arbitrary for function-3. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. - * @param cc A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. + * @param cc A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-3. */ - public static Gen> arbF3(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc, final Gen a) { + public static Gen> arbF3(final Cogen ca, final Cogen cb, + final Cogen cc, final Gen a) { return arbF(ca, arbF(cb, arbF(cc, a))).map(Function.uncurryF3()); } @@ -176,15 +176,15 @@ public static Gen> arbF3Invariant(final Gen a) { /** * An arbitrary for function-4. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. - * @param cc A coarbitrary for the part of the domain of the function. - * @param cd A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. + * @param cc A cogen for the part of the domain of the function. + * @param cd A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-4. */ - public static Gen> arbF4(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc, final Coarbitrary cd, + public static Gen> arbF4(final Cogen ca, final Cogen cb, + final Cogen cc, final Cogen cd, final Gen a) { return arbF(ca, arbF(cb, arbF(cc, arbF(cd, a)))).map(Function.uncurryF4()); } @@ -206,19 +206,19 @@ public static Gen> arbF4Invariant(final Gen /** * An arbitrary for function-5. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. - * @param cc A coarbitrary for the part of the domain of the function. - * @param cd A coarbitrary for the part of the domain of the function. - * @param ce A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. + * @param cc A cogen for the part of the domain of the function. + * @param cd A cogen for the part of the domain of the function. + * @param ce A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-5. */ - public static Gen> arbF5(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, + public static Gen> arbF5(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, final Gen a) { return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, a))))).map(Function.uncurryF5()); } @@ -241,21 +241,21 @@ public static Gen> arbF4Invariant(final Gen /** * An arbitrary for function-6. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. - * @param cc A coarbitrary for the part of the domain of the function. - * @param cd A coarbitrary for the part of the domain of the function. - * @param ce A coarbitrary for the part of the domain of the function. - * @param cf A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. + * @param cc A cogen for the part of the domain of the function. + * @param cd A cogen for the part of the domain of the function. + * @param ce A cogen for the part of the domain of the function. + * @param cf A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-6. */ - public static Gen> arbF6(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, + public static Gen> arbF6(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, + final Cogen cf, final Gen a) { return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, a)))))).map( Function.uncurryF6()); @@ -280,23 +280,23 @@ public static Gen> arbF4Invariant(final Gen /** * An arbitrary for function-7. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. - * @param cc A coarbitrary for the part of the domain of the function. - * @param cd A coarbitrary for the part of the domain of the function. - * @param ce A coarbitrary for the part of the domain of the function. - * @param cf A coarbitrary for the part of the domain of the function. - * @param cg A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. + * @param cc A cogen for the part of the domain of the function. + * @param cd A cogen for the part of the domain of the function. + * @param ce A cogen for the part of the domain of the function. + * @param cf A cogen for the part of the domain of the function. + * @param cg A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-7. */ - public static Gen> arbF7(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Coarbitrary cg, + public static Gen> arbF7(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, + final Cogen cf, + final Cogen cg, final Gen a) { return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, a))))))).map( Function.uncurryF7()); @@ -322,25 +322,25 @@ public static Gen> arbF4Invariant(final Gen /** * An arbitrary for function-8. * - * @param ca A coarbitrary for the part of the domain of the function. - * @param cb A coarbitrary for the part of the domain of the function. - * @param cc A coarbitrary for the part of the domain of the function. - * @param cd A coarbitrary for the part of the domain of the function. - * @param ce A coarbitrary for the part of the domain of the function. - * @param cf A coarbitrary for the part of the domain of the function. - * @param cg A coarbitrary for the part of the domain of the function. - * @param ch A coarbitrary for the part of the domain of the function. + * @param ca A cogen for the part of the domain of the function. + * @param cb A cogen for the part of the domain of the function. + * @param cc A cogen for the part of the domain of the function. + * @param cd A cogen for the part of the domain of the function. + * @param ce A cogen for the part of the domain of the function. + * @param cf A cogen for the part of the domain of the function. + * @param cg A cogen for the part of the domain of the function. + * @param ch A cogen for the part of the domain of the function. * @param a An arbitrary for the codomain of the function. * @return An arbitrary for function-8. */ - public static Gen> arbF8(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Coarbitrary cg, - final Coarbitrary ch, + public static Gen> arbF8(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, + final Cogen cf, + final Cogen cg, + final Cogen ch, final Gen a) { return arbF(ca, arbF(cb, arbF(cc, arbF(cd, arbF(ce, arbF(cf, arbF(cg, arbF(ch, a)))))))).map( Function.uncurryF8()); diff --git a/quickcheck/src/main/java/fj/test/Coarbitrary.java b/quickcheck/src/main/java/fj/test/Coarbitrary.java deleted file mode 100644 index 14c7acb4..00000000 --- a/quickcheck/src/main/java/fj/test/Coarbitrary.java +++ /dev/null @@ -1,1184 +0,0 @@ -package fj.test; - -import fj.*; - -import static fj.Function.curry; -import static fj.P.p; - -import fj.data.*; - -import static fj.data.Array.array; -import static fj.data.Array.iterableArray; -import static fj.data.List.fromString; -import static fj.data.List.nil; - -import static fj.test.Variant.variant; - -import static java.lang.Double.doubleToRawLongBits; -import static java.lang.Float.floatToRawIntBits; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Calendar; -import java.util.Date; -import java.util.EnumMap; -import java.util.EnumSet; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.Properties; -import java.util.Stack; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.Vector; -import java.util.WeakHashMap; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.DelayQueue; -import java.util.concurrent.Delayed; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.PriorityBlockingQueue; -import java.util.concurrent.SynchronousQueue; - -/** - * Transforms a type and a generator to produce a new generator. This function is used to generate - * {@link Arbitrary arbitrary} functions. - * - * @version %build.number% - */ -public abstract class Coarbitrary { - /** - * Transforms the given value and generator to a new generator with a high probability of being - * independent. - * - * @param a The value to produce the generator from. - * @param g The generator to produce the new generator from. - * @return A new generator with a high probability of being independent. - */ - public abstract Gen coarbitrary(A a, Gen g); - - - /** - * A curried version of {@link #coarbitrary(Object, Gen)}. - * - * @param a The value to produce the generator from. - * @return A curried version of {@link #coarbitrary(Object, Gen)}. - */ - public final F, Gen> coarbitrary(final A a) { - return g -> coarbitrary(a, g); - } - - /** - * Composes the given function with this coarbitrary to produce a new coarbitrary. - * - * @param f The function to compose. - * @return A new coarbitrary composed with the given function. - */ - public final Coarbitrary compose(final F f) { - return new Coarbitrary() { - public Gen coarbitrary(final B b, final Gen g) { - return Coarbitrary.this.coarbitrary(f.f(b), g); - } - }; - } - - /** - * Contra-maps this coarbitrary using the given function. - * - * @param f The function to co-map with. - * @return A contra-mapped coarbitrary. - */ - public final Coarbitrary contramap(final F f) { - return new Coarbitrary() { - public Gen coarbitrary(final B b, final Gen g) { - return Coarbitrary.this.coarbitrary(f.f(b), g); - } - }; - } - - /** - * A coarbitrary for a function. - * - * @param a An arbitrary for the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function. - */ - public static Coarbitrary> coarbF(final Gen a, final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F f, final Gen g) { - return a.bind(a1 -> c.coarbitrary(f.f(a1), g)); - } - }; - } - - /** - * A coarbitrary for a function-2. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-2. - */ - public static Coarbitrary> coarbF2(final Gen aa, final Gen ab, - final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F2 f, final Gen g) { - return coarbF(aa, coarbF(ab, c)).coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for a function-3. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param ac An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-3. - */ - public static Coarbitrary> coarbF3(final Gen aa, final Gen ab, - final Gen ac, final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F3 f, final Gen g) { - return coarbF(aa, coarbF(ab, coarbF(ac, c))).coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for a function-4. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param ac An arbitrary for part of the domain of the function. - * @param ad An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-4. - */ - public static Coarbitrary> coarbF4(final Gen aa, final Gen ab, - final Gen ac, final Gen ad, - final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F4 f, final Gen g) { - return coarbF(aa, coarbF(ab, coarbF(ac, coarbF(ad, c)))).coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for a function-5. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param ac An arbitrary for part of the domain of the function. - * @param ad An arbitrary for part of the domain of the function. - * @param ae An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-5. - */ - public static Coarbitrary> coarbF5(final Gen aa, - final Gen ab, - final Gen ac, - final Gen ad, - final Gen ae, - final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F5 f, final Gen g) { - return coarbF(aa, coarbF(ab, coarbF(ac, coarbF(ad, coarbF(ae, c))))).coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for a function-6. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param ac An arbitrary for part of the domain of the function. - * @param ad An arbitrary for part of the domain of the function. - * @param ae An arbitrary for part of the domain of the function. - * @param af An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-6. - */ - public static Coarbitrary> coarbF6(final Gen aa, - final Gen ab, - final Gen ac, - final Gen ad, - final Gen ae, - final Gen af, - final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F6 f, final Gen g) { - return coarbF(aa, coarbF(ab, coarbF(ac, coarbF(ad, coarbF(ae, coarbF(af, c)))))).coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for a function-7. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param ac An arbitrary for part of the domain of the function. - * @param ad An arbitrary for part of the domain of the function. - * @param ae An arbitrary for part of the domain of the function. - * @param af An arbitrary for part of the domain of the function. - * @param ag An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-7. - */ - public static Coarbitrary> coarbF7(final Gen aa, - final Gen ab, - final Gen ac, - final Gen ad, - final Gen ae, - final Gen af, - final Gen ag, - final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F7 f, final Gen g) { - return coarbF(aa, coarbF(ab, coarbF(ac, coarbF(ad, coarbF(ae, coarbF(af, coarbF(ag, c))))))) - .coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for a function-8. - * - * @param aa An arbitrary for part of the domain of the function. - * @param ab An arbitrary for part of the domain of the function. - * @param ac An arbitrary for part of the domain of the function. - * @param ad An arbitrary for part of the domain of the function. - * @param ae An arbitrary for part of the domain of the function. - * @param af An arbitrary for part of the domain of the function. - * @param ag An arbitrary for part of the domain of the function. - * @param ah An arbitrary for part of the domain of the function. - * @param c A coarbitrary for the codomain of the function. - * @return A coarbitrary for a function-8. - */ - public static Coarbitrary> coarbF8(final Gen aa, - final Gen ab, - final Gen ac, - final Gen ad, - final Gen ae, - final Gen af, - final Gen ag, - final Gen ah, - final Coarbitrary c) { - return new Coarbitrary>() { - public Gen coarbitrary(final F8 f, final Gen g) { - return coarbF(aa, coarbF(ab, coarbF(ac, coarbF(ad, coarbF(ae, coarbF(af, coarbF(ag, coarbF(ah, c)))))))) - .coarbitrary(curry(f), g); - } - }; - } - - /** - * A coarbitrary for booleans. - */ - public static final Coarbitrary coarbBoolean = new Coarbitrary() { - public Gen coarbitrary(final Boolean b, final Gen g) { - return variant(b ? 0 : 1, g); - } - }; - - /** - * A coarbitrary for integers. - */ - public static final Coarbitrary coarbInteger = new Coarbitrary() { - public Gen coarbitrary(final Integer i, final Gen g) { - return variant(i >= 0 ? 2 * i : -2 * i + 1, g); - } - }; - - /** - * A coarbitrary for bytes. - */ - public static final Coarbitrary coarbByte = new Coarbitrary() { - public Gen coarbitrary(final Byte b, final Gen g) { - return variant(b >= 0 ? 2 * b : -2 * b + 1, g); - } - }; - - /** - * A coarbitrary for shorts. - */ - public static final Coarbitrary coarbShort = new Coarbitrary() { - public Gen coarbitrary(final Short s, final Gen g) { - return variant(s >= 0 ? 2 * s : -2 * s + 1, g); - } - }; - - /** - * A coarbitrary for longs. - */ - public static final Coarbitrary coarbLong = new Coarbitrary() { - public Gen coarbitrary(final Long l, final Gen g) { - return variant(l >= 0L ? 2L * l : -2L * l + 1L, g); - } - }; - - /** - * A coarbitrary for characters. - */ - public static final Coarbitrary coarbCharacter = new Coarbitrary() { - public Gen coarbitrary(final Character c, final Gen g) { - return variant(c << 1, g); - } - }; - - /** - * A coarbitrary for floats. - */ - public static final Coarbitrary coarbFloat = new Coarbitrary() { - public Gen coarbitrary(final Float f, final Gen g) { - return coarbInteger.coarbitrary(floatToRawIntBits(f), g); - } - }; - - /** - * A coarbitrary for doubles. - */ - public static final Coarbitrary coarbDouble = new Coarbitrary() { - public Gen coarbitrary(final Double d, final Gen g) { - return coarbLong.coarbitrary(doubleToRawLongBits(d), g); - } - }; - - /** - * A coarbitrary for the optional value. - * - * @param ca A coarbitrary for the type of the optional value. - * @return A coarbitrary for the optional value. - */ - public static Coarbitrary> coarbOption(final Coarbitrary ca) { - return new Coarbitrary>() { - public Gen coarbitrary(final Option o, final Gen g) { - return o.isNone() ? variant(0, g) : variant(1, ca.coarbitrary(o.some(), g)); - } - }; - } - - /** - * A coarbitrary for the disjoint union. - * - * @param ca A coarbitrary for one side of the disjoint union. - * @param cb A coarbitrary for one side of the disjoint union. - * @return A coarbitrary for the disjoint union. - */ - public static Coarbitrary> coarbEither(final Coarbitrary ca, final Coarbitrary cb) { - return new Coarbitrary>() { - public Gen coarbitrary(final Either e, final Gen g) { - return e.isLeft() ? - variant(0, ca.coarbitrary(e.left().value(), g)) : - variant(1, cb.coarbitrary(e.right().value(), g)); - } - }; - } - - /** - * A coarbitrary for lists. - * - * @param ca A coarbitrary for the elements of the list. - * @return A coarbitrary for lists. - */ - public static Coarbitrary> coarbList(final Coarbitrary ca) { - return new Coarbitrary>() { - public Gen coarbitrary(final List as, final Gen g) { - return as.isEmpty() ? - variant(0, g) : - variant(1, ca.coarbitrary(as.head(), coarbitrary(as.tail(), g))); - } - }; - } - - /** - * A coarbitrary for strings. - */ - public static final Coarbitrary coarbString = new Coarbitrary() { - public Gen coarbitrary(final String s, final Gen g) { - return coarbList(coarbCharacter).coarbitrary(fromString(s), g); - } - }; - - /** - * A coarbitrary for string buffers. - */ - public static final Coarbitrary coarbStringBuffer = new Coarbitrary() { - public Gen coarbitrary(final StringBuffer s, final Gen g) { - return coarbString.coarbitrary(s.toString(), g); - } - }; - - /** - * A coarbitrary for string builders. - */ - public static final Coarbitrary coarbStringBuilder = new Coarbitrary() { - public Gen coarbitrary(final StringBuilder s, final Gen g) { - return coarbString.coarbitrary(s.toString(), g); - } - }; - - /** - * A coarbitrary for streams. - * - * @param ca A coarbitrary for the elements of the stream. - * @return A coarbitrary for streams. - */ - public static Coarbitrary> coarbStream(final Coarbitrary ca) { - return new Coarbitrary>() { - public Gen coarbitrary(final Stream as, final Gen g) { - return as.isEmpty() ? - variant(0, g) : - variant(1, ca.coarbitrary(as.head(), coarbitrary(as.tail()._1(), g))); - } - }; - } - - /** - * A coarbitrary for the provided LcgRng - * @return A coarbitrary for the provided LcgRng. - */ - public static Coarbitrary coarbLcgRng() { - return new Coarbitrary() { - @Override - public Gen coarbitrary(LcgRng rng, Gen g) { - long i = rng.getSeed(); - return variant(i >= 0 ? 2 * i : -2 * i + 1, g); - } - }; - } - - /** - * A coarbitrary for state. - */ - public static Coarbitrary> coarbState(Gen as, F2 f) { - return new Coarbitrary>() { - @Override - public Gen coarbitrary(State s1, Gen g) { - return as.bind(r -> { - P2 p = s1.run(r); - return variant(f.f(p._1(), p._2()), g); - }); - } - }; - } - - /** - * A coarbitrary for arrays. - * - * @param ca A coarbitrary for the elements of the array. - * @return A coarbitrary for arrays. - */ - public static Coarbitrary> coarbArray(final Coarbitrary ca) { - return new Coarbitrary>() { - public Gen coarbitrary(final Array as, final Gen g) { - return coarbList(ca).coarbitrary(as.toList(), g); - } - }; - } - - /** - * A coarbitrary for throwables. - * - * @param cs A coarbitrary for the throwable message. - * @return A coarbitrary for throwables. - */ - public static Coarbitrary coarbThrowable(final Coarbitrary cs) { - return cs.contramap(new F() { - public String f(final Throwable t) { - return t.getMessage(); - } - }); - } - - /** - * A coarbitrary for throwables. - */ - public static final Coarbitrary coarbThrowable = - coarbThrowable(coarbString); - - // BEGIN java.util - - /** - * A coarbitrary for array lists. - * - * @param ca A coarbitrary for the elements of the array list. - * @return A coarbitrary for array lists. - */ - public static Coarbitrary> coarbArrayList(final Coarbitrary ca) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final ArrayList as, final Gen g) { - return coarbArray(ca).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for bit sets. - */ - public static final Coarbitrary coarbBitSet = new Coarbitrary() { - public Gen coarbitrary(final BitSet s, final Gen g) { - List x = nil(); - - for (int i = 0; i < s.size(); i++) { - x = x.snoc(s.get(i)); - } - - return coarbList(coarbBoolean).coarbitrary(x, g); - } - }; - - /** - * A coarbitrary for calendars. - */ - public static final Coarbitrary coarbCalendar = new Coarbitrary() { - public Gen coarbitrary(final Calendar c, final Gen g) { - return coarbLong.coarbitrary(c.getTime().getTime(), g); - } - }; - - /** - * A coarbitrary for dates. - */ - public static final Coarbitrary coarbDate = new Coarbitrary() { - public Gen coarbitrary(final Date d, final Gen g) { - return coarbLong.coarbitrary(d.getTime(), g); - } - }; - - /** - * A coarbitrary for enum maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for enum maps. - */ - public static , V> Coarbitrary> coarbEnumMap(final Coarbitrary ck, - final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final EnumMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - /** - * A coarbitrary for enum sets. - * - * @param c A coarbitrary for the elements of the enum set. - * @return A coarbitrary for enum sets. - */ - public static > Coarbitrary> coarbEnumSet(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final EnumSet as, final Gen g) { - return coarbHashSet(c).coarbitrary(new HashSet<>(as), g); - } - }; - } - - /** - * A coarbitrary for gregorian calendars. - */ - public static final Coarbitrary coarbGregorianCalendar = new Coarbitrary() { - public Gen coarbitrary(final GregorianCalendar c, final Gen g) { - return coarbLong.coarbitrary(c.getTime().getTime(), g); - } - }; - - /** - * A coarbitrary for hash maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for hash maps. - */ - public static Coarbitrary> coarbHashMap(final Coarbitrary ck, final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final HashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - /** - * A coarbitrary for hash sets. - * - * @param c A coarbitrary for the elements of the hash set. - * @return A coarbitrary for hash sets. - */ - public static Coarbitrary> coarbHashSet(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final HashSet as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for hash tables. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for hash tables. - */ - public static Coarbitrary> coarbHashtable(final Coarbitrary ck, final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final Hashtable h, final Gen g) { - List> x = nil(); - - for (final Map.Entry entry : h.entrySet()) { - x = x.snoc(p(entry.getKey(), entry.getValue())); - } - - return coarbList(coarbP2(ck, cv)).coarbitrary(x, g); - } - }; - } - - /** - * A coarbitrary for identity hash maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for identity hash maps. - */ - public static Coarbitrary> coarbIdentityHashMap(final Coarbitrary ck, - final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final IdentityHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - /** - * A coarbitrary for linked hash maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for linked hash maps. - */ - public static Coarbitrary> coarbLinkedHashMap(final Coarbitrary ck, - final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final LinkedHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - /** - * A coarbitrary for linked hash sets. - * - * @param c A coarbitrary for the elements of the linked hash set. - * @return A coarbitrary for linked hash sets. - */ - public static Coarbitrary> coarbLinkedHashSet(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final LinkedHashSet as, final Gen g) { - return coarbHashSet(c).coarbitrary(new HashSet<>(as), g); - } - }; - } - - /** - * A coarbitrary for linked lists. - * - * @param c A coarbitrary for the elements of the linked list. - * @return A coarbitrary for linked lists. - */ - public static Coarbitrary> coarbLinkedList(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final LinkedList as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for priority queues. - * - * @param c A coarbitrary for the elements of the priority queue. - * @return A coarbitrary for priority queues. - */ - public static Coarbitrary> coarbPriorityQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final PriorityQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for properties. - */ - public static final Coarbitrary coarbProperties = new Coarbitrary() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final Properties p, final Gen g) { - final Hashtable t = new Hashtable<>(); - - for (final Object s : p.keySet()) { - t.put((String) s, p.getProperty((String) s)); - } - - return coarbHashtable(coarbString, coarbString).coarbitrary(t, g); - } - }; - - /** - * A coarbitrary for stacks. - * - * @param c A coarbitrary for the elements of the stack. - * @return A coarbitrary for stacks. - */ - public static Coarbitrary> coarbStack(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final Stack as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for tree maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for tree maps. - */ - public static Coarbitrary> coarbTreeMap(final Coarbitrary ck, final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final TreeMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - /** - * A coarbitrary for tree sets. - * - * @param c A coarbitrary for the elements of the tree set. - * @return A coarbitrary for tree sets. - */ - public static Coarbitrary> coarbTreeSet(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final TreeSet as, final Gen g) { - return coarbHashSet(c).coarbitrary(new HashSet<>(as), g); - } - }; - } - - /** - * A coarbitrary for vectors. - * - * @param c A coarbitrary for the elements of the vector. - * @return A coarbitrary for vectors. - */ - public static Coarbitrary> coarbVector(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"}) - public Gen coarbitrary(final Vector as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for weak hash maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for weak hash maps. - */ - public static Coarbitrary> coarbWeakHashMap(final Coarbitrary ck, - final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final WeakHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - // END java.util - - // BEGIN java.util.concurrent - - /** - * A coarbitrary for array blocking queues. - * - * @param c A coarbitrary for the elements of the array blocking queue. - * @return A coarbitrary for array blocking queues. - */ - public static Coarbitrary> coarbArrayBlockingQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final ArrayBlockingQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for concurrent hash maps. - * - * @param ck A coarbitrary for the map keys. - * @param cv A coarbitrary for the map values. - * @return A coarbitrary for concurrent hash maps. - */ - public static Coarbitrary> coarbConcurrentHashMap(final Coarbitrary ck, - final Coarbitrary cv) { - return new Coarbitrary>() { - @SuppressWarnings("UseOfObsoleteCollectionType") - public Gen coarbitrary(final ConcurrentHashMap m, final Gen g) { - return coarbHashtable(ck, cv).coarbitrary(new Hashtable<>(m), g); - } - }; - } - - /** - * A coarbitrary for concurrent linked queues. - * - * @param c A coarbitrary for the elements of the concurrent linked queue. - * @return A coarbitrary for concurrent linked queues. - */ - public static Coarbitrary> coarbConcurrentLinkedQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final ConcurrentLinkedQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for copy-on-write array lists. - * - * @param c A coarbitrary for the elements of the copy-on-write array list. - * @return A coarbitrary for copy-on-write array lists. - */ - public static Coarbitrary> coarbCopyOnWriteArrayList(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final CopyOnWriteArrayList as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for copy-on-write array sets. - * - * @param c A coarbitrary for the elements of the copy-on-write array set. - * @return A coarbitrary for copy-on-write array sets. - */ - public static Coarbitrary> coarbCopyOnWriteArraySet(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final CopyOnWriteArraySet as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for delay queues. - * - * @param c A coarbitrary for the elements of the delay queue. - * @return A coarbitrary for delay queues. - */ - public static Coarbitrary> coarbDelayQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final DelayQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for linked blocking queues. - * - * @param c A coarbitrary for the elements of the linked blocking queue. - * @return A coarbitrary for linked blocking queues. - */ - public static Coarbitrary> coarbLinkedBlockingQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final LinkedBlockingQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for priority blocking queues. - * - * @param c A coarbitrary for the elements of the priority blocking queue. - * @return A coarbitrary for priority blocking queues. - */ - public static Coarbitrary> coarbPriorityBlockingQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final PriorityBlockingQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - /** - * A coarbitrary for synchronous queues. - * - * @param c A coarbitrary for the elements of the synchronous queue. - * @return A coarbitrary for synchronous queues. - */ - public static Coarbitrary> coarbSynchronousQueue(final Coarbitrary c) { - return new Coarbitrary>() { - @SuppressWarnings("unchecked") - public Gen coarbitrary(final SynchronousQueue as, final Gen g) { - return coarbArray(c).coarbitrary(iterableArray(as), g); - } - }; - } - - // END java.util.concurrent - - // BEGIN java.sql - - public static final Coarbitrary coarbSQLDate = new Coarbitrary() { - public Gen coarbitrary(final java.sql.Date d, final Gen g) { - return coarbLong.coarbitrary(d.getTime(), g); - } - }; - - public static final Coarbitrary coarbTimestamp = new Coarbitrary() { - public Gen coarbitrary(final Timestamp t, final Gen g) { - return coarbLong.coarbitrary(t.getTime(), g); - } - }; - - public static final Coarbitrary Coarbitrary> coarbP1(final Coarbitrary ca) { - return new Coarbitrary>() { - public Gen coarbitrary(final P1 p, final Gen g) { - return ca.coarbitrary(p._1(), g); - } - }; - } - - /** - * A coarbitrary for product-2 values. - * - * @param ca A coarbitrary for one of the types over which the product-2 is defined. - * @param cb A coarbitrary for one of the types over which the product-2 is defined. - * @return A coarbitrary for product-2 values. - */ - public static Coarbitrary> coarbP2(final Coarbitrary ca, final Coarbitrary cb) { - return new Coarbitrary>() { - public Gen coarbitrary(final P2 p, final Gen g) { - return ca.coarbitrary(p._1(), cb.coarbitrary(p._2(), g)); - } - }; - } - - /** - * A coarbitrary for product-3 values. - * - * @param ca A coarbitrary for one of the types over which the product-3 is defined. - * @param cb A coarbitrary for one of the types over which the product-3 is defined. - * @param cc A coarbitrary for one of the types over which the product-3 is defined. - * @return A coarbitrary for product-3 values. - */ - public static Coarbitrary> coarbP3(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc) { - return new Coarbitrary>() { - public Gen coarbitrary(final P3 p, final Gen g) { - return ca.coarbitrary(p._1(), cb.coarbitrary(p._2(), cc.coarbitrary(p._3(), g))); - } - }; - } - - /** - * A coarbitrary for product-4 values. - * - * @param ca A coarbitrary for one of the types over which the product-4 is defined. - * @param cb A coarbitrary for one of the types over which the product-4 is defined. - * @param cc A coarbitrary for one of the types over which the product-4 is defined. - * @param cd A coarbitrary for one of the types over which the product-4 is defined. - * @return A coarbitrary for product-4 values. - */ - public static Coarbitrary> coarbP4(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc, final Coarbitrary cd) { - return new Coarbitrary>() { - public Gen coarbitrary(final P4 p, final Gen g) { - return ca.coarbitrary(p._1(), cb.coarbitrary(p._2(), cc.coarbitrary(p._3(), cd.coarbitrary(p._4(), g)))); - } - }; - } - - /** - * A coarbitrary for product-5 values. - * - * @param ca A coarbitrary for one of the types over which the product-5 is defined. - * @param cb A coarbitrary for one of the types over which the product-5 is defined. - * @param cc A coarbitrary for one of the types over which the product-5 is defined. - * @param cd A coarbitrary for one of the types over which the product-5 is defined. - * @param ce A coarbitrary for one of the types over which the product-5 is defined. - * @return A coarbitrary for product-5 values. - */ - public static Coarbitrary> coarbP5(final Coarbitrary ca, final Coarbitrary cb, - final Coarbitrary cc, final Coarbitrary cd, - final Coarbitrary ce) { - return new Coarbitrary>() { - public Gen coarbitrary(final P5 p, final Gen g) { - return ca.coarbitrary(p._1(), - cb.coarbitrary(p._2(), cc.coarbitrary(p._3(), cd.coarbitrary(p._4(), ce.coarbitrary(p._5(), g))))); - } - }; - } - - /** - * A coarbitrary for product-6 values. - * - * @param ca A coarbitrary for one of the types over which the product-6 is defined. - * @param cb A coarbitrary for one of the types over which the product-6 is defined. - * @param cc A coarbitrary for one of the types over which the product-6 is defined. - * @param cd A coarbitrary for one of the types over which the product-6 is defined. - * @param ce A coarbitrary for one of the types over which the product-6 is defined. - * @param cf A coarbitrary for one of the types over which the product-6 is defined. - * @return A coarbitrary for product-6 values. - */ - public static Coarbitrary> coarbP6(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf) { - return new Coarbitrary>() { - public Gen coarbitrary(final P6 p, final Gen g) { - return ca.coarbitrary(p._1(), cb.coarbitrary(p._2(), - cc.coarbitrary(p._3(), cd.coarbitrary(p._4(), ce.coarbitrary(p._5(), cf.coarbitrary(p._6(), g)))))); - } - }; - } - - /** - * A coarbitrary for product-7 values. - * - * @param ca A coarbitrary for one of the types over which the product-7 is defined. - * @param cb A coarbitrary for one of the types over which the product-7 is defined. - * @param cc A coarbitrary for one of the types over which the product-7 is defined. - * @param cd A coarbitrary for one of the types over which the product-7 is defined. - * @param ce A coarbitrary for one of the types over which the product-7 is defined. - * @param cf A coarbitrary for one of the types over which the product-7 is defined. - * @param cg A coarbitrary for one of the types over which the product-7 is defined. - * @return A coarbitrary for product-7 values. - */ - public static Coarbitrary> coarbP7(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Coarbitrary cg) { - return new Coarbitrary>() { - public Gen coarbitrary(final P7 p, final Gen g) { - return ca.coarbitrary(p._1(), cb.coarbitrary(p._2(), cc.coarbitrary(p._3(), - cd.coarbitrary(p._4(), ce.coarbitrary(p._5(), cf.coarbitrary(p._6(), cg.coarbitrary(p._7(), g))))))); - } - }; - } - - /** - * A coarbitrary for product-8 values. - * - * @param ca A coarbitrary for one of the types over which the product-8 is defined. - * @param cb A coarbitrary for one of the types over which the product-8 is defined. - * @param cc A coarbitrary for one of the types over which the product-8 is defined. - * @param cd A coarbitrary for one of the types over which the product-8 is defined. - * @param ce A coarbitrary for one of the types over which the product-8 is defined. - * @param cf A coarbitrary for one of the types over which the product-8 is defined. - * @param cg A coarbitrary for one of the types over which the product-8 is defined. - * @param ch A coarbitrary for one of the types over which the product-8 is defined. - * @return A coarbitrary for product-8 values. - */ - public static Coarbitrary> coarbP8(final Coarbitrary ca, - final Coarbitrary cb, - final Coarbitrary cc, - final Coarbitrary cd, - final Coarbitrary ce, - final Coarbitrary cf, - final Coarbitrary cg, - final Coarbitrary ch) { - return new Coarbitrary>() { - public Gen coarbitrary(final P8 p, final Gen g) { - return ca.coarbitrary(p._1(), cb.coarbitrary(p._2(), cc.coarbitrary(p._3(), cd.coarbitrary(p._4(), - ce.coarbitrary(p._5(), cf.coarbitrary(p._6(), cg.coarbitrary(p._7(), ch.coarbitrary(p._8(), g)))))))); - } - }; - } -} diff --git a/quickcheck/src/main/java/fj/test/Cogen.java b/quickcheck/src/main/java/fj/test/Cogen.java new file mode 100644 index 00000000..c4c3b0a0 --- /dev/null +++ b/quickcheck/src/main/java/fj/test/Cogen.java @@ -0,0 +1,1184 @@ +package fj.test; + +import fj.*; + +import static fj.Function.curry; +import static fj.P.p; + +import fj.data.*; + +import static fj.data.Array.array; +import static fj.data.Array.iterableArray; +import static fj.data.List.fromString; +import static fj.data.List.nil; + +import static fj.test.Variant.variant; + +import static java.lang.Double.doubleToRawLongBits; +import static java.lang.Float.floatToRawIntBits; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Calendar; +import java.util.Date; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Properties; +import java.util.Stack; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Vector; +import java.util.WeakHashMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Delayed; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.SynchronousQueue; + +/** + * Transforms a type and a generator to produce a new generator. This function is used to generate + * {@link Gen gen} functions. + * + * @version %build.number% + */ +public abstract class Cogen { + /** + * Transforms the given value and generator to a new generator with a high probability of being + * independent. + * + * @param a The value to produce the generator from. + * @param g The generator to produce the new generator from. + * @return A new generator with a high probability of being independent. + */ + public abstract Gen cogen(A a, Gen g); + + + /** + * A curried version of {@link #cogen(Object, Gen)}. + * + * @param a The value to produce the generator from. + * @return A curried version of {@link #cogen(Object, Gen)}. + */ + public final F, Gen> cogen(final A a) { + return g -> cogen(a, g); + } + + /** + * Composes the given function with this cogen to produce a new cogen. + * + * @param f The function to compose. + * @return A new cogen composed with the given function. + */ + public final Cogen compose(final F f) { + return new Cogen() { + public Gen cogen(final B b, final Gen g) { + return Cogen.this.cogen(f.f(b), g); + } + }; + } + + /** + * Contra-maps this cogen using the given function. + * + * @param f The function to co-map with. + * @return A contra-mapped cogen. + */ + public final Cogen contramap(final F f) { + return new Cogen() { + public Gen cogen(final B b, final Gen g) { + return Cogen.this.cogen(f.f(b), g); + } + }; + } + + /** + * A cogen for a function. + * + * @param a A gen for the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function. + */ + public static Cogen> cogenF(final Gen a, final Cogen c) { + return new Cogen>() { + public Gen cogen(final F f, final Gen g) { + return a.bind(a1 -> c.cogen(f.f(a1), g)); + } + }; + } + + /** + * A cogen for a function-2. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-2. + */ + public static Cogen> cogenF2(final Gen aa, final Gen ab, + final Cogen c) { + return new Cogen>() { + public Gen cogen(final F2 f, final Gen g) { + return cogenF(aa, cogenF(ab, c)).cogen(curry(f), g); + } + }; + } + + /** + * A cogen for a function-3. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param ac A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-3. + */ + public static Cogen> cogenF3(final Gen aa, final Gen ab, + final Gen ac, final Cogen c) { + return new Cogen>() { + public Gen cogen(final F3 f, final Gen g) { + return cogenF(aa, cogenF(ab, cogenF(ac, c))).cogen(curry(f), g); + } + }; + } + + /** + * A cogen for a function-4. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param ac A gen for part of the domain of the function. + * @param ad A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-4. + */ + public static Cogen> cogenF4(final Gen aa, final Gen ab, + final Gen ac, final Gen ad, + final Cogen c) { + return new Cogen>() { + public Gen cogen(final F4 f, final Gen g) { + return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, c)))).cogen(curry(f), g); + } + }; + } + + /** + * A cogen for a function-5. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param ac A gen for part of the domain of the function. + * @param ad A gen for part of the domain of the function. + * @param ae A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-5. + */ + public static Cogen> cogenF5(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Cogen c) { + return new Cogen>() { + public Gen cogen(final F5 f, final Gen g) { + return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, c))))).cogen(curry(f), g); + } + }; + } + + /** + * A cogen for a function-6. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param ac A gen for part of the domain of the function. + * @param ad A gen for part of the domain of the function. + * @param ae A gen for part of the domain of the function. + * @param af A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-6. + */ + public static Cogen> cogenF6(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Cogen c) { + return new Cogen>() { + public Gen cogen(final F6 f, final Gen g) { + return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, cogenF(af, c)))))).cogen(curry(f), g); + } + }; + } + + /** + * A cogen for a function-7. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param ac A gen for part of the domain of the function. + * @param ad A gen for part of the domain of the function. + * @param ae A gen for part of the domain of the function. + * @param af A gen for part of the domain of the function. + * @param ag A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-7. + */ + public static Cogen> cogenF7(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Cogen c) { + return new Cogen>() { + public Gen cogen(final F7 f, final Gen g) { + return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, cogenF(af, cogenF(ag, c))))))) + .cogen(curry(f), g); + } + }; + } + + /** + * A cogen for a function-8. + * + * @param aa A gen for part of the domain of the function. + * @param ab A gen for part of the domain of the function. + * @param ac A gen for part of the domain of the function. + * @param ad A gen for part of the domain of the function. + * @param ae A gen for part of the domain of the function. + * @param af A gen for part of the domain of the function. + * @param ag A gen for part of the domain of the function. + * @param ah A gen for part of the domain of the function. + * @param c A cogen for the codomain of the function. + * @return A cogen for a function-8. + */ + public static Cogen> cogenF8(final Gen aa, + final Gen ab, + final Gen ac, + final Gen ad, + final Gen ae, + final Gen af, + final Gen ag, + final Gen ah, + final Cogen c) { + return new Cogen>() { + public Gen cogen(final F8 f, final Gen g) { + return cogenF(aa, cogenF(ab, cogenF(ac, cogenF(ad, cogenF(ae, cogenF(af, cogenF(ag, cogenF(ah, c)))))))) + .cogen(curry(f), g); + } + }; + } + + /** + * A cogen for booleans. + */ + public static final Cogen cogenBoolean = new Cogen() { + public Gen cogen(final Boolean b, final Gen g) { + return variant(b ? 0 : 1, g); + } + }; + + /** + * A cogen for integers. + */ + public static final Cogen cogenInteger = new Cogen() { + public Gen cogen(final Integer i, final Gen g) { + return variant(i >= 0 ? 2 * i : -2 * i + 1, g); + } + }; + + /** + * A cogen for bytes. + */ + public static final Cogen cogenByte = new Cogen() { + public Gen cogen(final Byte b, final Gen g) { + return variant(b >= 0 ? 2 * b : -2 * b + 1, g); + } + }; + + /** + * A cogen for shorts. + */ + public static final Cogen cogenShort = new Cogen() { + public Gen cogen(final Short s, final Gen g) { + return variant(s >= 0 ? 2 * s : -2 * s + 1, g); + } + }; + + /** + * A cogen for longs. + */ + public static final Cogen cogenLong = new Cogen() { + public Gen cogen(final Long l, final Gen g) { + return variant(l >= 0L ? 2L * l : -2L * l + 1L, g); + } + }; + + /** + * A cogen for characters. + */ + public static final Cogen cogenCharacter = new Cogen() { + public Gen cogen(final Character c, final Gen g) { + return variant(c << 1, g); + } + }; + + /** + * A cogen for floats. + */ + public static final Cogen cogenFloat = new Cogen() { + public Gen cogen(final Float f, final Gen g) { + return cogenInteger.cogen(floatToRawIntBits(f), g); + } + }; + + /** + * A cogen for doubles. + */ + public static final Cogen cogenDouble = new Cogen() { + public Gen cogen(final Double d, final Gen g) { + return cogenLong.cogen(doubleToRawLongBits(d), g); + } + }; + + /** + * A cogen for the optional value. + * + * @param ca A cogen for the type of the optional value. + * @return A cogen for the optional value. + */ + public static Cogen> cogenOption(final Cogen ca) { + return new Cogen>() { + public Gen cogen(final Option o, final Gen g) { + return o.isNone() ? variant(0, g) : variant(1, ca.cogen(o.some(), g)); + } + }; + } + + /** + * A cogen for the disjoint union. + * + * @param ca A cogen for one side of the disjoint union. + * @param cb A cogen for one side of the disjoint union. + * @return A cogen for the disjoint union. + */ + public static Cogen> cogenEither(final Cogen ca, final Cogen cb) { + return new Cogen>() { + public Gen cogen(final Either e, final Gen g) { + return e.isLeft() ? + variant(0, ca.cogen(e.left().value(), g)) : + variant(1, cb.cogen(e.right().value(), g)); + } + }; + } + + /** + * A cogen for lists. + * + * @param ca A cogen for the elements of the list. + * @return A cogen for lists. + */ + public static Cogen> cogenList(final Cogen ca) { + return new Cogen>() { + public Gen cogen(final List as, final Gen g) { + return as.isEmpty() ? + variant(0, g) : + variant(1, ca.cogen(as.head(), cogen(as.tail(), g))); + } + }; + } + + /** + * A cogen for strings. + */ + public static final Cogen cogenString = new Cogen() { + public Gen cogen(final String s, final Gen g) { + return cogenList(cogenCharacter).cogen(fromString(s), g); + } + }; + + /** + * A cogen for string buffers. + */ + public static final Cogen cogenStringBuffer = new Cogen() { + public Gen cogen(final StringBuffer s, final Gen g) { + return cogenString.cogen(s.toString(), g); + } + }; + + /** + * A cogen for string builders. + */ + public static final Cogen cogenStringBuilder = new Cogen() { + public Gen cogen(final StringBuilder s, final Gen g) { + return cogenString.cogen(s.toString(), g); + } + }; + + /** + * A cogen for streams. + * + * @param ca A cogen for the elements of the stream. + * @return A cogen for streams. + */ + public static Cogen> cogenStream(final Cogen ca) { + return new Cogen>() { + public Gen cogen(final Stream as, final Gen g) { + return as.isEmpty() ? + variant(0, g) : + variant(1, ca.cogen(as.head(), cogen(as.tail()._1(), g))); + } + }; + } + + /** + * A cogen for the provided LcgRng + * @return A cogen for the provided LcgRng. + */ + public static Cogen cogenLcgRng() { + return new Cogen() { + @Override + public Gen cogen(LcgRng rng, Gen g) { + long i = rng.getSeed(); + return variant(i >= 0 ? 2 * i : -2 * i + 1, g); + } + }; + } + + /** + * A cogen for state. + */ + public static Cogen> cogenState(Gen as, F2 f) { + return new Cogen>() { + @Override + public Gen cogen(State s1, Gen g) { + return as.bind(r -> { + P2 p = s1.run(r); + return variant(f.f(p._1(), p._2()), g); + }); + } + }; + } + + /** + * A cogen for arrays. + * + * @param ca A cogen for the elements of the array. + * @return A cogen for arrays. + */ + public static Cogen> cogenArray(final Cogen ca) { + return new Cogen>() { + public Gen cogen(final Array as, final Gen g) { + return cogenList(ca).cogen(as.toList(), g); + } + }; + } + + /** + * A cogen for throwables. + * + * @param cs A cogen for the throwable message. + * @return A cogen for throwables. + */ + public static Cogen cogenThrowable(final Cogen cs) { + return cs.contramap(new F() { + public String f(final Throwable t) { + return t.getMessage(); + } + }); + } + + /** + * A cogen for throwables. + */ + public static final Cogen cogenThrowable = + cogenThrowable(cogenString); + + // BEGIN java.util + + /** + * A cogen for array lists. + * + * @param ca A cogen for the elements of the array list. + * @return A cogen for array lists. + */ + public static Cogen> cogenArrayList(final Cogen ca) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final ArrayList as, final Gen g) { + return cogenArray(ca).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for bit sets. + */ + public static final Cogen cogenBitSet = new Cogen() { + public Gen cogen(final BitSet s, final Gen g) { + List x = nil(); + + for (int i = 0; i < s.size(); i++) { + x = x.snoc(s.get(i)); + } + + return cogenList(cogenBoolean).cogen(x, g); + } + }; + + /** + * A cogen for calendars. + */ + public static final Cogen cogenCalendar = new Cogen() { + public Gen cogen(final Calendar c, final Gen g) { + return cogenLong.cogen(c.getTime().getTime(), g); + } + }; + + /** + * A cogen for dates. + */ + public static final Cogen cogenDate = new Cogen() { + public Gen cogen(final Date d, final Gen g) { + return cogenLong.cogen(d.getTime(), g); + } + }; + + /** + * A cogen for enum maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for enum maps. + */ + public static , V> Cogen> cogenEnumMap(final Cogen ck, + final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final EnumMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + /** + * A cogen for enum sets. + * + * @param c A cogen for the elements of the enum set. + * @return A cogen for enum sets. + */ + public static > Cogen> cogenEnumSet(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final EnumSet as, final Gen g) { + return cogenHashSet(c).cogen(new HashSet<>(as), g); + } + }; + } + + /** + * A cogen for gregorian calendars. + */ + public static final Cogen cogenGregorianCalendar = new Cogen() { + public Gen cogen(final GregorianCalendar c, final Gen g) { + return cogenLong.cogen(c.getTime().getTime(), g); + } + }; + + /** + * A cogen for hash maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for hash maps. + */ + public static Cogen> cogenHashMap(final Cogen ck, final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final HashMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + /** + * A cogen for hash sets. + * + * @param c A cogen for the elements of the hash set. + * @return A cogen for hash sets. + */ + public static Cogen> cogenHashSet(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final HashSet as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for hash tables. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for hash tables. + */ + public static Cogen> cogenHashtable(final Cogen ck, final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final Hashtable h, final Gen g) { + List> x = nil(); + + for (final Map.Entry entry : h.entrySet()) { + x = x.snoc(p(entry.getKey(), entry.getValue())); + } + + return cogenList(cogenP2(ck, cv)).cogen(x, g); + } + }; + } + + /** + * A cogen for identity hash maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for identity hash maps. + */ + public static Cogen> cogenIdentityHashMap(final Cogen ck, + final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final IdentityHashMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + /** + * A cogen for linked hash maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for linked hash maps. + */ + public static Cogen> cogenLinkedHashMap(final Cogen ck, + final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final LinkedHashMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + /** + * A cogen for linked hash sets. + * + * @param c A cogen for the elements of the linked hash set. + * @return A cogen for linked hash sets. + */ + public static Cogen> cogenLinkedHashSet(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final LinkedHashSet as, final Gen g) { + return cogenHashSet(c).cogen(new HashSet<>(as), g); + } + }; + } + + /** + * A cogen for linked lists. + * + * @param c A cogen for the elements of the linked list. + * @return A cogen for linked lists. + */ + public static Cogen> cogenLinkedList(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final LinkedList as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for priority queues. + * + * @param c A cogen for the elements of the priority queue. + * @return A cogen for priority queues. + */ + public static Cogen> cogenPriorityQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final PriorityQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for properties. + */ + public static final Cogen cogenProperties = new Cogen() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final Properties p, final Gen g) { + final Hashtable t = new Hashtable<>(); + + for (final Object s : p.keySet()) { + t.put((String) s, p.getProperty((String) s)); + } + + return cogenHashtable(cogenString, cogenString).cogen(t, g); + } + }; + + /** + * A cogen for stacks. + * + * @param c A cogen for the elements of the stack. + * @return A cogen for stacks. + */ + public static Cogen> cogenStack(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final Stack as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for tree maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for tree maps. + */ + public static Cogen> cogenTreeMap(final Cogen ck, final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final TreeMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + /** + * A cogen for tree sets. + * + * @param c A cogen for the elements of the tree set. + * @return A cogen for tree sets. + */ + public static Cogen> cogenTreeSet(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final TreeSet as, final Gen g) { + return cogenHashSet(c).cogen(new HashSet<>(as), g); + } + }; + } + + /** + * A cogen for vectors. + * + * @param c A cogen for the elements of the vector. + * @return A cogen for vectors. + */ + public static Cogen> cogenVector(final Cogen c) { + return new Cogen>() { + @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"}) + public Gen cogen(final Vector as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for weak hash maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for weak hash maps. + */ + public static Cogen> cogenWeakHashMap(final Cogen ck, + final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final WeakHashMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + // END java.util + + // BEGIN java.util.concurrent + + /** + * A cogen for array blocking queues. + * + * @param c A cogen for the elements of the array blocking queue. + * @return A cogen for array blocking queues. + */ + public static Cogen> cogenArrayBlockingQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final ArrayBlockingQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for concurrent hash maps. + * + * @param ck A cogen for the map keys. + * @param cv A cogen for the map values. + * @return A cogen for concurrent hash maps. + */ + public static Cogen> cogenConcurrentHashMap(final Cogen ck, + final Cogen cv) { + return new Cogen>() { + @SuppressWarnings("UseOfObsoleteCollectionType") + public Gen cogen(final ConcurrentHashMap m, final Gen g) { + return cogenHashtable(ck, cv).cogen(new Hashtable<>(m), g); + } + }; + } + + /** + * A cogen for concurrent linked queues. + * + * @param c A cogen for the elements of the concurrent linked queue. + * @return A cogen for concurrent linked queues. + */ + public static Cogen> cogenConcurrentLinkedQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final ConcurrentLinkedQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for copy-on-write array lists. + * + * @param c A cogen for the elements of the copy-on-write array list. + * @return A cogen for copy-on-write array lists. + */ + public static Cogen> cogenCopyOnWriteArrayList(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final CopyOnWriteArrayList as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for copy-on-write array sets. + * + * @param c A cogen for the elements of the copy-on-write array set. + * @return A cogen for copy-on-write array sets. + */ + public static Cogen> cogenCopyOnWriteArraySet(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final CopyOnWriteArraySet as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for delay queues. + * + * @param c A cogen for the elements of the delay queue. + * @return A cogen for delay queues. + */ + public static Cogen> cogenDelayQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final DelayQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for linked blocking queues. + * + * @param c A cogen for the elements of the linked blocking queue. + * @return A cogen for linked blocking queues. + */ + public static Cogen> cogenLinkedBlockingQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final LinkedBlockingQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for priority blocking queues. + * + * @param c A cogen for the elements of the priority blocking queue. + * @return A cogen for priority blocking queues. + */ + public static Cogen> cogenPriorityBlockingQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final PriorityBlockingQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + /** + * A cogen for synchronous queues. + * + * @param c A cogen for the elements of the synchronous queue. + * @return A cogen for synchronous queues. + */ + public static Cogen> cogenSynchronousQueue(final Cogen c) { + return new Cogen>() { + @SuppressWarnings("unchecked") + public Gen cogen(final SynchronousQueue as, final Gen g) { + return cogenArray(c).cogen(iterableArray(as), g); + } + }; + } + + // END java.util.concurrent + + // BEGIN java.sql + + public static final Cogen cogenSQLDate = new Cogen() { + public Gen cogen(final java.sql.Date d, final Gen g) { + return cogenLong.cogen(d.getTime(), g); + } + }; + + public static final Cogen cogenTimestamp = new Cogen() { + public Gen cogen(final Timestamp t, final Gen g) { + return cogenLong.cogen(t.getTime(), g); + } + }; + + public static final Cogen Cogen> cogenP1(final Cogen ca) { + return new Cogen>() { + public Gen cogen(final P1 p, final Gen g) { + return ca.cogen(p._1(), g); + } + }; + } + + /** + * A cogen for product-2 values. + * + * @param ca A cogen for one of the types over which the product-2 is defined. + * @param cb A cogen for one of the types over which the product-2 is defined. + * @return A cogen for product-2 values. + */ + public static Cogen> cogenP2(final Cogen ca, final Cogen cb) { + return new Cogen>() { + public Gen cogen(final P2 p, final Gen g) { + return ca.cogen(p._1(), cb.cogen(p._2(), g)); + } + }; + } + + /** + * A cogen for product-3 values. + * + * @param ca A cogen for one of the types over which the product-3 is defined. + * @param cb A cogen for one of the types over which the product-3 is defined. + * @param cc A cogen for one of the types over which the product-3 is defined. + * @return A cogen for product-3 values. + */ + public static Cogen> cogenP3(final Cogen ca, final Cogen cb, + final Cogen cc) { + return new Cogen>() { + public Gen cogen(final P3 p, final Gen g) { + return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), g))); + } + }; + } + + /** + * A cogen for product-4 values. + * + * @param ca A cogen for one of the types over which the product-4 is defined. + * @param cb A cogen for one of the types over which the product-4 is defined. + * @param cc A cogen for one of the types over which the product-4 is defined. + * @param cd A cogen for one of the types over which the product-4 is defined. + * @return A cogen for product-4 values. + */ + public static Cogen> cogenP4(final Cogen ca, final Cogen cb, + final Cogen cc, final Cogen cd) { + return new Cogen>() { + public Gen cogen(final P4 p, final Gen g) { + return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), cd.cogen(p._4(), g)))); + } + }; + } + + /** + * A cogen for product-5 values. + * + * @param ca A cogen for one of the types over which the product-5 is defined. + * @param cb A cogen for one of the types over which the product-5 is defined. + * @param cc A cogen for one of the types over which the product-5 is defined. + * @param cd A cogen for one of the types over which the product-5 is defined. + * @param ce A cogen for one of the types over which the product-5 is defined. + * @return A cogen for product-5 values. + */ + public static Cogen> cogenP5(final Cogen ca, final Cogen cb, + final Cogen cc, final Cogen cd, + final Cogen ce) { + return new Cogen>() { + public Gen cogen(final P5 p, final Gen g) { + return ca.cogen(p._1(), + cb.cogen(p._2(), cc.cogen(p._3(), cd.cogen(p._4(), ce.cogen(p._5(), g))))); + } + }; + } + + /** + * A cogen for product-6 values. + * + * @param ca A cogen for one of the types over which the product-6 is defined. + * @param cb A cogen for one of the types over which the product-6 is defined. + * @param cc A cogen for one of the types over which the product-6 is defined. + * @param cd A cogen for one of the types over which the product-6 is defined. + * @param ce A cogen for one of the types over which the product-6 is defined. + * @param cf A cogen for one of the types over which the product-6 is defined. + * @return A cogen for product-6 values. + */ + public static Cogen> cogenP6(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, + final Cogen cf) { + return new Cogen>() { + public Gen cogen(final P6 p, final Gen g) { + return ca.cogen(p._1(), cb.cogen(p._2(), + cc.cogen(p._3(), cd.cogen(p._4(), ce.cogen(p._5(), cf.cogen(p._6(), g)))))); + } + }; + } + + /** + * A cogen for product-7 values. + * + * @param ca A cogen for one of the types over which the product-7 is defined. + * @param cb A cogen for one of the types over which the product-7 is defined. + * @param cc A cogen for one of the types over which the product-7 is defined. + * @param cd A cogen for one of the types over which the product-7 is defined. + * @param ce A cogen for one of the types over which the product-7 is defined. + * @param cf A cogen for one of the types over which the product-7 is defined. + * @param cg A cogen for one of the types over which the product-7 is defined. + * @return A cogen for product-7 values. + */ + public static Cogen> cogenP7(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, + final Cogen cf, + final Cogen cg) { + return new Cogen>() { + public Gen cogen(final P7 p, final Gen g) { + return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), + cd.cogen(p._4(), ce.cogen(p._5(), cf.cogen(p._6(), cg.cogen(p._7(), g))))))); + } + }; + } + + /** + * A cogen for product-8 values. + * + * @param ca A cogen for one of the types over which the product-8 is defined. + * @param cb A cogen for one of the types over which the product-8 is defined. + * @param cc A cogen for one of the types over which the product-8 is defined. + * @param cd A cogen for one of the types over which the product-8 is defined. + * @param ce A cogen for one of the types over which the product-8 is defined. + * @param cf A cogen for one of the types over which the product-8 is defined. + * @param cg A cogen for one of the types over which the product-8 is defined. + * @param ch A cogen for one of the types over which the product-8 is defined. + * @return A cogen for product-8 values. + */ + public static Cogen> cogenP8(final Cogen ca, + final Cogen cb, + final Cogen cc, + final Cogen cd, + final Cogen ce, + final Cogen cf, + final Cogen cg, + final Cogen ch) { + return new Cogen>() { + public Gen cogen(final P8 p, final Gen g) { + return ca.cogen(p._1(), cb.cogen(p._2(), cc.cogen(p._3(), cd.cogen(p._4(), + ce.cogen(p._5(), cf.cogen(p._6(), cg.cogen(p._7(), ch.cogen(p._8(), g)))))))); + } + }; + } +} diff --git a/quickcheck/src/test/java/fj/data/test/TestCheck.java b/quickcheck/src/test/java/fj/data/test/TestCheck.java index 6bfaeaf7..935f1127 100644 --- a/quickcheck/src/test/java/fj/data/test/TestCheck.java +++ b/quickcheck/src/test/java/fj/data/test/TestCheck.java @@ -11,8 +11,6 @@ import static fj.Function.compose; import static fj.test.Arbitrary.arbLong; -import static fj.test.Coarbitrary.coarbInteger; -import static fj.test.Coarbitrary.coarbLong; import static fj.test.Property.prop; import static fj.test.Property.property; import static org.junit.Assert.*; diff --git a/quickcheck/src/test/java/fj/data/test/TestNull.java b/quickcheck/src/test/java/fj/data/test/TestNull.java index 0346407d..0fd44c6a 100644 --- a/quickcheck/src/test/java/fj/data/test/TestNull.java +++ b/quickcheck/src/test/java/fj/data/test/TestNull.java @@ -11,8 +11,6 @@ import static fj.Function.compose; import static fj.test.Arbitrary.arbLong; -import static fj.test.Coarbitrary.coarbInteger; -import static fj.test.Coarbitrary.coarbLong; import static fj.test.Property.prop; import static fj.test.Property.property; From e87d5be36daac7f52ffd44bb99a04ee13666fdee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 6 Jun 2016 20:26:23 -0400 Subject: [PATCH 557/811] Add DB.db method with Try1 --- core/src/main/java/fj/control/db/DB.java | 16 ++++++++++++ .../test/java/fj/control/db/TestDbState.java | 25 +++++++++---------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/fj/control/db/DB.java b/core/src/main/java/fj/control/db/DB.java index a7ba6a7f..4e16710e 100644 --- a/core/src/main/java/fj/control/db/DB.java +++ b/core/src/main/java/fj/control/db/DB.java @@ -2,6 +2,7 @@ import fj.F; import fj.Function; +import fj.function.Try1; import java.sql.Connection; import java.sql.SQLException; @@ -35,6 +36,21 @@ public A run(final Connection c) { }; } + /** + * Constructs a database action as a function from a database connection to a value. + * + * @param t A function from a database connection to a value allowed to throw + * SQLException + * @return A database action representing the given function. + */ + public static DB db(final Try1 t){ + return new DB() { + public A run(final Connection c) throws SQLException { + return t.f(c); + } + }; + } + /** * Returns the callable-valued function projection of this database action. * diff --git a/core/src/test/java/fj/control/db/TestDbState.java b/core/src/test/java/fj/control/db/TestDbState.java index 00933921..188eae3d 100644 --- a/core/src/test/java/fj/control/db/TestDbState.java +++ b/core/src/test/java/fj/control/db/TestDbState.java @@ -2,6 +2,7 @@ import fj.Unit; import fj.data.Option; +import fj.function.Try1; import org.apache.commons.dbutils.DbUtils; import org.junit.Test; @@ -16,20 +17,18 @@ public void testWriter() throws SQLException { final int TEN = 10; DbState writer = DbState.writer(DbState.driverManager("jdbc:h2:mem:")); - DB setup = new DB() { - @Override - public Unit run(Connection c) throws SQLException { - Statement s = null; - try { - s = c.createStatement(); - assertThat(s.executeUpdate("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))"), is(0)); - assertThat(s.executeUpdate("INSERT INTO TEST (ID, NAME) VALUES (" + TEN + ", 'FOO')"), is(1)); - } finally { - DbUtils.closeQuietly(s); - } - return Unit.unit(); + DB setup = DB.db((Try1) c -> { + Statement s = null; + try { + s = c.createStatement(); + assertThat(s.executeUpdate("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))"), is(0)); + assertThat(s.executeUpdate("INSERT INTO TEST (ID, NAME) VALUES (" + TEN + ", 'FOO')"), is(1)); + } finally { + DbUtils.closeQuietly(s); } - }; + return Unit.unit(); + }); + DB> query = new DB>() { @Override public Option run(Connection c) throws SQLException { From bcc0b711fbaaeed4912912ff7e8b569025ef446c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 14 Jun 2016 07:55:24 +0200 Subject: [PATCH 558/811] Remove extra type parameters on methods in P2.Optic. Fix #273 --- core/src/main/java/fj/P2.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 521fc14d..abe4d0d5 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -335,7 +335,7 @@ public static PLens, P2, A, C> _1p() { /** * Monomorphic lens targeted on _1. */ - public static Lens, A> _1() { + public static Lens, A> _1() { return new Lens<>(_1p()); } @@ -349,7 +349,7 @@ public static PLens, P2, B, C> _2p() { /** * Monomorphic lens targeted on _1. */ - public static Lens, B> _2() { + public static Lens, B> _2() { return new Lens<>(_2p()); } From 7a9f3d98c6f7f42eb567d237375ed1d2188b4fe6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 14 Jun 2016 08:17:12 +0200 Subject: [PATCH 559/811] Document version deprecated for toJavaArray methods. Fix #264 Also suppress unchecked warnings (#269) for them. --- core/src/main/java/fj/data/Array.java | 3 ++- core/src/main/java/fj/data/List.java | 3 ++- core/src/main/java/fj/data/Stream.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index b6538ba5..7e937200 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -135,8 +135,9 @@ public Object[] array() { * affectation of the result of this method to a non generic array * will result in runtime error (ClassCastException). * - * @deprecated use {@link #array(Class)} + * @deprecated As of release 4.6, use {@link #array(Class)}. */ + @SuppressWarnings("unchecked") @Deprecated public A[] toJavaArray() { return (A[]) array(); diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index cfd95898..2b1a728e 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -216,8 +216,9 @@ public final Object[] toArrayObject() { * affectation of the result of this method to a non generic array * will result in runtime error (ClassCastException). * - * @deprecated use {@link #array(Class)} + * @deprecated As of release 4.6, use {@link #array(Class)}. */ + @SuppressWarnings("unchecked") @Deprecated public final A[] toJavaArray() { return (A[]) toArrayObject(); diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index 01e1756b..ca4c870a 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -922,10 +922,11 @@ public final Option toOption() { * affectation of the result of this method to a non generic array * will result in runtime error (ClassCastException). * - * @deprecated use {@link #array(Class)} + * @deprecated As of release 4.6, use {@link #array(Class)}. */ @Deprecated public final A[] toJavaArray() { + @SuppressWarnings("unchecked") final A[] array = (A[]) new Object[length()]; int i = 0; for (A a: this) { From 7b84ad992b2b651cad5158de3b5e1d011cbb96b5 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 14 Jun 2016 08:22:13 +0200 Subject: [PATCH 560/811] Fix unchecked conversion warnings. Fix #269. --- core/src/test/java/fj/ClassTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/test/java/fj/ClassTest.java b/core/src/test/java/fj/ClassTest.java index 862c6fdd..2959e351 100644 --- a/core/src/test/java/fj/ClassTest.java +++ b/core/src/test/java/fj/ClassTest.java @@ -23,28 +23,28 @@ public void testInheritance() { @Test public void testClassParameters() { - Class c = Class.clas(Option.none().getClass()); + Class c = Class.clas(Option.none().getClass()); Tree cp = c.classParameters(); assertThat(cp.length(), is(1)); } @Test public void testSuperclassParameters() { - Class c = Class.clas(Option.none().getClass()); + Class c = Class.clas(Option.none().getClass()); Tree cp = c.superclassParameters(); assertThat(cp.length(), is(2)); } @Test public void testInterfaceParameters() { - Class c = Class.clas(Option.none().getClass()); - List l =c.interfaceParameters(); + Class c = Class.clas(Option.none().getClass()); + List> l =c.interfaceParameters(); assertThat(l.length(), is(0)); } @Test public void testTypeParameterTree() { - Class c = Class.clas(Option.none().getClass()); + Class c = Class.clas(Option.none().getClass()); Collection coll = c.classParameters().toCollection(); for (Type t: coll) { assertThat(Class.typeParameterTree(t).toString(), is("Tree(class fj.data.Option$None)")); From 8eac39a9ebbff5082ef98bd70bcaf8cb25038a0a Mon Sep 17 00:00:00 2001 From: mrbackend Date: Mon, 6 Jun 2016 17:17:43 +0200 Subject: [PATCH 561/811] Stack safe State --- core/src/main/java/fj/data/State.java | 213 ++++----- .../test/java/fj/data/StateProperties.java | 409 ++++++++++++++++++ 2 files changed, 516 insertions(+), 106 deletions(-) create mode 100644 props-core/src/test/java/fj/data/StateProperties.java diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 3128ae6c..1b30a55e 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -1,118 +1,119 @@ package fj.data; -import fj.*; +import fj.F; +import fj.P2; +import fj.Unit; +import fj.control.Trampoline; +import static fj.P.lazy; import static fj.P.p; +import static fj.control.Trampoline.suspend; +import static fj.data.List.cons; /** * Created by MarkPerry on 7/07/2014. */ public final class State { - private final F> run; - - private State(F> f) { - run = f; - } - - public P2 run(S s) { - return run.f(s); - } - - public static State unit(F> f) { - return new State<>(f); - } - - public static State units(F f) { - return unit((S s) -> { - S s2 = f.f(s); - return p(s2, s2); - }); - } - - public static State constant(A a) { - return unit(s -> p(s, a)); - } - - public State map(F f) { - return unit((S s) -> { - P2 p2 = run(s); - B b = f.f(p2._2()); - return p(p2._1(), b); - }); - } - - public static State modify(F f) { - return State.init().flatMap(s -> unit(s2 -> p(f.f(s), Unit.unit()))); - } - - public State mapState(F, P2> f) { - return unit(s -> f.f(run(s))); - } - - public static State flatMap(State mb, F> f) { - return mb.flatMap(f); - } - - public State flatMap(F> f) { - return unit((S s) -> { - P2 p = run(s); - A a = p._2(); - S s2 = p._1(); - State smb = f.f(a); - return smb.run(s2); - }); - } - - public static State init() { - return unit(s -> p(s, s)); - } - - public State gets() { - return unit(s -> { - P2 p = run(s); - S s2 = p._1(); - return p(s2, s2); - }); - } - - public static State put(S s) { - return unit((S z) -> p(s, Unit.unit())); - } - - public A eval(S s) { - return run(s)._2(); - } - - public S exec(S s) { - return run(s)._1(); - } - - public State withs(F f) { - return unit(F1Functions.andThen(f, run)); - } - - public static State gets(F f) { - return State.init().map(f); - } - - /** - * Evaluate each action in the sequence from left to right, and collect the results. - */ - public static State> sequence(List> list) { - return list.foldLeft((State> acc, State ma) -> - acc.flatMap((List xs) -> ma.map(xs::snoc) - ), constant(List.nil())); - } - - /** - * Map each element of a structure to an action, evaluate these actions from left to right - * and collect the results. - */ - public static State> traverse(List list, F> f) { - return list.foldLeft((State> acc, A a) -> - acc.flatMap(bs -> f.f(a).map(bs::snoc) - ), constant(List.nil())); - } + public static State unit(F> runF) { + return new State<>(s -> Trampoline.pure(runF.f(s))); + } + + public static State init() { + return unit(s -> dup(s)); + } + + public static State units(F f) { + return unit(s -> dup(f.f(s))); + } + + private static P2 dup(S s) { + return p(s, s); + } + + public static State constant(A a) { + return unit(s -> p(s, a)); + } + + public static State gets(F f) { + return unit(s -> p(s, f.f(s))); + } + + public static State put(S s) { + return unit(ignoredS -> p(s, Unit.unit())); + } + + public static State modify(F f) { + return unit(s -> p(f.f(s), Unit.unit())); + } + + public static State flatMap(State ts, F> f) { + return ts.flatMap(f); + } + + /** + * Evaluate each action in the sequence from left to right, and collect the results. + */ + public static State> sequence(List> list) { + return list + .foldLeft( + (acc, ts) -> acc.flatMap(as -> ts.map(a -> cons(a, as))), + State.>constant(List.nil())) + .map(as -> as.reverse()); + } + + /** + * Map each element of a structure to an action, evaluate these actions from left to right + * and collect the results. + */ + public static State> traverse(List list, F> f) { + return list + .foldLeft( + (acc, a) -> acc.flatMap(bs -> f.f(a).map(b -> cons(b, bs))), + State.>constant(List.nil())) + .map(bs -> bs.reverse()); + } + + private static State suspended(F>> runF) { + return new State<>(s -> suspend(lazy(() -> runF.f(s)))); + } + + private final F>> runF; + + private State(F>> runF) { + this.runF = runF; + } + + public P2 run(S s) { + return runF.f(s).run(); + } + + public A eval(S s) { + return run(s)._2(); + } + + public S exec(S s) { + return run(s)._1(); + } + + public State gets() { + return mapState(result -> p(result._1(), result._1())); + } + + public State map(F f) { + return mapState(result -> p(result._1(), f.f(result._2()))); + } + + public State mapState(F, P2> f) { + return suspended(s -> runF.f(s).map(result -> f.f(result))); + } + + public State withs(F f) { + return suspended(s -> runF.f(f.f(s))); + } + + public State flatMap(F> f) { + return suspended(s -> runF.f(s).bind(result -> Trampoline.pure(f.f(result._2()).run(result._1())))); + } } diff --git a/props-core/src/test/java/fj/data/StateProperties.java b/props-core/src/test/java/fj/data/StateProperties.java new file mode 100644 index 00000000..3fb0e2ba --- /dev/null +++ b/props-core/src/test/java/fj/data/StateProperties.java @@ -0,0 +1,409 @@ +package fj.data; + +import fj.F; +import fj.P2; +import fj.Unit; +import fj.test.Arbitrary; +import fj.test.Coarbitrary; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.P.p; +import static fj.data.List.range; +import static fj.test.Arbitrary.arbF; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbList; +import static fj.test.Arbitrary.arbP2; +import static fj.test.Arbitrary.arbitrary; +import static fj.test.Coarbitrary.coarbInteger; +import static fj.test.Coarbitrary.coarbP2; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +@RunWith(PropertyTestRunner.class) +public final class StateProperties { + + public Property unit() { + return property( + arbRunF(coarbInteger, arbInteger, arbInteger), + arbInteger, + (runF, initS) -> prop(testUnit(runF, initS))); + } + + private static boolean testUnit(F> runF, S initS) { + State instance = State.unit(runF); + P2 actual = instance.run(initS); + P2 expected = runF.f(initS); + return actual.equals(expected); + } + + public Property init() { + return property( + arbInteger, + initS -> prop(testInit(initS))); + } + + private static boolean testInit(S initS) { + State instance = State.init(); + P2 actual = instance.run(initS); + P2 expected = p(initS, initS); + return actual.equals(expected); + } + + public Property units() { + return property( + arbF(coarbInteger, arbInteger), + arbInteger, + (f, initS) -> prop(testUnits(f, initS))); + } + + private static boolean testUnits(F f, S initS) { + State instance = State.units(f); + P2 actual = instance.run(initS); + S expectedS = f.f(initS); + P2 expected = p(expectedS, expectedS); + return actual.equals(expected); + } + + public Property constant() { + return property( + arbInteger, + arbInteger, + (a, initS) -> prop(testConstant(a, initS))); + } + + private static boolean testConstant(A a, S initS) { + State instance = State.constant(a); + P2 actual = instance.run(initS); + P2 expected = p(initS, a); + return actual.equals(expected); + } + + public Property staticGets() { + return property( + arbF(coarbInteger, arbInteger), + arbInteger, + (f, initS) -> prop(testStaticGets(f, initS))); + } + + private static boolean testStaticGets(F f, S initS) { + State instance = State.gets(f); + P2 actual = instance.run(initS); + P2 expected = p(initS, f.f(initS)); + return actual.equals(expected); + } + + public Property put() { + return property( + arbInteger, + arbInteger, + (newS, initS) -> prop(testPut(newS, initS))); + } + + private static boolean testPut(S newS, S initS) { + State instance = State.put(newS); + P2 actual = instance.run(initS); + P2 expected = p(newS, Unit.unit()); + return actual.equals(expected); + } + + public Property modify() { + return property( + arbF(coarbInteger, arbInteger), + arbInteger, + (f, initS) -> prop(testModify(f, initS))); + } + + private static boolean testModify(F f, S initS) { + State instance = State.modify(f); + P2 actual = instance.run(initS); + P2 expected = p(f.f(initS), Unit.unit()); + return actual.equals(expected); + } + + public Property staticFlatMap() { + return property( + arbRunF(coarbInteger, arbInteger, arbInteger), + arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)), + arbInteger, + (runF, f, initS) -> prop(testStaticFlatMap(runF, f, initS))); + } + + private static boolean testStaticFlatMap(F> runF, F> f, S initS) { + State instance = State.flatMap(State.unit(runF), f); + P2 actual = instance.run(initS); + P2 intermediateExpected = runF.f(initS); + P2 expected = f.f(intermediateExpected._2()).run(intermediateExpected._1()); + return actual.equals(expected); + } + + public Property sequence() { + return property( + arbList(arbState(coarbInteger, arbInteger, arbInteger)), + arbInteger, + (states, initS) -> prop(testSequence(states, initS))); + } + + private static boolean testSequence(List> states, S initS) { + State> instance = State.sequence(states); + P2> actual = instance.run(initS); + + S expectedFinalS = initS; + List expectedAs = List.nil(); + List> remainingStates = states; + while (remainingStates.isNotEmpty()) { + P2 nextResult = remainingStates.head().run(expectedFinalS); + expectedFinalS = nextResult._1(); + expectedAs = List.cons(nextResult._2(), expectedAs); + remainingStates = remainingStates.tail(); + } + expectedAs = expectedAs.reverse(); + + P2> expected = p(expectedFinalS, expectedAs); + return actual.equals(expected); + } + + public Property traverse() { + return property( + arbList(arbInteger), + arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)), + arbInteger, + (as, f, initS) -> prop(testTraverse(as, f, initS))); + + } + + private static boolean testTraverse(List as, F> f, S initS) { + State> instance = State.traverse(as, f); + P2> actual = instance.run(initS); + + S expectedFinalS = initS; + List expectedFinalBs = List.nil(); + List currAs = as; + while (currAs.isNotEmpty()) { + P2 nextStateAndB = f.f(currAs.head()).run(expectedFinalS); + expectedFinalS = nextStateAndB._1(); + expectedFinalBs = List.cons(nextStateAndB._2(), expectedFinalBs); + currAs = currAs.tail(); + } + expectedFinalBs = expectedFinalBs.reverse(); + P2> expected = p(expectedFinalS, expectedFinalBs); + + return actual.equals(expected); + } + + public Property run() { + return property( + arbRunF(coarbInteger, arbInteger, arbInteger), + arbInteger, + (runF, initS) -> prop(testRun(runF, initS))); + } + + private static boolean testRun(F> runF, S initS) { + State instance = State.unit(runF); + P2 actual = instance.run(initS); + P2 expected = runF.f(initS); + return actual.equals(expected); + } + + public Property eval() { + return property( + arbRunF(coarbInteger, arbInteger, arbInteger), + arbInteger, + (runF, initS) -> prop(testEval(runF, initS))); + } + + private static boolean testEval(F> runF, S initS) { + State instance = State.unit(runF); + A actual = instance.eval(initS); + A expected = runF.f(initS)._2(); + return actual.equals(expected); + } + + public Property exec() { + return property( + arbRunF(coarbInteger, arbInteger, arbUnit), + arbInteger, + (runF, initS) -> prop(testExec(runF, initS))); + } + + private static boolean testExec(F> runF, S initS) { + State instance = State.unit(runF); + S actual = instance.exec(initS); + S expected = runF.f(initS)._1(); + return actual.equals(expected); + } + + public Property getsProperty() { + return property( + arbState(coarbInteger, arbInteger, arbInteger), + arbInteger, + (state, initS) -> prop(testGets(state, initS))); + } + + private static boolean testGets(State state, S initS) { + State instance = state.gets(); + P2 actual = instance.run(initS); + P2 expected = p(state.run(initS)._1(), state.run(initS)._1()); + return actual.equals(expected); + } + + public Property map() { + return property( + arbState(coarbInteger, arbInteger, arbInteger), + arbF(coarbInteger, arbInteger), + arbInteger, + (state, f, initS) -> prop(testMap(state, f, initS))); + } + + private static boolean testMap(State state, F f, S initS) { + State instance = state.map(f); + P2 actual = instance.run(initS); + P2 expected = state.run(initS).map2(f); + return actual.equals(expected); + } + + public Property mapState() { + return property( + arbState(coarbInteger, arbInteger, arbInteger), + arbMapStateF(coarbInteger, coarbInteger, arbInteger, arbInteger), + arbInteger, + (state, f, initS) -> prop(testMapState(state, f, initS))); + } + + private static boolean testMapState(State state, F, P2> f, S initS) { + State instance = state.mapState(f); + P2 actual = instance.run(initS); + P2 expected = f.f(state.run(initS)); + return actual.equals(expected); + } + + public Property withs() { + return property( + arbState(coarbInteger, arbInteger, arbInteger), + arbF(coarbInteger, arbInteger), + arbInteger, + (state, f, initS) -> prop(testWiths(state, f, initS))); + } + + private static boolean testWiths(State state, F f, S initS) { + State instance = state.withs(f); + P2 actual = instance.run(initS); + P2 expected = state.run(f.f(initS)); + return actual.equals(expected); + } + + public Property flatMap() { + return property( + arbState(coarbInteger, arbInteger, arbInteger), + arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)), + arbInteger, + (state, f, initS) -> prop(testFlatMap(state, f, initS))); + } + + private static boolean testFlatMap(State state, F> f, S initS) { + State instance = state.flatMap(f); + P2 actual = instance.run(initS); + P2 expected = f.f(state.run(initS)._2()).run(state.run(initS)._1()); + return actual.equals(expected); + } + + @CheckParams(minSuccessful = 1) + public Property getsStackSafety() { + return property( + arbHugeState( + arbState(coarbInteger, arbInteger, arbInteger), + currState -> arbitrary(Gen.value(currState.gets()))), + arbInteger, + (instance, initS) -> prop(testNoStackOverflow(instance, initS))); + } + + @CheckParams(minSuccessful = 1) + public Property mapStackSafety() { + return property( + arbHugeState( + arbState(coarbInteger, arbInteger, arbInteger), + currState -> arbitrary(Gen.gen(s -> r -> currState.map(arbF(coarbInteger, arbInteger).gen.gen(s, r))))), + arbInteger, + (instance, initS) -> prop(testNoStackOverflow(instance, initS))); + } + + @CheckParams(minSuccessful = 1) + public Property mapStateStackSafety() { + return property( + arbHugeState( + arbState(coarbInteger, arbInteger, arbInteger), + currState -> arbitrary(Gen.gen(s -> r -> + currState.mapState(arbMapStateF(coarbInteger, coarbInteger, arbInteger, arbInteger).gen.gen(s, r))))), + arbInteger, + (instance, initS) -> prop(testNoStackOverflow(instance, initS))); + } + + @CheckParams(minSuccessful = 1) + public Property withsStackSafety() { + return property( + arbHugeState( + arbState(coarbInteger, arbInteger, arbInteger), + currState -> arbitrary(Gen.gen(s -> r -> currState.withs(arbF(coarbInteger, arbInteger).gen.gen(s, r))))), + arbInteger, + (instance, initS) -> prop(testNoStackOverflow(instance, initS))); + } + + @CheckParams(minSuccessful = 1) + public Property flatMapStackSafety() { + return property( + arbHugeState( + arbState(coarbInteger, arbInteger, arbInteger), + currState -> arbitrary(Gen.gen(s -> r -> + currState.flatMap(arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)).gen.gen(s, r))))), + arbInteger, + (instance, initS) -> prop(testNoStackOverflow(instance, initS))); + } + + private static boolean testNoStackOverflow(State instance, S initS) { + instance.run(initS); + return true; + } + + private static final Arbitrary arbUnit = arbitrary(Gen.value(Unit.unit())); + + private static Arbitrary>> arbRunF( + Coarbitrary coarbInitS, + Arbitrary arbNextS, + Arbitrary arbValue) { + + return arbF(coarbInitS, arbP2(arbNextS, arbValue)); + } + + private static Arbitrary, P2>> arbMapStateF( + Coarbitrary coarbInitS, + Coarbitrary coarbInitValue, + Arbitrary arbNextS, + Arbitrary arbNextValue) { + + return arbF(coarbP2(coarbInitS, coarbInitValue), arbP2(arbNextS, arbNextValue)); + } + + private static Arbitrary> arbState( + Coarbitrary coarbInitS, + Arbitrary arbNextS, + Arbitrary arbValue) { + + Arbitrary>> arbRunF = arbRunF(coarbInitS, arbNextS, arbValue); + return arbitrary(Gen.gen(s -> r -> State.unit(arbRunF.gen.gen(s, r)))); + } + + private static final int HUGE_SIZE = 10000; + + private static Arbitrary> arbHugeState( + Arbitrary> arbInitState, + F, Arbitrary>> nextArbStateF) { + + return arbitrary(Gen.gen(s -> r -> range(0, HUGE_SIZE).foldLeft( + (acc, x) -> nextArbStateF.f(acc).gen.gen(s, r), + arbInitState.gen.gen(s, r)))); + } + +} From 2833a566c61cbeaf677d0519d823f7b7ab78b8bd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 14 Jun 2016 21:58:34 +0200 Subject: [PATCH 562/811] Remove use of Arbitrary wrapper --- .../test/java/fj/data/StateProperties.java | 381 +++++++++--------- 1 file changed, 189 insertions(+), 192 deletions(-) diff --git a/props-core/src/test/java/fj/data/StateProperties.java b/props-core/src/test/java/fj/data/StateProperties.java index 3fb0e2ba..c5ce2a2e 100644 --- a/props-core/src/test/java/fj/data/StateProperties.java +++ b/props-core/src/test/java/fj/data/StateProperties.java @@ -3,8 +3,7 @@ import fj.F; import fj.P2; import fj.Unit; -import fj.test.Arbitrary; -import fj.test.Coarbitrary; +import fj.test.Cogen; import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; @@ -17,21 +16,16 @@ import static fj.test.Arbitrary.arbInteger; import static fj.test.Arbitrary.arbList; import static fj.test.Arbitrary.arbP2; -import static fj.test.Arbitrary.arbitrary; -import static fj.test.Coarbitrary.coarbInteger; -import static fj.test.Coarbitrary.coarbP2; +import static fj.test.Cogen.cogenInteger; +import static fj.test.Cogen.cogenP2; import static fj.test.Property.prop; import static fj.test.Property.property; @RunWith(PropertyTestRunner.class) public final class StateProperties { - public Property unit() { - return property( - arbRunF(coarbInteger, arbInteger, arbInteger), - arbInteger, - (runF, initS) -> prop(testUnit(runF, initS))); - } + private static final Gen arbUnit = Gen.value(Unit.unit()); + private static final int HUGE_SIZE = 10000; private static boolean testUnit(F> runF, S initS) { State instance = State.unit(runF); @@ -40,12 +34,6 @@ private static boolean testUnit(F> runF, S initS) { return actual.equals(expected); } - public Property init() { - return property( - arbInteger, - initS -> prop(testInit(initS))); - } - private static boolean testInit(S initS) { State instance = State.init(); P2 actual = instance.run(initS); @@ -53,13 +41,6 @@ private static boolean testInit(S initS) { return actual.equals(expected); } - public Property units() { - return property( - arbF(coarbInteger, arbInteger), - arbInteger, - (f, initS) -> prop(testUnits(f, initS))); - } - private static boolean testUnits(F f, S initS) { State instance = State.units(f); P2 actual = instance.run(initS); @@ -68,13 +49,6 @@ private static boolean testUnits(F f, S initS) { return actual.equals(expected); } - public Property constant() { - return property( - arbInteger, - arbInteger, - (a, initS) -> prop(testConstant(a, initS))); - } - private static boolean testConstant(A a, S initS) { State instance = State.constant(a); P2 actual = instance.run(initS); @@ -82,13 +56,6 @@ private static boolean testConstant(A a, S initS) { return actual.equals(expected); } - public Property staticGets() { - return property( - arbF(coarbInteger, arbInteger), - arbInteger, - (f, initS) -> prop(testStaticGets(f, initS))); - } - private static boolean testStaticGets(F f, S initS) { State instance = State.gets(f); P2 actual = instance.run(initS); @@ -96,13 +63,6 @@ private static boolean testStaticGets(F f, S initS) { return actual.equals(expected); } - public Property put() { - return property( - arbInteger, - arbInteger, - (newS, initS) -> prop(testPut(newS, initS))); - } - private static boolean testPut(S newS, S initS) { State instance = State.put(newS); P2 actual = instance.run(initS); @@ -110,13 +70,6 @@ private static boolean testPut(S newS, S initS) { return actual.equals(expected); } - public Property modify() { - return property( - arbF(coarbInteger, arbInteger), - arbInteger, - (f, initS) -> prop(testModify(f, initS))); - } - private static boolean testModify(F f, S initS) { State instance = State.modify(f); P2 actual = instance.run(initS); @@ -124,14 +77,6 @@ private static boolean testModify(F f, S initS) { return actual.equals(expected); } - public Property staticFlatMap() { - return property( - arbRunF(coarbInteger, arbInteger, arbInteger), - arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)), - arbInteger, - (runF, f, initS) -> prop(testStaticFlatMap(runF, f, initS))); - } - private static boolean testStaticFlatMap(F> runF, F> f, S initS) { State instance = State.flatMap(State.unit(runF), f); P2 actual = instance.run(initS); @@ -140,13 +85,6 @@ private static boolean testStaticFlatMap(F> runF, F prop(testSequence(states, initS))); - } - private static boolean testSequence(List> states, S initS) { State> instance = State.sequence(states); P2> actual = instance.run(initS); @@ -166,15 +104,6 @@ private static boolean testSequence(List> states, S initS) { return actual.equals(expected); } - public Property traverse() { - return property( - arbList(arbInteger), - arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)), - arbInteger, - (as, f, initS) -> prop(testTraverse(as, f, initS))); - - } - private static boolean testTraverse(List as, F> f, S initS) { State> instance = State.traverse(as, f); P2> actual = instance.run(initS); @@ -194,13 +123,6 @@ private static boolean testTraverse(List as, F> f, S return actual.equals(expected); } - public Property run() { - return property( - arbRunF(coarbInteger, arbInteger, arbInteger), - arbInteger, - (runF, initS) -> prop(testRun(runF, initS))); - } - private static boolean testRun(F> runF, S initS) { State instance = State.unit(runF); P2 actual = instance.run(initS); @@ -208,13 +130,6 @@ private static boolean testRun(F> runF, S initS) { return actual.equals(expected); } - public Property eval() { - return property( - arbRunF(coarbInteger, arbInteger, arbInteger), - arbInteger, - (runF, initS) -> prop(testEval(runF, initS))); - } - private static boolean testEval(F> runF, S initS) { State instance = State.unit(runF); A actual = instance.eval(initS); @@ -222,13 +137,6 @@ private static boolean testEval(F> runF, S initS) { return actual.equals(expected); } - public Property exec() { - return property( - arbRunF(coarbInteger, arbInteger, arbUnit), - arbInteger, - (runF, initS) -> prop(testExec(runF, initS))); - } - private static boolean testExec(F> runF, S initS) { State instance = State.unit(runF); S actual = instance.exec(initS); @@ -236,13 +144,6 @@ private static boolean testExec(F> runF, S initS) { return actual.equals(expected); } - public Property getsProperty() { - return property( - arbState(coarbInteger, arbInteger, arbInteger), - arbInteger, - (state, initS) -> prop(testGets(state, initS))); - } - private static boolean testGets(State state, S initS) { State instance = state.gets(); P2 actual = instance.run(initS); @@ -250,14 +151,6 @@ private static boolean testGets(State state, S initS) { return actual.equals(expected); } - public Property map() { - return property( - arbState(coarbInteger, arbInteger, arbInteger), - arbF(coarbInteger, arbInteger), - arbInteger, - (state, f, initS) -> prop(testMap(state, f, initS))); - } - private static boolean testMap(State state, F f, S initS) { State instance = state.map(f); P2 actual = instance.run(initS); @@ -265,14 +158,6 @@ private static boolean testMap(State state, F f, S initS) return actual.equals(expected); } - public Property mapState() { - return property( - arbState(coarbInteger, arbInteger, arbInteger), - arbMapStateF(coarbInteger, coarbInteger, arbInteger, arbInteger), - arbInteger, - (state, f, initS) -> prop(testMapState(state, f, initS))); - } - private static boolean testMapState(State state, F, P2> f, S initS) { State instance = state.mapState(f); P2 actual = instance.run(initS); @@ -280,14 +165,6 @@ private static boolean testMapState(State state, F, P2< return actual.equals(expected); } - public Property withs() { - return property( - arbState(coarbInteger, arbInteger, arbInteger), - arbF(coarbInteger, arbInteger), - arbInteger, - (state, f, initS) -> prop(testWiths(state, f, initS))); - } - private static boolean testWiths(State state, F f, S initS) { State instance = state.withs(f); P2 actual = instance.run(initS); @@ -295,14 +172,6 @@ private static boolean testWiths(State state, F f, S initS) { return actual.equals(expected); } - public Property flatMap() { - return property( - arbState(coarbInteger, arbInteger, arbInteger), - arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)), - arbInteger, - (state, f, initS) -> prop(testFlatMap(state, f, initS))); - } - private static boolean testFlatMap(State state, F> f, S initS) { State instance = state.flatMap(f); P2 actual = instance.run(initS); @@ -310,12 +179,184 @@ private static boolean testFlatMap(State state, F return actual.equals(expected); } + private static boolean testNoStackOverflow(State instance, S initS) { + instance.run(initS); + return true; + } + + private static Gen>> arbRunF( + Cogen cogenInitS, + Gen arbNextS, + Gen arbValue) { + + return arbF(cogenInitS, arbP2(arbNextS, arbValue)); + } + + private static Gen, P2>> arbMapStateF( + Cogen cogenInitS, + Cogen cogenInitValue, + Gen arbNextS, + Gen arbNextValue) { + + return arbF(cogenP2(cogenInitS, cogenInitValue), arbP2(arbNextS, arbNextValue)); + } + + private static Gen> arbState( + Cogen cogenInitS, + Gen arbNextS, + Gen arbValue) { + + Gen>> arbRunF = arbRunF(cogenInitS, arbNextS, arbValue); + return Gen.gen(s -> r -> State.unit(arbRunF.gen(s, r))); + } + + private static Gen> arbHugeState( + Gen> arbInitState, + F, Gen>> nextArbStateF) { + + return Gen.gen(s -> r -> range(0, HUGE_SIZE).foldLeft( + (acc, x) -> nextArbStateF.f(acc).gen(s, r), + arbInitState.gen(s, r))); + } + + public Property unit() { + return property( + arbRunF(cogenInteger, arbInteger, arbInteger), + arbInteger, + (runF, initS) -> prop(testUnit(runF, initS))); + } + + public Property init() { + return property( + arbInteger, + initS -> prop(testInit(initS))); + } + + public Property units() { + return property( + arbF(cogenInteger, arbInteger), + arbInteger, + (f, initS) -> prop(testUnits(f, initS))); + } + + public Property constant() { + return property( + arbInteger, + arbInteger, + (a, initS) -> prop(testConstant(a, initS))); + } + + public Property staticGets() { + return property( + arbF(cogenInteger, arbInteger), + arbInteger, + (f, initS) -> prop(testStaticGets(f, initS))); + } + + public Property put() { + return property( + arbInteger, + arbInteger, + (newS, initS) -> prop(testPut(newS, initS))); + } + + public Property modify() { + return property( + arbF(cogenInteger, arbInteger), + arbInteger, + (f, initS) -> prop(testModify(f, initS))); + } + + public Property staticFlatMap() { + return property( + arbRunF(cogenInteger, arbInteger, arbInteger), + arbF(cogenInteger, arbState(cogenInteger, arbInteger, arbInteger)), + arbInteger, + (runF, f, initS) -> prop(testStaticFlatMap(runF, f, initS))); + } + + public Property sequence() { + return property( + arbList(arbState(cogenInteger, arbInteger, arbInteger)), + arbInteger, + (states, initS) -> prop(testSequence(states, initS))); + } + + public Property traverse() { + return property( + arbList(arbInteger), + arbF(cogenInteger, arbState(cogenInteger, arbInteger, arbInteger)), + arbInteger, + (as, f, initS) -> prop(testTraverse(as, f, initS))); + + } + + public Property run() { + return property( + arbRunF(cogenInteger, arbInteger, arbInteger), + arbInteger, + (runF, initS) -> prop(testRun(runF, initS))); + } + + public Property eval() { + return property( + arbRunF(cogenInteger, arbInteger, arbInteger), + arbInteger, + (runF, initS) -> prop(testEval(runF, initS))); + } + + public Property exec() { + return property( + arbRunF(cogenInteger, arbInteger, arbUnit), + arbInteger, + (runF, initS) -> prop(testExec(runF, initS))); + } + + public Property getsProperty() { + return property( + arbState(cogenInteger, arbInteger, arbInteger), + arbInteger, + (state, initS) -> prop(testGets(state, initS))); + } + + public Property map() { + return property( + arbState(cogenInteger, arbInteger, arbInteger), + arbF(cogenInteger, arbInteger), + arbInteger, + (state, f, initS) -> prop(testMap(state, f, initS))); + } + + public Property mapState() { + return property( + arbState(cogenInteger, arbInteger, arbInteger), + arbMapStateF(cogenInteger, cogenInteger, arbInteger, arbInteger), + arbInteger, + (state, f, initS) -> prop(testMapState(state, f, initS))); + } + + public Property withs() { + return property( + arbState(cogenInteger, arbInteger, arbInteger), + arbF(cogenInteger, arbInteger), + arbInteger, + (state, f, initS) -> prop(testWiths(state, f, initS))); + } + + public Property flatMap() { + return property( + arbState(cogenInteger, arbInteger, arbInteger), + arbF(cogenInteger, arbState(cogenInteger, arbInteger, arbInteger)), + arbInteger, + (state, f, initS) -> prop(testFlatMap(state, f, initS))); + } + @CheckParams(minSuccessful = 1) public Property getsStackSafety() { return property( arbHugeState( - arbState(coarbInteger, arbInteger, arbInteger), - currState -> arbitrary(Gen.value(currState.gets()))), + arbState(cogenInteger, arbInteger, arbInteger), + currState -> Gen.value(currState.gets())), arbInteger, (instance, initS) -> prop(testNoStackOverflow(instance, initS))); } @@ -324,8 +365,8 @@ public Property getsStackSafety() { public Property mapStackSafety() { return property( arbHugeState( - arbState(coarbInteger, arbInteger, arbInteger), - currState -> arbitrary(Gen.gen(s -> r -> currState.map(arbF(coarbInteger, arbInteger).gen.gen(s, r))))), + arbState(cogenInteger, arbInteger, arbInteger), + currState -> Gen.gen(s -> r -> currState.map(arbF(cogenInteger, arbInteger).gen(s, r)))), arbInteger, (instance, initS) -> prop(testNoStackOverflow(instance, initS))); } @@ -334,9 +375,9 @@ public Property mapStackSafety() { public Property mapStateStackSafety() { return property( arbHugeState( - arbState(coarbInteger, arbInteger, arbInteger), - currState -> arbitrary(Gen.gen(s -> r -> - currState.mapState(arbMapStateF(coarbInteger, coarbInteger, arbInteger, arbInteger).gen.gen(s, r))))), + arbState(cogenInteger, arbInteger, arbInteger), + currState -> Gen.gen(s -> r -> + currState.mapState(arbMapStateF(cogenInteger, cogenInteger, arbInteger, arbInteger).gen(s, r)))), arbInteger, (instance, initS) -> prop(testNoStackOverflow(instance, initS))); } @@ -345,8 +386,8 @@ public Property mapStateStackSafety() { public Property withsStackSafety() { return property( arbHugeState( - arbState(coarbInteger, arbInteger, arbInteger), - currState -> arbitrary(Gen.gen(s -> r -> currState.withs(arbF(coarbInteger, arbInteger).gen.gen(s, r))))), + arbState(cogenInteger, arbInteger, arbInteger), + currState -> Gen.gen(s -> r -> currState.withs(arbF(cogenInteger, arbInteger).gen(s, r)))), arbInteger, (instance, initS) -> prop(testNoStackOverflow(instance, initS))); } @@ -355,55 +396,11 @@ public Property withsStackSafety() { public Property flatMapStackSafety() { return property( arbHugeState( - arbState(coarbInteger, arbInteger, arbInteger), - currState -> arbitrary(Gen.gen(s -> r -> - currState.flatMap(arbF(coarbInteger, arbState(coarbInteger, arbInteger, arbInteger)).gen.gen(s, r))))), + arbState(cogenInteger, arbInteger, arbInteger), + currState -> Gen.gen(s -> r -> + currState.flatMap(arbF(cogenInteger, arbState(cogenInteger, arbInteger, arbInteger)).gen(s, r)))), arbInteger, (instance, initS) -> prop(testNoStackOverflow(instance, initS))); } - private static boolean testNoStackOverflow(State instance, S initS) { - instance.run(initS); - return true; - } - - private static final Arbitrary arbUnit = arbitrary(Gen.value(Unit.unit())); - - private static Arbitrary>> arbRunF( - Coarbitrary coarbInitS, - Arbitrary arbNextS, - Arbitrary arbValue) { - - return arbF(coarbInitS, arbP2(arbNextS, arbValue)); - } - - private static Arbitrary, P2>> arbMapStateF( - Coarbitrary coarbInitS, - Coarbitrary coarbInitValue, - Arbitrary arbNextS, - Arbitrary arbNextValue) { - - return arbF(coarbP2(coarbInitS, coarbInitValue), arbP2(arbNextS, arbNextValue)); - } - - private static Arbitrary> arbState( - Coarbitrary coarbInitS, - Arbitrary arbNextS, - Arbitrary arbValue) { - - Arbitrary>> arbRunF = arbRunF(coarbInitS, arbNextS, arbValue); - return arbitrary(Gen.gen(s -> r -> State.unit(arbRunF.gen.gen(s, r)))); - } - - private static final int HUGE_SIZE = 10000; - - private static Arbitrary> arbHugeState( - Arbitrary> arbInitState, - F, Arbitrary>> nextArbStateF) { - - return arbitrary(Gen.gen(s -> r -> range(0, HUGE_SIZE).foldLeft( - (acc, x) -> nextArbStateF.f(acc).gen.gen(s, r), - arbInitState.gen.gen(s, r)))); - } - } From 09b6713407a2f3e2d1eb2c2ebd72c402a8797262 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Sun, 12 Jun 2016 17:30:17 -0500 Subject: [PATCH 563/811] Implemented Equal, Hash, Arbitrary, and Shrink for Natural as well as the equals, hashCode and toString methods on Natural. Also fixed the subtract method on Natural as well as the Javadoc on the Natural Semigroup for addition. --- core/src/main/java/fj/Equal.java | 5 ++++ core/src/main/java/fj/Hash.java | 6 +++++ core/src/main/java/fj/Semigroup.java | 2 +- core/src/main/java/fj/data/Natural.java | 23 ++++++++++++++++++- .../src/main/java/fj/test/Arbitrary.java | 15 +++++++++++- quickcheck/src/main/java/fj/test/Shrink.java | 7 ++++++ 6 files changed, 55 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 2282b04e..465959e9 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -149,6 +149,11 @@ public static Equal anyEqual() { */ public static final Equal shortEqual = anyEqual(); + /** + * An equal instance for the Natural type. + */ + public static final Equal naturalEqual = bigintEqual.contramap(Natural::bigIntegerValue); + /** * An equal instance for the {@link String} type. */ diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 3e6c0ae8..14f8a9d7 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -115,6 +115,11 @@ public static Hash anyHash() { */ public static final Hash bigdecimalHash = anyHash(); + /** + * A hash instance for the {@link Natural} type. + */ + public static final Hash naturalHash = bigintHash.contramap(Natural::bigIntegerValue); + /** * A hash instance for the String type. */ @@ -535,4 +540,5 @@ public static Hash> v7Hash(final Hash ea) { public static Hash> v8Hash(final Hash ea) { return streamHash(ea).contramap(V8.toStream_()); } + } diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 1427f0e5..7c5538f2 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -219,7 +219,7 @@ public static Semigroup semigroup(final F2 sum) { semigroup(Natural::multiply); /** - * A semigroup that multiplies natural numbers. + * A semigroup that adds natural numbers. */ public static final Semigroup naturalAdditionSemigroup = semigroup(Natural::add); diff --git a/core/src/main/java/fj/data/Natural.java b/core/src/main/java/fj/data/Natural.java index 23080a49..e52f77ca 100644 --- a/core/src/main/java/fj/data/Natural.java +++ b/core/src/main/java/fj/data/Natural.java @@ -1,11 +1,16 @@ package fj.data; import static fj.Bottom.error; + +import fj.Equal; import fj.F; import static fj.Monoid.naturalAdditionMonoid; import static fj.Monoid.naturalMultiplicationMonoid; import static fj.Function.curry; + +import fj.Hash; +import fj.Show; import fj.data.vector.V2; import fj.data.vector.V; @@ -121,7 +126,7 @@ public Natural add(final Natural n) { * @return The difference between the two numbers, if this number is larger than the given one. Otherwise none. */ public Option subtract(final Natural n) { - return natural(n.value.subtract(value)); + return natural(value.subtract(n.value)); } /** @@ -286,4 +291,20 @@ public static Natural sum(final List ns) { public static Natural product(final List ns) { return naturalMultiplicationMonoid.sumLeft(ns); } + + + @Override + public int hashCode() { + return Hash.naturalHash.hash(this); + } + + @Override + public boolean equals(final Object that) { + return Equal.equals0(Natural.class, this, that, Equal.naturalEqual); + } + + @Override + public String toString() { + return Show.naturalShow.showS(this); + } } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index d8f88bed..ad671018 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -1,6 +1,8 @@ package fj.test; +import fj.Equal; import fj.F; +import fj.F1Functions; import fj.F2; import fj.F3; import fj.F4; @@ -11,6 +13,7 @@ import fj.Function; import fj.Bottom; +import static fj.Equal.longEqual; import static fj.Function.compose; import static fj.P.p; @@ -37,9 +40,12 @@ import fj.data.List; import fj.data.Set; import fj.data.TreeMap; +import fj.function.Booleans; import fj.function.Effect1; +import fj.function.Longs; import static fj.data.Stream.range; +import static fj.function.Booleans.not; import static fj.test.Gen.choose; import static fj.test.Gen.elements; import static fj.test.Gen.fail; @@ -469,6 +475,12 @@ public Gen f(final Integer i) { } }); + /** + * An arbitrary implementation for naturals. + */ + public static final Gen arbNatural = arbLong.filter(not(longEqual.eq(Long.MIN_VALUE))) + .map(Longs.abs).map(Natural::natural).map(o -> o.some()); + /** * An arbitrary implementation for character values. */ @@ -760,7 +772,7 @@ public static Gen> arbArrayList(final Gen aa) { /** * Returns an arbitrary implementation for a Java enumeration. * - * @param clazz The type of enum to return an arbtrary of. + * @param clazz The type of enum to return an arbitrary of. * @return An arbitrary for instances of the supplied enum type. */ public static > Gen arbEnumValue(final Class clazz) { @@ -1337,4 +1349,5 @@ public static Gen> arbP5(final Gen aa, fina return aa.bind(ab, ac, ad, ae, af, ag, ah, a -> b -> c -> d -> e -> f -> g -> h -> p(a, b, c, d, e, f, g, h)); } + } diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 2a2f0061..04fa6184 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -30,6 +30,7 @@ import fj.data.Either; import fj.data.Java; import fj.data.List; +import fj.data.Natural; import fj.data.Option; import fj.data.Stream; @@ -181,6 +182,11 @@ public static Shrink empty() { */ public static final Shrink shrinkDouble = shrinkLong.map(Long_Double, Double_Long); + /** + * A shrink strategy for naturals. + */ + public static final Shrink shrinkNatural = shrinkLong.map(l -> Natural.natural(l).orSome(Natural.ZERO), Natural::longValue); + /** * Returns a shrink strategy for optional values. A 'no value' is already fully * shrunk, otherwise, the shrinking occurs on the value with the given shrink strategy. @@ -846,4 +852,5 @@ public static Shrink> shrinkP5(final Shrink sg.shrink(p._7()), sh.shrink(p._8()), p8); }); } + } From 9e5b6ad23fa0ef0d9f1784396bfd86758f6b9215 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 15 Jun 2016 22:02:52 +0200 Subject: [PATCH 564/811] Remove unnecessary indirection in Equal#eq partial application. --- core/src/main/java/fj/Equal.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 465959e9..a09dceba 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -65,7 +65,7 @@ public F2 eq() { * @return A function that returns true if the given argument equals the argument to this method. */ public F eq(final A a) { - return a1 -> eq(a, a1); + return f.f(a); } /** From 03308243564d722e665de1d2f80fbfcbf449f891 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Wed, 15 Jun 2016 21:38:09 -0500 Subject: [PATCH 565/811] Fixed issue #276 by modifying the BigInteger Shrink implementation to use the same logic as the Shrink implementation for Long. Also fixed some Javadoc typos. --- quickcheck/src/main/java/fj/test/Shrink.java | 47 ++++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 04fa6184..7990401e 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -39,6 +39,8 @@ import static fj.data.Stream.nil; import static java.lang.System.arraycopy; +import static java.math.BigInteger.ZERO; + import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Time; @@ -354,7 +356,7 @@ public static Shrink> shrinkArrayList(final Shrink sa) { * A shrink strategy for enum maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for enum maps. */ public static , V> Shrink> shrinkEnumMap(final Shrink sk, final Shrink sv) { @@ -385,7 +387,7 @@ public static > Shrink> shrinkEnumSet(final Shrink< * A shrink strategy for hash maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for hash maps. */ public static Shrink> shrinkHashMap(final Shrink sk, final Shrink sv) { @@ -406,7 +408,7 @@ public static Shrink> shrinkHashSet(final Shrink sa) { * A shrink strategy for hash tables. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for hash tables. */ @SuppressWarnings("UseOfObsoleteCollectionType") @@ -430,7 +432,7 @@ public static Shrink> shrinkHashtable(final Shrink sk, * A shrink strategy for identity hash maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for identity hash maps. */ public static Shrink> shrinkIdentityHashMap(final Shrink sk, final Shrink sv) { @@ -441,7 +443,7 @@ public static Shrink> shrinkIdentityHashMap(final S * A shrink strategy for linked hash maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for linked hash maps. */ public static Shrink> shrinkLinkedHashMap(final Shrink sk, final Shrink sv) { @@ -514,7 +516,7 @@ public static Shrink> shrinkStack(final Shrink sa) { * A shrink strategy for tree maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for tree maps. */ public static Shrink> shrinkTreeMap(final Shrink sk, final Shrink sv) { @@ -545,7 +547,7 @@ public static Shrink> shrinkVector(final Shrink sa) { * A shrink strategy for weak hash maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for weak hash maps. */ public static Shrink> shrinkWeakHashMap(final Shrink sk, final Shrink sv) { @@ -570,7 +572,7 @@ public static Shrink> shrinkArrayBlockingQueue(final S * A shrink strategy for concurrent hash maps. * * @param sk The shrink strategy for keys. - * @param sv The shrink stratgey for values. + * @param sv The shrink strategy for values. * @return A shrink strategy for concurrent hash maps. */ public static Shrink> shrinkConcurrentHashMap(final Shrink sk, final Shrink sv) { @@ -676,23 +678,20 @@ public static Shrink> shrinkSynchronousQueue(final Shrin /** * A shrink strategy for big integers. */ - public static final Shrink shrinkBigInteger = - shrinkP2(shrinkByte, shrinkArray(shrinkByte)).map(bs -> { - final byte[] x = new byte[bs._2().length() + 1]; - - for (int i = 0; i < bs._2().array().length; i++) { - x[i] = bs._2().get(i); - } - - x[bs._2().length()] = bs._1(); + public static final Shrink shrinkBigInteger = shrink(i -> { + final Equal eq = Equal.bigintEqual; + final BigInteger two = BigInteger.valueOf(2L); + if (eq.eq(i, ZERO)) { + return nil(); + } else { + final Stream is = cons(ZERO, + () -> iterate(x -> x.divide(two), i) + .takeWhile(x2 -> eq.notEq(x2, ZERO)) + .map(i::subtract)); - return new BigInteger(x); - }, i -> { - final byte[] b = i.toByteArray(); - final Byte[] x = new Byte[b.length - 1]; - arraycopy(b, 0, x, 0, b.length - 1); - return p(b[0], array(x)); - }); + return Ord.bigintOrd.isLessThan(i, ZERO) ? cons(i.negate(), () -> is) : is; + } + }); /** * A shrink strategy for big decimals. From 56508b6f8ddea5f0e233b9732557ab846688ac6b Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Wed, 15 Jun 2016 23:14:12 -0500 Subject: [PATCH 566/811] Switched the the Gen and Shrink implementations for Natural to use BigInteger instead of Long. This will allow for generation of Naturals that are larger than Long.MAX_VALUE. The implementations had to be moved within their respective classes to avoid forward reference compilation errors. --- quickcheck/src/main/java/fj/test/Arbitrary.java | 11 +++++------ quickcheck/src/main/java/fj/test/Shrink.java | 10 ++++++---- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index ad671018..d7a62523 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -475,12 +475,6 @@ public Gen f(final Integer i) { } }); - /** - * An arbitrary implementation for naturals. - */ - public static final Gen arbNatural = arbLong.filter(not(longEqual.eq(Long.MIN_VALUE))) - .map(Longs.abs).map(Natural::natural).map(o -> o.some()); - /** * An arbitrary implementation for character values. */ @@ -1179,6 +1173,11 @@ public static Gen> arbSynchronousQueue(final Gen aa) // END java.math + /** + * An arbitrary implementation for naturals. + */ + public static final Gen arbNatural = arbBigInteger.map(BigInteger::abs).map(Natural::natural).map(o -> o.some()); + /** * An arbitrary implementation for locales. */ diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 7990401e..77c95381 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -184,10 +184,6 @@ public static Shrink empty() { */ public static final Shrink shrinkDouble = shrinkLong.map(Long_Double, Double_Long); - /** - * A shrink strategy for naturals. - */ - public static final Shrink shrinkNatural = shrinkLong.map(l -> Natural.natural(l).orSome(Natural.ZERO), Natural::longValue); /** * Returns a shrink strategy for optional values. A 'no value' is already fully @@ -701,6 +697,12 @@ public static Shrink> shrinkSynchronousQueue(final Shrin // END java.math + /** + * A shrink strategy for naturals. + */ + public static final Shrink shrinkNatural = shrinkBigInteger.map(l -> Natural.natural(l).orSome(Natural.ZERO), Natural::bigIntegerValue); + + /** * Returns a shrinking strategy for product-1 values. * From 6bd372ba515463051167ddc09f66f9c7641dc53c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 15:28:24 +1000 Subject: [PATCH 567/811] Added functional to PriorityQueue --- core/src/main/java/fj/data/PriorityQueue.java | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 67abdb88..18292768 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -3,6 +3,7 @@ import fj.Equal; import fj.F; import fj.Monoid; +import fj.Ord; import fj.P; import fj.P2; import fj.P3; @@ -41,10 +42,14 @@ public PriorityQueue map(F f) { ); } - public PriorityQueue filter(F f) { + public PriorityQueue filterValues(F f) { return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._2()))); } + public PriorityQueue filterKeys(F f) { + return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._1()))); + } + public boolean isEmpty() { return ftree.isEmpty(); } @@ -63,6 +68,22 @@ public PriorityQueue enqueue(List> list) { return list.foldLeft(pq -> p -> pq.enqueue(p._1(), p._2()), this); } + public boolean contains(final K k1) { + return !ftree.split(k2 -> equal.eq(k1, k2))._2().isEmpty(); + } + + public PriorityQueue enqueue(Iterable> it) { + PriorityQueue result = this; + for (P2 p: it) { + result = result.enqueue(p); + } + return result; + } + + public PriorityQueue enqueue(P2 p) { + return enqueue(p._1(), p._2()); + } + public PriorityQueue dequeue() { K top = ftree.measure(); P2>, FingerTree>> p = ftree.split(k -> equal.eq(k, top)); @@ -70,6 +91,10 @@ public PriorityQueue dequeue() { return right.isEmpty() ? this : priorityQueue(equal, p._1().append(right.tail())); } + public P2>, PriorityQueue> dequeueTop() { + return P.p(top(), dequeue()); + } + public PriorityQueue dequeue(int n) { int i = n; PriorityQueue result = this; @@ -80,8 +105,16 @@ public PriorityQueue dequeue(int n) { return result; } + public boolean isGreaterThan(Ord ok, K k) { + return top().map(p -> ok.isGreaterThan(k, p._1())).orSome(true); + } + public Stream> toStream() { - return ftree.toStream(); + return top().map(p -> Stream.cons(p, () -> dequeue().toStream())).orSome(() -> Stream.nil()); + } + + public List> toList() { + return toStream().toList(); } public String toString() { From 2a2b8eac96f2d2660987634fcf87394c0756b92c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 15:30:56 +1000 Subject: [PATCH 568/811] Added priority queue properties --- .../test/java/fj/data/PriorityQueueTest.java | 37 ------- .../properties/PriorityQueueProperties.java | 100 ++++++++++++++++++ 2 files changed, 100 insertions(+), 37 deletions(-) create mode 100644 props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java diff --git a/core/src/test/java/fj/data/PriorityQueueTest.java b/core/src/test/java/fj/data/PriorityQueueTest.java index 7e30cfc5..d7f532ed 100644 --- a/core/src/test/java/fj/data/PriorityQueueTest.java +++ b/core/src/test/java/fj/data/PriorityQueueTest.java @@ -14,42 +14,5 @@ */ public class PriorityQueueTest { - @Test - public void test1() { - PriorityQueue pq = PriorityQueue.emptyInt(); - PriorityQueue pq2 = pq.enqueue(List.list(p(1, 1))); - out.println(pq2.toString()); - } - - @Test - public void empty() { - PriorityQueue pq = PriorityQueue.emptyInt(); - assertThat(pq.isEmpty(), is(true)); - } - - @Test - public void top() { - PriorityQueue pq1 = PriorityQueue.emptyInt(); - Option> o = pq1.top(); - assertThat(o, is(Option.none())); - } - - @Test - public void dequeue() { - PriorityQueue pq1 = PriorityQueue.emptyInt().enqueue(List.list( - p(3, 6), p(10, 20), p(4, 8), p(1, 2) - )); - out.println(pq1); - assertThat(pq1.toString(), equalTo("PriorityQueue((3: 6), (10: 20), (4: 8), (1: 2))")); - - PriorityQueue pq2 = PriorityQueue.emptyInt(); - PriorityQueue pq3 = pq2.dequeue(); - out.println(pq3); - assertThat(pq3.toString(), equalTo("PriorityQueue()")); - - PriorityQueue pq4 = pq1.dequeue(); - out.println(pq4); - assertThat(pq4.toString(), equalTo("PriorityQueue((3: 6), (4: 8), (1: 2))")); - } } diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java new file mode 100644 index 00000000..92b45264 --- /dev/null +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -0,0 +1,100 @@ +package fj.data.properties; + +import fj.Ord; +import fj.P; +import fj.P2; +import fj.data.List; +import fj.data.Option; +import fj.data.PriorityQueue; +import fj.data.Set; +import fj.test.Arbitrary; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.data.Option.some; +import static fj.data.PriorityQueue.emptyInt; +import static fj.test.Arbitrary.arbAlphaNumString; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbSet; +import static fj.test.Arbitrary.arbitrary; +import static fj.test.Property.impliesBoolean; +import static fj.test.Property.prop; +import static fj.test.Property.property; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by MarkPerry on 18 Jun 16. + */ +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 100) +public class PriorityQueueProperties { + + public static Arbitrary> arbPriorityQueueIntegerString = arbUniqueQueue(arbAlphaNumString); + + public static Arbitrary> arbUniqueQueue(Arbitrary aa) { + Arbitrary> as = arbSet(Ord.intOrd, arbInteger); + Arbitrary> ints = arbitrary(as.gen.map(si -> si.toList())); + Arbitrary>> alp = arbitrary( + ints.gen.bind(li -> aa.gen.map(s -> li.map(i -> P.p(i, s)))) + ); + return arbitrary(alp.gen.map(l -> PriorityQueue.emptyInt().enqueue(l))); + } + + Property empty() { + PriorityQueue pq = emptyInt(); + return prop(pq.isEmpty()); + } + + Property addRemove() { + return property(arbPriorityQueueIntegerString, arbInteger, arbAlphaNumString, (q, i, s) -> { + Option> o = q.top(); + Option> o2 = q.enqueue(i, s).dequeue().top(); + return Property.impliesBoolean( + q.isGreaterThan(Ord.intOrd, i), +// o.map(p -> i > p._1()).orSome(true), + () -> o.equals(o2) + ); + }); + } + + Property emptyTop() { + return prop(emptyInt().top().isNone()); + } + + Property addTop() { + return property(arbPriorityQueueIntegerString, arbInteger, arbAlphaNumString, (q, i, s) -> { + Option> actual = q.enqueue(i, s).top(); + return impliesBoolean( + q.isGreaterThan(Ord.intOrd, i), +// q.top().map(p -> p._1() < i).orSome(true), + actual.equals(some(P.p(i, s)))); + }); + } + + Property sorted() { + Arbitrary> as = arbSet(Ord.intOrd, arbInteger); + Arbitrary> ints = arbitrary(as.gen.map(si -> si.toList())); + Arbitrary>> alp = arbitrary( + ints.gen.bind(li -> arbAlphaNumString.gen.map(s -> li.map(i -> P.p(i, s)))) + ); + return property(alp, list -> { + PriorityQueue q = PriorityQueue.emptyInt().enqueue(list); + List> expected = list.sort(Ord.p2Ord1(Ord.intOrd.reverse())); + List> actual = q.toStream().toList(); + assertThat(actual, equalTo(expected)); + System.out.println(actual); + return prop(actual.equals(expected)); + }); + } + + public Property sorted2() { + return property(arbPriorityQueueIntegerString, pq -> { + List> expected = pq.toList().sort(Ord.p2Ord1(Ord.intOrd.reverse())); + return prop(expected.equals(pq.toList())); + }); + } + +} From 1a7f3e672cfeeaf6fc3de66fdeeecbf671fd973a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 15:31:24 +1000 Subject: [PATCH 569/811] Added finger tree toStream property? --- .../fj/data/fingertrees/FingerTreeProperties.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java index a4265be6..b7ed83f5 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java @@ -1,5 +1,7 @@ package fj.data.fingertrees; +import fj.P2; +import fj.data.Stream; import fj.test.Property; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; @@ -17,10 +19,18 @@ @CheckParams(maxSize = 10000) public class FingerTreeProperties { - public Property size() { + Property size() { return property(arbList(arbInteger), list -> prop(list.foldLeft((acc, i) -> acc.snoc(i), FingerTree.emptyIntAddition()).length() == list.length()) ); } + Property stream() { + return property(arbList(arbInteger), list -> { + Stream s1 = list.foldLeft((acc, i) -> acc.snoc(i), FingerTree.emptyIntAddition()).toStream(); + Stream s2 = list.toStream(); + return prop(s1.equals(s2)); + }); + } + } From e0839e19d59d54cac5d2f02681c9a839d29c38e5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 17:39:28 +1000 Subject: [PATCH 570/811] Merge in upstream changes to remove arbitrary wrapper --- .../properties/PriorityQueueProperties.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java index 92b45264..9f4be0da 100644 --- a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -8,6 +8,7 @@ import fj.data.PriorityQueue; import fj.data.Set; import fj.test.Arbitrary; +import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; import fj.test.runner.PropertyTestRunner; @@ -18,7 +19,6 @@ import static fj.test.Arbitrary.arbAlphaNumString; import static fj.test.Arbitrary.arbInteger; import static fj.test.Arbitrary.arbSet; -import static fj.test.Arbitrary.arbitrary; import static fj.test.Property.impliesBoolean; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -32,15 +32,15 @@ @CheckParams(maxSize = 100) public class PriorityQueueProperties { - public static Arbitrary> arbPriorityQueueIntegerString = arbUniqueQueue(arbAlphaNumString); + public static Gen> arbPriorityQueueIntegerString = arbUniqueQueue(arbAlphaNumString); - public static Arbitrary> arbUniqueQueue(Arbitrary aa) { - Arbitrary> as = arbSet(Ord.intOrd, arbInteger); - Arbitrary> ints = arbitrary(as.gen.map(si -> si.toList())); - Arbitrary>> alp = arbitrary( - ints.gen.bind(li -> aa.gen.map(s -> li.map(i -> P.p(i, s)))) + public static Gen> arbUniqueQueue(Gen aa) { + Gen> as = arbSet(Ord.intOrd, arbInteger); + Gen> ints = (as.map(si -> si.toList())); + Gen>> alp = ( + ints.bind(li -> aa.map(s -> li.map(i -> P.p(i, s)))) ); - return arbitrary(alp.gen.map(l -> PriorityQueue.emptyInt().enqueue(l))); + return (alp.map(l -> PriorityQueue.emptyInt().enqueue(l))); } Property empty() { @@ -75,10 +75,10 @@ Property addTop() { } Property sorted() { - Arbitrary> as = arbSet(Ord.intOrd, arbInteger); - Arbitrary> ints = arbitrary(as.gen.map(si -> si.toList())); - Arbitrary>> alp = arbitrary( - ints.gen.bind(li -> arbAlphaNumString.gen.map(s -> li.map(i -> P.p(i, s)))) + Gen> as = arbSet(Ord.intOrd, arbInteger); + Gen> ints = (as.map(si -> si.toList())); + Gen>> alp = ( + ints.bind(li -> arbAlphaNumString.map(s -> li.map(i -> P.p(i, s)))) ); return property(alp, list -> { PriorityQueue q = PriorityQueue.emptyInt().enqueue(list); From e3d8fce63b2587d3fae0a769c82b00b8311dfc7d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 20:31:59 +1000 Subject: [PATCH 571/811] Added priority queue and related methods javadoc --- core/src/main/java/fj/Monoid.java | 15 ++++- core/src/main/java/fj/data/PriorityQueue.java | 66 ++++++++++++++++++- .../java/fj/data/fingertrees/FingerTree.java | 12 ++++ .../test/java/fj/data/PriorityQueueTest.java | 18 ----- .../properties/PriorityQueueProperties.java | 39 +++++------ 5 files changed, 107 insertions(+), 43 deletions(-) delete mode 100644 core/src/test/java/fj/data/PriorityQueueTest.java diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index d9bf40b5..3436d5a3 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -401,8 +401,14 @@ public static Monoid> ioMonoid(final Monoid ma) { return monoid(Semigroup.ioSemigroup(ma.semigroup()), IOFunctions.unit(ma.zero())); } + /** + * A monoid for the maximum of two integers. + */ public static final Monoid intMaxMonoid = monoid(Semigroup.intMaximumSemigroup, Integer.MIN_VALUE); + /** + * A monoid for the minimum of two integers. + */ public static final Monoid intMinMonoid = monoid(Semigroup.intMinimumSemigroup, Integer.MAX_VALUE); /** @@ -420,7 +426,14 @@ public static Monoid> setMonoid(final Ord o) { return monoid(Semigroup.setSemigroup(), Set.empty(o)); } - public static Monoid ordMonoid(Ord o, A zero) { + + /** + * A monoid for the maximum of elements with ordering o. + * + * @param o An ordering of elements. + * @param zero The minimum element. + */ + public static Monoid ordMaxMonoid(final Ord o, final A zero) { return monoid(o.max, zero); } diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 18292768..51abcabf 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -11,6 +11,8 @@ import fj.data.fingertrees.FingerTree; /** + * A priority queue implementation backed by a {@link fj.data.fingertrees.FingerTree}. The finger tree nodes are annotated with type K, are combined using a monoid of K and both the key and value are stored in the leaf. Priorities of the same value are returned FIFO (first in, first out). + * * Created by MarkPerry on 31 May 16. */ public class PriorityQueue { @@ -23,18 +25,33 @@ private PriorityQueue(Equal e, FingerTree> ft) { ftree = ft; } + /** + * Creates a priority queue from a finger tree. + */ public static PriorityQueue priorityQueue(Equal e, FingerTree> ft) { return new PriorityQueue(e, ft); } + /** + * Creates an empty priority queue. + * + * @param m A monoid to combine node annotations. + * @param e A value to compare key equality. + */ public static PriorityQueue empty(Monoid m, Equal e) { return priorityQueue(e, FingerTree.empty(m, (P2 p) -> p._1())); } + /** + * An empty priority queue with integer priorities. + */ public static PriorityQueue emptyInt() { return priorityQueue(Equal.intEqual, FingerTree.empty(Monoid.intMaxMonoid, (P2 p) -> p._1())); } + /** + * Maps the values in each node with function f. + */ public PriorityQueue map(F f) { return priorityQueue(equal, ftree.map(p2 -> p2.map2(a -> f.f(a)), @@ -42,36 +59,60 @@ public PriorityQueue map(F f) { ); } + /** + * Filters nodes based on the value inside each node. + */ public PriorityQueue filterValues(F f) { return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._2()))); } + /** + * Filters the nodes based on the annotation of each node. + */ public PriorityQueue filterKeys(F f) { return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._1()))); } + /** + * Is the tree empty? + */ public boolean isEmpty() { return ftree.isEmpty(); } + /** + * If the tree is not empty, returns the node with highest priority otherwise returns nothing. + */ public Option> top() { K top = ftree.measure(); P2>, FingerTree>> p = ftree.split(k -> equal.eq(top, k)); return p._2().headOption(); } + /** + * Adds a node with priority k and value a. This operation take O(1). + */ public PriorityQueue enqueue(K k, A a) { return priorityQueue(equal, ftree.snoc(P.p(k, a))); } + /** + * Adds nodes using the list of products with priority k and value a. This operation takes O(list.length()). + */ public PriorityQueue enqueue(List> list) { return list.foldLeft(pq -> p -> pq.enqueue(p._1(), p._2()), this); } - public boolean contains(final K k1) { - return !ftree.split(k2 -> equal.eq(k1, k2))._2().isEmpty(); + /** + * Does the priority k exist already? + */ + public boolean contains(final K k) { + return !ftree.split(k2 -> equal.eq(k, k2))._2().isEmpty(); } + /** + * Adds nodes using the iterable of products with priority k and value a. + */ public PriorityQueue enqueue(Iterable> it) { PriorityQueue result = this; for (P2 p: it) { @@ -80,10 +121,16 @@ public PriorityQueue enqueue(Iterable> it) { return result; } + /** + * Adds a node with priority k and value a. This operation take O(1). + */ public PriorityQueue enqueue(P2 p) { return enqueue(p._1(), p._2()); } + /** + * Removes the node with the highest priority. + */ public PriorityQueue dequeue() { K top = ftree.measure(); P2>, FingerTree>> p = ftree.split(k -> equal.eq(k, top)); @@ -91,10 +138,16 @@ public PriorityQueue dequeue() { return right.isEmpty() ? this : priorityQueue(equal, p._1().append(right.tail())); } + /** + * Returns a tuple of the node with the highest priority and the rest of the priority queue. + */ public P2>, PriorityQueue> dequeueTop() { return P.p(top(), dequeue()); } + /** + * Removes the top n elements with the highest priority. + */ public PriorityQueue dequeue(int n) { int i = n; PriorityQueue result = this; @@ -105,14 +158,23 @@ public PriorityQueue dequeue(int n) { return result; } + /** + * Does the priority k have greater priority than the top of the queue? + */ public boolean isGreaterThan(Ord ok, K k) { return top().map(p -> ok.isGreaterThan(k, p._1())).orSome(true); } + /** + * Returns a stream of products with priority k and value a. + */ public Stream> toStream() { return top().map(p -> Stream.cons(p, () -> dequeue().toStream())).orSome(() -> Stream.nil()); } + /** + * Returns a list of products with priority k and value a. + */ public List> toList() { return toStream().toList(); } diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index aa72f020..ee985611 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -231,10 +231,22 @@ public static FingerTree emptyIntAddition() { return empty(intAdditionMonoid, Function.constant(1)); } + /** + * Creates an empty finger tree with elements of type A and node annotations + * of type V. + * + * @param m A monoid to combine node annotations + * @param f Function to convert node element to annotation. + * @return An empty finger tree. + */ public static FingerTree empty(Monoid m, F f) { return FingerTree.mkTree(measured(m, f)).empty(); } + /** + * Returns a finger tree which combines the integer node annotations with the + * maximum function. A priority queue with integer priorities. + */ public static FingerTree> emptyIntMax() { return empty(intMaxMonoid, (P2 p) -> p._1()); } diff --git a/core/src/test/java/fj/data/PriorityQueueTest.java b/core/src/test/java/fj/data/PriorityQueueTest.java deleted file mode 100644 index d7f532ed..00000000 --- a/core/src/test/java/fj/data/PriorityQueueTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package fj.data; - -import fj.P2; -import org.junit.Test; - -import static fj.P.p; -import static java.lang.System.out; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -/** - * Created by MarkPerry on 1 Jun 16. - */ -public class PriorityQueueTest { - - -} diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java index 9f4be0da..aae27f67 100644 --- a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -7,7 +7,6 @@ import fj.data.Option; import fj.data.PriorityQueue; import fj.data.Set; -import fj.test.Arbitrary; import fj.test.Gen; import fj.test.Property; import fj.test.reflect.CheckParams; @@ -22,8 +21,6 @@ import static fj.test.Property.impliesBoolean; import static fj.test.Property.prop; import static fj.test.Property.property; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; /** * Created by MarkPerry on 18 Jun 16. @@ -34,6 +31,9 @@ public class PriorityQueueProperties { public static Gen> arbPriorityQueueIntegerString = arbUniqueQueue(arbAlphaNumString); + /** + * Returns a queue with unique integer priorities. + */ public static Gen> arbUniqueQueue(Gen aa) { Gen> as = arbSet(Ord.intOrd, arbInteger); Gen> ints = (as.map(si -> si.toList())); @@ -48,49 +48,44 @@ Property empty() { return prop(pq.isEmpty()); } + /** + * Adding a priority that is at the top and then removing it returns the original top. + */ Property addRemove() { return property(arbPriorityQueueIntegerString, arbInteger, arbAlphaNumString, (q, i, s) -> { Option> o = q.top(); Option> o2 = q.enqueue(i, s).dequeue().top(); return Property.impliesBoolean( q.isGreaterThan(Ord.intOrd, i), -// o.map(p -> i > p._1()).orSome(true), () -> o.equals(o2) ); }); } + /** + * An empty queue has no top. + */ Property emptyTop() { return prop(emptyInt().top().isNone()); } + /** + * Adding a value with the highest priority makes it the top item. + */ Property addTop() { return property(arbPriorityQueueIntegerString, arbInteger, arbAlphaNumString, (q, i, s) -> { Option> actual = q.enqueue(i, s).top(); return impliesBoolean( q.isGreaterThan(Ord.intOrd, i), -// q.top().map(p -> p._1() < i).orSome(true), actual.equals(some(P.p(i, s)))); }); } - Property sorted() { - Gen> as = arbSet(Ord.intOrd, arbInteger); - Gen> ints = (as.map(si -> si.toList())); - Gen>> alp = ( - ints.bind(li -> arbAlphaNumString.map(s -> li.map(i -> P.p(i, s)))) - ); - return property(alp, list -> { - PriorityQueue q = PriorityQueue.emptyInt().enqueue(list); - List> expected = list.sort(Ord.p2Ord1(Ord.intOrd.reverse())); - List> actual = q.toStream().toList(); - assertThat(actual, equalTo(expected)); - System.out.println(actual); - return prop(actual.equals(expected)); - }); - } - - public Property sorted2() { + /** + * Sorting a list returns the same as putting the list into a priority queue and getting + * the queue as a list. + */ + public Property sorted() { return property(arbPriorityQueueIntegerString, pq -> { List> expected = pq.toList().sort(Ord.p2Ord1(Ord.intOrd.reverse())); return prop(expected.equals(pq.toList())); From c9788d4a21c90444e06914ca834e2aa6f51bc72c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 22:14:13 +1000 Subject: [PATCH 572/811] Make sorting a list stable --- core/src/main/java/fj/data/List.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 2b1a728e..d1f5ae63 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -962,7 +962,7 @@ List merge(List xs, List ys, final Ord o) { final A x = xs.head(); final A y = ys.head(); - if (o.isLessThan(x, y)) { + if (o.isLessThan(x, y) || o.eq(x, y)) { buf.snoc(x); xs = xs.tail(); } else { From 72d980f73cb053723a000fa0cae85accc1207075 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 22:15:35 +1000 Subject: [PATCH 573/811] Added priority queue top N, equal to top, greater than top --- core/src/main/java/fj/data/PriorityQueue.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 51abcabf..0559ca00 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -10,6 +10,8 @@ import fj.Show; import fj.data.fingertrees.FingerTree; +import static fj.data.List.list; + /** * A priority queue implementation backed by a {@link fj.data.fingertrees.FingerTree}. The finger tree nodes are annotated with type K, are combined using a monoid of K and both the key and value are stored in the leaf. Priorities of the same value are returned FIFO (first in, first out). * @@ -89,6 +91,16 @@ public Option> top() { return p._2().headOption(); } + public List> topN() { + Stream> s = toStream(); + if (s.isEmpty()) { + return List.nil(); + } else { + final K k = s.head()._1(); + return s.takeWhile(p -> equal.eq(k, p._1())).toList(); + } + } + /** * Adds a node with priority k and value a. This operation take O(1). */ @@ -159,10 +171,18 @@ public PriorityQueue dequeue(int n) { } /** - * Does the priority k have greater priority than the top of the queue? + * Does the top of the queue have lower priority than k? */ + public boolean isLessThan(Ord ok, K k) { + return top().map(p -> ok.isLessThan(p._1(), k)).orSome(true); + } + public boolean isGreaterThan(Ord ok, K k) { - return top().map(p -> ok.isGreaterThan(k, p._1())).orSome(true); + return top().map(p -> ok.isGreaterThan(p._1(), k)).orSome(false); + } + + public boolean isEqual(Ord ok, K k) { + return top().map(p -> ok.eq(p._1(), k)).orSome(false); } /** From e5bc0e1bddb3df23966077bab0b6b67fcb1b41b2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 22:16:11 +1000 Subject: [PATCH 574/811] FIFO priority queue properties where the key is equal to the top key --- .../properties/PriorityQueueProperties.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java index aae27f67..ba387cad 100644 --- a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -17,10 +17,14 @@ import static fj.data.PriorityQueue.emptyInt; import static fj.test.Arbitrary.arbAlphaNumString; import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbList; +import static fj.test.Arbitrary.arbP2; import static fj.test.Arbitrary.arbSet; import static fj.test.Property.impliesBoolean; import static fj.test.Property.prop; import static fj.test.Property.property; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; /** * Created by MarkPerry on 18 Jun 16. @@ -29,7 +33,7 @@ @CheckParams(maxSize = 100) public class PriorityQueueProperties { - public static Gen> arbPriorityQueueIntegerString = arbUniqueQueue(arbAlphaNumString); + public static Gen> arbPriorityQueueIntegerString = arbQueue(arbAlphaNumString); /** * Returns a queue with unique integer priorities. @@ -43,6 +47,11 @@ public static Gen> arbUniqueQueue(Gen aa) { return (alp.map(l -> PriorityQueue.emptyInt().enqueue(l))); } + public static Gen> arbQueue(Gen aa) { + Gen>> g = arbList(arbP2(arbInteger, aa)); + return g.map(l -> PriorityQueue.emptyInt().enqueue(l)); + } + Property empty() { PriorityQueue pq = emptyInt(); return prop(pq.isEmpty()); @@ -53,11 +62,10 @@ Property empty() { */ Property addRemove() { return property(arbPriorityQueueIntegerString, arbInteger, arbAlphaNumString, (q, i, s) -> { - Option> o = q.top(); - Option> o2 = q.enqueue(i, s).dequeue().top(); - return Property.impliesBoolean( - q.isGreaterThan(Ord.intOrd, i), - () -> o.equals(o2) + Option> t1 = q.top(); + Option> t2 = q.enqueue(i, s).dequeue().top(); + return prop(q.isLessThan(Ord.intOrd, i) ? + t1.equals(t2) : t2.map(p -> p._1() >= i).orSome(true) ); }); } @@ -75,20 +83,36 @@ Property emptyTop() { Property addTop() { return property(arbPriorityQueueIntegerString, arbInteger, arbAlphaNumString, (q, i, s) -> { Option> actual = q.enqueue(i, s).top(); - return impliesBoolean( - q.isGreaterThan(Ord.intOrd, i), - actual.equals(some(P.p(i, s)))); + return prop(q.isLessThan(Ord.intOrd, i) ? actual.equals(some(P.p(i, s))) : actual.equals(q.top())); }); } /** - * Sorting a list returns the same as putting the list into a priority queue and getting - * the queue as a list. + * Sorting a list returns the same as putting the list into a priority queue and getting the queue as a list. */ public Property sorted() { return property(arbPriorityQueueIntegerString, pq -> { List> expected = pq.toList().sort(Ord.p2Ord1(Ord.intOrd.reverse())); - return prop(expected.equals(pq.toList())); + List> actual = pq.toList(); + assertThat(actual, equalTo(expected)); + return prop(actual.equals(expected)); + }); + } + + /** + * Where the top n of the queue has just one element then: + * - Enqueueing and then topN of the queue should return a list of the top and the new item + * - Enqueuing and then dequeueing and then topping the queue should return the new item + */ + Property singleTopSame() { + return property(arbPriorityQueueIntegerString, arbAlphaNumString, (pq, s) -> { + Option o1 = pq.top().map(p -> p._1()); + return o1.map(j -> { + boolean b = pq.topN().length() == 1; + Property p1 = impliesBoolean(b, () -> pq.enqueue(j, s).dequeue().top().equals(some(P.p(j, s)))); + Property p2 = impliesBoolean(b, () -> pq.enqueue(j, s).topN().equals(List.list(pq.top().some(), P.p(j, s)))); + return p1.and(p2); + }).orSome(prop(true)); }); } From fc9f9bd0a5b7a933d5ec6b4c726aaf9928672ef9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 18 Jun 2016 23:07:56 +1000 Subject: [PATCH 575/811] Added Ord.isLessThanOrEqualTo to Ord --- core/src/main/java/fj/Ord.java | 13 +++++++++++++ core/src/main/java/fj/data/List.java | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 41b87f94..e9fb2d4b 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -92,6 +92,19 @@ public boolean isLessThan(final A a1, final A a2) { return compare(a1, a2) == Ordering.LT; } + /** + * Returns true if the first given argument is less than or equal to the second given argument, + * false otherwise. + * + * @param a1 An instance to compare for ordering to another. + * @param a2 An instance to compare for ordering to another. + * @return true if the first given argument is less than or equal to the second given argument, + * false otherwise. + */ + public boolean isLessThanOrEqualTo(final A a1, final A a2) { + return isLessThan(a1, a2) || eq(a1, a2); + } + /** * Returns true if the first given argument is greater than the second given * argument, false otherwise. diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index d1f5ae63..c2d21b06 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -962,7 +962,7 @@ List merge(List xs, List ys, final Ord o) { final A x = xs.head(); final A y = ys.head(); - if (o.isLessThan(x, y) || o.eq(x, y)) { + if (o.isLessThanOrEqualTo(x, y)) { buf.snoc(x); xs = xs.tail(); } else { From 50433620e595ee70ab6aaa74ca6bed243b6ad382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Tue, 7 Jun 2016 22:01:00 -0400 Subject: [PATCH 576/811] Add test for IO --- core/src/test/java/fj/IOTest.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 core/src/test/java/fj/IOTest.java diff --git a/core/src/test/java/fj/IOTest.java b/core/src/test/java/fj/IOTest.java new file mode 100644 index 00000000..f965204c --- /dev/null +++ b/core/src/test/java/fj/IOTest.java @@ -0,0 +1,30 @@ +package fj; + +import fj.data.IO; +import fj.data.IOFunctions; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + + +public class IOTest { + + @Test + public void testLift() throws IOException { + final IO readName = () -> new BufferedReader(new StringReader("foo")).readLine(); + final F> upperCaseAndPrint = F1Functions., String>o(this::println).f(String::toUpperCase); + final IO readAndPrintUpperCasedName = IOFunctions.bind(readName, upperCaseAndPrint); + assertThat(readAndPrintUpperCasedName.run(), is("FOO")); + } + + public IO println(final String s) { + return () -> { + return s; + }; + } +} From 371831331cdc41486c0814f801e497ab12a26ed6 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 19 Jun 2016 23:58:40 +1000 Subject: [PATCH 577/811] Added asserts, remove commented out and printlns from FingerTreeTest --- .../fj/data/fingertrees/FingerTreeTest.java | 40 +++++-------------- 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index 901c9c89..2a64b44b 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -20,6 +20,8 @@ */ public class FingerTreeTest { + public static final int SIZE = 10; + @Test public void size() { validateSize(List.list(-92, 68, 54, -77, -18, 67)); @@ -36,20 +38,11 @@ void validateSize(List list) { public FingerTree midSeq() { FingerTree ft = FingerTree.emptyIntAddition(); - // out.println(ft.toString()); - return List.range(1, 10).foldLeft(ft2 -> i -> { - FingerTree ft3 = ft2.snoc(i); -// out.println(ft3.toString()); - return ft3; - }, ft); + return List.range(1, SIZE).foldLeft(ft2 -> i -> ft2.snoc(i), ft); } - - @Test public void testSeqString() { -// FingerTree ft = FingerTree.emptyIntAddition(); -// out.println(ft.toString()); String actual = midSeq().toString(); String expected = "Deep(9 -> One(1 -> 1), Deep(6 -> One(3 -> Node3(3 -> V3(2,3,4))), Empty(), One(3 -> Node3(3 -> V3(5,6,7)))), Two(2 -> V2(8,9)))"; assertThat(actual, equalTo(expected)); @@ -57,47 +50,34 @@ public void testSeqString() { public FingerTree> midPriorityQueue() { FingerTree> ft = FingerTree.emptyIntMax(); -// out.println(ft.toString()); - return List.range(1, 10).foldLeft(ft2 -> i -> { + return List.range(1, SIZE).foldLeft(ft2 -> i -> { int j = i % 2 == 0 ? 2 * i : i; FingerTree> ft3 = ft2.snoc(P.p(j, j)); -// out.println(ft3.toString()); return ft3; }, ft); } @Test public void testQueueString() { -// FingerTree> ft = FingerTree.emptyIntMax(); -// out.println(ft.toString()); String actual = midPriorityQueue().toString(); String expected = "Deep(16 -> One(1 -> (1,1)), Deep(12 -> One(8 -> Node3(8 -> V3((4,4),(3,3),(8,8)))), Empty(), One(12 -> Node3(12 -> V3((5,5),(12,12),(7,7))))), Two(16 -> V2((16,16),(9,9))))"; assertThat(actual, equalTo(expected)); - } @Test public void stream() { FingerTree ft = midSeq(); - out.println(ft); - Stream s = ft.toStream(); - System.out.println(s.toList()); - - out.println(midPriorityQueue()); - out.println(midPriorityQueue().toStream().toList()); + assertThat(ft.toStream().toList(), equalTo(List.range(1, SIZE))); } @Test public void split() { - + int splitPoint = 3; FingerTree ft = FingerTree.emptyIntAddition(); - FingerTree ft3 = List.range(1, 10).foldLeft(ft2 -> i -> ft2.snoc(i), ft); - P2, FingerTree> p = ft3.split(v -> v >= 3); - Show> fts = Show.fingerTreeShow(intShow, intShow); - Show, FingerTree>> s = Show.p2Show(fts, fts); - System.out.println(s.showS(p)); - System.out.println(p); - + FingerTree ft3 = List.range(1, SIZE).foldLeft(ft2 -> i -> ft2.snoc(i), ft); + P2, FingerTree> p = ft3.split(v -> v >= splitPoint); + assertThat(p._1().toStream().toList(), equalTo(List.range(1, splitPoint))); + assertThat(p._2().toStream().toList(), equalTo(List.range(splitPoint, SIZE))); } From a506f0619cffc9a4b0820ada03f69012280195b4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 20 Jun 2016 00:15:03 +1000 Subject: [PATCH 578/811] Implemented suggestons from @jbgi for PriorityQueue --- core/src/main/java/fj/data/PriorityQueue.java | 24 ++++++++++++------- .../properties/PriorityQueueProperties.java | 1 - 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 0559ca00..49d185c9 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -13,11 +13,15 @@ import static fj.data.List.list; /** - * A priority queue implementation backed by a {@link fj.data.fingertrees.FingerTree}. The finger tree nodes are annotated with type K, are combined using a monoid of K and both the key and value are stored in the leaf. Priorities of the same value are returned FIFO (first in, first out). + * A priority queue implementation backed by a + * {@link fj.data.fingertrees.FingerTree}. The finger tree nodes are + * annotated with type K, are combined using a monoid of K and both the + * key and value are stored in the leaf. Priorities of the same value + * are returned FIFO (first in, first out). * * Created by MarkPerry on 31 May 16. */ -public class PriorityQueue { +public final class PriorityQueue { private final FingerTree> ftree; private final Equal equal; @@ -31,7 +35,7 @@ private PriorityQueue(Equal e, FingerTree> ft) { * Creates a priority queue from a finger tree. */ public static PriorityQueue priorityQueue(Equal e, FingerTree> ft) { - return new PriorityQueue(e, ft); + return new PriorityQueue<>(e, ft); } /** @@ -41,14 +45,14 @@ public static PriorityQueue priorityQueue(Equal e, FingerTree PriorityQueue empty(Monoid m, Equal e) { - return priorityQueue(e, FingerTree.empty(m, (P2 p) -> p._1())); + return priorityQueue(e, FingerTree.empty(m, P2.__1())); } /** * An empty priority queue with integer priorities. */ public static PriorityQueue emptyInt() { - return priorityQueue(Equal.intEqual, FingerTree.empty(Monoid.intMaxMonoid, (P2 p) -> p._1())); + return empty(Monoid.intMaxMonoid, Equal.intEqual); } /** @@ -56,8 +60,9 @@ public static PriorityQueue emptyInt() { */ public PriorityQueue map(F f) { return priorityQueue(equal, - ftree.map(p2 -> p2.map2(a -> f.f(a)), - FingerTree.measured(ftree.measured().monoid(), (P2 p2) -> p2._1())) + ftree.map(P2.map2_(f), + FingerTree.measured(ftree.measured().monoid(), P2.__1()) + ) ); } @@ -91,6 +96,9 @@ public Option> top() { return p._2().headOption(); } + /** + * Returns all the elements of the queue with the highest (same) priority. + */ public List> topN() { Stream> s = toStream(); if (s.isEmpty()) { @@ -153,7 +161,7 @@ public PriorityQueue dequeue() { /** * Returns a tuple of the node with the highest priority and the rest of the priority queue. */ - public P2>, PriorityQueue> dequeueTop() { + public P2>, PriorityQueue> topDequeue() { return P.p(top(), dequeue()); } diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java index ba387cad..2bde7e6e 100644 --- a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -94,7 +94,6 @@ public Property sorted() { return property(arbPriorityQueueIntegerString, pq -> { List> expected = pq.toList().sort(Ord.p2Ord1(Ord.intOrd.reverse())); List> actual = pq.toList(); - assertThat(actual, equalTo(expected)); return prop(actual.equals(expected)); }); } From d2bd8cb2e91df657cee587b9fff87e016c59ce31 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 19 Jun 2016 09:11:18 +0200 Subject: [PATCH 579/811] Added F1Functions#dimap (profunctor pattern) --- core/src/main/java/fj/F1Functions.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 7b97675a..3b46642f 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -677,4 +677,11 @@ public static F contramap(F target, F f) { return andThen(f, target); } + /** + * Both map (with g) and contramap (with f) the target function. (Profunctor pattern) + */ + public static F dimap(F target, F f, F g) { + return c -> g.f(target.f(f.f(c))); + } + } From d1f24b3609640fa41d08be8628fbc80611a3216b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 19 Jun 2016 10:39:53 +0200 Subject: [PATCH 580/811] avoid andThen indirection in F1 map and contramap --- core/src/main/java/fj/F1Functions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java index 3b46642f..00bdf515 100644 --- a/core/src/main/java/fj/F1Functions.java +++ b/core/src/main/java/fj/F1Functions.java @@ -670,11 +670,11 @@ public static ArrayList mapJ(final F f, final ArrayList as) { } public static F map(F target, F f) { - return andThen(target, f); + return o(f, target); } public static F contramap(F target, F f) { - return andThen(f, target); + return o(target, f); } /** From 435109241022928961c01f877ee3a22e5438adab Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 19 Jun 2016 10:41:18 +0200 Subject: [PATCH 581/811] add an uncurried version of Function.apply for better perf. --- core/src/main/java/fj/Function.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 87888fad..f95b1c87 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -718,7 +718,18 @@ public static F bind(final F ma, final F> f) { * @return A new function after applying the given higher-order function to the given function. */ public static F apply(final F> cab, final F ca) { - return bind(cab, f -> compose(f, ca)); + return apply(uncurryF2(cab), ca); + } + + /** + * Performs function application within a higher-order function (applicative functor pattern). + * + * @param cab The higher-order function to apply a function to. + * @param ca A function to apply within a higher-order function. + * @return A new function after applying the given higher-order function to the given function. + */ + public static F apply(final F2 cab, final F ca) { + return c -> cab.f(c, ca.f(c)); } /** From 0704e22c5707ef8c6dbb1b459816bfba4a682ce9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 19 Jun 2016 10:50:08 +0200 Subject: [PATCH 582/811] Ord: Take better advantage of the curried comparison function. also improved isLessThanOrEqualTo and simplified Ord instances of Comparable types. --- core/src/main/java/fj/Ord.java | 107 +++++++++++---------------------- 1 file changed, 34 insertions(+), 73 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index e9fb2d4b..04cc46b9 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -14,6 +14,8 @@ import java.math.BigInteger; import java.util.Comparator; +import static fj.Function.apply; +import static fj.Function.compose; import static fj.Function.curry; import static fj.Semigroup.semigroup; @@ -27,6 +29,8 @@ public final class Ord { private Ord(final F> f) { this.f = f; + this.max = a1 -> apply((a2, o) -> o == Ordering.GT ? a1 : a2, f.f(a1)); + this.min = a1 -> apply((a2, o) -> o == Ordering.LT ? a1 : a2, f.f(a1)); } /** @@ -66,7 +70,7 @@ public boolean eq(final A a1, final A a2) { * @return An Equal for this order. */ public Equal equal() { - return Equal.equal(curry(this::eq)); + return Equal.equal(a -> compose(o -> o == Ordering.EQ, f.f(a))); } /** @@ -102,7 +106,7 @@ public boolean isLessThan(final A a1, final A a2) { * false otherwise. */ public boolean isLessThanOrEqualTo(final A a1, final A a2) { - return isLessThan(a1, a2) || eq(a1, a2); + return compare(a1, a2) != Ordering.GT; } /** @@ -125,7 +129,7 @@ public boolean isGreaterThan(final A a1, final A a2) { * @return A function that returns true if its argument is less than the argument to this method. */ public F isLessThan(final A a) { - return a2 -> compare(a2, a) == Ordering.LT; + return compose(o -> o != Ordering.LT, f.f(a)); } /** @@ -135,7 +139,7 @@ public F isLessThan(final A a) { * @return A function that returns true if its argument is greater than the argument to this method. */ public F isGreaterThan(final A a) { - return a2 -> compare(a2, a) == Ordering.GT; + return compose(o -> o != Ordering.GT, f.f(a)); } /** @@ -164,19 +168,19 @@ public A min(final A a1, final A a2) { /** * A function that returns the greater of its two arguments. */ - public final F> max = curry(this::max); + public final F> max; /** * A function that returns the lesser of its two arguments. */ - public final F> min = curry(this::min); + public final F> min; public final Semigroup minSemigroup() { - return semigroup(this::min); + return semigroup(min); } public final Semigroup maxSemigroup() { - return semigroup(this::max); + return semigroup(max); } public final Ord reverse() { return ord(Function.flip(f)); } @@ -194,92 +198,52 @@ public static Ord ord(final F> f) { /** * An order instance for the boolean type. */ - public static final Ord booleanOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord booleanOrd = comparableOrd(); /** * An order instance for the byte type. */ - public static final Ord byteOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord byteOrd = comparableOrd(); /** * An order instance for the char type. */ - public static final Ord charOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord charOrd = comparableOrd(); /** * An order instance for the double type. */ - public static final Ord doubleOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord doubleOrd = comparableOrd(); /** * An order instance for the float type. */ - public static final Ord floatOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord floatOrd = comparableOrd(); /** * An order instance for the int type. */ - public static final Ord intOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord intOrd = comparableOrd(); /** * An order instance for the BigInteger type. */ - public static final Ord bigintOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord bigintOrd = comparableOrd(); /** * An order instance for the BigDecimal type. */ - public static final Ord bigdecimalOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord bigdecimalOrd = comparableOrd(); /** * An order instance for the long type. */ - public static final Ord longOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord longOrd = comparableOrd(); /** * An order instance for the short type. */ - public static final Ord shortOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord shortOrd = comparableOrd(); /** * An order instance for the {@link Ordering} type. @@ -297,23 +261,17 @@ public static Ord ord(final F> f) { /** * An order instance for the {@link String} type. */ - public static final Ord stringOrd = ord( - a1 -> a2 -> { - final int x = a1.compareTo(a2); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; - }); + public static final Ord stringOrd = comparableOrd(); /** * An order instance for the {@link StringBuffer} type. */ - public static final Ord stringBufferOrd = - ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); + public static final Ord stringBufferOrd = stringOrd.contramap(StringBuffer::toString); /** * An order instance for the {@link StringBuffer} type. */ - public static final Ord stringBuilderOrd = - ord(a1 -> a2 -> stringOrd.compare(a1.toString(), a2.toString())); + public static final Ord stringBuilderOrd = stringOrd.contramap(StringBuilder::toString); /** * An order instance for the {@link Option} type. @@ -527,9 +485,9 @@ public static > Ord comparableOrd() { * @see #hashEqualsOrd() */ public static Ord hashOrd() { - return ord(a -> a2 -> { - final int x = a.hashCode() - a2.hashCode(); - return x < 0 ? Ordering.LT : x == 0 ? Ordering.EQ : Ordering.GT; + return ord(a -> { + int aHash = a.hashCode(); + return a2 -> Ordering.fromInt(Integer.compare(aHash, a2.hashCode())); }); } @@ -541,9 +499,12 @@ public static Ord hashOrd() { * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. */ public static Ord hashEqualsOrd() { - return ord(a -> a2 -> { - final int x = a.hashCode() - a2.hashCode(); - return x < 0 ? Ordering.LT : x == 0 && a.equals(a2) ? Ordering.EQ : Ordering.GT; + return ord(a -> { + int aHash = a.hashCode(); + return a2 -> { + final int a2Hash = a2.hashCode(); + return aHash < a2Hash ? Ordering.LT : aHash == a2Hash && a.equals(a2) ? Ordering.EQ : Ordering.GT; + }; }); } From 3812a832501f4b7be4024347c1e8f1fa89c45125 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 19 Jun 2016 14:51:08 +0200 Subject: [PATCH 583/811] Add uncons to FingerTree --- .../main/java/fj/data/fingertrees/FingerTree.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index ee985611..160b5508 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -167,6 +167,18 @@ public final Option headOption() { return isEmpty() ? Option.none() : Option.some(head()); } + /** + * Performs a reduction on this finger tree using the given arguments. + * + * @param nil The value to return if this finger tree is empty. + * @param cons The function to apply to the head and tail of this finger tree if it is not empty. + * @return A reduction on this finger tree. + */ + public final B uncons(B nil, F2, B> cons) { + return isEmpty() ? nil : cons.f(head(), tail()); + } + + /** * The last element of this tree. This is an O(1) operation. * From f21c310653b6f06d6d05c70030c6bbe1807408cd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 19 Jun 2016 14:55:24 +0200 Subject: [PATCH 584/811] Add PriorityQueue.unqueue and use it to implement some other methods. + some other minor refactoring. --- core/src/main/java/fj/data/PriorityQueue.java | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 49d185c9..2649a253 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -2,15 +2,17 @@ import fj.Equal; import fj.F; +import fj.F2; import fj.Monoid; import fj.Ord; import fj.P; import fj.P2; -import fj.P3; import fj.Show; import fj.data.fingertrees.FingerTree; -import static fj.data.List.list; +import static fj.Function.compose; +import static fj.data.Option.none; +import static fj.data.Option.some; /** * A priority queue implementation backed by a @@ -91,22 +93,17 @@ public boolean isEmpty() { * If the tree is not empty, returns the node with highest priority otherwise returns nothing. */ public Option> top() { - K top = ftree.measure(); - P2>, FingerTree>> p = ftree.split(k -> equal.eq(top, k)); - return p._2().headOption(); + return unqueue(none(), (top, tail) -> some(top)); } /** * Returns all the elements of the queue with the highest (same) priority. */ public List> topN() { - Stream> s = toStream(); - if (s.isEmpty()) { - return List.nil(); - } else { - final K k = s.head()._1(); - return s.takeWhile(p -> equal.eq(k, p._1())).toList(); - } + return toStream().uncons( + List.nil(), + top -> tail -> List.cons(top, tail._1().takeWhile(compose(equal.eq(top._1()), P2.__1())).toList()) + ); } /** @@ -127,7 +124,7 @@ public PriorityQueue enqueue(List> list) { * Does the priority k exist already? */ public boolean contains(final K k) { - return !ftree.split(k2 -> equal.eq(k, k2))._2().isEmpty(); + return !ftree.split(equal.eq(k))._2().isEmpty(); } /** @@ -152,17 +149,30 @@ public PriorityQueue enqueue(P2 p) { * Removes the node with the highest priority. */ public PriorityQueue dequeue() { - K top = ftree.measure(); - P2>, FingerTree>> p = ftree.split(k -> equal.eq(k, top)); - FingerTree> right = p._2(); - return right.isEmpty() ? this : priorityQueue(equal, p._1().append(right.tail())); + return unqueue(this, (top, tail) -> tail); } /** * Returns a tuple of the node with the highest priority and the rest of the priority queue. */ public P2>, PriorityQueue> topDequeue() { - return P.p(top(), dequeue()); + return unqueue(P.p(none(), this), (top, tail) -> P.p(some(top), tail)); + } + + /** + * Performs a reduction on this priority queue using the given arguments. + * + * @param empty The value to return if this queue is empty. + * @param topDequeue The function to apply to the top priority element and the tail of the queue (without its top element). + * @return A reduction on this queue. + */ + public B unqueue(B empty, F2, PriorityQueue, B> topDequeue) { + K top = ftree.measure(); + P2>, FingerTree>> p = ftree.split(equal.eq(top)); + return p._2().uncons( + empty, + (head, tail) -> topDequeue.f(head, priorityQueue(equal, p._1().append(tail))) + ); } /** @@ -182,22 +192,22 @@ public PriorityQueue dequeue(int n) { * Does the top of the queue have lower priority than k? */ public boolean isLessThan(Ord ok, K k) { - return top().map(p -> ok.isLessThan(p._1(), k)).orSome(true); + return top().option(true, p -> ok.isLessThan(p._1(), k)); } public boolean isGreaterThan(Ord ok, K k) { - return top().map(p -> ok.isGreaterThan(p._1(), k)).orSome(false); + return top().option(false, p -> ok.isGreaterThan(p._1(), k)); } public boolean isEqual(Ord ok, K k) { - return top().map(p -> ok.eq(p._1(), k)).orSome(false); + return top().option(false, p -> ok.eq(p._1(), k)); } /** * Returns a stream of products with priority k and value a. */ public Stream> toStream() { - return top().map(p -> Stream.cons(p, () -> dequeue().toStream())).orSome(() -> Stream.nil()); + return unqueue(Stream.nil(), (top, tail) -> Stream.cons(top, () -> tail.toStream())); } /** From 17efc98972b07644248ae8dec8d3bcbdd56fe66a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 22:04:58 +0200 Subject: [PATCH 585/811] remove old workaround for javac bugs that have been fixed. --- core/src/main/java/fj/control/Trampoline.java | 14 ++++++-------- core/src/main/java/fj/data/List.java | 5 +---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index cd477dd0..37491c3b 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -52,14 +52,12 @@ public Trampoline bind(final F> f) { // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result // gets shifted into the continuation. public Either>, A> resume() { - return left(sub.resume().either(p -> p.map(ot -> { - // WARNING: In JDK 8, update 25 (current version) the following code is a - // workaround for an internal JDK compiler error, likely due to - // https:bugs.openjdk.java.net/browse/JDK-8062253. - F, Trampoline> f = o -> o.foldNormal(cont, t -> t._1().bind(cont)); - F, Trampoline> g = c -> codense(c.sub, o -> c.cont.f(o).bind(cont)); - return ot.fold(f, g); - }), o -> P.lazy(() -> cont.f(o)))); + return left(sub.resume().either(p -> p.map(ot -> + ot.fold( + o -> o.foldNormal(cont, t -> t._1().bind(cont)), + c -> codense(c.sub, o -> c.cont.f(o).bind(cont)) + ) + ), o -> P.lazy(() -> cont.f(o)))); } } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index c2d21b06..c7e1562f 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -88,10 +88,7 @@ public final Iterator iterator() { * @return The length of this list. */ public final int length() { - // WARNING: In JDK 8, update 25 (current version) the following code triggers an internal JDK compiler error, likely due to https://bugs.openjdk.java.net/browse/JDK-8062253. The code below is a workaround for this compiler bug. - // return foldLeft(i -> a -> i + 1, 0); - F2 f = (i, a) -> i + 1; - return foldLeft(f, 0); + return foldLeft((i, a) -> i + 1, 0); } /** From 9983ab260fe7a7efb297106f8f967906a5360570 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 22:23:31 +0200 Subject: [PATCH 586/811] Use uncurried version of foldLeft as default implementation to avoid creation of closures in tight loop. --- core/src/main/java/fj/data/List.java | 30 +++++++++---------- core/src/main/java/fj/data/PriorityQueue.java | 2 +- core/src/main/java/fj/data/Stream.java | 30 ++++++++----------- 3 files changed, 29 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index c2d21b06..48e93e32 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -751,13 +751,7 @@ public final Trampoline foldRightC(final F2 f, final B b) { * @return The final result after the left-fold reduction. */ public final B foldLeft(final F> f, final B b) { - B x = b; - - for (List xs = this; !xs.isEmpty(); xs = xs.tail()) { - x = f.f(x).f(xs.head()); - } - - return x; + return foldLeft(uncurryF2(f), b); } /** @@ -768,7 +762,13 @@ public final B foldLeft(final F> f, final B b) { * @return The final result after the left-fold reduction. */ public final B foldLeft(final F2 f, final B b) { - return foldLeft(curry(f), b); + B x = b; + + for (List xs = this; !xs.isEmpty(); xs = xs.tail()) { + x = f.f(x, xs.head()); + } + + return x; } /** @@ -779,7 +779,9 @@ public final B foldLeft(final F2 f, final B b) { * @return The final result after the left-fold reduction. */ public final A foldLeft1(final F2 f) { - return foldLeft1(curry(f)); + if (isEmpty()) + throw error("Undefined: foldLeft1 on empty list"); + return tail().foldLeft(f, head()); } /** @@ -790,9 +792,7 @@ public final A foldLeft1(final F2 f) { * @return The final result after the left-fold reduction. */ public final A foldLeft1(final F> f) { - if (isEmpty()) - throw error("Undefined: foldLeft1 on empty list"); - return tail().foldLeft(f, head()); + return foldLeft1(uncurryF2(f)); } /** @@ -801,7 +801,7 @@ public final A foldLeft1(final F> f) { * @return A new list that is the reverse of this one. */ public final List reverse() { - return foldLeft(as -> a -> cons(a, as), List.nil()); + return foldLeft((as, a) -> cons(a, as), nil()); } /** @@ -904,7 +904,7 @@ public final List> partition(final int n) { * @param f Predicate function. */ public final P2, List> partition(F f) { - P2, List> p2 = foldLeft(acc -> a -> + P2, List> p2 = foldLeft((acc, a) -> f.f(a) ? p(acc._1().cons(a), acc._2()) : p(acc._1(), acc._2().cons(a)), p(nil(), nil()) ); @@ -1393,7 +1393,7 @@ public final TreeMap groupBy( final D groupingIdentity, final F2 groupingAcc, final Ord keyOrd) { - return this.foldLeft(map -> element -> { + return this.foldLeft((map, element) -> { final B key = keyFunction.f(element); final C value = valueFunction.f(element); return map.set(key, map.get(key) diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 2649a253..21f6ed6f 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -117,7 +117,7 @@ public PriorityQueue enqueue(K k, A a) { * Adds nodes using the list of products with priority k and value a. This operation takes O(list.length()). */ public PriorityQueue enqueue(List> list) { - return list.foldLeft(pq -> p -> pq.enqueue(p._1(), p._2()), this); + return list.foldLeft((pq, p) -> pq.enqueue(p._1(), p._2()), this); } /** diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index ca4c870a..ae37d714 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -22,11 +22,7 @@ import java.util.*; import static fj.Bottom.error; -import static fj.Function.compose; -import static fj.Function.constant; -import static fj.Function.curry; -import static fj.Function.flip; -import static fj.Function.identity; +import static fj.Function.*; import static fj.P.p; import static fj.P.p2; import static fj.Unit.unit; @@ -167,12 +163,7 @@ public final B foldRight1(final F2 f, final B b) { * @return The final result after the left-fold reduction. */ public final B foldLeft(final F> f, final B b) { - B x = b; - - for (Stream xs = this; !xs.isEmpty(); xs = xs.tail()._1()) - x = f.f(x).f(xs.head()); - - return x; + return foldLeft(uncurryF2(f), b); } /** @@ -183,7 +174,12 @@ public final B foldLeft(final F> f, final B b) { * @return The final result after the left-fold reduction. */ public final B foldLeft(final F2 f, final B b) { - return foldLeft(curry(f), b); + B x = b; + + for (Stream xs = this; !xs.isEmpty(); xs = xs.tail()._1()) + x = f.f(x, xs.head()); + + return x; } /** @@ -194,7 +190,9 @@ public final B foldLeft(final F2 f, final B b) { * @return The final result after the left-fold reduction. */ public final A foldLeft1(final F2 f) { - return foldLeft1(curry(f)); + if (isEmpty()) + throw error("Undefined: foldLeft1 on empty list"); + return tail()._1().foldLeft(f, head()); } /** @@ -205,9 +203,7 @@ public final A foldLeft1(final F2 f) { * @return The final result after the left-fold reduction. */ public final A foldLeft1(final F> f) { - if (isEmpty()) - throw error("Undefined: foldLeft1 on empty list"); - return tail()._1().foldLeft(f, head()); + return foldLeft1(uncurryF2(f)); } /** @@ -1188,7 +1184,7 @@ public final P2, Stream> split(final F p) { * @return A new stream that is the reverse of this one. */ public final Stream reverse() { - return foldLeft(as -> a -> cons(a, () -> as), Stream.nil()); + return foldLeft((as, a) -> cons(a, () -> as), Stream.nil()); } /** From cab3299d677dda81ade19849e18119e24ba35ea9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 22:29:33 +0200 Subject: [PATCH 587/811] Add first class either catamorphism --- core/src/main/java/fj/data/Either.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index a4f0fc02..c0c143af 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -737,6 +737,17 @@ public static Either right(final B b) { return new Right<>(b); } + /** + * First class catamorphism for either. Folds over this either breaking into left or right. + * + * @param left The function to call if this is left. + * @param right The function to call if this is right. + * @return The reducing function. + */ + public static F, X> cata(final F left, final F right) { + return e -> e.either(left, right); + } + /** * @return A function that maps another function across an either's left projection. */ From 7c2605ec48ce183b388d9d9a1b71bd936de63658 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 22:54:48 +0200 Subject: [PATCH 588/811] Add first class option catamorphism --- core/src/main/java/fj/data/Option.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 4cdb411f..f1b228d0 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -688,6 +688,18 @@ public static F> fromNull() { return Option::fromNull; } + /** + * First-class catamorphism for Option: return a function that will performs + * a reduction on an optional value using the given arguments. + * + * @param none The value to return if this optional value has no value. + * @param some The function to apply to the value of this optional value. + * @return the reducing function. + */ + public static final F, B> cata(final B none, final F some) { + return o -> o.option(none, some); + } + /** * Joins the given optional value of optional value using a bind operation. * From 25d10ea69eb94036f98bfbcb022aa7442edbfb9b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 23:29:43 +0200 Subject: [PATCH 589/811] Initial implementation of optimizable definitions for Equal --- core/src/main/java/fj/Equal.java | 167 ++++++++++++++++++++++++------- 1 file changed, 130 insertions(+), 37 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index a09dceba..bb10f442 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -1,8 +1,19 @@ package fj; -import static fj.Function.curry; - -import fj.data.*; +import fj.data.Array; +import fj.data.Either; +import fj.data.LazyString; +import fj.data.List; +import fj.data.Natural; +import fj.data.NonEmptyList; +import fj.data.Option; +import fj.data.Seq; +import fj.data.Set; +import fj.data.Stream; +import fj.data.Tree; +import fj.data.TreeMap; +import fj.data.Validation; +import fj.data.Writer; import fj.data.hlist.HList; import fj.data.vector.V2; import fj.data.vector.V3; @@ -12,8 +23,12 @@ import fj.data.vector.V7; import fj.data.vector.V8; -import java.math.BigInteger; import java.math.BigDecimal; +import java.math.BigInteger; + +import static fj.Function.compose; +import static fj.Function.constant; +import static fj.Function.curry; /** * Tests for equality between two objects. @@ -21,10 +36,37 @@ * @version %build.number% */ public final class Equal { - private final F> f; - private Equal(final F> f) { - this.f = f; + /** + * Primitives functions of Equal: minimal definition and overridable methods. + */ + interface Definition { + + F equal(A a); + + default boolean equal(A a1, A a2) { + return equal(a1).f(a2); + } + } + + /** + * Primitives functions of Equal: alternative minimal definition and overridable methods. + */ + interface AlternateDefinition extends Definition { + + @Override + default F equal(A a) { + return a2 -> equal(a, a2); + } + + @Override + boolean equal(A a1, A a2); + } + + private final Definition def; + + private Equal(final Definition def) { + this.def = def; } /** @@ -35,7 +77,7 @@ private Equal(final F> f) { * @return true if the two given arguments are equal, false otherwise. */ public boolean eq(final A a1, final A a2) { - return f.f(a1).f(a2); + return def.equal(a1, a2); } /** @@ -46,7 +88,7 @@ public boolean eq(final A a1, final A a2) { * @return true if the two given arguments are not equal, false otherwise. */ public boolean notEq(final A a1, final A a2) { - return !eq(a1, a2); + return !def.equal(a1, a2); } /** @@ -55,7 +97,7 @@ public boolean notEq(final A a1, final A a2) { * @return A function that returns true if the two given arguments are equal. */ public F2 eq() { - return this::eq; + return def::equal; } /** @@ -65,7 +107,7 @@ public F2 eq() { * @return A function that returns true if the given argument equals the argument to this method. */ public F eq(final A a) { - return f.f(a); + return def.equal(a); } /** @@ -75,7 +117,18 @@ public F eq(final A a) { * @return A new equal. */ public Equal contramap(final F f) { - return equal(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); + Definition eaDef = def; + return equalDef(new Definition(){ + @Override + public F equal(B b) { + return compose(eaDef.equal(f.f(b)), f); + } + + @Override + public boolean equal(B b1, B b2) { + return eaDef.equal(f.f(b1), f.f(b2)); + } + }); } /** @@ -85,7 +138,27 @@ public Equal contramap(final F f) { * @return An equal instance from the given function. */ public static Equal equal(final F> f) { - return new Equal<>(f); + return new Equal<>(f::f); + } + + /** + * Constructs an equal instance from the given definition. + * + * @param definition The minimal definition of the equal instance. + * @return An equal instance from the given function. + */ + public static Equal equalDef(final Definition definition) { + return new Equal<>(definition); + } + + /** + * Constructs an equal instance from the given definition. + * + * @param definition The minimal definition of the equal instance. + * @return An equal instance from the given function. + */ + public static Equal equalAltDef(final AlternateDefinition definition) { + return new Equal<>(definition); } /** @@ -96,7 +169,17 @@ public static Equal equal(final F> f) { * equality. */ public static Equal anyEqual() { - return equal(a1 -> a1::equals); + return equalDef(new Definition() { + @Override + public F equal(A a) { + return a::equals; + } + + @Override + public boolean equal(A a1, A a2) { + return a1.equals(a2); + } + }); } /** @@ -163,7 +246,7 @@ public static Equal anyEqual() { * An equal instance for the {@link StringBuffer} type. */ public static final Equal stringBufferEqual = - equal(sb1 -> sb2 -> { + equalAltDef((sb1, sb2) -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -177,7 +260,7 @@ public static Equal anyEqual() { * An equal instance for the {@link StringBuilder} type. */ public static final Equal stringBuilderEqual = - equal(sb1 -> sb2 -> { + equalAltDef((sb1, sb2) -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -195,8 +278,12 @@ public static Equal anyEqual() { * @return An equal instance for the {@link Either} type. */ public static Equal> eitherEqual(final Equal ea, final Equal eb) { - return equal(e1 -> e2 -> e1.isLeft() && e2.isLeft() && ea.f.f(e1.left().value()).f(e2.left().value()) || - e1.isRight() && e2.isRight() && eb.f.f(e1.right().value()).f(e2.right().value())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + return equalDef(e1 -> e1.either( + a1 -> Either.cata(eaDef.equal(a1), (B __) -> false), + b1 -> Either.cata((A __)-> false, ebDef.equal(b1)) + )); } /** @@ -217,12 +304,13 @@ public static Equal> validationEqual(final Equal ea, * @return An equal instance for the {@link List} type. */ public static Equal> listEqual(final Equal ea) { - return equal(a1 -> a2 -> { + Definition eaDef = ea.def; + return equalAltDef((a1, a2) -> { List x1 = a1; List x2 = a2; while (x1.isNotEmpty() && x2.isNotEmpty()) { - if (!ea.eq(x1.head(), x2.head())) + if (!eaDef.equal(x1.head(), x2.head())) return false; x1 = x1.tail(); @@ -250,12 +338,15 @@ public static Equal> nonEmptyListEqual(final Equal ea) { * @return An equal instance for the {@link Option} type. */ public static Equal> optionEqual(final Equal ea) { - return equal(o1 -> o2 -> o1.isNone() && o2.isNone() || - o1.isSome() && o2.isSome() && ea.f.f(o1.some()).f(o2.some())); + Definition eaDef = ea.def; + return equalDef(o1 -> o1.option( + Option.isNone_(), + a1 -> Option.cata(false, eaDef.equal(a1)) + )); } public static Equal> seqEqual(final Equal e) { - return equal(s1 -> s2 -> streamEqual(e).eq(s1.toStream(), s2.toStream())); + return streamEqual(e).contramap(Seq::toStream); } /** @@ -265,12 +356,13 @@ public static Equal> seqEqual(final Equal e) { * @return An equal instance for the {@link Stream} type. */ public static Equal> streamEqual(final Equal ea) { - return equal(a1 -> a2 -> { + Definition eaDef = ea.def; + return equalAltDef((a1, a2) -> { Stream x1 = a1; Stream x2 = a2; while (x1.isNotEmpty() && x2.isNotEmpty()) { - if (!ea.eq(x1.head(), x2.head())) + if (!eaDef.equal(x1.head(), x2.head())) return false; x1 = x1.tail()._1(); @@ -288,10 +380,11 @@ public static Equal> streamEqual(final Equal ea) { * @return An equal instance for the {@link Array} type. */ public static Equal> arrayEqual(final Equal ea) { - return equal(a1 -> a2 -> { + Definition eaDef = ea.def; + return equalAltDef((a1, a2) -> { if (a1.length() == a2.length()) { for (int i = 0; i < a1.length(); i++) { - if (!ea.eq(a1.get(i), a2.get(i))) + if (!eaDef.equal(a1.get(i), a2.get(i))) return false; } return true; @@ -307,7 +400,7 @@ public static Equal> arrayEqual(final Equal ea) { * @return An equal instance for the {@link Tree} type. */ public static Equal> treeEqual(final Equal ea) { - return Equal.equal(curry((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(Equal.treeEqual(ea))).eq(t2.subForest(), t1.subForest()))); + return equalAltDef((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest())); } /** @@ -317,7 +410,7 @@ public static Equal> treeEqual(final Equal ea) { * @return An equal instance for a product-1. */ public static Equal> p1Equal(final Equal ea) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1())); + return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1())); } /** @@ -328,7 +421,7 @@ public static Equal> p1Equal(final Equal ea) { * @return An equal instance for a product-2. */ public static Equal> p2Equal(final Equal ea, final Equal eb) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2())); + return equalAltDef((p1, p2)-> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2())); } /** @@ -340,7 +433,7 @@ public static Equal> p2Equal(final Equal ea, final Equal e * @return An equal instance for a product-3. */ public static Equal> p3Equal(final Equal ea, final Equal eb, final Equal ec) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3())); + return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3())); } /** @@ -354,7 +447,7 @@ public static Equal> p3Equal(final Equal ea, final Equa */ public static Equal> p4Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4())); } @@ -371,7 +464,7 @@ public static Equal> p4Equal(final Equal ea, fina public static Equal> p5Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5())); } @@ -389,7 +482,7 @@ public static Equal> p5Equal(final Equal ea public static Equal> p6Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee, final Equal ef) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6())); } @@ -409,7 +502,7 @@ public static Equal> p5Equal(final Equal ea final Equal ec, final Equal ed, final Equal ee, final Equal ef, final Equal eg) { - return equal(p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && eg.eq(p1._7(), p2._7())); } @@ -435,8 +528,8 @@ public static Equal> p5Equal(final Equal ea final Equal ef, final Equal eg, final Equal eh) { - return equal( - p1 -> p2 -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && + return equalAltDef( + (p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8())); } From 6945c784a98afccec1089f570f72d20f5cbcb193 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 22 Jun 2016 20:40:36 +0200 Subject: [PATCH 590/811] Finish migrating Equal to use optimizable definition --- core/src/main/java/fj/Equal.java | 114 ++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index bb10f442..e5b2ebb1 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -54,13 +54,13 @@ default boolean equal(A a1, A a2) { */ interface AlternateDefinition extends Definition { + @Override + boolean equal(A a1, A a2); + @Override default F equal(A a) { return a2 -> equal(a, a2); } - - @Override - boolean equal(A a1, A a2); } private final Definition def; @@ -144,7 +144,7 @@ public static Equal equal(final F> f) { /** * Constructs an equal instance from the given definition. * - * @param definition The minimal definition of the equal instance. + * @param definition a definition of the equal instance. * @return An equal instance from the given function. */ public static Equal equalDef(final Definition definition) { @@ -152,12 +152,12 @@ public static Equal equalDef(final Definition definition) { } /** - * Constructs an equal instance from the given definition. + * Constructs an equal instance from the given (alternative) definition. * - * @param definition The minimal definition of the equal instance. + * @param definition a definition of the equal instance. * @return An equal instance from the given function. */ - public static Equal equalAltDef(final AlternateDefinition definition) { + public static Equal equalDef(final AlternateDefinition definition) { return new Equal<>(definition); } @@ -246,7 +246,7 @@ public boolean equal(A a1, A a2) { * An equal instance for the {@link StringBuffer} type. */ public static final Equal stringBufferEqual = - equalAltDef((sb1, sb2) -> { + equalDef((sb1, sb2) -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -260,7 +260,7 @@ public boolean equal(A a1, A a2) { * An equal instance for the {@link StringBuilder} type. */ public static final Equal stringBuilderEqual = - equalAltDef((sb1, sb2) -> { + equalDef((sb1, sb2) -> { if (sb1.length() == sb2.length()) { for (int i = 0; i < sb1.length(); i++) if (sb1.charAt(i) != sb2.charAt(i)) @@ -305,7 +305,7 @@ public static Equal> validationEqual(final Equal ea, */ public static Equal> listEqual(final Equal ea) { Definition eaDef = ea.def; - return equalAltDef((a1, a2) -> { + return equalDef((a1, a2) -> { List x1 = a1; List x2 = a2; @@ -357,7 +357,7 @@ public static Equal> seqEqual(final Equal e) { */ public static Equal> streamEqual(final Equal ea) { Definition eaDef = ea.def; - return equalAltDef((a1, a2) -> { + return equalDef((a1, a2) -> { Stream x1 = a1; Stream x2 = a2; @@ -381,7 +381,7 @@ public static Equal> streamEqual(final Equal ea) { */ public static Equal> arrayEqual(final Equal ea) { Definition eaDef = ea.def; - return equalAltDef((a1, a2) -> { + return equalDef((a1, a2) -> { if (a1.length() == a2.length()) { for (int i = 0; i < a1.length(); i++) { if (!eaDef.equal(a1.get(i), a2.get(i))) @@ -400,7 +400,18 @@ public static Equal> arrayEqual(final Equal ea) { * @return An equal instance for the {@link Tree} type. */ public static Equal> treeEqual(final Equal ea) { - return equalAltDef((t1, t2) -> ea.eq(t1.root(), t2.root()) && p1Equal(streamEqual(treeEqual(ea))).eq(t2.subForest(), t1.subForest())); + Definition eaDef = ea.def; + return equalDef(new AlternateDefinition>() { + + final Definition>>> subForestEqDef = p1Equal(streamEqual(equalDef(this))).def; + + @Override + public boolean equal(Tree t1, Tree t2) { + return eaDef.equal(t1.root(), t2.root()) + && subForestEqDef.equal(t1.subForest(), t2.subForest()); + + } + }); } /** @@ -410,7 +421,7 @@ public static Equal> treeEqual(final Equal ea) { * @return An equal instance for a product-1. */ public static Equal> p1Equal(final Equal ea) { - return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1())); + return ea.contramap(P1.__1()); } /** @@ -421,7 +432,9 @@ public static Equal> p1Equal(final Equal ea) { * @return An equal instance for a product-2. */ public static Equal> p2Equal(final Equal ea, final Equal eb) { - return equalAltDef((p1, p2)-> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + return equalDef((p1, p2)-> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2())); } /** @@ -433,7 +446,10 @@ public static Equal> p2Equal(final Equal ea, final Equal e * @return An equal instance for a product-3. */ public static Equal> p3Equal(final Equal ea, final Equal eb, final Equal ec) { - return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + Definition ecDef = ec.def; + return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3())); } /** @@ -447,8 +463,12 @@ public static Equal> p3Equal(final Equal ea, final Equa */ public static Equal> p4Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed) { - return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + Definition ecDef = ec.def; + Definition edDef = ed.def; + return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) && + edDef.equal(p1._4(), p2._4())); } /** @@ -464,8 +484,13 @@ public static Equal> p4Equal(final Equal ea, fina public static Equal> p5Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee) { - return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + Definition ecDef = ec.def; + Definition edDef = ed.def; + Definition eeDef = ee.def; + return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) && + edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5())); } /** @@ -482,8 +507,14 @@ public static Equal> p5Equal(final Equal ea public static Equal> p6Equal(final Equal ea, final Equal eb, final Equal ec, final Equal ed, final Equal ee, final Equal ef) { - return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + Definition ecDef = ec.def; + Definition edDef = ed.def; + Definition eeDef = ee.def; + Definition efDef = ef.def; + return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) && + edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()) && efDef.equal(p1._6(), p2._6())); } /** @@ -502,9 +533,16 @@ public static Equal> p5Equal(final Equal ea final Equal ec, final Equal ed, final Equal ee, final Equal ef, final Equal eg) { - return equalAltDef((p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && - eg.eq(p1._7(), p2._7())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + Definition ecDef = ec.def; + Definition edDef = ed.def; + Definition eeDef = ee.def; + Definition efDef = ef.def; + Definition egDef = eg.def; + return equalDef((p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) && + edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()) && efDef.equal(p1._6(), p2._6()) && + egDef.equal(p1._7(), p2._7())); } /** @@ -528,10 +566,18 @@ public static Equal> p5Equal(final Equal ea final Equal ef, final Equal eg, final Equal eh) { - return equalAltDef( - (p1, p2) -> ea.eq(p1._1(), p2._1()) && eb.eq(p1._2(), p2._2()) && ec.eq(p1._3(), p2._3()) && - ed.eq(p1._4(), p2._4()) && ee.eq(p1._5(), p2._5()) && ef.eq(p1._6(), p2._6()) && - eg.eq(p1._7(), p2._7()) && eh.eq(p1._8(), p2._8())); + Definition eaDef = ea.def; + Definition ebDef = eb.def; + Definition ecDef = ec.def; + Definition edDef = ed.def; + Definition eeDef = ee.def; + Definition efDef = ef.def; + Definition egDef = eg.def; + Definition ehDef = eh.def; + return equalDef( + (p1, p2) -> eaDef.equal(p1._1(), p2._1()) && ebDef.equal(p1._2(), p2._2()) && ecDef.equal(p1._3(), p2._3()) && + edDef.equal(p1._4(), p2._4()) && eeDef.equal(p1._5(), p2._5()) && efDef.equal(p1._6(), p2._6()) && + egDef.equal(p1._7(), p2._7()) && ehDef.equal(p1._8(), p2._8())); } /** @@ -622,7 +668,9 @@ public static Equal> v8Equal(final Equal ea) { * @return an equal instance for a heterogeneous list. */ public static > Equal> hListEqual(final Equal e, final Equal l) { - return equal(curry((HList.HCons c1, HList.HCons c2) -> e.eq(c1.head(), c2.head()) && l.eq(c1.tail(), c2.tail()))); + Definition eDef = e.def; + Definition lDef = l.def; + return equalDef((c1, c2) -> eDef.equal(c1.head(), c2.head()) && lDef.equal(c1.tail(), c2.tail())); } /** @@ -632,15 +680,15 @@ public static > Equal> hListEqual(final * @return An equal instance for sets. */ public static Equal> setEqual(final Equal e) { - return equal(curry((Set a, Set b) -> streamEqual(e).eq(a.toStream(), b.toStream()))); + return streamEqual(e).contramap(Set::toStream); } public static Equal> treeMapEqual(Equal k, Equal v) { - return equal(t1 -> t2 -> streamEqual(p2Equal(k, v)).eq(t1.toStream(), t2.toStream())); + return streamEqual(p2Equal(k, v)).contramap(TreeMap::toStream); } public static Equal> writerEqual(Equal eq1, Equal eq2) { - return equal(w1 -> w2 -> p2Equal(eq1, eq2).eq(w1.run(), w2.run())); + return p2Equal(eq1, eq2).contramap(Writer::run); } /** From 7ee7a49c2460fac22cf413afa346036031d2277e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 22 Jun 2016 21:06:09 +0200 Subject: [PATCH 591/811] Implement either catamorphism with method dispatch avoiding creation of Left/Right projections. Also some minor cleanup and refactoring to make more use of catamorphism. --- core/src/main/java/fj/data/Either.java | 113 +++++++++++++------------ 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index a4f0fc02..ebfe3b2c 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -1,24 +1,29 @@ package fj.data; -import static fj.Bottom.error; +import fj.Equal; +import fj.F; +import fj.F0; +import fj.Function; +import fj.Hash; +import fj.P1; +import fj.Show; +import fj.Unit; +import fj.function.Effect1; -import fj.*; +import java.util.Collection; +import java.util.Iterator; +import static fj.Bottom.error; +import static fj.Function.compose; import static fj.Function.identity; import static fj.P.p; - -import fj.function.Effect1; - import static fj.Unit.unit; import static fj.data.Array.mkArray; +import static fj.data.List.cons_; import static fj.data.List.list; import static fj.data.List.single; -import static fj.data.List.cons_; import static fj.data.Option.some; -import java.util.Collection; -import java.util.Iterator; - /** * The Either type represents a value of one of two possible types (a disjoint union). * The data constructors; Left and Right represent the two possible @@ -72,11 +77,7 @@ public final RightProjection right() { * @param right The function to call if this is right. * @return The reduced value. */ - public final X either(final F left, final F right) { - return isLeft() ? - left.f(left().value()) : - right.f(right().value()); - } + public abstract X either(final F left, final F right); /** * Map the given functions across the appropriate side. @@ -86,9 +87,7 @@ public final X either(final F left, final F right) { * @return A new either value after mapping with the appropriate function applied. */ public final Either bimap(final F left, final F right) { - return isLeft() ? - left(left.f(left().value())) : - right(right.f(right().value())); + return either(compose(left_(), left), compose(right_(), right)); } @Override @@ -107,7 +106,7 @@ public final int hashCode() { * @return The value of this either swapped to the opposing side. */ public final Either swap() { - return isLeft() ? new Right<>(((Left) this).a) : new Left<>(((Right) this).b); + return either(right_(), left_()); } private static final class Left extends Either { @@ -124,6 +123,11 @@ public boolean isLeft() { public boolean isRight() { return false; } + + @Override + public X either(F left, F right) { + return left.f(a); + } } private static final class Right extends Either { @@ -140,6 +144,11 @@ public boolean isLeft() { public boolean isRight() { return true; } + + @Override + public X either(F left, F right) { + return right.f(b); + } } /** @@ -414,17 +423,17 @@ public Collection toCollection() { return toList().toCollection(); } - public Option> traverseOption(F> f) { + public Option> traverseOption(F> f) { return e.isLeft() ? - f.f(value()).map(Either::left) : - some(Either.right(e.right().value())); - } + f.f(value()).map(left_()) : + some(right(e.right().value())); + } - public Stream> traverseStream(F> f) { - return e.isLeft() ? - f.f(value()).map(Either::left) : - Stream.single(Either.right(e.right().value())); - } + public Stream> traverseStream(F> f) { + return e.isLeft() ? + f.f(value()).map(left_()) : + Stream.single(right(e.right().value())); + } } /** @@ -543,7 +552,6 @@ public Either bind(final F> f) { return e.isRight() ? f.f(value()) : new Left<>(e.left().value()); } - /** * Anonymous bind through this projection. * @@ -553,17 +561,18 @@ public Either bind(final F> f) { public Either sequence(final Either e) { return bind(Function.constant(e)); } + /** - * Traverse with function that produces List (non-determinism). - * - * @param f the function to traverse with - * @return An either after traversing through this projection. - */ - public List> traverseList(final F> f) { - return e.isRight() ? - f.f(value()).map(Either::right) : - list(left(e.left().value())); - } + * Traverse with function that produces List (non-determinism). + * + * @param f the function to traverse with + * @return An either after traversing through this projection. + */ + public List> traverseList(final F> f) { + return e.isRight() ? + f.f(value()).map(right_()) : + list(left(e.left().value())); + } /** * Traverse with a function that has IO effect @@ -573,19 +582,19 @@ public List> traverseList(final F> f) { */ public IO> traverseIO(final F> f) { return e.isRight() ? - IOFunctions.map(f.f(value()), Either::right) : + IOFunctions.map(f.f(value()), right_()) : IOFunctions.lazy(() -> left(e.left().value())); } public P1> traverseP1(final F> f) { return e.isRight() ? - f.f(value()).map(Either::right) : + f.f(value()).map(right_()) : p(left(e.left().value())); } public Option> traverseOption(final F> f) { return e.isRight() ? - f.f(value()).map(Either::right) : + f.f(value()).map(right_()) : some(left(e.left().value())); } @@ -758,8 +767,7 @@ public static F, F, Either>> rightMap_() { * @return An either after joining. */ public static Either joinLeft(final Either, B> e) { - final F, Either> id = identity(); - return e.left().bind(id); + return e.left().bind(identity()); } /** @@ -769,8 +777,7 @@ public static Either joinLeft(final Either, B> e) { * @return An either after joining. */ public static Either joinRight(final Either> e) { - final F, Either> id = identity(); - return e.right().bind(id); + return e.right().bind(identity()); } /** @@ -781,7 +788,7 @@ public static Either joinRight(final Either> e) { */ public static Either, X> sequenceLeft(final List> a) { return a.isEmpty() ? - Either.left(List.nil()) : + left(List.nil()) : a.head().left().bind(aa -> sequenceLeft(a.tail()).left().map(cons_(aa))); } @@ -793,7 +800,7 @@ public static Either, X> sequenceLeft(final List> a) */ public static Either> sequenceRight(final List> a) { return a.isEmpty() ? - Either.right(List.nil()) : + right(List.nil()) : a.head().right().bind(bb -> sequenceRight(a.tail()).right().map(cons_(bb))); } @@ -807,10 +814,10 @@ public final List> traverseListRight(final F> f) { } /** - * Traversable instance of LeftProjection of Either for List. - * - * @return traversed value - */ + * Traversable instance of LeftProjection of Either for List. + * + * @return traversed value + */ public final List> traverseListLeft(final F> f) { return left().traverseList(f); } @@ -869,8 +876,6 @@ public final Stream> traverseStreamLeft(final F> f return left().traverseStream(f); } - - /** * Takes an Either to its contained value within left or right. * @@ -878,7 +883,7 @@ public final Stream> traverseStreamLeft(final F> f * @return An Either to its contained value within left or right. */ public static A reduce(final Either e) { - return e.isLeft() ? e.left().value() : e.right().value(); + return e.either(identity(), identity()); } /** From 2aa3878bf8e803232da57788b75a055a9859606a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 22 Jun 2016 21:25:24 +0200 Subject: [PATCH 592/811] Definition interfaces should be public --- core/src/main/java/fj/Equal.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index e5b2ebb1..1db2c492 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -40,7 +40,7 @@ public final class Equal { /** * Primitives functions of Equal: minimal definition and overridable methods. */ - interface Definition { + public interface Definition { F equal(A a); @@ -52,7 +52,7 @@ default boolean equal(A a1, A a2) { /** * Primitives functions of Equal: alternative minimal definition and overridable methods. */ - interface AlternateDefinition extends Definition { + public interface AlternateDefinition extends Definition { @Override boolean equal(A a1, A a2); From 1c94e087fd35abe6f2224e1165183d065f6a9fc8 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 22 Jun 2016 21:52:16 +0200 Subject: [PATCH 593/811] Initial refactoring of Ord to use Definition interface --- core/src/main/java/fj/Ord.java | 166 +++++++++++++++++++++++++-------- 1 file changed, 126 insertions(+), 40 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 04cc46b9..a2ffb7ca 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -16,6 +16,7 @@ import static fj.Function.apply; import static fj.Function.compose; +import static fj.Function.compose2; import static fj.Function.curry; import static fj.Semigroup.semigroup; @@ -25,12 +26,49 @@ * @version %build.number% */ public final class Ord { - private final F> f; - private Ord(final F> f) { - this.f = f; - this.max = a1 -> apply((a2, o) -> o == Ordering.GT ? a1 : a2, f.f(a1)); - this.min = a1 -> apply((a2, o) -> o == Ordering.LT ? a1 : a2, f.f(a1)); + /** + * Primitives functions of Ord: minimal definition and overridable methods. + */ + public interface Definition extends Equal.Definition { + + F compare(A a); + + default Ordering compare(A a1, A a2) { + return compare(a1).f(a2); + } + + @Override + default boolean equal(A a1, A a2) { + return compare(a1, a2) == Ordering.EQ; + } + + @Override + default F equal(A a) { + return compose(o -> o == Ordering.EQ, compare(a)); + } + } + + /** + * Primitives functions of Ord: alternative minimal definition and overridable methods. + */ + public interface AlternateDefinition extends Definition { + + Ordering compare(A a1, A a2); + + default F compare(A a1) { + return a2 -> compare(a1, a2); + } + + } + + + private final Definition def; + + private Ord(final Definition def) { + this.def = def; + this.max = a1 -> apply((a2, o) -> o == Ordering.GT ? a1 : a2, def.compare(a1)); + this.min = a1 -> apply((a2, o) -> o == Ordering.LT ? a1 : a2, def.compare(a1)); } /** @@ -39,7 +77,7 @@ private Ord(final F> f) { * @return A function that returns an ordering for its arguments. */ public F> compare() { - return f; + return def::compare; } /** @@ -50,7 +88,7 @@ public F> compare() { * @return An ordering for the given arguments. */ public Ordering compare(final A a1, final A a2) { - return f.f(a1).f(a2); + return def.compare(a1, a2); } /** @@ -61,7 +99,7 @@ public Ordering compare(final A a1, final A a2) { * @return true if the given arguments are equal, false otherwise. */ public boolean eq(final A a1, final A a2) { - return compare(a1, a2) == Ordering.EQ; + return def.compare(a1, a2) == Ordering.EQ; } /** @@ -70,7 +108,7 @@ public boolean eq(final A a1, final A a2) { * @return An Equal for this order. */ public Equal equal() { - return Equal.equal(a -> compose(o -> o == Ordering.EQ, f.f(a))); + return Equal.equalDef(def); } /** @@ -80,7 +118,18 @@ public Equal equal() { * @return A new ord. */ public Ord contramap(final F f) { - return ord(F1Functions.o(F1Functions.o(F1Functions.andThen(f), this.f), f)); + Definition selfDef = def; + return ordDef(new Definition() { + @Override + public F compare(B b) { + return compose(selfDef.compare(f.f(b)), f); + } + + @Override + public Ordering compare(B b1, B b2) { + return selfDef.compare(f.f(b1), f.f(b2)); + } + }); } /** @@ -93,7 +142,7 @@ public Ord contramap(final F f) { * false otherwise. */ public boolean isLessThan(final A a1, final A a2) { - return compare(a1, a2) == Ordering.LT; + return def.compare(a1, a2) == Ordering.LT; } /** @@ -106,7 +155,7 @@ public boolean isLessThan(final A a1, final A a2) { * false otherwise. */ public boolean isLessThanOrEqualTo(final A a1, final A a2) { - return compare(a1, a2) != Ordering.GT; + return def.compare(a1, a2) != Ordering.GT; } /** @@ -119,7 +168,7 @@ public boolean isLessThanOrEqualTo(final A a1, final A a2) { * argument, false otherwise. */ public boolean isGreaterThan(final A a1, final A a2) { - return compare(a1, a2) == Ordering.GT; + return def.compare(a1, a2) == Ordering.GT; } /** @@ -129,7 +178,7 @@ public boolean isGreaterThan(final A a1, final A a2) { * @return A function that returns true if its argument is less than the argument to this method. */ public F isLessThan(final A a) { - return compose(o -> o != Ordering.LT, f.f(a)); + return compose(o -> o != Ordering.LT, def.compare(a)); } /** @@ -139,7 +188,7 @@ public F isLessThan(final A a) { * @return A function that returns true if its argument is greater than the argument to this method. */ public F isGreaterThan(final A a) { - return compose(o -> o != Ordering.GT, f.f(a)); + return compose(o -> o != Ordering.GT, def.compare(a)); } /** @@ -183,7 +232,20 @@ public final Semigroup maxSemigroup() { return semigroup(max); } - public final Ord reverse() { return ord(Function.flip(f)); } + public final Ord reverse() { + Definition selfDef = def; + return ordDef(new Definition() { + @Override + public F compare(A a) { + return compose(Ordering::reverse, selfDef.compare(a)); + } + + @Override + public Ordering compare(A a1, A a2) { + return selfDef.compare(a2, a1); + } + }); + } /** * Returns an order instance that uses the given equality test and ordering function. @@ -192,9 +254,30 @@ public final Semigroup maxSemigroup() { * @return An order instance. */ public static Ord ord(final F> f) { - return new Ord<>(f); + return new Ord<>(f::f); } + /** + * Returns an order instance that uses the given minimal equality test and ordering definiion. + * + * @param def The order definition. + * @return An order instance. + */ + public static Ord ordDef(final Definition def) { + return new Ord<>(def); + } + + /** + * Returns an order instance that uses the given minimal equality test and ordering definiion. + * + * @param def The order definition. + * @return An order instance. + */ + public static Ord ordDef(final AlternateDefinition def) { + return new Ord<>(def); + } + + /** * An order instance for the boolean type. */ @@ -248,7 +331,7 @@ public static Ord ord(final F> f) { /** * An order instance for the {@link Ordering} type. */ - public static final Ord orderingOrd = Ord.ord(curry((o1, o2) -> o1 == o2 ? + public static final Ord orderingOrd = ordDef((o1, o2) -> o1 == o2 ? Ordering.EQ : o1 == Ordering.LT ? Ordering.LT : @@ -256,7 +339,7 @@ public static Ord ord(final F> f) { Ordering.GT : o1 == Ordering.EQ ? Ordering.LT : - Ordering.GT)); + Ordering.GT); /** * An order instance for the {@link String} type. @@ -280,13 +363,14 @@ public static Ord ord(final F> f) { * @return An order instance for the {@link Option} type. */ public static Ord> optionOrd(final Ord oa) { - return ord(o1 -> o2 -> o1.isNone() ? + Definition oaDef = oa.def; + return ordDef((o1, o2) -> o1.isNone() ? o2.isNone() ? Ordering.EQ : Ordering.LT : o2.isNone() ? Ordering.GT : - oa.f.f(o1.some()).f(o2.some())); + oaDef.compare(o1.some()).f(o2.some())); } /** @@ -297,13 +381,15 @@ public static Ord> optionOrd(final Ord oa) { * @return An order instance for the {@link Either} type. */ public static Ord> eitherOrd(final Ord oa, final Ord ob) { - return ord(e1 -> e2 -> e1.isLeft() ? + Definition oaDef = oa.def; + Definition obDef = ob.def; + return ordDef((e1, e2) -> e1.isLeft() ? e2.isLeft() ? - oa.f.f(e1.left().value()).f(e2.left().value()) : - Ordering.LT : + oaDef.compare(e1.left().value()).f(e2.left().value()) : + Ordering.LT : e2.isLeft() ? - Ordering.GT : - ob.f.f(e1.right().value()).f(e2.right().value())); + Ordering.GT : + obDef.compare(e1.right().value()).f(e2.right().value())); } /** @@ -324,7 +410,7 @@ public static Ord> validationOrd(final Ord oa, final * @return An order instance for the {@link List} type. */ public static Ord> listOrd(final Ord oa) { - return ord(l1 -> l2 -> { + return ordDef((l1, l2) -> { List x1 = l1; List x2 = l2; @@ -364,14 +450,15 @@ public static Ord> nonEmptyListOrd(final Ord oa) { * @return An order instance for the {@link Stream} type. */ public static Ord> streamOrd(final Ord oa) { - return ord(s1 -> s2 -> { + return ordDef((s1, s2) -> { if (s1.isEmpty()) return s2.isEmpty() ? Ordering.EQ : Ordering.LT; else if (s2.isEmpty()) return s1.isEmpty() ? Ordering.EQ : Ordering.GT; else { final Ordering c = oa.compare(s1.head(), s2.head()); - return c == Ordering.EQ ? streamOrd(oa).f.f(s1.tail()._1()).f(s2.tail()._1()) : c; + // FIXME: not stack safe + return c == Ordering.EQ ? streamOrd(oa).def.compare(s1.tail()._1()).f(s2.tail()._1()) : c; } }); } @@ -383,7 +470,7 @@ else if (s2.isEmpty()) * @return An order instance for the {@link Array} type. */ public static Ord> arrayOrd(final Ord oa) { - return ord(a1 -> a2 -> { + return ordDef((a1, a2) -> { int i = 0; //noinspection ForLoopWithMissingComponent for (; i < a1.length() && i < a2.length(); i++) { @@ -414,7 +501,7 @@ public static Ord> setOrd(final Ord oa) { /** * An order instance for the {@link Unit} type. */ - public static final Ord unitOrd = ord(curry((Unit u1, Unit u2) -> Ordering.EQ)); + public static final Ord unitOrd = ordDef((u1, u2) -> Ordering.EQ); /** * An order instance for a product-1. @@ -435,15 +522,15 @@ public static Ord> p1Ord(final Ord oa) { * @return An order instance for a product-2, with the first factor considered most significant. */ public static Ord> p2Ord(final Ord oa, final Ord ob) { - return ord(curry((P2 a, P2 b) -> oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1()))); + return ordDef((a, b) -> oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1())); } public static Ord> p2Ord1(Ord oa) { - return ord(p1 -> p2 -> oa.compare(p1._1(), p2._1())); + return ordDef((p1, p2) -> oa.compare(p1._1(), p2._1())); } public static Ord> p2Ord2(Ord ob) { - return ord(p1 -> p2 -> ob.compare(p1._2(), p2._2())); + return ordDef((p1, p2) -> ob.compare(p1._2(), p2._2())); } /** @@ -455,9 +542,9 @@ public static Ord> p2Ord2(Ord ob) { * @return An order instance for a product-3, with the first factor considered most significant. */ public static Ord> p3Ord(final Ord oa, final Ord ob, final Ord oc) { - return ord(curry((P3 a, P3 b) -> oa.eq(a._1(), b._1()) ? + return ordDef((a, b) -> oa.eq(a._1(), b._1()) ? p2Ord(ob, oc).compare(P.p(a._2(), a._3()), P.p(b._2(), b._3())) - : oa.compare(a._1(), b._1()))); + : oa.compare(a._1(), b._1())); } /** @@ -472,8 +559,7 @@ public static Ord> p3Ord(final Ord oa, final Ord ob, * @return An order instance for the Comparable interface. */ public static > Ord comparableOrd() { - - return ord(a1 -> a2 -> Ordering.fromInt(a1.compareTo(a2))); + return ordDef((a1, a2) -> Ordering.fromInt(a1.compareTo(a2))); } /** @@ -485,7 +571,7 @@ public static > Ord comparableOrd() { * @see #hashEqualsOrd() */ public static Ord hashOrd() { - return ord(a -> { + return ordDef(a -> { int aHash = a.hashCode(); return a2 -> Ordering.fromInt(Integer.compare(aHash, a2.hashCode())); }); @@ -499,7 +585,7 @@ public static Ord hashOrd() { * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. */ public static Ord hashEqualsOrd() { - return ord(a -> { + return ordDef(a -> { int aHash = a.hashCode(); return a2 -> { final int a2Hash = a2.hashCode(); From f040341840ea037a851326c5b3d43cf6d1ac0cb8 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 22:29:33 +0200 Subject: [PATCH 594/811] Add first class either catamorphism --- core/src/main/java/fj/data/Either.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index a4f0fc02..c0c143af 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -737,6 +737,17 @@ public static Either right(final B b) { return new Right<>(b); } + /** + * First class catamorphism for either. Folds over this either breaking into left or right. + * + * @param left The function to call if this is left. + * @param right The function to call if this is right. + * @return The reducing function. + */ + public static F, X> cata(final F left, final F right) { + return e -> e.either(left, right); + } + /** * @return A function that maps another function across an either's left projection. */ From 59e35fa9d69a2154211516086bf28330baa26c34 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 21 Jun 2016 22:54:48 +0200 Subject: [PATCH 595/811] Add first class option catamorphism --- core/src/main/java/fj/data/Option.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 4cdb411f..f1b228d0 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -688,6 +688,18 @@ public static F> fromNull() { return Option::fromNull; } + /** + * First-class catamorphism for Option: return a function that will performs + * a reduction on an optional value using the given arguments. + * + * @param none The value to return if this optional value has no value. + * @param some The function to apply to the value of this optional value. + * @return the reducing function. + */ + public static final F, B> cata(final B none, final F some) { + return o -> o.option(none, some); + } + /** * Joins the given optional value of optional value using a bind operation. * From 18690a20a1a634f35ef178204e2cd4f8ee959db2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 1 Jul 2016 12:41:23 +0200 Subject: [PATCH 596/811] Use '_' suffix scheme for first class cata of Option and Either --- core/src/main/java/fj/Equal.java | 6 +++--- core/src/main/java/fj/data/Either.java | 2 +- core/src/main/java/fj/data/Option.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 1db2c492..c743f03e 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -281,8 +281,8 @@ public static Equal> eitherEqual(final Equal ea, final Eq Definition eaDef = ea.def; Definition ebDef = eb.def; return equalDef(e1 -> e1.either( - a1 -> Either.cata(eaDef.equal(a1), (B __) -> false), - b1 -> Either.cata((A __)-> false, ebDef.equal(b1)) + a1 -> Either.either_(eaDef.equal(a1), (B __) -> false), + b1 -> Either.either_((A __)-> false, ebDef.equal(b1)) )); } @@ -341,7 +341,7 @@ public static Equal> optionEqual(final Equal ea) { Definition eaDef = ea.def; return equalDef(o1 -> o1.option( Option.isNone_(), - a1 -> Option.cata(false, eaDef.equal(a1)) + a1 -> Option.option_(false, eaDef.equal(a1)) )); } diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index c0c143af..e3e9d5d9 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -744,7 +744,7 @@ public static Either right(final B b) { * @param right The function to call if this is right. * @return The reducing function. */ - public static F, X> cata(final F left, final F right) { + public static F, X> either_(final F left, final F right) { return e -> e.either(left, right); } diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index f1b228d0..54b4bb01 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -696,7 +696,7 @@ public static F> fromNull() { * @param some The function to apply to the value of this optional value. * @return the reducing function. */ - public static final F, B> cata(final B none, final F some) { + public static final F, B> option_(final B none, final F some) { return o -> o.option(none, some); } From 9f1cf575b62d8c924538e497b5f7fd8f24845d27 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Fri, 1 Jul 2016 12:41:23 +0200 Subject: [PATCH 597/811] Use '_' suffix scheme for first class cata of Option and Either --- core/src/main/java/fj/data/Either.java | 2 +- core/src/main/java/fj/data/Option.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index c0c143af..e3e9d5d9 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -744,7 +744,7 @@ public static Either right(final B b) { * @param right The function to call if this is right. * @return The reducing function. */ - public static F, X> cata(final F left, final F right) { + public static F, X> either_(final F left, final F right) { return e -> e.either(left, right); } diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index f1b228d0..54b4bb01 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -696,7 +696,7 @@ public static F> fromNull() { * @param some The function to apply to the value of this optional value. * @return the reducing function. */ - public static final F, B> cata(final B none, final F some) { + public static final F, B> option_(final B none, final F some) { return o -> o.option(none, some); } From a85308f4a3c2a16e8d5bde7f39a40f68e8f09e4a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 2 Jul 2016 01:02:38 +1000 Subject: [PATCH 598/811] Added release notes for 4.6, added placeholder for 4.7 release notes --- etc/release-notes/release-notes-4.6.adoc | 58 +++++++++++++++++++++--- etc/release-notes/release-notes-4.7.adoc | 28 ++++++++++++ 2 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 etc/release-notes/release-notes-4.7.adoc diff --git a/etc/release-notes/release-notes-4.6.adoc b/etc/release-notes/release-notes-4.6.adoc index d9bc2b3d..628457c5 100644 --- a/etc/release-notes/release-notes-4.6.adoc +++ b/etc/release-notes/release-notes-4.6.adoc @@ -1,23 +1,60 @@ = Release 4.6 -Proposed release: Jun 2016 +Proposed release: June 2016 == Enhancements -* TODO. +* Added various list permutation generation for Gen (#235). +* Reduced memory for hard memos (#257). +* Added a priority queue based on finger trees (#261). +* Construct a database action from a Connection to a value (#267). +* Added methods and instances on Natural for Equal, Hash, Arbitrary, Shirnk, equals, hashCode and toString (#274). +* Use BigIntegers for Natural Gen and Shrink, instead of Long (#278). +* Various optics for Option (#244). +* First class catamorphism for Either and Option (#286). +* Added IO walkthrough (#254). +* Added numerous Semigroup methods, Monoid.dual, conversion from Ord to Semigroup and NonEmptyList folds (#251). +* Added ignored Optional optic (#250). +* Added IO methods: as, voided, when and unless (#245). +* Added monoid instances for io and unit; added semigroup instances for first, last and io (#246). == Fixes -* TODO. +* Fixed Gen.pick (#235). Affects Gen.variant, Coarbitrary and dependencies. +* Fixed Rand.reseed (#237). +* IOFunctions.bracket runs finaliser (#240). +* Fixed backwards List.traverseIO (#248). +* Run IOW map, bind and append lazily (#252, 253). +* Make State class stack safe (#259). +* Removed extra type parameters in P2.Optic (#273). +* Fixed BigInteger.shrink (#276, 277). == Internal -* TODO. +* Upgrade to Gradle 2.13 (#243). +* Document version deprecated for all deprecated methods (#264). +* Fixed various unchecked conversion warnings (#269). +* Added tests for DbState (#234). +* Added test for quickcheck Bool (#233). +* Various improvements (using final classes, method references, diamond operators, type inference, import lists, replace anonymous classes with lambdas etc. - #238). +* Use Either catamorphism internally (#285). +* Use uncurried foldLeft as default implementation (#283). +* Removed workarounds for fixed javac bugs (#282). +* Added IO test (#272). +* Exclude the demo subproject from Coveralls code coverage metrics (#268). +* Added tests for fj.Class (#262). +* Use method reference in IOWalkthrough (#255). +* Update retro lambda plugin version from 3.2.0 to 3.2.5 (#247). == Breaking Changes -* TODO. +* Removed deprecated Equal.shallowEquals0 (#239). +* Removed use of Arbitrary wrapper (#271). + +== Deprecations + +* Array.toJavaArray (#241). == Documentation @@ -25,4 +62,13 @@ Proposed release: Jun 2016 == Contributors -* TODO. +* Mark Perry +* JB Giraudeau +* @mrbackend +* Brian McKenna +* Clinton Selke +* Gabor Liptak +* Ryan Johnson +* Charles O'Farrell +* Fabian Kramer + diff --git a/etc/release-notes/release-notes-4.7.adoc b/etc/release-notes/release-notes-4.7.adoc new file mode 100644 index 00000000..3c1b265f --- /dev/null +++ b/etc/release-notes/release-notes-4.7.adoc @@ -0,0 +1,28 @@ + += Release 4.7 + +Proposed release: September 2016 + +== Enhancements + +* TODO. + +== Fixes + +* TODO. + +== Internal + +* TODO. + +== Breaking Changes + +* TODO. + +== Documentation + +* TODO. + +== Contributors + +* TODO. From 901f48e82480e0933475ff00565a8ea7bfe9a3c9 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 2 Jul 2016 01:03:18 +1000 Subject: [PATCH 599/811] Added release note process step to go through Github issues and pull requests --- etc/release-process.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etc/release-process.txt b/etc/release-process.txt index f62cb01f..e9bdbb15 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -2,6 +2,8 @@ Current Release Process ======================= +Go through the issues and pull requests and set the Label and Milestone field. Add information to /etc/release-notes/release-notes-.adoc. + Update build.gradle: * set isSnapshot to false * set useRetroLambda to true From 1efd9cbe5dd1afa577cff218b1a7a227d4458846 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 2 Jul 2016 01:03:49 +1000 Subject: [PATCH 600/811] Added deprecated release version for remaining methods --- quickcheck/src/main/java/fj/test/Gen.java | 5 +++++ quickcheck/src/main/java/fj/test/Rand.java | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 1ea9be0a..1e4a4c5e 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -2,6 +2,7 @@ import fj.F; import fj.Function; +import fj.Ord; import fj.P2; import fj.Unit; import fj.control.Trampoline; @@ -506,6 +507,8 @@ public static Gen pickOne(List as) { *

* Note: pick is synonymous with combinationOf * + * @deprecated As of release 4.6, use {@link #combinationOf} + * * @param n The number of elements to pick from the given list. * @param as The list from which to pick elements. * @return A generator of lists that picks the given number of elements from the given list. @@ -644,6 +647,8 @@ private static Gen> pick(Gen> indexesGen, Array as) *

* Note: someOf is synonymous with someCombinationOf * + * @deprecated As of release 4.6, use {@link #someCombinationOf} + * * @param as The list from which to pick values. * @return A generator of lists that produces some of the values of the given list. */ diff --git a/quickcheck/src/main/java/fj/test/Rand.java b/quickcheck/src/main/java/fj/test/Rand.java index 97f94596..f1849bb3 100644 --- a/quickcheck/src/main/java/fj/test/Rand.java +++ b/quickcheck/src/main/java/fj/test/Rand.java @@ -97,7 +97,9 @@ public Rand reseed(long seed) { * result. *

* Calling {@link #reseed(long)} on an instance returned from this method will - * result in an exception being thrown. Use {@link #rand(F, F, F)} instead. + * result in an exception being thrown. + * + * @deprecated As of release 4.6, use {@link #rand(F, F, F)}. * * @param f The integer random generator. * @param g The floating-point random generator. From 4f9083d909d4f8dc40c3bf4eb584c9e0803eef1e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 2 Jul 2016 01:12:35 +1000 Subject: [PATCH 601/811] Changed 4.6 proposed release date to July 2016 --- etc/release-notes/release-notes-4.6.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.6.adoc b/etc/release-notes/release-notes-4.6.adoc index 628457c5..756c10e2 100644 --- a/etc/release-notes/release-notes-4.6.adoc +++ b/etc/release-notes/release-notes-4.6.adoc @@ -1,7 +1,7 @@ = Release 4.6 -Proposed release: June 2016 +Proposed release: July 2016 == Enhancements From d4746a413a00d69572abbf4adb24077a286fc96c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 2 Jul 2016 01:15:12 +1000 Subject: [PATCH 602/811] Added doc section to release notes for 4.6 --- etc/release-notes/release-notes-4.6.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.6.adoc b/etc/release-notes/release-notes-4.6.adoc index 756c10e2..c67cf8b7 100644 --- a/etc/release-notes/release-notes-4.6.adoc +++ b/etc/release-notes/release-notes-4.6.adoc @@ -58,7 +58,7 @@ Proposed release: July 2016 == Documentation -* TODO. +* Added IO walkthrough (as per enhancements, #254). == Contributors From 3c5bd85a34ebb2add4e56ad24c7e6b7a92e306cf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 3 Jul 2016 21:27:23 +1000 Subject: [PATCH 603/811] Do not use method introduced to Java 7 Integer.compare --- core/src/main/java/fj/Ord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 04cc46b9..4c3ab5c5 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -487,7 +487,7 @@ public static > Ord comparableOrd() { public static Ord hashOrd() { return ord(a -> { int aHash = a.hashCode(); - return a2 -> Ordering.fromInt(Integer.compare(aHash, a2.hashCode())); + return a2 -> Ordering.fromInt(Integer.valueOf(aHash).compareTo(a2.hashCode())); }); } From 72289054848eee812add97d31c17bda92e6822af Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 3 Jul 2016 21:28:01 +1000 Subject: [PATCH 604/811] Added first time contributors --- etc/CONTRIBUTORS | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/etc/CONTRIBUTORS b/etc/CONTRIBUTORS index 63be1827..06536883 100644 --- a/etc/CONTRIBUTORS +++ b/etc/CONTRIBUTORS @@ -214,3 +214,14 @@ jb@giraudeau.info Zheka Kozlov @orionll +@mrbackend + +Brian McKenna + +Clinton Selke + +Ryan Johnson + +Charles O'Farrell + +Fabian Kramer From 56597e33a0ede3c6a2b3c6647243c3a286c5d223 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 3 Jul 2016 21:28:19 +1000 Subject: [PATCH 605/811] Changes to release 4.6 --- build.gradle | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 2744cd00..e11b2274 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.6" snapshotAppendix = "-SNAPSHOT" @@ -56,7 +56,7 @@ allprojects { fjConsumeVersion = "4.5" signModule = false - useRetroLambda = false + useRetroLambda = true projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/gradle.properties b/gradle.properties index d4552a30..07c2b60c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false +signingEnabled = true From b1796a9c008bb0978eae01b6e4766f35906b0fd8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 3 Jul 2016 21:48:51 +1000 Subject: [PATCH 606/811] Get ready for 4.7 snapshot --- build.gradle | 8 ++++---- gradle.properties | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index e11b2274..7d9efae1 100644 --- a/build.gradle +++ b/build.gradle @@ -48,15 +48,15 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.6" + isSnapshot = true + fjBaseVersion = "4.7" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.5" + fjConsumeVersion = "4.6" signModule = false - useRetroLambda = true + useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From a8584ad52992724e44f6304d74009eea1c6656c8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 3 Jul 2016 23:01:25 +1000 Subject: [PATCH 607/811] Updated github readme for release 4.6 --- README.adoc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/README.adoc b/README.adoc index 40fec847..9addaff8 100644 --- a/README.adoc +++ b/README.adoc @@ -13,7 +13,7 @@ The library is intended for use in production applications and is thoroughly tes Functional Java provides abstractions for the following types: * Basic Data Structures - total and partial functions, products, unit, option, unbiased and right biased unions (either and validation), void. -* Immutable Collections - array, list, vector, stream, set, map, finger tree, heterogenous list, difference list. +* Immutable Collections - array, list, vector, stream, set, map, priority queue, finger tree, heterogenous list, difference list. * Other Abstractions - monoid, semigroup, natural, random number generator, reader, writer, state, input/output, parser, zipper, specification based testing (quickcheck), actors, optics (lens, prism, fold, traversal and others), concurrency and type conversion. == URLs @@ -35,12 +35,12 @@ The Functional Java artifact is published to Maven Central using the group `org. * Java 8 specific support (`functionaljava-java8`) * property based testing (`functionaljava-quickcheck`) -The latest stable version is `4.5`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.6`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.5" -compile "org.functionaljava:functionaljava-java8:4.5" -compile "org.functionaljava:functionaljava-quickcheck:4.5" -compile "org.functionaljava:functionaljava-java-core:4.5" +compile "org.functionaljava:functionaljava:4.6" +compile "org.functionaljava:functionaljava-java8:4.6" +compile "org.functionaljava:functionaljava-quickcheck:4.6" +compile "org.functionaljava:functionaljava-java-core:4.6" ---- and in Maven: @@ -48,22 +48,22 @@ and in Maven: org.functionaljava functionaljava - 4.5 + 4.6 org.functionaljava functionaljava-java8 - 4.5 + 4.6 org.functionaljava functionaljava-quickcheck - 4.5 + 4.6 org.functionaljava functionaljava-java-core - 4.5 + 4.6 ---- @@ -71,7 +71,7 @@ and in Maven: FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 6 bytecode. This requires access to both JDK 6 and 8. The build system requires the environment variables `JAVA6_HOME` and `JAVA8_HOME` to refer to the appropriate directories. -Building is done using Gradle 2.10. In the root directory run: +Building is done using Gradle 2.13. In the root directory run: ---- ./gradlew ---- @@ -100,6 +100,7 @@ A more complete description of the features mentioned above are: ** Immutable set implementation using a red/black tree (`fj.data.Set`). ** Immutable multi-way tree - aka rose tree (`fj.data.Tree`). ** Immutable tree-map using a red/black tree implementation (`fj.data.TreeMap`). +** Immutable priority queue using finger trees (`fj.data.PriorityQueue`). ** Difference lists, a highly performant list. * Other Abstractions ** Monoid (`fj.Monoid`). From 8069b9e82161a55ec3fc2c6724d6779315a1072a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 3 Jul 2016 23:34:01 +1000 Subject: [PATCH 608/811] Added 4.6 release date to release notes --- etc/release-notes/release-notes-4.6.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.6.adoc b/etc/release-notes/release-notes-4.6.adoc index c67cf8b7..c0d12558 100644 --- a/etc/release-notes/release-notes-4.6.adoc +++ b/etc/release-notes/release-notes-4.6.adoc @@ -1,7 +1,7 @@ = Release 4.6 -Proposed release: July 2016 +Proposed release: July 3 2016 == Enhancements From 726f0245f7812b2ab42b3e5cf0084523160c8626 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 4 Jul 2016 00:46:41 +1000 Subject: [PATCH 609/811] Modified language in release notes slightly --- etc/release-notes/release-notes-4.6.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/release-notes/release-notes-4.6.adoc b/etc/release-notes/release-notes-4.6.adoc index c0d12558..a33c1214 100644 --- a/etc/release-notes/release-notes-4.6.adoc +++ b/etc/release-notes/release-notes-4.6.adoc @@ -1,7 +1,7 @@ = Release 4.6 -Proposed release: July 3 2016 +Released: 3 July 2016 == Enhancements From 4e369f59032b4c4e695c155aed23b53da9ae4d4c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 18 Jul 2016 22:05:50 +0200 Subject: [PATCH 610/811] Deprecate unsafe Ord instance and List#groupBy that use them. --- core/src/main/java/fj/Ord.java | 12 +++++++++--- core/src/main/java/fj/data/List.java | 12 ++++++++++-- demo/src/main/java/fj/demo/List_groupBy.java | 6 +++--- .../src/test/scala/fj/data/CheckList.scala | 2 +- .../test/java/fj/data/properties/ListProperties.java | 2 +- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 4c3ab5c5..5c84c24e 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -478,12 +478,14 @@ public static > Ord comparableOrd() { /** * An order instance that uses {@link Object#hashCode()} for computing the order and equality, - * thus objects returning the same hashCode are considered to be equals (check {@link #hashEqualsOrd()} - * for an additional check on {@link Object#equals(Object)}). + * thus objects returning the same hashCode are considered to be equals. + * This is not safe and therefore this method is deprecated. * * @return An order instance that is based on {@link Object#hashCode()}. - * @see #hashEqualsOrd() + * + * @deprecated As of release 4.7. */ + @Deprecated public static Ord hashOrd() { return ord(a -> { int aHash = a.hashCode(); @@ -495,9 +497,13 @@ public static Ord hashOrd() { * An order instance that uses {@link Object#hashCode()} and {@link Object#equals} for computing * the order and equality. First the hashCode is compared, if this is equal, objects are compared * using {@link Object#equals}. + * WARNING: This ordering violate antisymmetry on hash collisions. * * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. + * + * @deprecated As of release 4.7. */ + @Deprecated public static Ord hashEqualsOrd() { return ord(a -> { int aHash = a.hashCode(); diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index c49fd63a..ac846393 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1299,11 +1299,15 @@ public final A mode(final Ord o) { /** * Groups the elements of this list by a given keyFunction into a {@link TreeMap}. - * The ordering of the keys is determined by {@link fj.Ord#hashOrd()}. + * The ordering of the keys is determined by {@link fj.Ord#hashOrd()} (ie. Object#hasCode). + * This is not safe and therefore this method is deprecated. * * @param keyFunction The function to select the keys for the map. * @return A TreeMap containing the keys with the accumulated list of matched elements. + * + * @deprecated As of release 4.7, use {@link #groupBy(F, Ord)} */ + @Deprecated public final TreeMap> groupBy(final F keyFunction) { return groupBy(keyFunction, Ord.hashOrd()); } @@ -1322,12 +1326,16 @@ public final TreeMap> groupBy(final F keyFunction, final Or /** * Groups the elements of this list by a given keyFunction into a {@link TreeMap} and transforms * the matching elements with the given valueFunction. The ordering of the keys is determined by - * {@link fj.Ord#hashOrd()}. + * {@link fj.Ord#hashOrd()} (ie. Object#hasCode). + * This is not safe and therefore this method is deprecated. * * @param keyFunction The function to select the keys for the map. * @param valueFunction The function to apply on each matching value. * @return A TreeMap containing the keys with the accumulated list of matched and mapped elements. + * + * @deprecated As of release 4.7, use {@link #groupBy(F, F, Ord)} */ + @Deprecated public final TreeMap> groupBy( final F keyFunction, final F valueFunction) { diff --git a/demo/src/main/java/fj/demo/List_groupBy.java b/demo/src/main/java/fj/demo/List_groupBy.java index f557ec74..b415e19c 100644 --- a/demo/src/main/java/fj/demo/List_groupBy.java +++ b/demo/src/main/java/fj/demo/List_groupBy.java @@ -18,7 +18,7 @@ public static void main(final String... args) { private static void keyDemo() { System.out.println("KeyDemo"); final List words = list("Hello", "World", "how", "are", "your", "doing"); - final TreeMap> lengthMap = words.groupBy(String::length); + final TreeMap> lengthMap = words.groupBy(String::length, Ord.intOrd); lengthMap.forEach(entry -> System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2()))); } @@ -26,7 +26,7 @@ private static void keyDemo() { private static void keyValueDemo() { System.out.println("KeyValueDemo"); final List xs = list(1, 2, 3, 4, 5, 6, 7, 8, 9); - final TreeMap> result = xs.groupBy(x -> x % 3, Integer::toBinaryString); + final TreeMap> result = xs.groupBy(x -> x % 3, Integer::toBinaryString, Ord.intOrd); result.forEach(entry -> System.out.println(String.format("Numbers with reminder %d are %s", entry._1(), entry._2()))); } @@ -35,7 +35,7 @@ private static void keyValueAccDemo() { System.out.println("KeyValueAccDemo"); final List words = list("Hello", "World", "how", "are", "your", "doing"); final TreeMap lengthCounts = - words.groupBy(String::length, Function.identity(), 0, (word, sum) -> sum + 1, Ord.hashOrd()); + words.groupBy(String::length, Function.identity(), 0, (word, sum) -> sum + 1, Ord.intOrd); lengthCounts.forEach(entry -> System.out.println(String.format("Words with %d chars: %s", entry._1(), entry._2()))); } diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala index 36bd99f0..d675db81 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckList.scala @@ -187,7 +187,7 @@ object CheckList extends Properties("List") { join(a))) property("groupBy") = forAll((a: List[Int]) => { - val result = a.groupBy((x: Int) => (x % 2 == 0): lang.Boolean) + val result = a.groupBy((x: Int) => (x % 2 == 0): lang.Boolean, Ord.booleanOrd) result.get(true).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 == 0): lang.Boolean): lang.Boolean) && result.get(false).forall((xs: List[Int]) => xs.forall((x: Int) => (x % 2 != 0): lang.Boolean): lang.Boolean) && a.map((x: Int) => (x % 2) == 0: lang.Boolean).nub().length() == result.size() diff --git a/props-core/src/test/java/fj/data/properties/ListProperties.java b/props-core/src/test/java/fj/data/properties/ListProperties.java index 9724488f..fad5f66f 100644 --- a/props-core/src/test/java/fj/data/properties/ListProperties.java +++ b/props-core/src/test/java/fj/data/properties/ListProperties.java @@ -255,7 +255,7 @@ public Property nub() { public Property groupBy() { return property(arbList(arbInteger), list -> { - final TreeMap> map = list.groupBy(i -> i % 2 == 0); + final TreeMap> map = list.groupBy(i -> i % 2 == 0, Ord.booleanOrd); final List list1 = map.get(true).orSome(nil()); final List list2 = map.get(false).orSome(nil()); return prop(list.length() == list1.length() + list2.length()) From 10b1c79a02162cb222e3d9de9b118ae2b32e769b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 18 Jul 2016 23:10:25 +0200 Subject: [PATCH 611/811] Improve performance of List#groupBy via a mutable buffer. Fix #288 --- core/src/main/java/fj/data/List.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index ac846393..a4fa19eb 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1398,14 +1398,15 @@ public final TreeMap groupBy( final D groupingIdentity, final F2 groupingAcc, final Ord keyOrd) { - return this.foldLeft((map, element) -> { - final B key = keyFunction.f(element); - final C value = valueFunction.f(element); - return map.set(key, map.get(key) - .map(existing -> groupingAcc.f(value, existing)) - .orSome(groupingAcc.f(value, groupingIdentity))); - }, TreeMap.empty(keyOrd) - ); + java.util.TreeMap buffer = new java.util.TreeMap<>(keyOrd.toComparator()); + foreachDoEffect(element -> { + final B key = keyFunction.f(element); + final C value = valueFunction.f(element); + buffer.put(key, buffer.containsKey(key) + ? groupingAcc.f(value, buffer.get(key)) + : groupingAcc.f(value, groupingIdentity)); + }); + return TreeMap.fromMutableMap(keyOrd, buffer); } From 49c6f8d6fd51e92e32a0649205b3699aba1a60e6 Mon Sep 17 00:00:00 2001 From: JB Giraudeau Date: Fri, 22 Jul 2016 14:32:05 +0200 Subject: [PATCH 612/811] Fix #293 regression. isGreaterThan(A)/isLesserThan(A) were not using strict inequality --- core/src/main/java/fj/Ord.java | 4 ++-- core/src/test/java/fj/OrdTest.java | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 core/src/test/java/fj/OrdTest.java diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 5c84c24e..df654a23 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -129,7 +129,7 @@ public boolean isGreaterThan(final A a1, final A a2) { * @return A function that returns true if its argument is less than the argument to this method. */ public F isLessThan(final A a) { - return compose(o -> o != Ordering.LT, f.f(a)); + return compose(o -> o == Ordering.GT, f.f(a)); } /** @@ -139,7 +139,7 @@ public F isLessThan(final A a) { * @return A function that returns true if its argument is greater than the argument to this method. */ public F isGreaterThan(final A a) { - return compose(o -> o != Ordering.GT, f.f(a)); + return compose(o -> o == Ordering.LT, f.f(a)); } /** diff --git a/core/src/test/java/fj/OrdTest.java b/core/src/test/java/fj/OrdTest.java new file mode 100644 index 00000000..d218387a --- /dev/null +++ b/core/src/test/java/fj/OrdTest.java @@ -0,0 +1,27 @@ +package fj; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +public class OrdTest { + + @Test + public void isGreaterThan() { + F pred = Ord.longOrd.isGreaterThan(1L); + + assertThat(pred.f(0L), is(false)); + assertThat(pred.f(1L), is(false)); + assertThat(pred.f(2L), is(true)); + } + + @Test + public void isLessThan() { + F pred = Ord.longOrd.isLessThan(1L); + + assertThat(pred.f(0L), is(true)); + assertThat(pred.f(1L), is(false)); + assertThat(pred.f(2L), is(false)); + } +} From e6abe86c7527ffafae908710e14c2212ff865007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Thu, 15 Sep 2016 14:13:03 -0400 Subject: [PATCH 613/811] Add tests for Strings (#295) --- .../test/java/fj/function/StringsTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 core/src/test/java/fj/function/StringsTest.java diff --git a/core/src/test/java/fj/function/StringsTest.java b/core/src/test/java/fj/function/StringsTest.java new file mode 100644 index 00000000..92cf44d3 --- /dev/null +++ b/core/src/test/java/fj/function/StringsTest.java @@ -0,0 +1,67 @@ +package fj.function; + +import fj.Function; +import org.junit.Test; + +import static fj.F1Functions.o; +import static fj.Function.compose; +import static fj.function.Strings.*; +import static org.junit.Assert.*; +import static org.hamcrest.core.Is.is; + +public class StringsTest { + @Test + public void testLines() { + assertThat(compose(unlines(), lines()).f("one two three"), is("one two three")); + } + + @Test + public void testLinesEmpty() { + assertThat(o(unlines(), lines()).f(""), is("")); + } + + @Test + public void testLength() { + assertThat(length.f("functionaljava"), is(14)); + } + + @Test + public void testMatches() { + assertThat(matches.f("foo").f("foo"), is(true)); + } + + @Test + public void testContains() { + assertThat(contains.f("bar").f("foobar1"), is(true)); + } + + @Test(expected = NullPointerException.class) + public void testIsEmptyException() { + assertThat(isEmpty.f(null), is(true)); + } + + @Test + public void testIsEmpty() { + assertThat(isEmpty.f(""), is(true)); + } + + @Test + public void testIsNotNullOrEmpty() { + assertThat(isNotNullOrEmpty.f("foo"), is(true)); + } + + @Test + public void testIsNullOrEmpty() { + assertThat(isNullOrEmpty.f(null), is(true)); + } + + @Test + public void testIsNotNullOrBlank() { + assertThat(isNotNullOrBlank.f("foo"), is(true)); + } + + @Test + public void testIsNullOrBlank() { + assertThat(isNullOrBlank.f(" "), is(true)); + } +} From 2798b2c4101585a887a1ba9dc4608ac1d752f237 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 00:32:38 +0200 Subject: [PATCH 614/811] Avoid unecessary currying in uncurried version of foldRight. --- core/src/main/java/fj/data/List.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index a4fa19eb..da4a624e 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -716,7 +716,7 @@ public final List append(final List as) { * @return The final result after the right-fold reduction. */ public final B foldRight(final F> f, final B b) { - return reverse().foldLeft(flip(f), b); + return foldRight(uncurryF2(f), b); } /** @@ -727,7 +727,7 @@ public final B foldRight(final F> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight(final F2 f, final B b) { - return foldRight(curry(f), b); + return reverse().foldLeft(flip(f), b); } /** From bd665e14ac9f07333c1fcd81c56884de1c26dc9f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 00:34:09 +0200 Subject: [PATCH 615/811] NonEmtyList. Add uncurried version of foldRight/foldLeft + append(List). --- core/src/main/java/fj/data/NonEmptyList.java | 27 +++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index db994dc0..da06e0f4 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -8,6 +8,7 @@ import static fj.Function.flip; import static fj.Function.identity; +import static fj.Function.uncurryF2; import static fj.data.Option.some; import static fj.data.Option.somes; @@ -73,6 +74,16 @@ public NonEmptyList snoc(final A a) { */ public int length() { return 1 + tail.length(); } + /** + * Appends the given list to this list. + * + * @param as The list to append. + * @return A new list with the given list appended. + */ + public NonEmptyList append(final List as) { + return nel(head, tail.append(as)); + } + /** * Appends the given list to this list. * @@ -95,14 +106,28 @@ public final A foldRight1(final F> f) { return reverse().foldLeft1(flip(f)); } + /** + * Performs a right-fold reduction across this list. This function uses O(length) stack space. + */ + public final A foldRight1(final F2 f) { + return reverse().foldLeft1(flip(f)); + } + /** * Performs a left-fold reduction across this list. This function runs in constant space. */ public final A foldLeft1(final F> f) { + return foldLeft1(uncurryF2(f)); + } + + /** + * Performs a left-fold reduction across this list. This function runs in constant space. + */ + public final A foldLeft1(final F2 f) { A x = head; for (List xs = tail; !xs.isEmpty(); xs = xs.tail()) { - x = f.f(x).f(xs.head()); + x = f.f(x, xs.head()); } return x; From 87d9b30e8ecdb8775637426022e36c25601ca8e2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 00:35:20 +0200 Subject: [PATCH 616/811] Stream: Avoid unecessary currying in uncurried version of foldRight. --- core/src/main/java/fj/data/Stream.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index ae37d714..b3fa156d 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -119,7 +119,7 @@ public final B uncons(final B nil, final F>, B>> cons) { * @return The final result after the right-fold reduction. */ public final B foldRight(final F, B>> f, final B b) { - return isEmpty() ? b : f.f(head()).f(P.lazy(() -> tail()._1().foldRight(f, b))); + return foldRight(uncurryF2(f), b); } /** @@ -130,7 +130,7 @@ public final B foldRight(final F, B>> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight(final F2, B> f, final B b) { - return foldRight(curry(f), b); + return isEmpty() ? b : f.f(head(), P.lazy(() -> tail()._1().foldRight(f, b))); } /** @@ -141,7 +141,7 @@ public final B foldRight(final F2, B> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight1(final F> f, final B b) { - return foldRight(compose(Function., B, B>andThen().f(P1.__1()), f), b); + return foldRight1(uncurryF2(f), b); } /** @@ -152,7 +152,7 @@ public final B foldRight1(final F> f, final B b) { * @return The final result after the right-fold reduction. */ public final B foldRight1(final F2 f, final B b) { - return foldRight1(curry(f), b); + return isEmpty() ? b : f.f(head(), tail()._1().foldRight1(f, b)); } /** From 7aa9e3b79989b3ce9d2388094913ea3f393b0686 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 00:45:32 +0200 Subject: [PATCH 617/811] Monoid/Semigroup: implement optimizable/optimized definitions. + add generic compose and xmap + deprecate double semigroups due to round errors. --- core/src/main/java/fj/Monoid.java | 781 ++++++++++++++++-- core/src/main/java/fj/Ord.java | 75 +- core/src/main/java/fj/Semigroup.java | 392 +++++++-- core/src/main/java/fj/data/optic/Fold.java | 2 +- .../main/java/fj/data/optic/PTraversal.java | 2 +- core/src/main/java/fj/function/Doubles.java | 17 +- .../java/fj/demo/concurrent/WordCount.java | 7 +- 7 files changed, 1097 insertions(+), 179 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 3436d5a3..a342b8c7 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -1,18 +1,22 @@ package fj; -import static fj.Function.curry; -import static fj.Function.flip; +import static fj.F1Functions.dimap; + import fj.data.Array; +import fj.data.DList; import fj.data.List; import fj.data.IO; -import fj.data.IOFunctions; import fj.data.Natural; import fj.data.Option; import fj.data.Set; import fj.data.Stream; -import static fj.Function.flip; -import static fj.Semigroup.multiply1p; +import static fj.Function.*; +import static fj.Semigroup.semigroupDef; +import static fj.Unit.unit; +import static fj.data.List.nil; +import static fj.data.Natural.natural; +import static fj.data.Option.none; import static fj.data.Stream.iterableStream; import java.math.BigInteger; @@ -30,20 +34,83 @@ * @version %build.number% */ public final class Monoid { - private final F> sum; - private final A zero; - private Monoid(final F> sum, final A zero) { - this.sum = sum; - this.zero = zero; + + private final Definition def; + + public interface Definition extends Semigroup.Definition { + + A empty(); + + + default A sum(F0> as) { + return as.f().foldLeft(this::append, empty()); + } + + @Override + default A sum(A a, F0> as) { + return sum(() -> Stream.cons(a, as)); + } + + default A multiply(int n, A a) { + return (n <= 0) + ? empty() + : Semigroup.Definition.super.multiply1p(n - 1, a); + } + + @Override + default A multiply1p(int n, A a) { + return n == Integer.MAX_VALUE + ? append(a, multiply(n, a)) + : multiply(n + 1, a); + } + + default Definition dual() { + return new Definition(){ + + @Override + public A empty() { + return Definition.this.empty(); + } + + @Override + public A append(A a1, A a2) { + return Definition.this.append(a2, a1); + } + + @Override + public A multiply(int n, A a) { + return Definition.this.multiply(n, a); + } + + @Override + public Definition dual() { + return Definition.this; + } + }; + } + } + + public interface AltDefinition extends Definition { + + @Override + F prepend(A a); + + @Override + default A append(A a1, A a2) { + return prepend(a1).f(a2); + } + } + + private Monoid(Definition def) { + this.def = def; } /** * Composes this monoid with another. */ public Monoid>compose(Monoid m) { - return monoid((P2 x) -> (P2 y) -> - P.p(sum(x._1(), y._1()), m.sum(x._2(), y._2())), P.p(zero, m.zero)); + return compose(m, P2.__1(), P2.__2(), P::p); } /** @@ -52,7 +119,81 @@ private Monoid(final F> sum, final A zero) { * @return A semigroup projection of this monoid. */ public Semigroup semigroup() { - return Semigroup.semigroup(sum); + return semigroupDef(def); + } + + /** + * Maps the given functions across this monoid as an invariant functor. + * + * @param f The covariant map. + * @param g The contra-variant map. + * @return A new monoid. + */ + public Monoid xmap(final F f, final F g) { + Monoid.Definition def = this.def; + B zero = f.f(def.empty()); + return monoidDef(new Definition() { + @Override + public B empty() { + return zero; + } + + @Override + public B append(B a1, B a2) { + return f.f(def.append(g.f(a1), g.f(a2))); + } + + @Override + public F prepend(B b) { + return dimap(def.prepend(g.f(b)), g, f); + } + + @Override + public B multiply(int n, B b) { + return f.f(def.multiply(n , g.f(b))); + } + + @Override + public B sum(F0> as) { + return f.f(def.sum(() -> as.f().map(g))); + } + }); + } + + + public Monoid compose(Monoid mb, final F a, final F b, final F2 c) { + Definition maDef = this.def; + Definition mbDef = mb.def; + C empty = c.f(maDef.empty(), mbDef.empty()); + return monoidDef(new Definition() { + + @Override + public C empty() { + return empty; + } + + @Override + public C append(C c1, C c2) { + return c.f(maDef.append(a.f(c1), a.f(c2)), mbDef.append(b.f(c1), b.f(c2))); + } + + @Override + public F prepend(C c1) { + F prependA = maDef.prepend(a.f(c1)); + F prependB = mbDef.prepend(b.f(c1)); + return c2 -> c.f(prependA.f(a.f(c2)), prependB.f(b.f(c2))); + } + + @Override + public C multiply(int n, C c1) { + return c.f(maDef.multiply(n, a.f(c1)), mbDef.multiply(n, b.f(c1))); + } + + @Override + public C sum(F0> cs) { + return c.f(maDef.sum(() -> cs.f().map(a)), mbDef.sum(() -> cs.f().map(b))); + } + }); } /** @@ -63,7 +204,7 @@ public Semigroup semigroup() { * @return The of the two given arguments. */ public A sum(final A a1, final A a2) { - return sum.f(a1).f(a2); + return def.append(a1, a2); } /** @@ -73,7 +214,7 @@ public A sum(final A a1, final A a2) { * @return A function that sums the given value according to this monoid. */ public F sum(final A a1) { - return sum.f(a1); + return def.prepend(a1); } /** @@ -82,7 +223,7 @@ public F sum(final A a1) { * @return A function that sums according to this monoid. */ public F> sum() { - return sum; + return def::prepend; } /** @@ -91,7 +232,7 @@ public F> sum() { * @return The zero value for this monoid. */ public A zero() { - return zero; + return def.empty(); } /** @@ -106,9 +247,7 @@ public A zero() { * {@code zero()} */ public A multiply(final int n, final A a) { - return (n <= 0) - ? zero - : multiply1p(sum, n - 1, a); + return def.multiply(n, a); } /** @@ -118,7 +257,7 @@ public A multiply(final int n, final A a) { * @return The sum of the given values. */ public A sumRight(final List as) { - return as.foldRight(sum, zero); + return as.foldRight(def::append, def.empty()); } /** @@ -128,7 +267,7 @@ public A sumRight(final List as) { * @return The sum of the given values. */ public A sumRight(final Stream as) { - return as.foldRight((a, ap1) -> sum(a, ap1._1()), zero); + return as.foldRight1(def::append, def.empty()); } /** @@ -138,7 +277,7 @@ public A sumRight(final Stream as) { * @return The sum of the given values. */ public A sumLeft(final List as) { - return as.foldLeft(sum, zero); + return as.foldLeft(def::append, def.empty()); } /** @@ -148,7 +287,7 @@ public A sumLeft(final List as) { * @return The sum of the given values. */ public A sumLeft(final Stream as) { - return as.foldLeft(sum, zero); + return def.sum(() -> as); } /** @@ -187,147 +326,495 @@ public F, A> sumLeftS() { */ public A join(final Iterable as, final A a) { final Stream s = iterableStream(as); - return s.isEmpty() ? - zero : - s.foldLeft1(Function.compose(sum, flip(sum).f(a))); + F prependA = def.prepend(a); + return s.isEmpty() + ? def.empty() + : s.foldLeft1((a1, a2) -> def.append(a1, prependA.f(a2))); } /** * Swaps the arguments when summing. */ public Monoid dual() { - return monoid(flip(sum), zero); + return monoidDef(def.dual()); + } + + /** + * Constructs a monoid from the given definition, which must follow the monoidal + * laws. + * + * @param def The definition for the monoid. + * @return A monoid instance that uses the given sun function and zero value. + */ + public static Monoid monoidDef(Definition def) { + return new Monoid<>(def); + } + + /** + * Constructs a monoid from the given definition, which must follow the monoidal + * laws. + * + * @param def The definition for the monoid. + * @return A monoid instance that uses the given sun function and zero value. + */ + public static Monoid monoidDef(AltDefinition def) { + return new Monoid<>(def); + } + + /** + * Constructs a monoid from the given semigroup definition and zero value, which must follow the monoidal laws. + * + * @param s The semigroup definition for the monoid. + * @param zero The zero for the monoid. + * @return A monoid instance that uses the given sun function and zero value. + */ + public static Monoid monoidDef(final Semigroup.Definition s, final A zero) { + return new Monoid<>(new Monoid.Definition() { + @Override + public A empty() { + return zero; + } + + @Override + public A sum(F0> as) { + return s.sum(zero, as); + } + + @Override + public A sum(A a, F0> as) { + return s.sum(a, as); + } + + @Override + public A multiply(int n, A a) { + return (n <= 0) + ? zero + : s.multiply1p(n - 1, a); + } + + @Override + public A multiply1p(int n, A a) { + return s.multiply1p(n, a); + } + + @Override + public A append(A a1, A a2) { + return s.append(a1, a2); + } + + @Override + public F prepend(A a) { + return s.prepend(a); + } + }); + } + + /** + * Constructs a monoid from the given semigroup definition and zero value, which must follow the monoidal laws. + * + * @param s The semigroup definition for the monoid. + * @param zero The zero for the monoid. + * @return A monoid instance that uses the given sun function and zero value. + */ + public static Monoid monoidDef(final Semigroup.AltDefinition s, final A zero) { + return monoidDef((Semigroup.Definition) s, zero); } /** * Constructs a monoid from the given sum function and zero value, which must follow the monoidal * laws. + * @deprecated since 4.7. Use {@link #monoidDef(Semigroup.Definition, Object)} instead. * * @param sum The sum function for the monoid. * @param zero The zero for the monoid. * @return A monoid instance that uses the given sun function and zero value. */ + @Deprecated public static Monoid monoid(final F> sum, final A zero) { - return new Monoid<>(sum, zero); + return new Monoid<>(new AltDefinition() { + @Override + public F prepend(A a) { + return sum.f(a); + } + + @Override + public A empty() { + return zero; + } + }); } /** * Constructs a monoid from the given sum function and zero value, which must follow the monoidal * laws. + * @deprecated since 4.7. Use {@link #monoidDef(Semigroup.Definition, Object)} instead. * * @param sum The sum function for the monoid. * @param zero The zero for the monoid. * @return A monoid instance that uses the given sun function and zero value. */ + @Deprecated public static Monoid monoid(final F2 sum, final A zero) { - return new Monoid<>(curry(sum), zero); + return new Monoid<>(new Definition() { + @Override + public A empty() { + return zero; + } + + @Override + public A append(A a1, A a2) { + return sum.f(a1, a2); + } + }); } /** * Constructs a monoid from the given semigroup and zero value, which must follow the monoidal laws. + * @deprecated since 4.7. Use {@link #monoidDef(Semigroup.Definition, Object)} or {@link Semigroup#monoid(Object)} instead. * * @param s The semigroup for the monoid. * @param zero The zero for the monoid. * @return A monoid instance that uses the given sun function and zero value. */ + @Deprecated public static Monoid monoid(final Semigroup s, final A zero) { - return new Monoid<>(s.sum(), zero); + return s.monoid(zero); } + /** * A monoid that adds integers. */ - public static final Monoid intAdditionMonoid = monoid(Semigroup.intAdditionSemigroup, 0); + public static final Monoid intAdditionMonoid = monoidDef(new Definition() { + @Override + public Integer empty() { + return 0; + } + + @Override + public Integer append(Integer a1, Integer a2) { + return a1 + a2; + } + + @Override + public Integer multiply(int n, Integer i) { + return n <= 0 ? 0 : n * i; + } + }); /** * A monoid that multiplies integers. */ - public static final Monoid intMultiplicationMonoid = monoid(Semigroup.intMultiplicationSemigroup, 1); + public static final Monoid intMultiplicationMonoid = monoidDef(new Definition() { + @Override + public Integer empty() { + return 1; + } + + @Override + public Integer append(Integer i1, Integer i2) { + return i1 * i2; + } + + @Override + public Integer sum(F0> as) { + int x = 1; + for (Stream xs = as.f(); x != 0 && !xs.isEmpty(); xs = xs.tail()._1()) { + x *= xs.head(); + } + return x; + } + + @Override + public Integer multiply(int n, Integer integer) { + return n <= 0 ? 1 : (int) StrictMath.pow(integer.doubleValue(), n); + } + }); /** - * A monoid that adds doubles. + * @deprecated Since 4.7. Due to rounding errors, addition of doubles does not comply with monoid laws */ - public static final Monoid doubleAdditionMonoid = monoid(Semigroup.doubleAdditionSemigroup, 0.0); + @Deprecated + public static final Monoid doubleAdditionMonoid = monoidDef((d1, d2) -> d1 + d2, 0.0); /** - * A monoid that multiplies doubles. + * @deprecated Since 4.7. Due to rounding errors, multiplication of doubles does not comply with monoid laws */ - public static final Monoid doubleMultiplicationMonoid = monoid(Semigroup.doubleMultiplicationSemigroup, 1.0); + @Deprecated + public static final Monoid doubleMultiplicationMonoid = monoidDef((d1, d2) -> d1 * d2, 1.0); /** * A monoid that adds big integers. */ - public static final Monoid bigintAdditionMonoid = monoid(Semigroup.bigintAdditionSemigroup, BigInteger.ZERO); + public static final Monoid bigintAdditionMonoid = monoidDef(new Definition() { + @Override + public BigInteger empty() { + return BigInteger.ZERO; + } + + @Override + public BigInteger append(BigInteger a1, BigInteger a2) { + return a1.add(a2); + } + + @Override + public BigInteger multiply(int n, BigInteger a) { + return n <= 0 ? BigInteger.ZERO : a.multiply(BigInteger.valueOf(n)); + } + }); /** * A monoid that multiplies big integers. */ - public static final Monoid bigintMultiplicationMonoid = - monoid(Semigroup.bigintMultiplicationSemigroup, BigInteger.ONE); + public static final Monoid bigintMultiplicationMonoid = monoidDef(new Definition() { + @Override + public BigInteger empty() { + return BigInteger.ONE; + } + + @Override + public BigInteger append(BigInteger a1, BigInteger a2) { + return a1.multiply(a2); + } + + @Override + public BigInteger multiply(int n, BigInteger a) { + return n <= 0 ? BigInteger.ONE : a.pow(n); + } + + }); /** * A monoid that adds big decimals. */ public static final Monoid bigdecimalAdditionMonoid = - monoid(Semigroup.bigdecimalAdditionSemigroup, BigDecimal.ZERO); + monoidDef(new Definition() { + @Override + public BigDecimal empty() { + return BigDecimal.ZERO; + } + + @Override + public BigDecimal append(BigDecimal a1, BigDecimal a2) { + return a1.add(a2); + } + + @Override + public BigDecimal multiply(int n, BigDecimal a) { + return n <= 0 ? BigDecimal.ZERO : a.multiply(BigDecimal.valueOf(n)); + } + }); /** * A monoid that multiplies big decimals. */ public static final Monoid bigdecimalMultiplicationMonoid = - monoid(Semigroup.bigdecimalMultiplicationSemigroup, BigDecimal.ONE); + monoidDef(new Definition() { + @Override + public BigDecimal empty() { + return BigDecimal.ONE; + } + + @Override + public BigDecimal append(BigDecimal a1, BigDecimal a2) { + return a1.multiply(a2); + } + + @Override + public BigDecimal multiply(int n, BigDecimal decimal) { + return n <= 0 ? BigDecimal.ONE : decimal.pow(n); + } + }); + + /** * A monoid that adds natural numbers. */ public static final Monoid naturalAdditionMonoid = - monoid(Semigroup.naturalAdditionSemigroup, Natural.ZERO); + monoidDef(new Definition() { + @Override + public Natural empty() { + return Natural.ZERO; + } + + @Override + public Natural append(Natural a1, Natural a2) { + return a1.add(a2); + } + + @Override + public Natural multiply(int n, Natural a) { + return natural(n).map(positiveN -> a.multiply(positiveN)).orSome(Natural.ZERO); + } + }); /** * A monoid that multiplies natural numbers. */ public static final Monoid naturalMultiplicationMonoid = - monoid(Semigroup.naturalMultiplicationSemigroup, Natural.ONE); + monoidDef(new Definition() { + @Override + public Natural empty() { + return Natural.ONE; + } + + @Override + public Natural append(Natural a1, Natural a2) { + return a1.multiply(a2); + } + }); /** * A monoid that adds longs. */ - public static final Monoid longAdditionMonoid = monoid(Semigroup.longAdditionSemigroup, 0L); + public static final Monoid longAdditionMonoid = monoidDef(new Definition() { + @Override + public Long empty() { + return 0L; + } + + @Override + public Long append(Long a1, Long a2) { + return a1 + a2; + } + + @Override + public Long multiply(int n, Long a) { + return n <= 0 ? 0L : n * a; + } + }); /** * A monoid that multiplies longs. */ - public static final Monoid longMultiplicationMonoid = monoid(Semigroup.longMultiplicationSemigroup, 1L); + public static final Monoid longMultiplicationMonoid = monoidDef(new Definition() { + @Override + public Long empty() { + return 1L; + } + + @Override + public Long append(Long i1, Long i2) { + return i1 * i2; + } + + @Override + public Long sum(F0> as) { + long x = 1L; + for (Stream xs = as.f(); x != 0L && !xs.isEmpty(); xs = xs.tail()._1()) { + x *= xs.head(); + } + return x; + } + + @Override + public Long multiply(int n, Long l) { + return n <= 0 ? 1L : (long) StrictMath.pow(l.doubleValue(), n); + } + }); /** * A monoid that ORs booleans. */ - public static final Monoid disjunctionMonoid = monoid(Semigroup.disjunctionSemigroup, false); + public static final Monoid disjunctionMonoid = monoidDef(new Definition() { + @Override + public Boolean empty() { + return false; + } + + @Override + public Boolean append(Boolean a1, Boolean a2) { + return a1 | a2; + } + + @Override + public Boolean sum(F0> as) { + return as.f().filter(identity()).isNotEmpty(); + } + + @Override + public Boolean multiply(int n, Boolean a) { + return n <= 0 ? false : a; + } + }); /** * A monoid that XORs booleans. */ - public static final Monoid exclusiveDisjunctionMonoid = monoid(Semigroup.exclusiveDisjunctionSemiGroup, false); + public static final Monoid exclusiveDisjunctionMonoid = monoidDef(new Definition() { + @Override + public Boolean empty() { + return false; + } + + @Override + public Boolean append(Boolean a1, Boolean a2) { + return a1 ^ a2; + } + + @Override + public Boolean multiply(int n, Boolean a) { + return a && (n == 1); + } + }); /** * A monoid that ANDs booleans. */ - public static final Monoid conjunctionMonoid = monoid(Semigroup.conjunctionSemigroup, true); + public static final Monoid conjunctionMonoid = monoidDef(new Definition() { + @Override + public Boolean empty() { + return true; + } + + @Override + public Boolean append(Boolean a1, Boolean a2) { + return a1 & a2; + } + + @Override + public Boolean multiply(int n, Boolean a) { + return a; + } + + @Override + public Boolean sum(F0> as) { + return as.f().filter(a -> !a).isEmpty(); + } + }); /** * A monoid that appends strings. */ - public static final Monoid stringMonoid = monoid(Semigroup.stringSemigroup, ""); + public static final Monoid stringMonoid = monoidDef(new Definition() { + @Override + public String empty() { + return ""; + } + + @Override + public String append(String a1, String a2) { + return a1.concat(a2); + } + + @Override + public String sum(F0> as) { + StringBuilder sb = new StringBuilder(); + as.f().foreachDoEffect(sb::append); + return sb.toString(); + } + }); /** * A monoid that appends string buffers. */ - public static final Monoid stringBufferMonoid = monoid(Semigroup.stringBufferSemigroup, new StringBuffer()); + public static final Monoid stringBufferMonoid = monoidDef((s1, s2) -> new StringBuffer(s1).append(s2), new StringBuffer(0)); /** * A monoid that appends string builders. */ - public static final Monoid stringBuilderMonoid = monoid(Semigroup.stringBuilderSemigroup, new StringBuilder()); + public static final Monoid stringBuilderMonoid = monoidDef((s1, s2) -> new StringBuilder(s1).append(s2), new StringBuilder(0)); /** * A monoid for functions. @@ -336,7 +823,18 @@ public static Monoid monoid(final Semigroup s, final A zero) { * @return A monoid for functions. */ public static Monoid> functionMonoid(final Monoid mb) { - return monoid(Semigroup.functionSemigroup(mb.semigroup()), Function.constant(mb.zero)); + Definition mbDef = mb.def; + return monoidDef(new Definition>() { + @Override + public F empty() { + return __ -> mbDef.empty(); + } + + @Override + public F append(F a1, F a2) { + return a -> mbDef.append(a1.f(a), a2.f(a)); + } + }); } /** @@ -345,16 +843,33 @@ public static Monoid> functionMonoid(final Monoid mb) { * @return A monoid for lists. */ public static Monoid> listMonoid() { - return monoid(Semigroup.listSemigroup(), List.nil()); + return monoidDef(new Definition>() { + @Override + public List empty() { + return nil(); + } + + @Override + public List append(List a1, List a2) { + return a1.append(a2); + } + + @Override + public List sum(F0>> as) { + return as.f().map(DList::listDList).foldLeft(DList::append, DList.nil()).run(); + } + }); } /** * A monoid for options. + * @deprecated since 4.7. Use {@link #firstOptionMonoid()}. * * @return A monoid for options. */ + @Deprecated public static Monoid> optionMonoid() { - return monoid(Semigroup.optionSemigroup(), Option.none()); + return firstOptionMonoid(); } /** @@ -363,7 +878,32 @@ public static Monoid> optionMonoid() { * @return A monoid for options that take the first available value. */ public static Monoid> firstOptionMonoid() { - return monoid(Semigroup.firstOptionSemigroup(), Option.none()); + return monoidDef(new Definition>() { + @Override + public Option empty() { + return none(); + } + + @Override + public Option append(Option a1, Option a2) { + return a1.orElse(a2); + } + + @Override + public F, Option> prepend(Option a1) { + return a1.isSome() ? __ -> a1 : identity(); + } + + @Override + public Option multiply(int n, Option as) { + return as; + } + + @Override + public Option sum(F0>> as) { + return as.f().filter(Option.isSome_()).orHead(Option::none); + } + }); } /** @@ -372,7 +912,27 @@ public static Monoid> firstOptionMonoid() { * @return A monoid for options that take the last available value. */ public static Monoid> lastOptionMonoid() { - return monoid(Semigroup.lastOptionSemigroup(), Option.none()); + return monoidDef(new Definition>() { + @Override + public Option empty() { + return none(); + } + + @Override + public Option append(Option a1, Option a2) { + return a2.orElse(a1); + } + + @Override + public F, Option> prepend(Option a1) { + return a1.isNone() ? identity() : a2 -> a2.orElse(a1); + } + + @Override + public Option multiply(int n, Option as) { + return as; + } + }); } /** @@ -381,7 +941,22 @@ public static Monoid> lastOptionMonoid() { * @return A monoid for streams. */ public static Monoid> streamMonoid() { - return monoid(Semigroup.streamSemigroup(), Stream.nil()); + return monoidDef(new Definition>() { + @Override + public Stream empty() { + return Stream.nil(); + } + + @Override + public Stream append(Stream a1, Stream a2) { + return a1.append(a2); + } + + @Override + public Stream sum(F0>> as) { + return Stream.join(as.f()); + } + }); } /** @@ -391,30 +966,91 @@ public static Monoid> streamMonoid() { */ @SuppressWarnings("unchecked") public static Monoid> arrayMonoid() { - return monoid(Semigroup.arraySemigroup(), Array.empty()); + return monoidDef(new Definition>() { + @Override + public Array empty() { + return Array.empty(); + } + + @Override + public Array append(Array a1, Array a2) { + return a1.append(a2); + } + }); } /** * A monoid for IO values. */ - public static Monoid> ioMonoid(final Monoid ma) { - return monoid(Semigroup.ioSemigroup(ma.semigroup()), IOFunctions.unit(ma.zero())); + public static Monoid> ioMonoid(final Monoid ma) { + Definition maDef = ma.def; + return monoidDef(new Definition>() { + @Override + public IO empty() { + return () -> maDef.empty(); + } + + @Override + public IO append(IO a1, IO a2) { + return () -> maDef.append(a1.run(), a2.run()); + } + }); } /** * A monoid for the maximum of two integers. */ - public static final Monoid intMaxMonoid = monoid(Semigroup.intMaximumSemigroup, Integer.MIN_VALUE); + public static final Monoid intMaxMonoid = monoidDef(new Definition() { + @Override + public Integer empty() { + return Integer.MIN_VALUE; + } + + @Override + public Integer append(Integer a1, Integer a2) { + return Math.max(a1, a2); + } + + @Override + public Integer multiply(int n, Integer a) { + return a; + } + }); /** * A monoid for the minimum of two integers. */ - public static final Monoid intMinMonoid = monoid(Semigroup.intMinimumSemigroup, Integer.MAX_VALUE); + public static final Monoid intMinMonoid = monoidDef(new Definition() { + @Override + public Integer empty() { + return Integer.MAX_VALUE; + } + + @Override + public Integer append(Integer a1, Integer a2) { + return Math.min(a1, a2); + } + + @Override + public Integer multiply(int n, Integer a) { + return a; + } + }); /** * A monoid for the Unit value. */ - public static final Monoid unitMonoid = monoid(Semigroup.unitSemigroup, Unit.unit()); + public static final Monoid unitMonoid = monoidDef(new Definition() { + @Override + public Unit empty() { + return unit(); + } + + @Override + public Unit append(Unit a1, Unit a2) { + return unit(); + } + }); /** * A monoid for sets. @@ -423,18 +1059,29 @@ public static Monoid> ioMonoid(final Monoid ma) { * @return A monoid for sets whose elements have the given order. */ public static Monoid> setMonoid(final Ord o) { - return monoid(Semigroup.setSemigroup(), Set.empty(o)); - } + return monoidDef(new Definition>() { + @Override + public Set empty() { + return Set.empty(o); + } + @Override + public Set append(Set a1, Set a2) { + return a1.union(a2); + } + }); + } /** * A monoid for the maximum of elements with ordering o. + * @deprecated since 4.7. Use {@link Ord#maxMonoid(Object)} * * @param o An ordering of elements. * @param zero The minimum element. */ + @Deprecated public static Monoid ordMaxMonoid(final Ord o, final A zero) { - return monoid(o.max, zero); + return o.maxMonoid(zero); } } diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 86d560b7..1764ea74 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -19,6 +19,7 @@ import static fj.Function.compose2; import static fj.Function.curry; import static fj.Semigroup.semigroup; +import static fj.Semigroup.semigroupDef; /** * Tests for ordering between two objects. @@ -30,7 +31,7 @@ public final class Ord { /** * Primitives functions of Ord: minimal definition and overridable methods. */ - public interface Definition extends Equal.Definition { + public interface Definition extends Equal.Definition, Semigroup.Definition { F compare(A a); @@ -38,6 +39,7 @@ default Ordering compare(A a1, A a2) { return compare(a1).f(a2); } + // equal: @Override default boolean equal(A a1, A a2) { return compare(a1, a2) == Ordering.EQ; @@ -47,6 +49,42 @@ default boolean equal(A a1, A a2) { default F equal(A a) { return compose(o -> o == Ordering.EQ, compare(a)); } + + // max semigroup: + @Override + default A append(A a1, A a2) { + return compare(a1, a2) == Ordering.GT ? a1 : a2; + } + + @Override + default A multiply1p(int n, A a) { + return a; + } + + @Override + default F prepend(A a1) { + return apply((a2, o) -> o == Ordering.GT ? a1 : a2, compare(a1)); + } + + @Override + default Definition dual() { + return new Definition() { + @Override + public F compare(A a) { + return compose(Ordering::reverse, Definition.this.compare(a)); + } + + @Override + public Ordering compare(A a1, A a2) { + return Definition.this.compare(a2, a1); + } + + @Override + public Definition dual() { + return Definition.this; + } + }; + } } /** @@ -60,6 +98,11 @@ default F compare(A a1) { return a2 -> compare(a1, a2); } + @Override + default F prepend(A a1) { + return a2 -> append(a1, a2); + } + } @@ -199,7 +242,7 @@ public F isGreaterThan(final A a) { * @return The greater of the two values. */ public A max(final A a1, final A a2) { - return isGreaterThan(a1, a2) ? a1 : a2; + return def.append(a1, a2); } @@ -216,6 +259,7 @@ public A min(final A a1, final A a2) { /** * A function that returns the greater of its two arguments. + * */ public final F> max; @@ -225,34 +269,33 @@ public A min(final A a1, final A a2) { public final F> min; public final Semigroup minSemigroup() { - return semigroup(min); + return semigroupDef(def.dual()); + } + + public final Monoid minMonoid(A zero) { + return Monoid.monoidDef(def.dual(), zero); } public final Semigroup maxSemigroup() { - return semigroup(max); + return semigroupDef(def); } - public final Ord reverse() { - Definition selfDef = def; - return ordDef(new Definition() { - @Override - public F compare(A a) { - return compose(Ordering::reverse, selfDef.compare(a)); - } + public final Monoid maxMonoid(A zero) { + return Monoid.monoidDef(def, zero); + } - @Override - public Ordering compare(A a1, A a2) { - return selfDef.compare(a2, a1); - } - }); + public final Ord reverse() { + return ordDef(def.dual()); } /** * Returns an order instance that uses the given equality test and ordering function. * + * @deprecated since 4.7. Use {@link #ordDef(Definition)}. * @param f The order function. * @return An order instance. */ + @Deprecated public static Ord ord(final F> f) { return new Ord<>(f::f); } diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 7c5538f2..cba1f04b 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -1,9 +1,9 @@ package fj; import fj.data.Array; +import fj.data.DList; import fj.data.List; import fj.data.IO; -import fj.data.IOFunctions; import fj.data.Natural; import fj.data.NonEmptyList; import fj.data.Option; @@ -13,8 +13,13 @@ import java.math.BigDecimal; import java.math.BigInteger; -import static fj.Function.curry; -import static fj.Function.flip; +import static fj.F1Functions.dimap; +import static fj.Function.constant; +import static fj.Function.identity; +import static fj.Monoid.*; +import static fj.data.DList.listDList; +import static fj.data.Option.none; +import static fj.data.Option.some; /** * Implementations must satisfy the law of associativity: @@ -25,10 +30,69 @@ * @version %build.number% */ public final class Semigroup { - private final F> sum; - private Semigroup(final F> sum) { - this.sum = sum; + public interface Definition { + + A append(A a1, A a2); + + default F prepend(A a) { + return a2 -> append(a, a2); + } + + default A sum(A a, F0> as) { + return as.f().foldLeft(this::append, a); + } + + default A multiply1p(int n, A a) { + if (n <= 0) { + return a; + } + + A xTmp = a; + int yTmp = n; + A zTmp = a; + while (true) { + if ((yTmp & 1) == 1) { + zTmp = append(xTmp, zTmp); + if (yTmp == 1) { + return zTmp; + } + } + xTmp = append(xTmp, xTmp); + yTmp = (yTmp) >>> 1; + } + } + + default Definition dual() { + return new Definition(){ + + @Override + public A append(A a1, A a2) { + return Definition.this.append(a2, a1); + } + + @Override + public A multiply1p(int n, A a) { + return Definition.this.multiply1p(n, a); + } + }; + } + } + + public interface AltDefinition extends Definition { + @Override + F prepend(A a); + + @Override + default A append(A a1, A a2) { + return prepend(a1).f(a2); + } + } + + private final Definition def; + + private Semigroup(final Definition def) { + this.def = def; } /** @@ -39,7 +103,7 @@ private Semigroup(final F> sum) { * @return The of the two given arguments. */ public A sum(final A a1, final A a2) { - return sum.f(a1).f(a2); + return def.append(a1, a2); } /** @@ -49,7 +113,7 @@ public A sum(final A a1, final A a2) { * @return A function that sums the given value according to this semigroup. */ public F sum(final A a1) { - return sum.f(a1); + return def.prepend(a1); } /** @@ -58,7 +122,7 @@ public F sum(final A a1) { * @return A function that sums according to this semigroup. */ public F> sum() { - return sum; + return def::prepend; } /** @@ -73,106 +137,213 @@ public F> sum() { * {@code zero()} */ public A multiply1p(int n, A a) { - return multiply1p(sum, n, a); + return def.multiply1p(n, a); } - // shared implementation between Semigroup and Monoid - static A multiply1p(F> sum, int n, A a) { - if (n <= 0) { - return a; - } - - A xTmp = a; - int yTmp = n; - A zTmp = a; - while (true) { - if ((yTmp & 1) == 1) { - zTmp = sum.f(xTmp).f(zTmp); - if (yTmp == 1) { - return zTmp; - } - } - xTmp = sum.f(xTmp).f(xTmp); - yTmp = yTmp >>> 1; - } - } /** * Sums the given values with left-fold. */ public A sumNel(final NonEmptyList as) { - return as.foldLeft1(sum); + return as.foldLeft1(def::append); + } + + /** + * Sums the given values with left-fold, shortcutting the computation as early as possible. + */ + public A sumStream(A a, F0> as) { + return def.sum(a, as); } /** * Swaps the arguments when summing. */ public Semigroup dual() { - return semigroup(flip(sum)); + return semigroupDef(def.dual()); } /** * Lifts the semigroup to obtain a trivial monoid. */ public Monoid> lift() { - return Monoid.monoid(a -> b -> Option.liftM2(sum).f(a).f(b).orElse(a).orElse(b), Option.none()); + Definition def = this.def; + return monoidDef(new Monoid.Definition>() { + @Override + public Option empty() { + return none(); + } + + @Override + public Option append(Option a1, Option a2) { + return a1.liftM2(a1, def::append).orElse(a1).orElse(a2); + } + + @Override + public Option multiply(int n, Option oa) { + return n > 0 ? oa.map(a -> def.multiply1p(n - 1, a)) : none(); + } + + @Override + public Option sum(F0>> oas) { + Stream as = oas.f().bind(Option::toStream); + return as.uncons(none(), h -> tail -> some(def.sum(h, tail::_1))); + } + }); + } + + /** + * Maps the given functions across this monoid as an invariant functor. + * + * @param f The covariant map. + * @param g The contra-variant map. + * @return A new monoid. + */ + public Semigroup xmap(final F f, final F g) { + Definition def = this.def; + return semigroupDef(new Definition() { + + @Override + public B append(B a1, B a2) { + return f.f(def.append(g.f(a1), g.f(a2))); + } + + @Override + public F prepend(B b) { + return dimap(def.prepend(g.f(b)), g, f); + } + + @Override + public B multiply1p(int n, B b) { + return f.f(def.multiply1p(n , g.f(b))); + } + + @Override + public B sum(B b, F0> bs) { + return f.f(def.sum(g.f(b), () -> bs.f().map(g))); + } + }); + } + + public Semigroup compose(Semigroup sb, final F b, final F a, final F2 c) { + Definition saDef = this.def; + Definition sbDef = sb.def; + return semigroupDef(new Definition() { + + @Override + public C append(C c1, C c2) { + return c.f(saDef.append(a.f(c1), a.f(c2)), sbDef.append(b.f(c1), b.f(c2))); + } + + @Override + public F prepend(C c1) { + F prependA = saDef.prepend(a.f(c1)); + F prependB = sbDef.prepend(b.f(c1)); + return c2 -> c.f(prependA.f(a.f(c2)), prependB.f(b.f(c2))); + } + + @Override + public C multiply1p(int n, C c1) { + return c.f(saDef.multiply1p(n, a.f(c1)), sbDef.multiply1p(n, b.f(c1))); + } + + @Override + public C sum(C c1, F0> cs) { + return c.f(saDef.sum(a.f(c1), () -> cs.f().map(a)), sbDef.sum(b.f(c1), () -> cs.f().map(b))); + } + }); + } + + /** + * Constructs a monoid from this semigroup and a zero value, which must follow the monoidal laws. + * + * @param zero The zero for the monoid. + * @return A monoid instance that uses the given sun function and zero value. + */ + public Monoid monoid(A zero) { + return monoidDef(this.def, zero); + } + + /** + * Constructs a semigroup from the given definition. + * + * @param def The definition to construct this semigroup with. + * @return A semigroup from the given definition. + */ + public static Semigroup semigroupDef(final Definition def) { + return new Semigroup<>(def); + } + + /** + * Constructs a semigroup from the given definition. + * + * @param def The definition to construct this semigroup with. + * @return A semigroup from the given definition. + */ + public static Semigroup semigroupDef(final AltDefinition def) { + return new Semigroup<>(def); } /** * Constructs a semigroup from the given function. + * @deprecated since 4.7. Use {@link #semigroupDef(Definition)}. * * @param sum The function to construct this semigroup with. * @return A semigroup from the given function. */ + @Deprecated public static Semigroup semigroup(final F> sum) { - return new Semigroup<>(sum); + return semigroupDef(sum::f); } /** * Constructs a semigroup from the given function. + * @deprecated since 4.7. Use {@link #semigroupDef(Definition)}. * * @param sum The function to construct this semigroup with. * @return A semigroup from the given function. */ + @Deprecated public static Semigroup semigroup(final F2 sum) { - return new Semigroup<>(curry(sum)); + return new Semigroup<>(sum::f); } + /** * A semigroup that adds integers. */ - public static final Semigroup intAdditionSemigroup = semigroup((i1, i2) -> i1 + i2); + public static final Semigroup intAdditionSemigroup = intAdditionMonoid.semigroup(); /** - * A semigroup that adds doubles. + * @deprecated Since 4.7. Due to rounding errors, addition of doubles does not comply with monoid laws */ - public static final Semigroup doubleAdditionSemigroup = semigroup((d1, d2) -> d1 + d2); + @Deprecated + public static final Semigroup doubleAdditionSemigroup = semigroupDef((d1, d2) -> d1 + d2); /** * A semigroup that multiplies integers. */ - public static final Semigroup intMultiplicationSemigroup = semigroup((i1, i2) -> i1 * i2); + public static final Semigroup intMultiplicationSemigroup = intMultiplicationMonoid.semigroup(); /** - * A semigroup that multiplies doubles. + * @deprecated Since 4.7. Due to rounding errors, addition of doubles does not comply with monoid laws */ - public static final Semigroup doubleMultiplicationSemigroup = semigroup((d1, d2) -> d1 * d2); + @Deprecated + public static final Semigroup doubleMultiplicationSemigroup = semigroupDef((d1, d2) -> d1 * d2); /** * A semigroup that yields the maximum of integers. */ - public static final Semigroup intMaximumSemigroup = Ord.intOrd.maxSemigroup(); + public static final Semigroup intMaximumSemigroup = intMaxMonoid.semigroup(); /** * A semigroup that yields the minimum of integers. */ - public static final Semigroup intMinimumSemigroup = Ord.intOrd.minSemigroup(); + public static final Semigroup intMinimumSemigroup = intMinMonoid.semigroup(); /** * A semigroup that adds big integers. */ - public static final Semigroup bigintAdditionSemigroup = - semigroup(BigInteger::add); + public static final Semigroup bigintAdditionSemigroup = bigintAdditionMonoid.semigroup(); /** * A semigroup that multiplies big integers. @@ -193,14 +364,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that adds big decimals. */ - public static final Semigroup bigdecimalAdditionSemigroup = - semigroup(BigDecimal::add); + public static final Semigroup bigdecimalAdditionSemigroup = bigdecimalAdditionMonoid.semigroup(); /** * A semigroup that multiplies big decimals. */ - public static final Semigroup bigdecimalMultiplicationSemigroup = - semigroup(BigDecimal::multiply); + public static final Semigroup bigdecimalMultiplicationSemigroup = bigdecimalMultiplicationMonoid.semigroup(); /** * A semigroup that yields the maximum of big decimals. @@ -215,14 +384,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that multiplies natural numbers. */ - public static final Semigroup naturalMultiplicationSemigroup = - semigroup(Natural::multiply); + public static final Semigroup naturalMultiplicationSemigroup = naturalMultiplicationMonoid.semigroup(); /** * A semigroup that adds natural numbers. */ - public static final Semigroup naturalAdditionSemigroup = - semigroup(Natural::add); + public static final Semigroup naturalAdditionSemigroup = naturalAdditionMonoid.semigroup(); /** * A semigroup that yields the maximum of natural numbers. @@ -237,12 +404,12 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that adds longs. */ - public static final Semigroup longAdditionSemigroup = semigroup((x, y) -> x + y); + public static final Semigroup longAdditionSemigroup = longAdditionMonoid.semigroup(); /** * A semigroup that multiplies longs. */ - public static final Semigroup longMultiplicationSemigroup = semigroup((x, y) -> x * y); + public static final Semigroup longMultiplicationSemigroup = longMultiplicationMonoid.semigroup(); /** * A semigroup that yields the maximum of longs. @@ -257,47 +424,80 @@ public static Semigroup semigroup(final F2 sum) { /** * A semigroup that ORs booleans. */ - public static final Semigroup disjunctionSemigroup = semigroup((b1, b2) -> b1 || b2); + public static final Semigroup disjunctionSemigroup = disjunctionMonoid.semigroup(); /** * A semigroup that XORs booleans. */ - public static final Semigroup exclusiveDisjunctionSemiGroup = semigroup((p, q) -> p ? !q : q); + public static final Semigroup exclusiveDisjunctionSemiGroup = exclusiveDisjunctionMonoid.semigroup(); /** * A semigroup that ANDs booleans. */ - public static final Semigroup conjunctionSemigroup = semigroup((b1, b2) -> b1 && b2); + public static final Semigroup conjunctionSemigroup = conjunctionMonoid.semigroup(); /** * A semigroup that appends strings. */ - public static final Semigroup stringSemigroup = semigroup((s1, s2) -> s1 + s2); + public static final Semigroup stringSemigroup = stringMonoid.semigroup(); /** * A semigroup that appends string buffers. */ - public static final Semigroup stringBufferSemigroup = - semigroup((s1, s2) -> new StringBuffer(s1).append(s2)); + public static final Semigroup stringBufferSemigroup = stringBufferMonoid.semigroup(); /** * A semigroup that appends string builders. */ - public static final Semigroup stringBuilderSemigroup = - semigroup((s1, s2) -> new StringBuilder(s1).append(s2)); + public static final Semigroup stringBuilderSemigroup = stringBuilderMonoid.semigroup(); /** * A semigroup which always uses the "first" (left-hand side) value. */ public static Semigroup firstSemigroup() { - return semigroup((a1, a2) -> a1); + return semigroupDef(new Definition() { + @Override + public A append(A a1, A a2) { + return a1; + } + + @Override + public F prepend(A a) { + return constant(a); + } + + @Override + public A multiply1p(int n, A a) { + return a; + } + + @Override + public A sum(A a, F0> as) { + return a; + } + }); } /** * A semigroup which always uses the "last" (right-hand side) value. */ public static Semigroup lastSemigroup() { - return semigroup((a1, a2) -> a2); + return semigroupDef(new Definition() { + @Override + public A append(A a1, A a2) { + return a2; + } + + @Override + public F prepend(A a) { + return identity(); + } + + @Override + public A multiply1p(int n, A a) { + return a; + } + }); } /** @@ -307,7 +507,8 @@ public static Semigroup lastSemigroup() { * @return A semigroup for functions. */ public static Semigroup> functionSemigroup(final Semigroup sb) { - return semigroup((a1, a2) -> a -> sb.sum(a1.f(a), a2.f(a))); + Definition sbDef = sb.def; + return semigroupDef((a1, a2) -> a -> sbDef.append(a1.f(a), a2.f(a))); } /** @@ -316,7 +517,7 @@ public static Semigroup> functionSemigroup(final Semigroup sb) * @return A semigroup for lists. */ public static Semigroup> listSemigroup() { - return semigroup(List::append); + return Monoid.listMonoid().semigroup(); } /** @@ -325,15 +526,29 @@ public static Semigroup> listSemigroup() { * @return A semigroup for non-empty lists. */ public static Semigroup> nonEmptyListSemigroup() { - return semigroup(NonEmptyList::append); + + return semigroupDef(new Definition>() { + @Override + public NonEmptyList append(NonEmptyList a1, NonEmptyList a2) { + return a1.append(a1); + } + + @Override + public NonEmptyList sum(NonEmptyList nea, F0>> neas) { + List tail = neas.f().map(nel -> listDList(nel.toList())).foldLeft(DList::append, DList.nil()).run(); + return nea.append(tail); + } + }); } /** * A semigroup for optional values. + * @deprecated since 4.7. Use {@link #firstOptionSemigroup()}. + * ** @return A semigroup for optional values. */ public static Semigroup> optionSemigroup() { - return semigroup((a1, a2) -> a1.isSome() ? a1 : a2); + return firstOptionSemigroup(); } /** @@ -342,7 +557,7 @@ public static Semigroup> optionSemigroup() { * @return A semigroup for optional values that take the first available value. */ public static Semigroup> firstOptionSemigroup() { - return semigroup((a1, a2) -> a1.orElse(a2)); + return Monoid.firstOptionMonoid().semigroup(); } /** @@ -351,7 +566,7 @@ public static Semigroup> firstOptionSemigroup() { * @return A semigroup for optional values that take the last available value. */ public static Semigroup> lastOptionSemigroup() { - return semigroup((a1, a2) -> a2.orElse(a1)); + return Monoid.lastOptionMonoid().semigroup(); } /** @@ -360,7 +575,7 @@ public static Semigroup> lastOptionSemigroup() { * @return A semigroup for streams. */ public static Semigroup> streamSemigroup() { - return semigroup((a1, a2) -> a1.append(a2)); + return Monoid.streamMonoid().semigroup(); } /** @@ -369,41 +584,58 @@ public static Semigroup> streamSemigroup() { * @return A semigroup for arrays. */ public static Semigroup> arraySemigroup() { - return semigroup(Array::append); + return Monoid.arrayMonoid().semigroup(); } /** - * A semigroup for unary products. + * A lazy semigroup for unary products. * * @param sa A semigroup for the product's type. * @return A semigroup for unary products. */ public static Semigroup> p1Semigroup(final Semigroup sa) { - return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()))); + Definition def = sa.def; + return semigroupDef(new Definition>() { + @Override + public P1 append(P1 a1, P1 a2) { + return P.lazy(() -> def.append(a1._1(), a2._1())); + } + + @Override + public P1 multiply1p(int n, P1 ap1) { + return P.lazy(() -> def.multiply1p(n, ap1._1())); + } + + @Override + public P1 sum(P1 ap1, F0>> as) { + return P.lazy(() -> def.sum(ap1._1(), () -> as.f().map(P1.__1()))); + } + }); } /** - * A semigroup for binary products. + * A lazy semigroup for binary products. * * @param sa A semigroup for the product's first type. * @param sb A semigroup for the product's second type. * @return A semigroup for binary products. */ public static Semigroup> p2Semigroup(final Semigroup sa, final Semigroup sb) { - return semigroup((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); + return semigroupDef((a1, a2) -> P.lazy(() -> sa.sum(a1._1(), a2._1()), () -> sb.sum(a1._2(), a2._2()))); } /** * A semigroup for IO values. */ public static Semigroup> ioSemigroup(final Semigroup sa) { - return semigroup((a1, a2) -> IOFunctions.liftM2(a1, a2, sa::sum)); + Definition def = sa.def; + return semigroupDef((a1, a2) -> () -> def.append(a1.run(), a2.run())); } /** * A semigroup for the Unit value. */ - public static final Semigroup unitSemigroup = semigroup((u1, u2) -> Unit.unit()); + public static final Semigroup unitSemigroup = unitMonoid.semigroup(); /** * A semigroup for sets. @@ -411,7 +643,7 @@ public static Semigroup> ioSemigroup(final Semigroup sa) { * @return a semigroup for sets. */ public static Semigroup> setSemigroup() { - return semigroup(Set::union); + return semigroupDef(Set::union); } } diff --git a/core/src/main/java/fj/data/optic/Fold.java b/core/src/main/java/fj/data/optic/Fold.java index af6b5739..691c779c 100644 --- a/core/src/main/java/fj/data/optic/Fold.java +++ b/core/src/main/java/fj/data/optic/Fold.java @@ -39,7 +39,7 @@ public final List getAll(final S s) { /** find the first target of a {@link Fold} matching the predicate */ public final F> find(final F p) { - return foldMap(Monoid.optionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none()); + return foldMap(Monoid.firstOptionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none()); } /** get the first target of a {@link Fold} */ diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index 50c1e14c..dbd8b0cd 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -104,7 +104,7 @@ public final List getAll(final S s) { /** find the first target of a {@link PTraversal} matching the predicate */ public final F> find(final F p) { - return foldMap(Monoid.optionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none()); + return foldMap(Monoid.firstOptionMonoid(), a -> p.f(a) ? Option.some(a) : Option.none()); } /** get the first target of a {@link PTraversal} */ diff --git a/core/src/main/java/fj/function/Doubles.java b/core/src/main/java/fj/function/Doubles.java index 7bff2409..6fe1b033 100644 --- a/core/src/main/java/fj/function/Doubles.java +++ b/core/src/main/java/fj/function/Doubles.java @@ -6,11 +6,8 @@ import fj.data.Option; import static fj.Function.curry; -import static fj.Semigroup.doubleAdditionSemigroup; -import static fj.Semigroup.doubleMultiplicationSemigroup; import static fj.data.Option.none; import static fj.data.Option.some; -import static java.lang.Math.abs; /** * Curried functions over Doubles. @@ -25,17 +22,17 @@ private Doubles() { /** * Curried Double addition. */ - public static final F> add = doubleAdditionSemigroup.sum(); + public static final F> add = x -> y -> x + y; /** * Curried Double multiplication. */ - public static final F> multiply = doubleMultiplicationSemigroup.sum(); + public static final F> multiply = x -> y -> x * y; /** * Curried Double subtraction. */ - public static final F> subtract = curry((x, y) -> x - y); + public static final F> subtract = x -> y -> x - y; /** * Negation. @@ -50,12 +47,12 @@ private Doubles() { /** * Remainder. */ - public static final F> remainder = curry((a, b) -> a % b); + public static final F> remainder = x -> y -> x % y; /** * Power. */ - public static final F> power = curry(StrictMath::pow); + public static final F> power = x -> y -> StrictMath.pow(x, y); /** * Evenness. @@ -69,7 +66,7 @@ private Doubles() { * @return The sum of the doubless in the list. */ public static double sum(final List doubles) { - return Monoid.doubleAdditionMonoid.sumLeft(doubles); + return doubles.foldLeft((x, y) -> x + y, 0.0); } /** @@ -79,7 +76,7 @@ public static double sum(final List doubles) { * @return The product of the doubles in the list. */ public static double product(final List doubles) { - return Monoid.doubleMultiplicationMonoid.sumLeft(doubles); + return doubles.foldLeft((x, y) -> x * y, 1.0); } /** diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index 203b8feb..c90a0b2d 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -1,6 +1,7 @@ package fj.demo.concurrent; import static fj.Monoid.monoid; +import static fj.Monoid.monoidDef; import static fj.control.parallel.ParModule.parModule; import static fj.data.List.nil; import static java.util.concurrent.Executors.newFixedThreadPool; @@ -14,6 +15,7 @@ import java.io.StringWriter; import java.io.Writer; import java.nio.charset.Charset; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -307,10 +309,7 @@ public static Map getWordsAndCountsFromFilesInParallel( // Read documents and extract words and word counts of documents public static Promise> getWordsAndCountsFromFiles( final List fileNames, final F> fileNameToWordsAndCounts, final ParModule m) { - final F, F, Map>> MapSum = - a -> b -> plus(a, b); - final Monoid> monoid = monoid(MapSum, - new HashMap()); + final Monoid> monoid = monoidDef(WordCount::plus, Collections.emptyMap()); return m.parFoldMap(fileNames, fileNameToWordsAndCounts, monoid); } From 1970c3e04db3dcadaaa6b33accc3ff2cffc16358 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 26 Sep 2016 21:24:07 +0200 Subject: [PATCH 618/811] use more method references. make Stream conversions respect laziness. optimize collectors. --- java8/src/main/java/fj/data/Collectors.java | 4 +- java8/src/main/java/fj/data/Java8.java | 49 +++++++++++---------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/java8/src/main/java/fj/data/Collectors.java b/java8/src/main/java/fj/data/Collectors.java index 3f3d7e40..5ee9ead6 100644 --- a/java8/src/main/java/fj/data/Collectors.java +++ b/java8/src/main/java/fj/data/Collectors.java @@ -21,7 +21,7 @@ public static Collector, Array> toArray() { List.Buffer::new, List.Buffer::snoc, (acc1, acc2) -> acc1.append(acc2.toList()), - (buf) -> Array.iterableArray(buf.toList()) + (buf) -> buf.toList().toArray() ); } @@ -30,7 +30,7 @@ public static Collector, Stream> toStream() { List.Buffer::new, List.Buffer::snoc, (acc1, acc2) -> acc1.append(acc2.toList()), - (buf) -> Stream.iterableStream(buf.toList()) + (buf) -> buf.toList().toStream() ); } } diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index be776822..d2d23fb2 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -2,6 +2,7 @@ import java.util.Iterator; import java.util.Optional; +import java.util.Spliterators; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -28,75 +29,75 @@ private Java8() { } public static P1 Supplier_P1(final Supplier s) { - return Java8.Supplier_P1().f(s); + return P.lazy(s::get); } public static F, P1> Supplier_P1() { - return s -> P.lazy(s::get); + return Java8::Supplier_P1; } public static Supplier P1_Supplier(final P1 p) { - return Java8.P1_Supplier().f(p); + return p::_1; } public static F, Supplier> P1_Supplier() { - return (p) -> p::_1; + return Java8::P1_Supplier; } public static F Function_F(final Function f) { - return Java8.Function_F().f(f); + return f::apply; } public static F, F> Function_F() { - return f -> f::apply; + return Java8::Function_F; } public static Function F_Function(final F f) { - return Java8.F_Function().f(f); + return f::f; } public static F, Function> F_Function() { - return f -> f::f; + return Java8::F_Function; } public static F2 BiFunction_F2(final BiFunction f) { - return Java8.BiFunction_F2().f(f); + return f::apply; } public static F, F2> BiFunction_F2() { - return f -> f::apply; + return Java8::BiFunction_F2; } public static BiFunction F2_BiFunction(final F2 f) { - return Java8.F2_BiFunction().f(f); + return f::f; } public static F, BiFunction> F2_BiFunction() { - return f -> f::f; + return Java8::F2_BiFunction; } public static Supplier> TryCatch0_Supplier(final Try0 t) { - return Java8.TryCatch0_Supplier().f(t); + return () -> Try.f(t)._1(); } public static F, Supplier>> TryCatch0_Supplier() { - return t -> () -> Try.f(t)._1(); + return Java8::TryCatch0_Supplier; } public static Function> TryCatch1_Function(final Try1 t) { - return Java8.TryCatch1_Function().f(t); + return a -> Try.f(t).f(a); } public static F, Function>> TryCatch1_Function() { - return t -> a -> Try.f(t).f(a); + return Java8::TryCatch1_Function; } public static BiFunction> TryCatch2_BiFunction(final Try2 t) { - return Java8.TryCatch2_BiFunction().f(t); + return (a, b) -> Try.f(t).f(a, b); } public static F, BiFunction>> TryCatch2_BiFunction() { - return t -> (a, b) -> Try.f(t).f(a, b); + return Java8::TryCatch2_BiFunction; } public static java.util.stream.Stream List_JavaStream(final List list) { @@ -104,19 +105,19 @@ public static java.util.stream.Stream List_JavaStream(final List list) } public static Option Optional_Option(final Optional o) { - return Java8.Optional_Option().f(o); + return o.isPresent() ? Option.some(o.get()) : Option.none(); } public static F, Option> Optional_Option() { - return o -> o.isPresent() ? Option.some(o.get()) : Option.none(); + return Java8::Optional_Option; } public static Optional Option_Optional(final Option o) { - return Java8.Option_Optional().f(o); + return o.option(Optional.empty(), Optional::ofNullable); } public static F, Optional> Option_Optional() { - return o -> o.isSome() ? Optional.ofNullable(o.some()) : Optional.empty(); + return Java8::Option_Optional; } public static F, F> Consumer_F() { @@ -139,7 +140,7 @@ public static java.util.stream.Stream Iterable_JavaStream(final Iterable< } public static java.util.stream.Stream Iterator_JavaStream(final Iterator it) { - return Iterable_JavaStream(() -> it); + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, 0), false); } public static F, java.util.stream.Stream> Stream_JavaStream() { @@ -147,7 +148,7 @@ public static F, java.util.stream.Stream> Stream_JavaSt } public static Stream JavaStream_Stream(final java.util.stream.Stream s) { - return s.collect(Collectors.toStream()); + return Stream.iteratorStream(s.iterator()); } public static List JavaStream_List(final java.util.stream.Stream s) { From a8f9db4320e78f459525a96fa6e7ff3b3da7f94a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 10:38:28 +0200 Subject: [PATCH 619/811] Java8 converter: Do not silently convert Option.some(null) to Optional.absent() Let's not try to cover for Optional mistakes. Otherwise bugs will silently happen. --- java8/src/main/java/fj/data/Java8.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java8/src/main/java/fj/data/Java8.java b/java8/src/main/java/fj/data/Java8.java index d2d23fb2..e41f0958 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/java8/src/main/java/fj/data/Java8.java @@ -112,8 +112,11 @@ public static F, Option> Optional_Option() { return Java8::Optional_Option; } + /** + * Convert an Option to {@link Optional}. Will throw a {@link NullPointerException} if the Option is some(null). + */ public static Optional Option_Optional(final Option o) { - return o.option(Optional.empty(), Optional::ofNullable); + return o.option(Optional.empty(), Optional::of); } public static F, Optional> Option_Optional() { From 9c28f6f19cc383bf660ac0d4d1c441123313b372 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Thu, 15 Sep 2016 21:05:17 +0200 Subject: [PATCH 620/811] Fix #287: Add semigroup constraint to List.traverseValidation for now implement traverse from sequence. (but the other way around would be better) --- core/src/main/java/fj/data/List.java | 11 ++++----- core/src/main/java/fj/data/optic/PIso.java | 3 ++- core/src/main/java/fj/data/optic/PLens.java | 3 ++- .../main/java/fj/data/optic/POptional.java | 3 ++- core/src/main/java/fj/data/optic/PPrism.java | 3 ++- .../main/java/fj/data/optic/PTraversal.java | 23 ++++++++++--------- .../main/java/fj/data/optic/Traversal.java | 5 ++-- 7 files changed, 28 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index a4fa19eb..07b21862 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -10,6 +10,7 @@ import fj.Ordering; import fj.P; import fj.P1; +import fj.Semigroup; import fj.Show; import fj.Unit; import fj.P2; @@ -676,10 +677,8 @@ public final List> traverseList(final F> f) { single(List.nil())); } - public final Validation> traverseValidation(final F> f) { - return foldRight( - (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - Validation.success(List.nil())); + public final Validation> traverseValidation(Semigroup s, final F> f) { + return Validation.sequence(s, map(f)); } public final V2> traverseV2(final F> f) { @@ -2166,8 +2165,8 @@ public F, P1>> modifyP1F(F> f) { } @Override - public F, Validation>> modifyValidationF(F> f) { - return l -> l.traverseValidation(f); + public F, Validation>> modifyValidationF(Semigroup s, F> f) { + return l -> l.traverseValidation(s, f); } @Override diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java index 7dcd0888..e10b47bb 100644 --- a/core/src/main/java/fj/data/optic/PIso.java +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -6,6 +6,7 @@ import fj.P; import fj.P1; import fj.P2; +import fj.Semigroup; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.data.Either; @@ -314,7 +315,7 @@ public F> modifyP1F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { + public F> modifyValidationF(Semigroup s, final F> f) { return self.modifyValidationF(f); } diff --git a/core/src/main/java/fj/data/optic/PLens.java b/core/src/main/java/fj/data/optic/PLens.java index 68de9079..971f76ff 100644 --- a/core/src/main/java/fj/data/optic/PLens.java +++ b/core/src/main/java/fj/data/optic/PLens.java @@ -4,6 +4,7 @@ import fj.Function; import fj.Monoid; import fj.P1; +import fj.Semigroup; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.data.Either; @@ -320,7 +321,7 @@ public F> modifyP1F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { + public F> modifyValidationF(Semigroup s, final F> f) { return self.modifyValidationF(f); } diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java index 73cc6fe9..d35979d8 100644 --- a/core/src/main/java/fj/data/optic/POptional.java +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -6,6 +6,7 @@ import fj.P; import fj.P1; import fj.P2; +import fj.Semigroup; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; @@ -345,7 +346,7 @@ public F> modifyP1F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { + public F> modifyValidationF(Semigroup s, final F> f) { return self.modifyValidationF(f); } diff --git a/core/src/main/java/fj/data/optic/PPrism.java b/core/src/main/java/fj/data/optic/PPrism.java index f6712989..c4a65a68 100644 --- a/core/src/main/java/fj/data/optic/PPrism.java +++ b/core/src/main/java/fj/data/optic/PPrism.java @@ -5,6 +5,7 @@ import fj.Monoid; import fj.P; import fj.P1; +import fj.Semigroup; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; @@ -310,7 +311,7 @@ public F> modifyP1F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { + public F> modifyValidationF(Semigroup s, final F> f) { return self.modifyValidationF(f); } diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index 50c1e14c..6344d4d8 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -10,6 +10,7 @@ import fj.Monoid; import fj.P; import fj.P1; +import fj.Semigroup; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.data.Either; @@ -82,7 +83,7 @@ public abstract class PTraversal { /** * modify polymorphically the target of a {@link PTraversal} with an Applicative function */ - public abstract F> modifyValidationF(F> f); + public abstract F> modifyValidationF(Semigroup s, F> f); /** * modify polymorphically the target of a {@link PTraversal} with an Applicative function @@ -218,10 +219,10 @@ public F, V2>> modifyV2F(final F> f) { } @Override - public F, Validation>> modifyValidationF(final F> f) { + public F, Validation>> modifyValidationF(Semigroup se, final F> f) { return ss1 -> ss1.either( - s -> self.modifyValidationF(f).f(s).map(Either.left_()), - s1 -> other.modifyValidationF(f).f(s1).map(Either.right_()) + s -> self.modifyValidationF(se, f).f(s).map(Either.left_()), + s1 -> other.modifyValidationF(se, f).f(s1).map(Either.right_()) ); } @@ -307,8 +308,8 @@ public F> modifyP1F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { - return self.modifyValidationF(other.modifyValidationF(f)); + public F> modifyValidationF(Semigroup s, final F> f) { + return self.modifyValidationF(s, other.modifyValidationF(s, f)); } @Override @@ -450,7 +451,7 @@ public F, V2>> modifyV2F(final F> f) { } @Override - public F, Validation>> modifyValidationF(final F> f) { + public F, Validation>> modifyValidationF(Semigroup se, final F> f) { return s -> s.bimap(f, f).either( v -> v.map(Either.left_()), v -> v.map(Either.right_()) @@ -520,8 +521,8 @@ public F> modifyV2F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { - return s -> f.f(get2.f(s)).apply(f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); + public F> modifyValidationF(Semigroup se, final F> f) { + return s -> f.f(get2.f(s)).accumapply(se, f.f(get1.f(s)).> map(b1 -> b2 -> set.f(b1, b2, s))); } @Override @@ -611,8 +612,8 @@ public F> modifyV2F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { - return s -> f.f(lastGet.f(s)).apply(curriedTraversal.modifyValidationF(f).f(s)); + public F> modifyValidationF(Semigroup se, final F> f) { + return s -> f.f(lastGet.f(s)).accumapply(se, curriedTraversal.modifyValidationF(se, f).f(s)); } @Override diff --git a/core/src/main/java/fj/data/optic/Traversal.java b/core/src/main/java/fj/data/optic/Traversal.java index 4064385e..a1a466d8 100644 --- a/core/src/main/java/fj/data/optic/Traversal.java +++ b/core/src/main/java/fj/data/optic/Traversal.java @@ -8,6 +8,7 @@ import fj.F7; import fj.Monoid; import fj.P1; +import fj.Semigroup; import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.data.Either; @@ -72,8 +73,8 @@ public F> modifyP1F(final F> f) { } @Override - public F> modifyValidationF(final F> f) { - return pTraversal.modifyValidationF(f); + public F> modifyValidationF(Semigroup s, final F> f) { + return pTraversal.modifyValidationF(s, f); } @Override From 3ceef52530e378a9b5a61222705c98c267d1254d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 25 Sep 2016 18:35:35 +0200 Subject: [PATCH 621/811] Convert to property based tests to use runner. add test for hardMemo (also, previously, they did not fails the test if a property failed. --- .../src/test/java/fj/MemoisationTest.java | 76 +++++++------------ 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/props-core/src/test/java/fj/MemoisationTest.java b/props-core/src/test/java/fj/MemoisationTest.java index b3c2853b..ac686465 100644 --- a/props-core/src/test/java/fj/MemoisationTest.java +++ b/props-core/src/test/java/fj/MemoisationTest.java @@ -1,7 +1,9 @@ package fj; import fj.test.Property; +import fj.test.runner.PropertyTestRunner; import org.junit.Test; +import org.junit.runner.RunWith; import static fj.test.Arbitrary.arbInteger; import static fj.test.CheckResult.summary; @@ -12,99 +14,77 @@ /** * Created by mperry on 14/07/2014. */ +@RunWith(PropertyTestRunner.class) public class MemoisationTest { - @Test - public void test1() { - final Property p = property(arbInteger, a -> { - P1 t = P.p(a).memo(); - return prop(t._1() == t._1()); + public Property test1() { + return property(arbInteger, a -> { + P1 t = P.lazy(() -> a).memo(); + return prop(t._1().equals(t._1())).and(prop(t._1().equals(a))); }); - summary.println(p.check()); } - @Test - public void test2() { - final Property p = property(arbInteger, arbInteger, (a, b) -> { - P2 t = P.p(a, b).memo(); - return prop(t._1() == t._1() && t._2() == t._2()); + public Property test1_hardMemo() { + return property(arbInteger, a -> { + P1 t = P.lazy(() -> new Integer(a)).hardMemo(); + return prop(t._1() == t._1()).and(prop(t._1().equals(a))); }); - summary.println(p.check()); - } - - static P2 pair = P.p(0, 0); - - static Integer count(int i) { - if (i == 1) { - pair = P.p(pair._1() + 1, pair._2()); - return pair._1(); - } else if (i == 2) { - pair = P.p(pair._1(), pair._2() + 1); - return pair._2(); - } else { - return -1; - } } @Test - public void testRecomputeP2() { - P2 t = P.lazy(u -> count(1), u -> count(2)).memo(); - System.out.println("tuple: " + t + " 1:" + t._1() + " 2: " + t._2()); - assertTrue(t._1() == t._1() && t._2() == t._2()); + public Property test2() { + return property(arbInteger, arbInteger, (a, b) -> { + P2 t = P.lazy(u -> new Integer(a), u -> new Integer(b)).memo(); + return prop(t._1().equals(t._1()) && t._1().equals(a) && t._2().equals(t._2()) && t._2().equals(b) ); + }); } @Test - public void test3() { - final Property p = property(arbInteger, arbInteger, arbInteger, (a, b, c) -> { + public Property test3() { + return property(arbInteger, arbInteger, arbInteger, (a, b, c) -> { P3 t = P.p(a, b, c).memo(); return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3()); }); - summary.println(p.check()); } @Test - public void test4() { - final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d) -> { + public Property test4() { + return property(arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d) -> { P4 t = P.p(a, b, c, d).memo(); return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4()); }); - summary.println(p.check()); } @Test - public void test5() { - final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e) -> { + public Property test5() { + return property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e) -> { P5 t = P.p(a, b, c, d, e).memo(); return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5()); }); - summary.println(p.check()); } @Test - public void test6() { - final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f) -> { + public Property test6() { + return property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f) -> { P6 t = P.p(a, b, c, d, e, f).memo(); return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5() && t._6() == t._6()); }); - summary.println(p.check()); } @Test - public void test7() { - final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f, g) -> { + public Property test7() { + return property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f, g) -> { P7 t = P.p(a, b, c, d, e, f, g).memo(); return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5() && t._6() == t._6() && t._7() == t._7()); }); - summary.println(p.check()); } @Test - public void test8() { - final Property p = property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f, g, h) -> { + public Property test8() { + return property(arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, arbInteger, (a, b, c, d, e, f, g, h) -> { P8 t = P.p(a, b, c, d, e, f, g, h).memo(); return prop(t._1() == t._1() && t._2() == t._2() && t._3() == t._3() && t._4() == t._4() && t._5() == t._5() && t._6() == t._6() && t._7() == t._7() && t._8() == t._8()); }); - summary.println(p.check()); } } From ac116dfa81a15e63274adb13463e436a012ae3d1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 25 Sep 2016 18:45:58 +0200 Subject: [PATCH 622/811] Make _1() method of memoized P1s smaller so that the fast path can be inlined by the jvm. Also replaced Option by P1 in implementation, also avoid wrapping some more memoized instances. --- core/src/main/java/fj/P1.java | 84 +++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 1b36e0a7..cf763f55 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -1,15 +1,17 @@ package fj; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.lang.ref.WeakReference; - import fj.data.Array; -import fj.data.List; -import fj.data.Stream; import fj.data.Either; +import fj.data.List; import fj.data.Option; +import fj.data.Stream; import fj.data.Validation; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; + +import static fj.P.p; //import fj.data.*; @@ -138,7 +140,7 @@ public final P1 liftM2(P1 pb, F2 f) { * @return A single P1 for the given List. */ public static P1> sequence(final List> as) { - return as.foldRight(liftM2(List.cons()), P.p(List.nil())); + return as.foldRight(liftM2(List.cons()), p(List.nil())); } /** @@ -157,7 +159,7 @@ public static F>, P1>> sequenceList() { * @return A single P1 for the given stream. */ public static P1> sequence(final Stream> as) { - return as.foldRight(liftM2(Stream.cons()), P.p(Stream.nil())); + return as.foldRight(liftM2(Stream.cons()), p(Stream.nil())); } /** @@ -238,7 +240,7 @@ public final P1 map(final F f) { return P.lazy(() -> f.f(self._1())); } - public P1 memo() { + public final P1 memo() { return weakMemo(); } @@ -247,7 +249,7 @@ public P1 memo() { * * @return A P1 that calls this P1 once and remembers the value for subsequent calls. */ - public final P1 hardMemo() { return new Memo<>(this); } + public P1 hardMemo() { return new Memo<>(this); } /** * Like memo, but the memoized value is wrapped into a WeakReference @@ -267,65 +269,69 @@ public static P1 memo(F0 f) { return P.lazy(f).memo(); } - static class Memo extends P1 { + static final class Memo extends P1 { private volatile P1 self; private A value; Memo(P1 self) { this.self = self; } @Override public final A _1() { + return (self == null) ? value : computeValue(); + } + + private synchronized A computeValue() { + P1 self = this.self; if (self != null) { - synchronized (this) { - if (self != null) { - A a = self._1(); - value = a; - self = null; - return a; - } - } + value = self._1(); + this.self = null; } return value; } - @Override public final P1 memo() { return this; } + @Override public P1 hardMemo() { return this; } + @Override public P1 softMemo() { return this; } + @Override public P1 weakMemo() { return this; } } abstract static class ReferenceMemo extends P1 { private final P1 self; - private final Object latch = new Object(); - private volatile Reference> v = null; + private volatile Reference> v = null; ReferenceMemo(final P1 self) { this.self = self; } @Override public final A _1() { - Option o = v != null ? v.get() : null; - if (o == null) { - synchronized (latch) { - o = v != null ? v.get() : null; - if (o == null) { - o = Option.some(self._1()); - v = newReference(o); - } - } + Reference> v = this.v; + P1 p1 = v != null ? v.get() : null; + return p1 != null ? p1._1() : computeValue(); + } + + private synchronized A computeValue() { + Reference> v = this.v; + P1 p1 = v != null ? v.get() : null; + if (p1 == null) { + A a = self._1(); + this.v = newReference(p(a)); + return a; } - return o.some(); + return p1._1(); } - abstract Reference> newReference(Option o); + abstract Reference newReference(B ref); } - static class WeakReferenceMemo extends ReferenceMemo { + static final class WeakReferenceMemo extends ReferenceMemo { WeakReferenceMemo(P1 self) { super(self); } @Override - final Reference> newReference(final Option o) { return new WeakReference<>(o); } - @Override public final P1 weakMemo() { return this; } + Reference newReference(final B ref) { return new WeakReference<>(ref); } + @Override public P1 weakMemo() { return this; } } - static class SoftReferenceMemo extends ReferenceMemo { + static final class SoftReferenceMemo extends ReferenceMemo { SoftReferenceMemo(P1 self) { super(self); } @Override - final Reference> newReference(final Option o) { return new SoftReference<>(o); } - @Override public final P1 softMemo() { return this; } + Reference newReference(final B ref) { return new SoftReference<>(ref); } + @Override public P1 softMemo() { return this; } + @Override public P1 weakMemo() { return this; } } /** From 9394d84652156be1d1ffe359f0a7b37523fab452 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 25 Sep 2016 18:49:32 +0200 Subject: [PATCH 623/811] Use weakMemo() explicitly. --- core/src/main/java/fj/P1.java | 4 ++-- core/src/test/java/fj/P1Test.java | 2 +- props-core/src/test/java/fj/MemoisationTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index cf763f55..2f3fa721 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -262,11 +262,11 @@ public final P1 memo() { public P1 softMemo() { return new SoftReferenceMemo<>(this); } public static P1 memo(F f) { - return P.lazy(f).memo(); + return P.lazy(f).weakMemo(); } public static P1 memo(F0 f) { - return P.lazy(f).memo(); + return P.lazy(f).weakMemo(); } static final class Memo extends P1 { diff --git a/core/src/test/java/fj/P1Test.java b/core/src/test/java/fj/P1Test.java index a866e0c2..788c2829 100644 --- a/core/src/test/java/fj/P1Test.java +++ b/core/src/test/java/fj/P1Test.java @@ -11,7 +11,7 @@ public final class P1Test { @Test public void bug105() throws Exception { - final P1 p1 = P.p("Foo").memo(); + final P1 p1 = P.p("Foo").weakMemo(); final AtomicInteger nullCounter = new AtomicInteger(); ExecutorService executorService = Executors.newCachedThreadPool(); diff --git a/props-core/src/test/java/fj/MemoisationTest.java b/props-core/src/test/java/fj/MemoisationTest.java index ac686465..e86e2a8b 100644 --- a/props-core/src/test/java/fj/MemoisationTest.java +++ b/props-core/src/test/java/fj/MemoisationTest.java @@ -19,7 +19,7 @@ public class MemoisationTest { public Property test1() { return property(arbInteger, a -> { - P1 t = P.lazy(() -> a).memo(); + P1 t = P.lazy(() -> a).weakMemo(); return prop(t._1().equals(t._1())).and(prop(t._1().equals(a))); }); } From e723d7122c00feec41d3375f327a819f7804f454 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 25 Sep 2016 19:09:01 +0200 Subject: [PATCH 624/811] Fix wrong override in P.p(A) --- core/src/main/java/fj/P.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 1ff82475..ebc2d9e4 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -32,7 +32,7 @@ public static P1 p(final A a) { @Override public A _1() { return a; } - @Override public P1 memo() { return this; } + @Override public P1 hardMemo() { return this; } @Override public P1 weakMemo() { return this; } @Override public P1 softMemo() { return this; } }; From f56fa238e3dd6022f8558ab5f35835123953d331 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 11:32:27 +0200 Subject: [PATCH 625/811] P1.*memo: avoid uncessary wrapping of F0 value into a P1.lazy when possible. Expose static factories in P for this. Deprecated redondant API. --- core/src/main/java/fj/P.java | 50 ++++++++++++++----- core/src/main/java/fj/P1.java | 43 ++++++++++------ core/src/main/java/fj/P2.java | 5 +- core/src/main/java/fj/P3.java | 8 +-- core/src/main/java/fj/P4.java | 10 ++-- core/src/main/java/fj/P5.java | 12 +++-- core/src/main/java/fj/P6.java | 14 +++--- core/src/main/java/fj/P7.java | 16 +++--- core/src/main/java/fj/P8.java | 18 ++++--- core/src/main/java/fj/data/Stream.java | 3 +- core/src/test/java/fj/P1Test.java | 2 +- .../src/test/java/fj/MemoisationTest.java | 4 +- 12 files changed, 119 insertions(+), 66 deletions(-) diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index ebc2d9e4..b0f3a31d 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -38,10 +38,45 @@ public static P1 p(final A a) { }; } + /** + * Convert a F0 into a P1, using call-by-need semantic: + * function f is evaluated at most once, at first to {@link P1#_1()}. + */ + public static P1 hardMemo(F0 f) { + return new P1.Memo<>(f); + } - public static P1 lazy(final P1 pa) { - return pa; - } + /** + * Convert a F0 into a P1, using weak call-by-need semantic: + * function f is evaluated at first call to {@link P1#_1()} + * and at each subsequent call if and only if the reference have been garbage collected. + */ + public static P1 weakMemo(F0 f) { + return new P1.WeakReferenceMemo<>(f); + } + + /** + * Convert a F0 into a P1, using soft call-by-need semantic: + * function f is evaluated at first call to {@link P1#_1()} + * and at each subsequent call if and only if the reference have been garbage collected + * due of shortage of memory (ie. to avoid OutOfMemoryErrors). + */ + public static P1 sofMemo(F0 f) { + return new P1.SoftReferenceMemo<>(f); + } + + /** + * Convert a F0 into a P1, using call-by-name semantic: + * function f is evaluated at each call to {@link P1#_1()}. + */ + public static P1 lazy(F0 f) { + return new P1() { + @Override + public A _1() { + return f.f(); + } + }; + } public static P2 lazy(final F0 pa, final F0 pb) { return new P2() { @@ -538,15 +573,6 @@ public H _8() { }; } - public static P1 lazy(F0 f) { - return new P1() { - @Override - public A _1() { - return f.f(); - } - }; - } - public static P1 lazy(F f) { return lazy(() -> f.f(unit())); } diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 2f3fa721..555a28ae 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -12,6 +12,7 @@ import java.lang.ref.WeakReference; import static fj.P.p; +import static fj.Unit.unit; //import fj.data.*; @@ -240,6 +241,10 @@ public final P1 map(final F f) { return P.lazy(() -> f.f(self._1())); } + /** + * @deprecated since 4.7. Use {@link P1#weakMemo()} instead. + */ + @Deprecated public final P1 memo() { return weakMemo(); } @@ -261,29 +266,37 @@ public final P1 memo() { */ public P1 softMemo() { return new SoftReferenceMemo<>(this); } + /** + * @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead. + */ + @Deprecated public static P1 memo(F f) { - return P.lazy(f).weakMemo(); + return P.weakMemo(() -> f.f(unit())); } - public static P1 memo(F0 f) { - return P.lazy(f).weakMemo(); + /** + * @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead. + */ + @Deprecated + public static P1 memo(F0 f) { + return P.weakMemo(f); } static final class Memo extends P1 { - private volatile P1 self; + private volatile F0 fa; private A value; - Memo(P1 self) { this.self = self; } + Memo(F0 fa) { this.fa = fa; } @Override public final A _1() { - return (self == null) ? value : computeValue(); + return (fa == null) ? value : computeValue(); } private synchronized A computeValue() { - P1 self = this.self; - if (self != null) { - value = self._1(); - this.self = null; + F0 fa = this.fa; + if (fa != null) { + value = fa.f(); + this.fa = null; } return value; } @@ -294,10 +307,10 @@ private synchronized A computeValue() { } abstract static class ReferenceMemo extends P1 { - private final P1 self; + private final F0 fa; private volatile Reference> v = null; - ReferenceMemo(final P1 self) { this.self = self; } + ReferenceMemo(final F0 fa) { this.fa = fa; } @Override public final A _1() { Reference> v = this.v; @@ -309,7 +322,7 @@ private synchronized A computeValue() { Reference> v = this.v; P1 p1 = v != null ? v.get() : null; if (p1 == null) { - A a = self._1(); + A a = fa.f(); this.v = newReference(p(a)); return a; } @@ -320,14 +333,14 @@ private synchronized A computeValue() { } static final class WeakReferenceMemo extends ReferenceMemo { - WeakReferenceMemo(P1 self) { super(self); } + WeakReferenceMemo(F0 fa) { super(fa); } @Override Reference newReference(final B ref) { return new WeakReference<>(ref); } @Override public P1 weakMemo() { return this; } } static final class SoftReferenceMemo extends ReferenceMemo { - SoftReferenceMemo(P1 self) { super(self); } + SoftReferenceMemo(F0 self) { super(self); } @Override Reference newReference(final B ref) { return new SoftReference<>(ref); } @Override public P1 softMemo() { return this; } diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index abe4d0d5..e503ff40 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -1,6 +1,7 @@ package fj; import static fj.Function.*; +import static fj.P.weakMemo; import static fj.data.optic.PLens.pLens; import fj.data.*; import fj.data.optic.Lens; @@ -185,8 +186,8 @@ public final P1 _2_() { public final P2 memo() { P2 self = this; return new P2() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 26c51b05..ec277346 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -1,5 +1,7 @@ package fj; +import static fj.P.weakMemo; + /** * A product-3. * @@ -128,9 +130,9 @@ public final P1 _3_() { public final P3 memo() { P3 self = this; return new P3() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); - private final P1 c = P1.memo(u -> self._3()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); + private final P1 c = weakMemo(self::_3); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index c2f94f8f..3f7236fe 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -1,5 +1,7 @@ package fj; +import static fj.P.weakMemo; + /** * A product-4. * @@ -182,10 +184,10 @@ public final P1 _4_() { public final P4 memo() { P4 self = this; return new P4() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); - private final P1 c = P1.memo(u -> self._3()); - private final P1 d = P1.memo(u -> self._4()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); + private final P1 c = weakMemo(self::_3); + private final P1 d = weakMemo(self::_4); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 902da93c..393b0632 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -1,5 +1,7 @@ package fj; +import static fj.P.weakMemo; + /** * A product-5. * @@ -244,11 +246,11 @@ public final P1 _5_() { public final P5 memo() { P5 self = this; return new P5() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); - private final P1 c = P1.memo(u -> self._3()); - private final P1 d = P1.memo(u -> self._4()); - private final P1 e = P1.memo(u -> self._5()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); + private final P1 c = weakMemo(self::_3); + private final P1 d = weakMemo(self::_4); + private final P1 e = weakMemo(self::_5); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 37f5fe6c..1e8c3055 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -1,5 +1,7 @@ package fj; +import static fj.P.weakMemo; + /** * A product-6. * @@ -315,12 +317,12 @@ public final P1 _6_() { public final P6 memo() { P6 self = this; return new P6() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); - private final P1 c = P1.memo(u -> self._3()); - private final P1 d = P1.memo(u -> self._4()); - private final P1 e = P1.memo(u -> self._5()); - private final P1 f = P1.memo(u -> self._6()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); + private final P1 c = weakMemo(self::_3); + private final P1 d = weakMemo(self::_4); + private final P1 e = weakMemo(self::_5); + private final P1 f = weakMemo(self::_6); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index e2673183..ca24b40e 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -1,5 +1,7 @@ package fj; +import static fj.P.weakMemo; + /** * A product-7. * @@ -393,13 +395,13 @@ public final P1 _7_() { public final P7 memo() { P7 self = this; return new P7() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); - private final P1 c = P1.memo(u -> self._3()); - private final P1 d = P1.memo(u -> self._4()); - private final P1 e = P1.memo(u -> self._5()); - private final P1 f = P1.memo(u -> self._6()); - private final P1 g = P1.memo(u -> self._7()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); + private final P1 c = weakMemo(self::_3); + private final P1 d = weakMemo(self::_4); + private final P1 e = weakMemo(self::_5); + private final P1 f = weakMemo(self::_6); + private final P1 g = weakMemo(self::_7); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index cfa916eb..f15d63a1 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -1,5 +1,7 @@ package fj; +import static fj.P.weakMemo; + /** * A product-8. * @@ -480,14 +482,14 @@ public final P1 _8_() { public final P8 memo() { P8 self = this; return new P8() { - private final P1 a = P1.memo(u -> self._1()); - private final P1 b = P1.memo(u -> self._2()); - private final P1 c = P1.memo(u -> self._3()); - private final P1 d = P1.memo(u -> self._4()); - private final P1 e = P1.memo(u -> self._5()); - private final P1 f = P1.memo(u -> self._6()); - private final P1 g = P1.memo(u -> self._7()); - private final P1 h = P1.memo(u -> self._8()); + private final P1 a = weakMemo(self::_1); + private final P1 b = weakMemo(self::_2); + private final P1 c = weakMemo(self::_3); + private final P1 d = weakMemo(self::_4); + private final P1 e = weakMemo(self::_5); + private final P1 f = weakMemo(self::_6); + private final P1 g = weakMemo(self::_7); + private final P1 h = weakMemo(self::_8); public A _1() { return a._1(); diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index ae37d714..e4baccf5 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -25,6 +25,7 @@ import static fj.Function.*; import static fj.P.p; import static fj.P.p2; +import static fj.P.weakMemo; import static fj.Unit.unit; import static fj.control.parallel.Promise.promise; import static fj.data.Array.mkArray; @@ -1442,7 +1443,7 @@ private static final class Cons extends Stream { Cons(final A head, final F0> tail) { this.head = head; - this.tail = P1.memo(tail); + this.tail = weakMemo(tail); } public A head() { diff --git a/core/src/test/java/fj/P1Test.java b/core/src/test/java/fj/P1Test.java index 788c2829..4d3c5c35 100644 --- a/core/src/test/java/fj/P1Test.java +++ b/core/src/test/java/fj/P1Test.java @@ -11,7 +11,7 @@ public final class P1Test { @Test public void bug105() throws Exception { - final P1 p1 = P.p("Foo").weakMemo(); + final P1 p1 = P.weakMemo(() -> "Foo"); final AtomicInteger nullCounter = new AtomicInteger(); ExecutorService executorService = Executors.newCachedThreadPool(); diff --git a/props-core/src/test/java/fj/MemoisationTest.java b/props-core/src/test/java/fj/MemoisationTest.java index e86e2a8b..65fa83fc 100644 --- a/props-core/src/test/java/fj/MemoisationTest.java +++ b/props-core/src/test/java/fj/MemoisationTest.java @@ -19,14 +19,14 @@ public class MemoisationTest { public Property test1() { return property(arbInteger, a -> { - P1 t = P.lazy(() -> a).weakMemo(); + P1 t = P.weakMemo(() -> a); return prop(t._1().equals(t._1())).and(prop(t._1().equals(a))); }); } public Property test1_hardMemo() { return property(arbInteger, a -> { - P1 t = P.lazy(() -> new Integer(a)).hardMemo(); + P1 t = P.hardMemo(() -> new Integer(a)); return prop(t._1() == t._1()).and(prop(t._1().equals(a))); }); } From 0e3187feb37751669028ceb6f06e6b012d47fa8b Mon Sep 17 00:00:00 2001 From: JB Giraudeau Date: Sun, 6 Nov 2016 11:46:20 +0100 Subject: [PATCH 626/811] Add a Hash Array Mapped Trie * Copied hamt from personal repo * Created show instances. Fixed BitSet.xor * Fixing overflow on BitSet longs. Adding tests * BitSet properties test * More BitSetProperties tests * Added remaining BitSet properties required * Moved hamt to String to the Show class * Clean up hamt test print lines * Updated after Gen/Arbitrary changes * Changed BitSet method name for creation from a long value * Fixed BitSet.asString * Added javadoc for HAMT * Added javadoc for HAMT * More tests on BitSet * Added more tests and minor refactoring for BitSet * Fixed BitSet.takeUpper * Fixed HAMT issue * Deleted BitSetTest * Fixed find and set. Added folds for HAMT * Properties and ad hoc tests for HAMT properties * Added Seq insert and filter * Added count population (CTPOP) from the paper for a bit set * Minor clean-up, remove dead-code. * improve BitSet#range performance (use bitwise operations) * remove unnecessary lambda --- core/src/main/java/fj/Equal.java | 3 + core/src/main/java/fj/Show.java | 22 +- core/src/main/java/fj/data/Seq.java | 17 ++ core/src/main/java/fj/data/hamt/BitSet.java | 204 ++++++++++++++++ .../fj/data/hamt/HashArrayMappedTrie.java | 220 ++++++++++++++++++ core/src/main/java/fj/data/hamt/Node.java | 56 +++++ core/src/test/java/fj/data/SeqTest.java | 9 + core/src/test/java/fj/data/hamt/HamtTest.java | 66 ++++++ .../java/fj/data/hamt/BitSetProperties.java | 218 +++++++++++++++++ .../hamt/HashArrayMappedTrieProperties.java | 94 ++++++++ quickcheck/src/main/java/fj/test/Gen.java | 10 + quickcheck/src/main/java/fj/test/Rand.java | 3 + .../src/test/java/fj/test/TestRand.java | 2 +- 13 files changed, 921 insertions(+), 3 deletions(-) create mode 100644 core/src/main/java/fj/data/hamt/BitSet.java create mode 100644 core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java create mode 100644 core/src/main/java/fj/data/hamt/Node.java create mode 100644 core/src/test/java/fj/data/hamt/HamtTest.java create mode 100644 props-core/src/test/java/fj/data/hamt/BitSetProperties.java create mode 100644 props-core/src/test/java/fj/data/hamt/HashArrayMappedTrieProperties.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index a09dceba..b3709f4b 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -3,6 +3,7 @@ import static fj.Function.curry; import fj.data.*; +import fj.data.hamt.BitSet; import fj.data.hlist.HList; import fj.data.vector.V2; import fj.data.vector.V3; @@ -104,6 +105,8 @@ public static Equal anyEqual() { */ public static final Equal booleanEqual = anyEqual(); + public static final Equal bitSetSequal = Equal.equal(bs1 -> bs2 -> bs1.longValue() == bs2.longValue()); + /** * An equal instance for the byte type. */ diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 9e55a1d6..2d2c4707 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -1,8 +1,9 @@ package fj; import fj.data.*; +import fj.data.hamt.BitSet; +import fj.data.hamt.HashArrayMappedTrie; import fj.data.fingertrees.FingerTree; -import fj.data.fingertrees.Node; import fj.data.hlist.HList; import fj.data.vector.V2; import fj.data.vector.V3; @@ -315,7 +316,7 @@ public static Show> digitShow(final Show< }); } - public static Show> nodeShow(final Show sv, final Show sa) { + public static Show> nodeShow(final Show sv, final Show sa) { return show(n -> { final String s = n.match( n2 -> "Node2(" + n2.measure() + " -> " + v2Show(sa).showS(n2.toVector()) + ")", @@ -701,4 +702,21 @@ public static Show> unlineShow(final Show sa) { public static > Show> HListShow(final Show e, final Show l) { return show(c -> fromString("HList(").append(e.show(c.head())).append(l.show(c.tail())).append(fromString(")"))); } + + public static Show> hamtNodeShow(Show sk, Show sv) { + F, String> f = n -> n.match(p -> p2Show(sk, sv).showS(p), h -> hamtShow(sk, sv).showS(h)); + return Show.showS(f); + } + + public static Show> hamtShow(Show sk, Show sv) { + return Show.showS(hamt -> + "HashArrayMappedTrie(" + Show.bitSetShow.showS(hamt.getBitSet()) + + ", " + Show.seqShow(Show.hamtNodeShow(sk, sv)).showS(hamt.getSeq()) + ")" + ); + } + + public static final Show bitSetShow = Show.showS( + bs -> "BitSet(" + bs.asString() + ")" + ); + } diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index c6eb98be..abd20162 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -275,6 +275,18 @@ public boolean isEmpty() { return ftree.isEmpty(); } + /** + * Inserts the element at the given index. This is an O(log(n)) operation. + * + * @param index The index of the element to return. + * @return The sequence with the element inserted at the given index, + * or throws an error if the index is out of bounds. + */ + public Seq insert(int index, A a) { + final P2, Seq> p = split(index); + return p._1().append(single(a)).append(p._2()); + } + /** * Checks if this sequence is not empty. * @@ -370,6 +382,11 @@ public B foldRight(final F2 f, final B z) { return ftree.foldRight(f, z); } + + public Seq filter(F f) { + return foldLeft((acc, a) -> f.f(a) ? acc.snoc(a) : acc, empty()); + } + @Override public int hashCode() { return Hash.seqHash(Hash.anyHash()).hash(this); diff --git a/core/src/main/java/fj/data/hamt/BitSet.java b/core/src/main/java/fj/data/hamt/BitSet.java new file mode 100644 index 00000000..d164642d --- /dev/null +++ b/core/src/main/java/fj/data/hamt/BitSet.java @@ -0,0 +1,204 @@ +package fj.data.hamt; + +import fj.Equal; +import fj.F2; +import fj.Monoid; +import fj.Show; +import fj.data.List; +import fj.data.Stream; + +/** + * A sequence of bits representing a value. The most significant bit (the + * bit with the highest value) is the leftmost bit and has the highest index. + * For example, the BitSet("1011") represents the decimal number 11 and has + * indices [3, 0] inclusive where the bit with the lowest value has the lowest + * index and is the rightmost bit. + * + * Created by maperr on 31/05/2016. + */ +public final class BitSet { + + public static final int TRUE_BIT = 1; + public static final int FALSE_BIT = 0; + public static final BitSet EMPTY = new BitSet(FALSE_BIT); + + public static final long BASE_LONG = 1L; + public static final int MAX_BIT_SIZE = Long.SIZE; + public static final int MAX_BIT_INDEX = Long.SIZE - 1; + + private final long value; + + private BitSet(final long l) { + value = l; + } + + public static BitSet empty() { + return EMPTY; + } + + public static BitSet longBitSet(final long l) { + return new BitSet(l); + } + + public static BitSet listBitSet(final List list) { + final int n = list.length(); + if (n > MAX_BIT_SIZE) { + throw new IllegalArgumentException("Does not support lists greater than " + MAX_BIT_SIZE + " bits, actual size is " + n); + } + long result = 0; + for (Boolean b: list) { + result = (result << 1) | toInt(b); + } + return longBitSet(result); + } + + public static BitSet streamBitSet(final Stream s) { + return listBitSet(s.toList()); + } + + public static BitSet stringBitSet(final String s) { + return streamBitSet(Stream.fromString(s).map(BitSet::toBoolean)); + } + + public boolean isSet(final int index) { + return (value & (BASE_LONG << index)) != 0; + } + + public boolean isEmpty() { + return value == 0; + } + + public BitSet set(final int index) { + return longBitSet(value | (BASE_LONG << index)); + } + + public BitSet set(final int index, boolean b) { + return b ? set(index) : clear(index); + } + + public BitSet clear(final int index) { + return longBitSet(value & ~(BASE_LONG << index)); + } + + public long longValue() { + return value; + } + + public BitSet and(final BitSet bs) { + return longBitSet(value & bs.longValue()); + } + + public BitSet or(final BitSet bs) { + return longBitSet(value | bs.longValue()); + } + + public BitSet shiftRight(final int n) { + return longBitSet(value >> n); + } + + public BitSet shiftLeft(final int n) { + return longBitSet(value << n); + } + + public int bitsUsed() { + return toStream().length(); + } + + public int bitsOn() { + return toStream().foldLeft((acc, b) -> acc + (b ? 1 : 0), 0); + } + + /** + * Returns a stream of boolean where the head is the most significant bit + * (the bit with the largest value) + */ + public Stream toStream() { + return Stream.fromString(Long.toBinaryString(value)).map(BitSet::toBoolean).dropWhile(b -> !b); + } + + @Override + public String toString() { + return Show.bitSetShow.showS(this); + } + + @Override + public boolean equals(Object obj) { + return Equal.equals0(BitSet.class, this, obj, Equal.bitSetSequal); + } + + public int bitsToRight(final int index) { + if (index >= MAX_BIT_SIZE) { + throw new IllegalArgumentException("Does not support an index " + + "greater than or equal to " + MAX_BIT_SIZE + " bits, actual argument is " + index); + } + int pos = index - 1; + long mask = BASE_LONG << (pos); + int result = 0; + while (pos >= 0) { + if ((mask & value) != 0) { + result++; + } + mask = mask >> 1; + pos--; + } + return result; + } + + public List toList() { + return toStream().toList(); + } + + public A foldRight(final F2 f, A acc) { + return toStream().foldRight(b -> p -> f.f(b, p._1()), acc); + } + + public A foldLeft(final F2 f, A acc) { + return toStream().foldLeft(f, acc); + } + + public BitSet xor(final BitSet bs) { + return longBitSet(value ^ bs.longValue()); + } + + public BitSet not() { + return longBitSet(~value); + } + + public BitSet takeLower(final int n) { + return streamBitSet(toStream().reverse().take(n).reverse()); + } + + public BitSet takeUpper(final int n) { + String zero = Integer.toString(FALSE_BIT); + String current = asString(); + String pad = Monoid.stringMonoid.sumLeft(List.replicate(MAX_BIT_SIZE - current.length(), zero)); + return stringBitSet(pad + current.substring(0, Math.max(n - pad.length(), 0))); + } + + /** + * Returns the bit set from indices in the range from low (inclusive) + * to high(exclusive) from the least significant bit (on the right), + * e.g. "101101".range(1, 4) == "0110" + */ + public BitSet range(final int highIndex, final int lowIndex) { + int max = Math.max(lowIndex, highIndex); + int min = Math.min(lowIndex, highIndex); + return new BitSet(max == min ? 0L : (value << (64 - max)) >>> (64 - max + min)); + } + + public static boolean toBoolean(final char c) { + return c != '0'; + } + + public static boolean toBoolean(final int i) { + return i != FALSE_BIT; + } + + public static int toInt(final boolean b) { + return b ? TRUE_BIT : FALSE_BIT; + } + + public String asString() { + return Long.toBinaryString(value); + } +} diff --git a/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java b/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java new file mode 100644 index 00000000..f13ae90f --- /dev/null +++ b/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java @@ -0,0 +1,220 @@ +package fj.data.hamt; + +import fj.Equal; +import fj.F2; +import fj.Hash; +import fj.Ord; +import fj.P2; +import fj.Show; +import fj.data.List; +import fj.data.Option; +import fj.data.Seq; +import fj.data.Stream; + +import static fj.P.p; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.hamt.BitSet.longBitSet; + +/** + * A hash array mapped trie (HAMT) is an implementation of an associative + * array that combines the characteristics of a hash table and an array + * mapped trie. It is a refined version of the more general notion of + * a hash tree. + * + * @author Mark Perry + * + * Based on "Ideal Hash Trees" by Phil Bagwell, available from + * http://lampwww.epfl.ch/papers/idealhashtrees.pdf + */ +public final class HashArrayMappedTrie { + + private final Seq> seq; + private final BitSet bitSet; + private final Hash hash; + private final Equal equal; + + public static final int BITS_IN_INDEX = 5; + public static final int SIZE = (int) StrictMath.pow(2, BITS_IN_INDEX); + public static final int MIN_INDEX = 0; + public static final int MAX_INDEX = SIZE - 1; + + /** + * Creates an empty trie for the bitset, sequence of nodes, equal and hash. + * + * @param bs - The set of bits to indicate which of the SIZE nodes in the sequence are used. + * @param s - The sequence of HAMT nodes - either a HAMT or a key-value pair. + * @param e - Equality instance for keys. + * @param h - Hash instance for keys. + */ + private HashArrayMappedTrie(final BitSet bs, final Seq> s, final Equal e, final Hash h) { + bitSet = bs; + seq = s; + hash = h; + equal = e; + } + + /** + * Creates an empty trie. + */ + public static HashArrayMappedTrie empty(final Equal e, final Hash h) { + return new HashArrayMappedTrie<>(BitSet.empty(), Seq.empty(), e, h); + } + + /** + * Create and empty trie keyed by integer. + */ + public static HashArrayMappedTrie emptyKeyInteger() { + return empty(Equal.intEqual, Hash.intHash); + } + + /** + * Returns if the trie is empty. + */ + public boolean isEmpty() { + return bitSet.isEmpty(); + } + + /** + * Static constructor for a HAMT instance. + */ + private static HashArrayMappedTrie hamt(final BitSet bs, final Seq> s, final Equal e, final Hash h) { + return new HashArrayMappedTrie<>(bs, s, e, h); + } + + /** + * Returns an optional value for the given key k. + */ + public Option find(final K k) { + return find(k, MIN_INDEX, MIN_INDEX + BITS_IN_INDEX); + } + + /** + * Returns an optional value for the given key k for those nodes between + * lowIndex (inclusive) and highIndex (exclusive). + */ + public Option find(final K k, final int lowIndex, final int highIndex) { + BitSet bs1 = longBitSet(hash.hash(k)).range(lowIndex, highIndex); + int i = (int) bs1.longValue(); + boolean b = bitSet.isSet(i); + final int index = bitSet.bitsToRight(i); + if (!b) { + return none(); + } else { + final Node oldNode = seq.index(index); + return oldNode.match( + n -> equal.eq(n._1(), k) ? some(n._2()) : none(), + hamt -> hamt.find(k, lowIndex + BITS_IN_INDEX, highIndex + BITS_IN_INDEX) + ); + } + } + + /** + * Adds the key-value pair (k, v) to the trie. + */ + public HashArrayMappedTrie set(final K k, final V v) { + return set(k, v, MIN_INDEX, MIN_INDEX + BITS_IN_INDEX); + } + + /** + * Adds the product of key-value (k, v) pairs to the trie. + */ + public HashArrayMappedTrie set(final List> list) { + return list.foldLeft(h -> p -> h.set(p._1(), p._2()), this); + } + + /** + * Sets the key-value pair (k, v) for the bit range lowIndex (inclusive) to highIndex (exclusive). + */ + private HashArrayMappedTrie set(final K k, final V v, final int lowIndex, final int highIndex) { + final BitSet bs1 = longBitSet(hash.hash(k)).range(lowIndex, highIndex); + final int i = (int) bs1.longValue(); + final boolean b = bitSet.isSet(i); + final int index = bitSet.bitsToRight(i); + + if (!b) { + // append new node + final Node sn1 = Node.p2Node(p(k, v)); + return hamt(bitSet.set(i), seq.insert(index, sn1), equal, hash); + } else { + final Node oldNode = seq.index(index); + final Node newNode = oldNode.match(n -> { + if (equal.eq(n._1(), k)) { + return Node.p2Node(p(k, v)); + } else { + final HashArrayMappedTrie e = HashArrayMappedTrie.empty(equal, hash); + final HashArrayMappedTrie h1 = e.set(n._1(), n._2(), lowIndex + BITS_IN_INDEX, highIndex + BITS_IN_INDEX); + final HashArrayMappedTrie h2 = h1.set(k, v, lowIndex + BITS_IN_INDEX, highIndex + BITS_IN_INDEX); + return Node.hamtNode(h2); + } + }, hamt -> Node.hamtNode(hamt.set(k, v, lowIndex + BITS_IN_INDEX, highIndex + BITS_IN_INDEX)) + ); + return hamt(bitSet, seq.update(index, newNode), equal, hash); + } + } + + /** + * Returns a stream of key-value pairs. + */ + public Stream> toStream() { + return seq.toStream().bind(Node::toStream); + } + + /** + * Returns the list of key-value pairs, ordered by key. + */ + public List> toList(Ord o) { + return toStream().sort(Ord.p2Ord1(o)).toList(); + } + + /** + * Returns a list of key-value pairs. + */ + public List> toList() { + return toStream().toList(); + } + + @Override + public String toString() { + return Show.hamtShow(Show.anyShow(), Show.anyShow()).showS(this); + } + + /** + * Performs a left-fold reduction across this trie. + */ + public B foldLeftOnNode(F2, B> f, B b) { + return seq.foldLeft(f, b); + } + + /** + * Performs a left-fold reduction across this trie. + */ + public B foldLeft(F2, B> f, F2, B> g, B b) { + return foldLeftOnNode((acc, n) -> n.match(p -> f.f(acc, p), h -> g.f(acc, h)), b); + } + + /** + * Performs a left-fold reduction across this trie. + */ + public B foldLeft(F2, B> f, B b) { + return foldLeftOnNode((acc, n) -> n.match(p -> f.f(acc, p), h -> h.foldLeft(f, acc)), b); + } + + public BitSet getBitSet() { + return bitSet; + } + + public Seq> getSeq() { + return seq; + } + + /** + * Returns the number of elements in the trie. + */ + public int length() { + return seq.foldLeft( + (acc, node) -> node.match(p2 -> acc + 1, hamt -> acc + hamt.length()), 0 + ); + } + +} diff --git a/core/src/main/java/fj/data/hamt/Node.java b/core/src/main/java/fj/data/hamt/Node.java new file mode 100644 index 00000000..f8a1ff40 --- /dev/null +++ b/core/src/main/java/fj/data/hamt/Node.java @@ -0,0 +1,56 @@ +package fj.data.hamt; + +import fj.F; +import fj.P2; +import fj.Show; +import fj.data.Either; +import fj.data.Option; +import fj.data.Stream; + +/** + * A Hash Array Mapped Trie node that is either a key-value pair or a + * Hash Array Mapped Trie. + * + * Created by maperr on 31/05/2016. + */ +public final class Node { + + private final Either, HashArrayMappedTrie> either; + + public Node(final Either, HashArrayMappedTrie> e) { + either = e; + } + + public Node(final P2 simpleNode) { + this(Either.left(simpleNode)); + } + + public Node(final HashArrayMappedTrie hamt) { + this(Either.right(hamt)); + } + + public static Node p2Node(final P2 p) { + return new Node<>(p); + } + + public static Node hamtNode(final HashArrayMappedTrie hamt) { + return new Node<>(hamt); + } + + /** + * Performs a reduction on this Node using the given arguments. + */ + public B match(final F, B> f, final F, B> g) { + return either.either(f, g); + } + + public Stream> toStream() { + return match(Stream::single, HashArrayMappedTrie::toStream); + } + + @Override + public String toString() { + return Show.hamtNodeShow(Show.anyShow(), Show.anyShow()).showS(this); + } + +} diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java index 633ae321..27ec26e2 100644 --- a/core/src/test/java/fj/data/SeqTest.java +++ b/core/src/test/java/fj/data/SeqTest.java @@ -1,5 +1,6 @@ package fj.data; +import fj.P2; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -34,4 +35,12 @@ public void convertToString() { expected.append(')'); assertEquals(expected.toString(), Seq.seq(Array.range(0, 10000).array()).toString()); } + + + @Test + public void test() { + P2, Seq> p2 = Seq.single(1).split(5); + System.out.println(p2); + } + } diff --git a/core/src/test/java/fj/data/hamt/HamtTest.java b/core/src/test/java/fj/data/hamt/HamtTest.java new file mode 100644 index 00000000..1e601f24 --- /dev/null +++ b/core/src/test/java/fj/data/hamt/HamtTest.java @@ -0,0 +1,66 @@ +package fj.data.hamt; + +import fj.Ord; +import fj.P2; +import fj.data.List; +import fj.data.Option; +import org.junit.Test; + +import static fj.Equal.intEqual; +import static fj.Equal.optionEqual; +import static fj.Hash.intHash; +import static fj.P.p; +import static fj.data.List.list; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * @author Mark Perry + */ +public class HamtTest { + + public static final HashArrayMappedTrie empty = HashArrayMappedTrie.emptyKeyInteger(); + + @Test + public void empty() { + assertThat(empty.length(), equalTo(0)); + } + + @Test + public void lengthOne() { + assertThat(empty.set(3, 6).length(), equalTo(1)); + } + + @Test + public void updateLength() { + HashArrayMappedTrie h1 = empty.set(3, 3).set(3, 5); + assertThat(h1.length(), equalTo(1)); + } + + @Test + public void streamLength() { + List> list = list(p(0, 1), p(31, 1), p(32, 1), p(33, 1)); + HashArrayMappedTrie h2 = empty.set(list); + assertThat(h2.toStream().length(), equalTo(list.length())); + } + + @Test + public void allIn() { + List> list = List.list(p(-5, 0), p(-1, -5), p(2, 4), p(4, -2)); + HashArrayMappedTrie h = empty.set(list); + Boolean b = list.foldLeft((acc, p) -> h.find(p._1()).option(false, i -> true && acc), true); + assertThat(b, equalTo(true)); + } + + @Test + public void sampleInts() { + List> ps = List.list(p(-3, 0), p(1, 2)); + int key = -3; + HashArrayMappedTrie h = empty.set(ps); + Option o1 = ps.find(p -> intEqual.eq(p._1(), key)).map(p -> p._2()); + Option o2 = h.find(key); + boolean b = optionEqual(intEqual).eq(o1, o2); + assertThat(b, equalTo(true)); + } + +} diff --git a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java new file mode 100644 index 00000000..0ae976ef --- /dev/null +++ b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java @@ -0,0 +1,218 @@ +package fj.data.hamt; + +import fj.Equal; +import fj.Ord; +import fj.P; +import fj.P3; +import fj.data.List; +import fj.data.Seq; +import fj.data.test.PropertyAssert; +import fj.function.Booleans; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.math.BigInteger; + +import static fj.Equal.bitSetSequal; +import static fj.Equal.booleanEqual; +import static fj.Equal.listEqual; +import static fj.Equal.stringEqual; +import static fj.Function.identity; +import static fj.data.hamt.BitSet.MAX_BIT_SIZE; +import static fj.data.hamt.BitSet.listBitSet; +import static fj.data.hamt.BitSet.longBitSet; +import static fj.test.Arbitrary.arbBoolean; +import static fj.test.Arbitrary.arbLong; +import static fj.test.Property.impliesBoolean; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * Created by maperr on 31/05/2016. + */ + +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 10000) +public class BitSetProperties { + + Property andTest() { + return property(arbLong, arbLong, (a, b) -> prop(longBitSet(a).and(longBitSet(b)).longValue() == (a & b))); + } + + Property asStringTest() { + return property(arbLong, a -> prop(longBitSet(a).asString().equals(Long.toBinaryString(a)))); + } + + Property bitsToRightTest() { + return property(arbLong, arbBitSetSize, (a, i) -> + prop( + longBitSet(a).bitsToRight(i) == + longBitSet(a).toList().reverse().take(i).filter(identity()).length() + )); + } + + Property longRoundTripTest() { + return property(arbNaturalLong, l -> prop(longBitSet(l).longValue() == l)); + } + + Property empty() { + return prop(BitSet.empty().isEmpty() && BitSet.empty().longValue() == 0); + } + + Property generalEmptinessTest() { + return property(arbListBoolean, list -> + prop(list.dropWhile(Booleans.not).isEmpty() == listBitSet(list).isEmpty()) + ); + } + + Property foldLeftTest() { + return property(arbLong, l -> prop( + BitSet.longBitSet(l).toList().dropWhile(b -> !b).foldLeft( + (acc, b) -> acc + 1, 0 + ) == BitSet.longBitSet(l).bitsUsed() + )); + } + + Property fromListTest() { + return property(arbListBoolean, l -> prop(listBitSet(l).toList().equals(l.dropWhile(b -> !b)))); + } + + Property fromStreamTest() { + return property(arbListBoolean, l -> prop(listBitSet(l).toStream().toList().equals(l.dropWhile(b -> !b)))); + } + + Property fromLongTest() { + return property(arbLong, l -> prop(BitSet.longBitSet(l).longValue() == l)); + } + + Property fromStringTest() { + Gen g = arbListBoolean.map(l -> l.map(b -> Integer.toString(BitSet.toInt(b))).foldLeft((acc, s) -> acc + s, "")); + return property(g, (s) -> { + boolean zeroLength = s.isEmpty(); + return Property.implies(!zeroLength, () -> { + long x = new BigInteger(s, 2).longValue(); + long y = BitSet.stringBitSet(s).longValue(); + return prop(x == y); + }); + }); + } + + Gen> arbListBoolean = Gen.choose(0, MAX_BIT_SIZE).bind(i -> Gen.sequenceN(i, arbBoolean)); + + Property toListTest() { + return property(arbListBoolean, list -> { + List expected = list.dropWhile(Booleans.not); + List actual = listBitSet(list).toList(); + return prop(Equal.listEqual(Equal.booleanEqual).eq(expected, actual)); + }); + } + + Property clearTest() { + return property(arbLong, arbBitSetSize, (l, i) -> + prop(BitSet.longBitSet(l).clear(i).isSet(i) == false) + ); + } + + Property bitsUsedTest() { + return property(arbListBoolean, list -> prop( + list.dropWhile(b -> !b).length() == + listBitSet(list).bitsUsed() + )); + } + + Property isSetTest() { + return property(arbNaturalLong, Gen.choose(0, MAX_BIT_SIZE), + (Long l, Integer i) -> prop(longBitSet(l).isSet(i) == ((l & (1L << i)) != 0)) + ); + } + + Property stringBitSet() { + return property(arbNaturalLong, l -> + prop(BitSet.stringBitSet(BitSet.longBitSet(l).asString()).longValue() == l) + ); + } + + Property notTest() { + return property(arbLong, l -> prop(longBitSet(l).not().longValue() == ~l)); + } + + Property orTest() { + return property(arbLong, arbLong, (x, y) -> prop( + longBitSet(x).or(longBitSet(y)).longValue() == (x | y) + )); + } + + Gen> bitSetIndices(int n) { + return Gen.listOfSorted(Gen.choose(0, MAX_BIT_SIZE - 1), n, Ord.intOrd); + } + + Property rangeTest() { + return property(arbNaturalLong, bitSetIndices(4), (x, list) -> { + int l = list.index(0); + int m = list.index(1); + int h = list.index(2); + int vh = list.index(3); + + BitSet bs1 = longBitSet(x); + BitSet bs2 = bs1.range(l, h); + boolean b = + bs1.isSet(m) == bs2.isSet(m - l) && + bs2.isSet(vh - l) == false; + return prop(b); + }); + } + + Property setTest() { + return property(arbNaturalLong, arbBitSetSize, (l, i) -> prop(longBitSet(l).set(i).isSet(i))); + } + + Property setBooleanTest() { + return property(arbNaturalLong, arbBitSetSize, arbBoolean, (l, i, b) -> prop(longBitSet(l).set(i, b).isSet(i) == b)); + } + + Property shiftLeftTest() { + return property(arbNaturalLong, arbBitSetSize, (l, i) -> { + BitSet bs = longBitSet(l); + boolean b = bs.shiftLeft(i).longValue() == (l << i); + return impliesBoolean(bs.bitsUsed() + i < MAX_BIT_SIZE, b); + }); + } + + Property shiftRightTest() { + return property(arbNaturalLong, arbBitSetSize, (l, i) -> { + return prop(longBitSet(l).shiftRight(i).longValue() == (l >> i)); + }); + } + + Property takeLowerTest() { + return property(arbNaturalLong, arbBitSetSize, (l, i) -> { + return prop(bitSetSequal.eq(longBitSet(l).takeLower(i), longBitSet(l).range(0, i))); + }); + } + + Property takeUpperTest() { + return property(arbNaturalLong, arbBitSetSize, (l, i) -> { + return prop(bitSetSequal.eq(longBitSet(l).takeUpper(i), longBitSet(l).range(MAX_BIT_SIZE, MAX_BIT_SIZE - i))); + }); + } + + Property toStreamTest() { + return property(arbNaturalLong, l -> { + return prop(listEqual(booleanEqual).eq(longBitSet(l).toList(), longBitSet(l).toStream().toList())); + }); + } + + Property xorTest() { + return property(arbNaturalLong, arbNaturalLong, (a, b) -> { + return prop(longBitSet(a).xor(longBitSet(b)).longValue() == (a ^ b)); + }); + } + static final Gen arbNaturalLong = Gen.choose(0, Long.MAX_VALUE); + + static final Gen arbBitSetSize = Gen.choose(0, MAX_BIT_SIZE - 1); + +} diff --git a/props-core/src/test/java/fj/data/hamt/HashArrayMappedTrieProperties.java b/props-core/src/test/java/fj/data/hamt/HashArrayMappedTrieProperties.java new file mode 100644 index 00000000..05001a1a --- /dev/null +++ b/props-core/src/test/java/fj/data/hamt/HashArrayMappedTrieProperties.java @@ -0,0 +1,94 @@ +package fj.data.hamt; + +import fj.Equal; +import fj.Hash; +import fj.Ord; +import fj.P2; +import fj.data.List; +import fj.data.Option; +import fj.data.Set; +import fj.test.Gen; +import fj.test.Property; +import fj.test.reflect.CheckParams; +import fj.test.runner.PropertyTestRunner; +import org.junit.runner.RunWith; + +import static fj.Equal.intEqual; +import static fj.Equal.optionEqual; +import static fj.Ord.intOrd; +import static fj.Ord.p2Ord; +import static fj.Ord.p2Ord2; +import static fj.data.Option.some; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbList; +import static fj.test.Arbitrary.arbListInteger; +import static fj.test.Arbitrary.arbP2; +import static fj.test.Arbitrary.arbSet; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +/** + * @author Mark Perry + */ +@RunWith(PropertyTestRunner.class) +@CheckParams(maxSize = 100) +public class HashArrayMappedTrieProperties { + + private static final HashArrayMappedTrie empty = HashArrayMappedTrie.emptyKeyInteger(); + private static final Gen>> arbListProducts = arbSet(intOrd, arbInteger).bind(s -> Gen.listOf(arbInteger, s.size()).map(list -> s.toList().zip(list))); + private static final Gen> arbHamt = arbListProducts.map(l -> empty.set(l)); + + Property empty() { + return prop(empty.isEmpty()); + } + + Property setFromList() { + return property(arbListProducts, list -> { + List> actual = empty.set(list).toList(intOrd); + List> expected = list.sort(p2Ord(intOrd, intOrd)); + boolean b = actual.equals(expected); + return prop(b); + }); + } + + Property overwriteKey() { + return property(arbHamt, arbInteger, arbInteger, arbInteger, (h, k, v1, v2) -> { + Option actual = h.set(k, v1).set(k, v2).find(k); + return prop(optionEqual(intEqual).eq(actual, some(v2))); + }); + } + + Property allIn() { + return property(arbListProducts, list -> { + HashArrayMappedTrie h = empty.set(list); + Boolean b = list.foldLeft((acc, p) -> h.find(p._1()).option(false, i -> true && acc), true); + return prop(b); + }); + } + + Property sampleInts() { + return property(arbListProducts, arbInteger, (ps, i) -> { + HashArrayMappedTrie h = empty.set(ps); + Option o1 = ps.find(p -> intEqual.eq(p._1(), i)).map(p -> p._2()); + Option o2 = h.find(i); + return prop(optionEqual(intEqual).eq(o1, o2)); + }); + } + + Property fold() { + return property(arbListProducts, list -> { + Integer actual = empty.set(list).foldLeft((acc, p) -> acc + p._2(), 0); + Integer expected = list.foldLeft((acc, p) -> acc + p._2(), 0); + return prop(intEqual.eq(actual, expected)); + }); + } + + Property length() { + return property(arbListProducts, list -> { + Integer actual = empty.set(list).length(); + Integer expected = list.length(); + return prop(intEqual.eq(actual, expected)); + }); + } + +} diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 1e4a4c5e..5b0a98bc 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -363,6 +363,12 @@ public static Gen choose(final int from, final int to) { return parameterised(curry((i, r) -> value(r.choose(f, t)))); } + public static Gen choose(final long from, final long to) { + final long f = min(from, to); + final long t = max(from, to); + return parameterised(i -> r -> value(r.choose(f, t))); + } + /** * Returns a generator that produces values between the given range (inclusive). * @@ -468,6 +474,10 @@ public static Gen> listOf(final Gen g, final int x) { return sized(size -> choose(x, max(x, size)).bind(n -> sequenceN(n, g))); } + public static Gen> listOfSorted(final Gen g, final int x, Ord ord) { + return listOf(g, x).map(l -> l.sort(ord)); + } + /** * Returns a generator of lists whose values come from the given generator. * diff --git a/quickcheck/src/main/java/fj/test/Rand.java b/quickcheck/src/main/java/fj/test/Rand.java index f1849bb3..b622dfe7 100644 --- a/quickcheck/src/main/java/fj/test/Rand.java +++ b/quickcheck/src/main/java/fj/test/Rand.java @@ -55,6 +55,9 @@ public int choose(final int from, final int to) { return f.f(Option.none()).f(from).f(to); } + public long choose(final long from, final long to) { + return g.f(Option.none()).f((double) from).f((double) to).longValue(); + } /** * Randomly chooses a value between the given range (inclusive). * diff --git a/quickcheck/src/test/java/fj/test/TestRand.java b/quickcheck/src/test/java/fj/test/TestRand.java index 6c72b3b1..1ca7c749 100644 --- a/quickcheck/src/test/java/fj/test/TestRand.java +++ b/quickcheck/src/test/java/fj/test/TestRand.java @@ -20,7 +20,7 @@ public void testRandLowHighInclusive() { int max = 10; int n = 100; Stream s = Stream.range(0, n).map(i -> Rand.standard.choose(min, max)).sort(Ord.intOrd); -// System.out.println(s); +// System.out.println(s.toList()); assertTrue(s.head() == min && s.last() == max); } From 732a15176efbee751abfbeb97d82f3029d8cc9a1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Nov 2016 17:35:16 +0100 Subject: [PATCH 627/811] rename Ord/Equal.AltDef --- core/src/main/java/fj/Equal.java | 6 +++--- core/src/main/java/fj/Ord.java | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index ae20c4df..35232412 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -53,7 +53,7 @@ default boolean equal(A a1, A a2) { /** * Primitives functions of Equal: alternative minimal definition and overridable methods. */ - public interface AlternateDefinition extends Definition { + public interface AltDefinition extends Definition { @Override boolean equal(A a1, A a2); @@ -158,7 +158,7 @@ public static Equal equalDef(final Definition definition) { * @param definition a definition of the equal instance. * @return An equal instance from the given function. */ - public static Equal equalDef(final AlternateDefinition definition) { + public static Equal equalDef(final AltDefinition definition) { return new Equal<>(definition); } @@ -407,7 +407,7 @@ public static Equal> arrayEqual(final Equal ea) { */ public static Equal> treeEqual(final Equal ea) { Definition eaDef = ea.def; - return equalDef(new AlternateDefinition>() { + return equalDef(new AltDefinition>() { final Definition>>> subForestEqDef = p1Equal(streamEqual(equalDef(this))).def; diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 1764ea74..5fdb6046 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -16,7 +16,6 @@ import static fj.Function.apply; import static fj.Function.compose; -import static fj.Function.compose2; import static fj.Function.curry; import static fj.Semigroup.semigroup; import static fj.Semigroup.semigroupDef; @@ -90,7 +89,7 @@ public Definition dual() { /** * Primitives functions of Ord: alternative minimal definition and overridable methods. */ - public interface AlternateDefinition extends Definition { + public interface AltDefinition extends Definition { Ordering compare(A a1, A a2); @@ -301,7 +300,7 @@ public static Ord ord(final F> f) { } /** - * Returns an order instance that uses the given minimal equality test and ordering definiion. + * Returns an order instance that uses the given minimal equality test and ordering definition. * * @param def The order definition. * @return An order instance. @@ -311,12 +310,12 @@ public static Ord ordDef(final Definition def) { } /** - * Returns an order instance that uses the given minimal equality test and ordering definiion. + * Returns an order instance that uses the given minimal equality test and ordering definition. * * @param def The order definition. * @return An order instance. */ - public static Ord ordDef(final AlternateDefinition def) { + public static Ord ordDef(final AltDefinition def) { return new Ord<>(def); } From 5f73cac759e57aba717420fa3d86d380ca783e45 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Nov 2016 17:50:38 +0100 Subject: [PATCH 628/811] List.minimum/maximum: use uncurried Ord.max/min for better perf. --- core/src/main/java/fj/data/List.java | 4 ++-- demo/src/main/java/fj/demo/euler/Problem4.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 8bc31a37..fa82359f 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1462,7 +1462,7 @@ public static F, Integer> length_() { * @return The maximum element in this list according to the given ordering. */ public final A maximum(final Ord o) { - return foldLeft1(o.max); + return foldLeft1(o::max); } /** @@ -1472,7 +1472,7 @@ public final A maximum(final Ord o) { * @return The minimum element in this list according to the given ordering. */ public final A minimum(final Ord o) { - return foldLeft1(o.min); + return foldLeft1(o::min); } public final java.util.List toJavaList() { diff --git a/demo/src/main/java/fj/demo/euler/Problem4.java b/demo/src/main/java/fj/demo/euler/Problem4.java index 60c04d85..c768ed78 100644 --- a/demo/src/main/java/fj/demo/euler/Problem4.java +++ b/demo/src/main/java/fj/demo/euler/Problem4.java @@ -19,6 +19,6 @@ public static void main(final String[] a) { intShow.println(tdl.tails().bind(tdl.zipWith(multiply)).filter(i -> { final Stream s = intShow.show(i); return streamEqual(charEqual).eq(s.reverse().take(3), s.take(3)); - }).foldLeft1(intOrd.max)); + }).foldLeft1(intOrd::max)); } } From 05275dbf41969b88b6f46426350e1d0662b2a78d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Nov 2016 18:27:54 +0100 Subject: [PATCH 629/811] Do not deprecate monoid/ord/semigroup constructors for non java 8 users. --- core/src/main/java/fj/Equal.java | 15 ++++ core/src/main/java/fj/Monoid.java | 14 +++- core/src/main/java/fj/Ord.java | 16 +++- core/src/main/java/fj/Semigroup.java | 12 ++- .../java/fj/demo/concurrent/WordCount.java | 74 +++++++++---------- 5 files changed, 83 insertions(+), 48 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 35232412..b64c758d 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -135,6 +135,8 @@ public boolean equal(B b1, B b2) { /** * Constructs an equal instance from the given function. * + * Java 8+ users: use {@link #equalDef(Definition)} instead. + * * @param f The function to construct the equal with. * @return An equal instance from the given function. */ @@ -142,6 +144,19 @@ public static Equal equal(final F> f) { return new Equal<>(f::f); } + + /** + * Constructs an equal instance from the given function. + * + * Java 8+ users: use {@link #equalDef(AltDefinition)} instead. + * + * @param f The function to construct the equal with. + * @return An equal instance from the given function. + */ + public static Equal equal(final F2 f) { + return equalDef(f::f); + } + /** * Constructs an equal instance from the given definition. * diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index a342b8c7..3fcf1775 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -38,6 +38,9 @@ public final class Monoid { private final Definition def; + /** + * Primitives functions of Monoid: minimal definition and overridable methods. + */ public interface Definition extends Semigroup.Definition { A empty(); @@ -91,6 +94,10 @@ public Definition dual() { } } + + /** + * Primitives functions of Monoid: alternative minimal definition and overridable methods. + */ public interface AltDefinition extends Definition { @Override @@ -423,13 +430,12 @@ public static Monoid monoidDef(final Semigroup.AltDefinition s, final /** * Constructs a monoid from the given sum function and zero value, which must follow the monoidal * laws. - * @deprecated since 4.7. Use {@link #monoidDef(Semigroup.Definition, Object)} instead. + * Java 8+ users: use {@link #monoidDef(Semigroup.Definition, Object)} instead. * * @param sum The sum function for the monoid. * @param zero The zero for the monoid. * @return A monoid instance that uses the given sun function and zero value. */ - @Deprecated public static Monoid monoid(final F> sum, final A zero) { return new Monoid<>(new AltDefinition() { @Override @@ -447,13 +453,13 @@ public A empty() { /** * Constructs a monoid from the given sum function and zero value, which must follow the monoidal * laws. - * @deprecated since 4.7. Use {@link #monoidDef(Semigroup.Definition, Object)} instead. + * + * Java 8+ users: use {@link #monoidDef(Semigroup.Definition, Object)} instead. * * @param sum The sum function for the monoid. * @param zero The zero for the monoid. * @return A monoid instance that uses the given sun function and zero value. */ - @Deprecated public static Monoid monoid(final F2 sum, final A zero) { return new Monoid<>(new Definition() { @Override diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 5fdb6046..a3e55edc 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -290,15 +290,27 @@ public final Ord reverse() { /** * Returns an order instance that uses the given equality test and ordering function. * - * @deprecated since 4.7. Use {@link #ordDef(Definition)}. + * Java 8+ users: use {@link #ordDef(Definition)} instead. + * * @param f The order function. * @return An order instance. */ - @Deprecated public static Ord ord(final F> f) { return new Ord<>(f::f); } + /** + * Returns an order instance that uses the given equality test and ordering function. + * + * Java 8+ users: use {@link #ordDef(AltDefinition)} instead. + * + * @param f The order function. + * @return An order instance. + */ + public static Ord ord(final F2 f) { + return ordDef(f::f); + } + /** * Returns an order instance that uses the given minimal equality test and ordering definition. * diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index cba1f04b..74d7de9b 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -31,6 +31,9 @@ */ public final class Semigroup { + /** + * Primitives functions of Semigroup: minimal definition and overridable methods. + */ public interface Definition { A append(A a1, A a2); @@ -79,6 +82,9 @@ public A multiply1p(int n, A a) { } } + /** + * Primitives functions of Semigroup: alternative minimal definition and overridable methods. + */ public interface AltDefinition extends Definition { @Override F prepend(A a); @@ -285,24 +291,22 @@ public static Semigroup semigroupDef(final AltDefinition def) { /** * Constructs a semigroup from the given function. - * @deprecated since 4.7. Use {@link #semigroupDef(Definition)}. + * Java 8+ users: use {@link #semigroupDef(AltDefinition)} instead. * * @param sum The function to construct this semigroup with. * @return A semigroup from the given function. */ - @Deprecated public static Semigroup semigroup(final F> sum) { return semigroupDef(sum::f); } /** * Constructs a semigroup from the given function. - * @deprecated since 4.7. Use {@link #semigroupDef(Definition)}. + * Java 8+ users: use {@link #semigroupDef(Definition)} instead. * * @param sum The function to construct this semigroup with. * @return A semigroup from the given function. */ - @Deprecated public static Semigroup semigroup(final F2 sum) { return new Semigroup<>(sum::f); } diff --git a/demo/src/main/java/fj/demo/concurrent/WordCount.java b/demo/src/main/java/fj/demo/concurrent/WordCount.java index c90a0b2d..175d2d09 100644 --- a/demo/src/main/java/fj/demo/concurrent/WordCount.java +++ b/demo/src/main/java/fj/demo/concurrent/WordCount.java @@ -1,10 +1,18 @@ package fj.demo.concurrent; -import static fj.Monoid.monoid; -import static fj.Monoid.monoidDef; -import static fj.control.parallel.ParModule.parModule; -import static fj.data.List.nil; -import static java.util.concurrent.Executors.newFixedThreadPool; +import fj.F; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.P2; +import fj.control.parallel.ParModule; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.IOFunctions; +import fj.data.Iteratee.Input; +import fj.data.Iteratee.IterV; +import fj.data.List; +import fj.data.Option; import java.io.BufferedWriter; import java.io.File; @@ -14,35 +22,25 @@ import java.io.Reader; import java.io.StringWriter; import java.io.Writer; -import java.nio.charset.Charset; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; -import fj.F; -import fj.Monoid; -import fj.P; -import fj.P1; -import fj.P2; -import fj.Unit; -import fj.control.parallel.ParModule; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import fj.data.*; -import fj.data.Iteratee.Input; -import fj.data.Iteratee.IterV; -import fj.function.Effect1; +import static fj.Monoid.monoid; +import static fj.control.parallel.ParModule.parModule; +import static fj.data.List.nil; +import static java.util.concurrent.Executors.newFixedThreadPool; /** * Reads words and their counts from files ({@link #getWordsAndCountsFromFiles} in a single thread * and {@link #getWordsAndCountsFromFilesInParallel} in multiple threads). The files are created * initially and populated with some sample content. - * + * * @author Martin Grotzke */ public class WordCount { - + // Integers.add.f(1) caused an SOE... private static final F addOne = a -> a.intValue() + 1; @@ -55,7 +53,7 @@ private static Map update(Map map, K key, F valueFuncti map.put(key, valueFunction.f(value)); return map; } - + private static final F> fileNameToWordsAndCountsWithCharChunkIteratee = fileName -> { try { return IOFunctions.enumFileCharChunks(new File(fileName), Option.none(), wordCountsFromCharChunks()).run().run(); @@ -63,7 +61,7 @@ private static Map update(Map map, K key, F valueFuncti throw new RuntimeException(e); } }; - + private static final F> fileNameToWordsAndCountsWithCharChunk2Iteratee = fileName -> { try { return IOFunctions.enumFileChars(new File(fileName), Option.none(), wordCountsFromChars()).run().run(); @@ -71,7 +69,7 @@ private static Map update(Map map, K key, F valueFuncti throw new RuntimeException(e); } }; - + private static final F> fileNameToWordsAndCountsWithCharIteratee = fileName -> { try { return IOFunctions.enumFileChars(new File(fileName), Option.none(), wordCountsFromChars()).run().run(); @@ -181,7 +179,7 @@ public static void main(String[] args) throws IOException { final Map expectedWordsAndCounts = result._2(); long avgSize = fileNames.foldLeft((a, file) -> a.longValue() + new File(file).length(), 0l) / fileNames.length(); System.out.println("Processing " + numFiles + " files with ~"+numSharedWords+" words and an avg size of " + avgSize + " bytes."); - + // warmup for(int i = 0; i < 1; i++) { // getWordsAndCountsFromFiles(fileNames.take(1)).size(); @@ -211,7 +209,7 @@ public static void main(String[] args) throws IOException { assertTrue(wordsAndCountsFromFiles != null); assertEquals(wordsAndCountsFromFiles.size(), numFiles + numSharedWords); assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); - + System.gc(); // get word counts sequentially / single threaded \w iteratee @@ -223,7 +221,7 @@ public static void main(String[] args) throws IOException { assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); System.gc(); - + // get word counts sequentially / single threaded \w iteratee start = System.currentTimeMillis(); wordsAndCountsFromFiles = getWordsAndCountsFromFilesWithIteratee(fileNames, fileNameToWordsAndCountsWithCharChunk2Iteratee); @@ -233,7 +231,7 @@ public static void main(String[] args) throws IOException { assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); System.gc(); - + // start = System.currentTimeMillis(); // wordsAndCountsFromFiles = getWordsAndCountsFromFilesInParallel(fileNames, fileNameToWordsAndCounts, 8); // System.out.println("Getting word counts in 8 threads took " + (System.currentTimeMillis() - start) + " ms."); @@ -249,14 +247,14 @@ public static void main(String[] args) throws IOException { assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); System.gc(); - + start = System.currentTimeMillis(); wordsAndCountsFromFiles = getWordsAndCountsFromFilesInParallel(fileNames, fileNameToWordsAndCountsWithCharChunkIteratee, 32); System.out.println("Getting word counts in 32 threads with char chunk iteratee took " + (System.currentTimeMillis() - start) + " ms."); assertTrue(wordsAndCountsFromFiles != null); assertEquals(wordsAndCountsFromFiles.size(), numFiles + numSharedWords); assertEquals(wordsAndCountsFromFiles, expectedWordsAndCounts); - + // we have tmpfiles, but still want to be sure not to leave rubbish fileNames.foreachDoEffect(a -> new File(a).delete()); } @@ -286,13 +284,13 @@ private static P2, Map> writeSampleFiles( } return P.p(fileNames, expectedWordsAndCounts); } - + public static Map getWordsAndCountsFromFilesWithIteratee(final List fileNames, final F> fileNameToWordsAndCountsWithIteratee) { final List> maps = fileNames.map(fileNameToWordsAndCountsWithIteratee); return maps.foldLeft(WordCount::plus, new HashMap()); } - + public static Map getWordsAndCountsFromFilesInParallel( final List fileNames, final F> fileNameToWordsAndCounts, int numThreads) { final ExecutorService pool = newFixedThreadPool(numThreads); @@ -305,14 +303,14 @@ public static Map getWordsAndCountsFromFilesInParallel( return result; } - + // Read documents and extract words and word counts of documents public static Promise> getWordsAndCountsFromFiles( final List fileNames, final F> fileNameToWordsAndCounts, final ParModule m) { - final Monoid> monoid = monoidDef(WordCount::plus, Collections.emptyMap()); + final Monoid> monoid = monoid(WordCount::plus, Collections.emptyMap()); return m.parFoldMap(fileNames, fileNameToWordsAndCounts, monoid); } - + private static Map plus(Map a, Map b) { final Map result = new HashMap<>(a); for(Map.Entry entry : b.entrySet()) { @@ -321,7 +319,7 @@ private static Map plus(Map a, Map Date: Sun, 6 Nov 2016 18:48:05 +0100 Subject: [PATCH 630/811] retrolambda: enable backport of default methods. --- lib.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/lib.gradle b/lib.gradle index 5b84e98b..28be5e34 100644 --- a/lib.gradle +++ b/lib.gradle @@ -89,6 +89,7 @@ void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String ol jdk System.getenv(newJdkEnvVar) oldJdk System.getenv(oldJdkEnvVar) javaVersion retroLambdaTarget + defaultMethods true } dependencies { retrolambdaConfig "net.orfjackal.retrolambda:retrolambda:$retrolambdaVersion" From f583adb8f6fad8f2fcb46bcbd6707e4e0590cc69 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 6 Nov 2016 20:32:34 +0100 Subject: [PATCH 631/811] Fix BitSet.range property checking. --- props-core/src/test/java/fj/data/hamt/BitSetProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java index 0ae976ef..f3527972 100644 --- a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java +++ b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java @@ -153,8 +153,8 @@ Gen> bitSetIndices(int n) { Property rangeTest() { return property(arbNaturalLong, bitSetIndices(4), (x, list) -> { int l = list.index(0); - int m = list.index(1); int h = list.index(2); + int m = Math.max(l, Math.min(list.index(1), h - 1)); int vh = list.index(3); BitSet bs1 = longBitSet(x); From b897b745636d51218bcd8d8ffaa7275fa4bb2423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Tue, 6 Dec 2016 21:42:53 -0500 Subject: [PATCH 632/811] Upgrade Gradle to 2.14.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 51106 -> 53637 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 10 +++------- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3c7abdf12790879c06b07176de29647f77aa4129..05ef575b0cd0173fc735f2857ce4bd594ce4f6bd 100644 GIT binary patch delta 40807 zcmZ6SQ;;UmlC8_OZQDkdZQHh8f7!Ne+v>7yqsz9dZ_k;B8)u#}BX&Nni2dct%%XVE z&|**oMHx^q7$6`hC?Hq{Rf$9da`^v=E~6A=f?vKzXJ1_A`+2nGZs3Y47Rjh@T|A`gg-gl3kj zl9Ls*GXk}!^DuQte5iklwqv`8d@GJ={*_7ujCwmXd&T!S&BxpQdUU#W3pD9zO%fXf z4GRuxL%q$>7#EAip`y8ZgO94yVMBs2HqaL612=)Gzh9{r)}g{@D!DvZW~f=^6X?0b z&yDdwFZe=jyfy^!irD$||<4t=`4ao<=ru&nwBzULL98KjnK#=Pyn2O&{$DpuxOUx zxR^52wWVI9@O+Hlk`Tl5H7Ewjc-%pD>|2|T{n{85;akKf!1Ww#_yi1@jeo0i1J}&v z0ExK&dh(ig4)?=a{KyO2`GC`r_oEY&Vzg9?0)%7b$w_@lSi7@`lc;LixM-y&B}as) z@KrJYDR1GbI=|G9onlY@!I%(QEb zKx}nMvwtDHBX>$G#UA$)|Ln@=nEaOC9OYIva6E@QDUWnEuF>_^j2nQnkD27B#KpBT zT5A0h22D!8sq=dV*v>5h0IM;v`KMHA7(Jsy9%Eyf@jv=O{g2%KM<1tGnl4rUWVQvA zJTH!uTnRS#AN@2tfER-x{7(Viq2AUAI1tbWOfnG^KLFJX@2_1Jg;kdw@h@UUTcFSu z#ULt-rJ%HRV@vG<_)>86_6ZKXuASIyIT=49fs0SKyR+P47E*dm$Wd$wiLqdwqrm&Y z5p2dhEJlLiz4q+1K753Cg1@J?e?K?`e?C{>fe??9iP{RAL6A#^7mp=8ko56hk3^9K zT%)F>oB$Wl1sYdYLfqtOeMIubd+~ulvtUZ35$s&J!>pbhk}7lHP6%_KgV^3Wwhc9 zt2R1Wi8hIfsZ6m!wOH=?MVM;P=xrQTSz_JQL;xXa>5AFxt~@r|6&w{;p{G{sFmu8* zMFKer+z&EORP(ebcIp|$?&#v+s#J9dH?=ob)~MZb&8&{}2z?*T;#AGa7U#yCQd2i} z4twhN9_x`!M$;!_AzT$+Ha)v3(`Dg88RnE6Yvc+ACn%K7B73|nY*c6Zn_5d7Z#om4 zOhA!YWf;B;RTl$a8{2gB$J@RayU9{UKCzB__6$}$aLV}E38q(dTX2h|467xs7YBVblSc@sn*jp=?LS zlv=%vzmZ?I@C3T}Mm9V<&KVyFZ8x9LrWmRR7J@-}?Cu7YAU;89Y{r442B&*dd}?cN^;T0f!zn7`nCnK3IY7)f z7G?+)!+6F(w0{rTky#Ik(UP=S`hMf6neK44zi!e!j(&RLfQo+)@sXTtlfljV4KW?Y1oRbsqTWUaV%V>x@lb}=}nH9Eh~%Yt5a3)wXpwK zyoXs&`0MxEuhH=F&-=uf_(Y4mbO3c|NZDtW6T;A8UXmgPI(z+OM!Qnw(}&iE6uhMOe_?99-gF?njp}h>7WX4 zN|-jD$uLH_U@H0avdb*m>2j)ZCX{Br0@TD6vE*vAs<8bn2-q_HmKD?}{%LGIhBd$D3Jq`Evv|bxzK#@^ z`qz`xA;W>Rs%q&#@l}RQKZrkk2w$2KZ=jP%qwZHgd!oC1P$Xm&xu*$O?h?Yrmz<7v zf9wKS%(iWC%8A+SJ7E+|b^vNAdQK@Gyw>`4TOIZi;P4ttcLd5LbvRiKn2z#;v43(x zND=3luZq!jJTKk~(}5>gL2n0cs8i+!IGNxD;{&NxLxOb66uIF$yCb)$Rddr0^{Ms! z;a6q^s0pAT`y?P4Tl+>C4>DB+zTswAE3hqLYBNVSJ2D-z95#Dv(8Lw0> z>jSc!%1zLa8TY|_rGPiiTEfqFhYMu5M4q6r1PRu?;oy!Cb=gBC{?-Kz5QAd;y#mm^ zLn{A)rKhz>1Iq&pul9-0;2yz=&*&cBKi?vG70!qtExy5dFU>)a%pwNyNu$!U>Urg$ zPjuYn=98WgZyW@awJ|LH#Bms-J&64%OT;NhOsRjk-zlm7l9^KLD_=yaKkXp5(f31@ zV(?Gx9JQQzR9N@KL6Yf)ak_O!jCrf`8 z_%RqjOzq5bIb7)ON7T6vTxmtQ36EW|6ni=SYcFdsXjtK{>f=C;fu^l{Jl3MY)sZDi ze9`VQ>sDhhd6;Kw+f0I{+iPW>!+P9vo6mAn&#QSg>hASTX0F{*^Sc%q>hHj7)@7W! zHIB`^&b`K%xjZjlTdz_1KN@r2c!#ajJy!f)ca0{GzFr9TgEGOV{2$ ztFYO({;I9}T0c1O=x_`A2KEf~>=)fSGan~6)v=sz@WJD(a5?_OKeYGkXbEeIhh@`% z*f3ytv0bj`e1p_F9)m;i%lS=MCg7iNAmxbrNVJi+>q15-1GGLeU+yPR!<_sprd)Tb zx$*c*!GR~`D=??t6fPl_7!{+OAB;)HWPI@?TX5(o=M-wglp^LBMfGS1CG!}*A#`2z zbgVyK^pyaKlgo{U6r`N!WQ#*5UDQJW`9<8lz265|rb~)$MlR9JjN_o=GC9SaB<$X# zBR(e@krTG5GBk_O5&FNZL>#9V5$Z3~*P)JdLJ1s8F<56Ugw!OFOG)M}s4@~!vUEZX zTvGv9XEDUYBvHK7V+o?9Qh+SAkTT1-3%R5kd{UB7npE>5WC__XYw3g*IAv0epfl@# zNt1lmn%}QU5L2Gz?QhusR&6sTG9&nZNVn9BsZ0Hzeu4hM3gLf97a;3kVPWRXU}9_J z;u4zt>9DAXHrAg$MpMr`>L{CmnhPVQ5$3>55oQXFObBgG@mZUaT_oHvY!FNg5J2CPF5ZL$urY@fn4UPxVM=-c@WU^nRv9oCl*33%*Q`X$SAbhnjd zja8XI@p8p+vOH2UguR3s*b4A>z#MT z8J*K7D&jm$h_3X)(ITkk2WWwYjT-xYs=9gm@*Ss*>a>PN12FU2spQF4DNMqQHSt7P zQ#Q^+l#fs~+=iccQhw9gm2V|_^{9|25FzAjkKvD1r5nRs!!w z9a7(2gwfRo189UVOaA1TZ0<^GmW>qXw&bH99*is*L{iU6^ty(^_0DQ%ECo&pq@+ra|(_DO%;O3lkgm z!DVQ@^OEEzeuY{3g{`x6fI*ur)-wb&yEvxFxA8k719*Yo)PQE+_frt#`qTUA3TZ?7 zOil>0Jiy2IwWaHFR zb4I0l^#cP*`GmmKrXFqq_Wu(P(zl_f(?+xO0@=%XYqdMg$-0-_{`Y6@n-e%^wEvJR zYLFmjL>UjlewezKNJJ^@m`Zk|&9o6^B-#lutdxMSLq-XqaiWZ;w4HLT!%`#Oh%qMQ zOBNSD39z_Vh9itVJaX~{$&Wcuaq`8%t#7HU06$8@p?QGl)2hR`R6|V;oxu ztslNqQ~Jq*Gr-K=Lpsl9_LVtt7`w~G>cbs-z4QC+L>Wdnd?&)~MH$r%gAk(`t?dLD zchud|r0NVaqfvAztK13}n{jfL_?;+|{4GK{^vJ3*l>C@JCJ}yGUPkF+l8#0uZg0ui zYOBNwyFrb^1bd2ph2J7Owj%4HPMhWm{z*YGmXAk}v&++3Z)o#gBye>0VrHYo=F1wE z>NiMr!G`R$%>@5i6f~;(S`##1kXjDd{6QXC9+RGe?c%ScM{~Pp+_zxgN^onyc20*Y zy1{F_5?=L4?KQKZrR~bio!>6?7jKo7%Z@`Raqq%#_=N51W+i;A^lr<$w-EQ)p-Qop zbDi_(uU$iRkm~qj>(q@7?l!aRRzcKO!2OXy5gBuAwThW-J7tX3)*m%Vs0$8QL^l!p z?RinV;)Ch5TIt(jipgj*i$Z=fpH5JBRC;sJJJoe$3GO#ebrx4$Fr?x9G?HZ3VY9Jt z4Nwv6X*hx5#jQi2Qp7qcv{Mh)zsbiatl(tAZU9hPJ= z8#MXJeF>M4-Ibl2Iem@NRN?{{Ww1~5RLLII&~yiP!ofET?YZ)}$&01=6j4?r$Z3*( zDPqVr{Xjr?o`6QjbW|Gg;v*P|SA{zoqsbd$M|bhm9#O$M65F-c8d125iUOy5kX|do zqQV~Ov9ErsJo|zZv=DEi@h7f^eJhPJh54J;If@v#7Qf|2?HwWZycLVYi{DG20|xWeYL3*<0ly8QqEwx@tDoS=4O&8T@Lsn%|GDALl4Xlu!JIjoxYytv9-sB-mU5_m1aP2QZ^Oo8hv(%%3UB& zqCS4*vE#SE{rq1mbN{0WulN%Z6TV&_agXaT=5rQ*5xCN>QgU%=TCbVXPREOj08yL? z$X$}koPHOo)M{7`y<4-28(GGUReCR*UNDY(*1-M8kBc`qW-UnG$F4DIdfS(Sp-Nr9 z{s(KYt3?AkD=|R%=&pHC{Z-9U*3re3KMJL7G@9d@J1|T1(bq1|q(irO%i*^tTn&u| z{J5i^{Z?1Hpu74c^G)M|^B0juyrVi-_!2r*y>}JiA=W9JE79<6v%hpzeF!j|GX|(g zU?61$b(a%!!fa1mSXHWD2soM5G1p7MQnTy&8UkG;SpxuUn91&)|_f_yN%rystQ@rkP znej#pcs_s|s)DlhAFX7CO%vG}qGySWAg1f95vo!s_V;b@iH_d@;hgx=$cDxk5p+BP z89eCzz+#u!%*sy1+hzWiy0w%WHW~L(k<=FjheDncVnsfwJ9b6ZKqo}C;2w*>y>32A z%1;!#*SmSD1h+}?qvTTJECtrY{E2y4JBx=pV1Z3Xv5uN*KT+Oo! z-Y-;Uwq%}MI(N(|`nOq@KB!IRNa{RGWAid*5jwpTi~AT%xjl>z0pE3zJt6~e;6k_1+GftRk5m)~%|YUmzU;NNsFc@~xwDI}pe{Ncs=LL>g^5bv|+z^MjM&1{p{l0kLHRZ22(_DS+E3V1s-v(8~4 zLD^C*#=kOQ<{loefaZ+k4wgV&apvIfu=y0crAxR~4&H&YhK@jWC(VGXj-20X63Udb zs+@FZ*kKs&9)&|OCt^l`v*u(<0G0Xa69AXa2%of=T>Jv#y5~n2uR6MY7f-c-x#LF= z&uSGw{?YUE~7wgRQ~zw|C|D4%sZ4P{1=# zt5f%2A&}jvyI}aY?OUhFpKH2(1`e_6sqY?@JY-~wDo46s_zh%PZ(KJgv?WqhIdJpx z_9>%Dk<_6c)Z3^9_L;b+`dagpQTo{X)o<4CJ=(hh^a7pQ2R0c&@Ub=*9GnhaErpeC zOQU5g*_`aP4xO$dJ7ul1p)={1-GHa82!hKRt5y{A8W-@Tw+~M`t8-?XXaXsr2b)aa zL{E$IM8m8FJO$TPSBfXc;fiyqvz;CBqOuKwVQB!@E^74fGt-i7d!!uvxzoX7t&X1C zLt;F`JAeS2Ze7dQE?AOf zS@pQ19Y~NR38Bd0c35zxOGaGVsv&f8De*Rq+{;k9%tlRUC-KU&?{OLUd0i=ki@{Om{7H_!(|ILn`~LTk8#VuZDZ`U(p2AA?@%B_ zDxqp}N&jvy9;i-k2Td%QJ+U-K8ld8B870p}lL(u0FC~jpr83p_WdYm*C>%Eo-EpL3 z)ZL*VqMG=!jCZJEUE%qol)}_}uPfsag#343R-pP`1OkNGUCTh2+{g^G1f;80UTEes zHmo$=8t*VjjohD(H?2+h5G3ib3im9Z#fdAq)>h!fSyGs~@e#d;%t0<>oz)Hbl$UHb zz2$KUfc*o;1iTwx02<-rcbYW+B(efZ;$i)uru&gz72{1+o)j^S1bwY)<20rUZ*3YD;!r zlde>0tYST;q_SwKGD`UBM$Cey;V9e~(Pdc*@bQS6#N{@qDS#;k>6u4^Q3xlF_qtS~ z6fK^DmKM=w&Dt=k(oWMA^e&V#&Y5dFDgP;!n+OTRguB~h3|C4+;X=v+s_8IR*yHoY zzD^=|U~dsML|UXOXG}gX`94`t>pj(3jEBI*(Lx1*NJ^z9vO>+2_lm4NyUBW4L2G%7 zEiPINrH-qX766HZB&=j9B)XJINviDX8ua0Citr-H7#egwuW5(3)j#{gkE8N+H z4xPP8O1G0G`7KJqMM1>Xm}++?Jvlg|N=DBmxmy)s6<|moA4{PiN{2ab7d@-fUI)a%uc-VNd(z81vqMHVtj&9=aVc%jZNl)0^*3_{ge~NIp^3-FU zS+@B21PGGuFZ593k^QFm&hal?B;qe#bbG>1tt+%q^9~_UI~VUGh#6CLoGhBFYRR@& zJoo;n8SGZ;3v^I@r`RpNJNZVqqg7(ui>GRG3=6(~B;|PxIEp)J@))(Ag1bEPRmrs4Y*BfWJF$*5_sQzOA>6(1K z^H04!c93+*pL~r*L9F;9`i8^(J%1QmnPDa#YddJ(b>*u=N#CwMf09miYID$$xNPhs zBO+vdZZ5lI;+K&&;E$V*r(Vlm#%VAUWrHvICuUz=(TeZhxo>?s3X|k~4FI!R5Lur;*Pa)pg8 zobjL^IJMb{KrKxYpPPGl}a0C$y7>?QVh$vsTmPDf2dn^M;o_v zbC2b){&g$?9vffj8$qb?2A!IZHb!{jf3+%-+02kQ|4HUo#rI242MU@CavNZiESpcqnL**A}CdcQI4M*9-hbIk6n+U%b3V5TALj;z$ zvSZmqr=~HAyu@%OJ_m%)QwI4$#vtBr10G`zPGV%Lds8>KL&&BZ3mx7ur7+PsD$P58Bm!N(+uOzT`(2iznGq0q}&64gfG-RtX-H z?}iUMZ+q!kd=$YRT6-^rQo#iYn7``Bd-u;Y{c|29?RlO$zuvRY6B8t6+AXgjk7F$C zUXS14j+;^{OXcJqasW{pU{rWclX&s~Wvh*G-k@_*ietRy^0Y33n$~2iQP*?L8&QFU zSm6Vx#_J&w_1;2bwg9he#Zm0eXEN4Y%kg4`T3D-?&Zd?ILFJNA`G^m`O2~g zSLD3W8s6*)47i2wv>wFlwBp_>BSz2CU>S9ZxdrU2#gmdCg8H<%Z zG^+Q0lhWvT*OrBDAX*Nd5c!b2{K~A+X5>%Tiz#1H6I^8ZLAEI&4d~lKFg?jDj3HEkVSCFj>NFa4O|E8*qJDkZK})QXxY=k-ou; zJ3)ZESW2^$S#Fwyj-A5|OjfDGP|4A5{`WMIwPA1;c;=pfOdbtKgwOf3<3UkT2&?y! zR~|`T?&Vo?(W(EEUa5g?4Q$B4EJ_y=NmLCk}v9nkojm@}@crgEb7cSCdq>Va7mE`4PHsS~rcKO#%FP`L_WDzcIQ__=gf zR7TyX27zA|%&}+et1!3CmO@U_HD%nir~L12+;fT+pF1~vD$n~I4S`?a$H8cpw0NAE z`UFJJOtFmhT(Z($$3_pS8u(?<;kF3*B0f0p^Rpw;v4FBg>;xl%nKG1~Tq#bIlI=pN z_W4@Tm+bN3mu$&Yi~dMmf+zpHz5s&66DV-W-!5umf^xdy=E^ef$!x%k$u_-04ua^b zCsQWUwTRzG!F@tmo9YBl;E%MlRS*>w`DOePBk{2b&2T(v!OrBSwME#f@DrHp&UJ1b zX2-f>27nSqp(0^@l^A@W}`XB_Km!L7%xygSe{=D+6rTrtgON;6$KcYUAOYhH|x z*BT*C)g%b*g$;m6Inm?=g@3yRyK3u<0L@t5(>==PiO#**JVy6;eOj5TG4LrKr_IDQ3B`e*6E(x0}#C#Y9@rUBlgzl8P{J}rNn@(?_szhfG>gvi&^ zLt#8E>E8CTF;vKE&nsBi!qY6WJ6zfe5_0``E1s7p5jWQqPFS`JUqxGzv;yO7?GIkF zg)@}Bw}6Iqh0K!RpFl0Vqm{*)&YLX@QMfIlTYk=a(2Loky8rq;)$pN@RT;ogQ2GSl z6%Y6-a$T+Aod0G*A%UnSD1am$5#1EqD*OE4tv51|3fZEufvJAaX$|kOKe`X&g zI4XDrn=nHy_sJ7gsFM$`6s%opZU}I+tMN{}n4*QOC|lJbuP|`Lq=z8Fu&388SufIP zY4ciW>}aL$uWFsae2SuJeUD#4`Msoki>%Fo*6dcwJ z!xrelq0M9=e%n_3L!QL1D`&sd||R?+?{8Dj)gk z1%wrMgKrwx>&B-gGeIl8nnb!6|I|Y?68vkTx>`zq#VY30^HP*wi8_Rz!onoqW*0A^ zq<_2fIA^n6P`gm=)o3HLOI5Gg2S;Fd| zrd%lI(^C2Hg6ETpi(oD9FB^!;QoDrJ_K7ceP}c(>yA;`lDDZ4+bmqO2HtoOBs(7j} z?Ock8A3C2_m+F7erJyid@d~UEw(LCdPkZ#YLDo}`S@xKdI^i(%gVIIjd!g>Xkenm< z@_!*X4Y)(27w;fm?!iXygv$X={e4D_Mg8ax{n=MrNC$n8PS=S09E4g7CA_3(O@ft zP&S8Dig_J(&EttsudKP?1m%X#p24_qYrYt_Jhf(;M(7-U`=M&*Rg!(1fS#s6L!Ae_ z?dwF%-^-yQ!d&-%N#FoaD4M-7hMwRQKIqg}>||f*R>;d}g=qnL(B{2z{UPh9NCZjq z{F*Kl-!KSBiRl(ItvUX7*|ZAwpG)1lV*6x54IT+Rru~<$2`l918!1n=hsVxg#O^$f z@mIyh3nj_|Mf0Wk#=p*SgV7*|ySKt(;pfpoQ+@#>JxOb@oZ$k9WcKrTejVZOmj_KY zf{r<0mUWjbIrM{nk0A&Z}#&Bn|jw|4nM?7s7K%D0EJ$iUgRYDD+yl-Yec4Y~yX1`9Y{A zAGw{`bYk>N*yRGe1XT^#qg)gt3ax-*zXS{s68liJw;6pY?C<|s)tRS6qRzY$lUq<$ z3e_&M%Y3!ZQq(fjK;egs`-^ROCWclnj^P9l`gBlysi!jgK|S8yBf0>X1p*amAtw7>om+r${mK3ri;a8T$2$LF{5IH}#x=y3V)xI$er`BTpd~N2 zytkl!7n+dYnE7sKZqEKZza8>$x#OPwb1}>3!9jRC+wHs!UBl#(m(9GM`vM&!%pF2=eJk|tYb~n>B3*o|DIJfuhPMS|7XifaE99}DOU0=Gb2F5%Mecu z`>$NnggwVnh<#EUH8mZ%-QtYc)J__ylnT!HitS=n(dxtvo7VbO$i@Z%6buy=O%Wam zny6T9yU;mAL_iV72=48t!2KYo!`X9Kh z_a6O_k0}?~kk9ecr>SRugD+74;^eDH(}Pi_A6WqQ`!3^<1n66aFJZ#<5X%$<6YU

XhBcXI}C`MuApy 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 cU()pvI`_d}*<&- +cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" -cd "$SAVED" >&- +cd "$SAVED" >/dev/null CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -114,6 +109,7 @@ fi if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` From bb1663394fd8f15e25041b745184bc970fc44c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Wed, 7 Dec 2016 18:21:47 -0500 Subject: [PATCH 633/811] Switch coverage to cover.io --- .travis.yml | 2 +- README.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bf8f8d78..4a7c9290 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,4 +30,4 @@ script: - ./gradlew build coverage -s -i after_success: - - ./gradlew jacocoRootReport coveralls + - bash <(curl -s https://codecov.io/bash) diff --git a/README.adoc b/README.adoc index 9addaff8..418605de 100644 --- a/README.adoc +++ b/README.adoc @@ -1,7 +1,7 @@ = Functional Java image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] -image:https://coveralls.io/repos/github/functionaljava/functionaljava/badge.svg?branch=master["Coverage Status", link="https://coveralls.io/github/functionaljava/functionaljava?branch=master"] +image:https://codecov.io/gh/functionaljava/functionaljava/branch/master/graph/badge.svg["Code Coverage", link="https://codecov.io/gh/functionaljava/functionaljava"] image:https://badges.gitter.im/functionaljava/functionaljava.svg[link="https://gitter.im/functionaljava/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] image::http://www.functionaljava.org/img/logo-600x144.png[] From e95182ad090ff8c1bbdc9d4bd7bf37ba7ae5c4be Mon Sep 17 00:00:00 2001 From: JB Giraudeau Date: Fri, 16 Dec 2016 08:54:46 +0100 Subject: [PATCH 634/811] Change coverage executionData on root project to use wildcard path (#310) otherwise it is skipped because some sub-projects do not have execution Data. Also only aggregate results for published artefacts. Also removed unsused gradle task, --- build.gradle | 41 ++++++++--------------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/build.gradle b/build.gradle index 7d9efae1..1ccd524a 100644 --- a/build.gradle +++ b/build.gradle @@ -20,12 +20,10 @@ buildscript { dependencies { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" classpath "me.tatarka:gradle-retrolambda:$retrolambdaPluginVersion" - classpath 'org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.6.3' } } apply plugin: "jacoco" -apply plugin: 'com.github.kt3k.coveralls' if (JavaVersion.current().isJava8Compatible()) { allprojects { @@ -129,27 +127,24 @@ subprojects { reports { html.enabled = true xml.enabled = true - csv.enabled = false -// html.destination "${buildDir}/jacocoHtml" } } - - task coverage(dependsOn: ["test", "jacocoTestReport"]) << { - - } + task coverage(dependsOn: ["test", "jacocoTestReport"]) << {} } task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { - dependsOn = subprojects.test - sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) - classDirectories = files(subprojects.sourceSets.main.output) - executionData = files(subprojects.jacocoTestReport.executionData) + dependsOn = subprojects.coverage + executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec") + // We only care about coverage of: + def projectForFoverage = ["core", "java8", "quickcheck", "java-core"] + classDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.output) + sourceDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs) + reports { html.enabled = true xml.enabled = true - csv.enabled = false } } @@ -210,23 +205,3 @@ configure(subprojects.findAll { it.name != "props-core" }) { task env << { println System.getenv() } - -task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) { - dependsOn = subprojects.jacocoTestReport - sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) - classDirectories = files(subprojects.sourceSets.main.output) - executionData = files(subprojects.jacocoTestReport.executionData) - reports { - xml.enabled true - xml.destination ="${buildDir}/reports/jacoco/test/jacocoTestReport.xml" - } - // We could remove the following setOnlyIf line, but then - // jacocoRootReport would silently be SKIPPED if something with - // the projectsWithUnitTests is wrong (e.g. a project is missing - // in there). - setOnlyIf { true } -} - -coveralls { - sourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs).files.absolutePath -} From 6ac5f9547dbb1f0ca3777be6b366f256e9943194 Mon Sep 17 00:00:00 2001 From: Shimi Bandiel Date: Mon, 23 Jan 2017 21:22:20 +0200 Subject: [PATCH 635/811] Add NEL.minimum/maximum and safe versions of minimum/maximum for List * added minimum/maximum on NEL && changed impl of minimumOption/maximumOption in List to use it * spaces for tabs --- core/src/main/java/fj/data/List.java | 20 ++++++++++++++++++ core/src/main/java/fj/data/NonEmptyList.java | 22 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index fa82359f..f58fd73f 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1465,6 +1465,16 @@ public final A maximum(final Ord o) { return foldLeft1(o::max); } + /** + * Returns the maximum element in this list according to the given ordering. + * + * @param o An ordering for the elements of the list. + * @return The optional maximum element in this list according to the given ordering. + */ + public final Option maximumOption(final Ord o) { + return NonEmptyList.fromList(this).map(nel -> nel.maximum(o)); + } + /** * Returns the minimum element in this list according to the given ordering. * @@ -1474,6 +1484,16 @@ public final A maximum(final Ord o) { public final A minimum(final Ord o) { return foldLeft1(o::min); } + + /** + * Returns the minimum element in this list according to the given ordering. + * + * @param o An ordering for the elements of the list. + * @return The optional minimum element in this list according to the given ordering. + */ + public final Option minimumOption(final Ord o) { + return NonEmptyList.fromList(this).map(nel -> nel.minimum(o)); + } public final java.util.List toJavaList() { return new java.util.LinkedList<>(toCollection()); diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index da06e0f4..4073476d 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -226,6 +226,28 @@ public NonEmptyList sort(final Ord o) { return nel(list.head(), list.tail()); } + + /** + * Returns the minimum element in this non empty list according to the given ordering. + * + * @param o An ordering for the elements of this non empty list. + * @return The minimum element in this list according to the given ordering. + */ + public final A minimum(final Ord o) { + return foldLeft1(o::min); + } + + /** + * Returns the maximum element in this non empty list according to the given ordering. + * + * @param o An ordering for the elements of this non empty list. + * @return The maximum element in this list according to the given ordering. + */ + public final A maximum(final Ord o) { + return foldLeft1(o::max); + } + + /** * Zips this non empty list with the given non empty list to produce a list of pairs. If this list and the given list * have different lengths, then the longer list is normalised so this function never fails. From 7417c434e29c0f62b15c93f9cfc6dd06c06764d0 Mon Sep 17 00:00:00 2001 From: siro-mateos Date: Tue, 6 Dec 2016 17:45:08 +0100 Subject: [PATCH 636/811] + Added 'Set.lookup', and 'Set.lookupLT', 'Set.lookupGT','Set.lookupLE' and 'Set.lookupGE' from Haskell. + Added some test cases for new Set.lookup* functionality. * Changed 'get(K)' to use 'Set.lookup' instead of 'Set.split', so it can run much faster. --- core/src/main/java/fj/data/Set.java | 123 ++++++++++++++++++++++++ core/src/main/java/fj/data/TreeMap.java | 3 +- core/src/test/java/fj/data/SetTest.java | 16 +++ 3 files changed, 140 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 35b3c683..15207d83 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -515,6 +515,129 @@ public final P3, Option, Set> split(final A a) { } } + /** + * Find element equal to the given one. + * + * @param a An element to compare with. + * @return Some element in this set equal to the given one, or None. + */ + public final Option lookup(final A a) { + Set s = this; + while (true) + if (s.isEmpty()) + return none(); + else { + final A h = s.head(); + final Ordering i = ord.compare(a, h); + if (i == LT) + s = s.l(); + else if (i == GT) + s = s.r(); + else + return some(h); + } + } + + /** + * Find largest element smaller than the given one. + * + * @param a An element to compare with. + * @return Some largest element in this set smaller than the given one, or None. + */ + public final Option lookupLT(final A a) { + Set s = this; + Option r = none(); + while (true) + if (s.isEmpty()) + return r; + else { + final A h = s.head(); + final Ordering i = ord.compare(a, h); + if (i == GT) { + r = some(h); + s = s.r(); + } + else + s = s.l(); + } + } + + /** + * Find smallest element greater than the given one. + * + * @param a An element to compare with. + * @return Some smallest element in this set greater than the given one, or None. + */ + public final Option lookupGT(final A a) { + Set s = this; + Option r = none(); + while (true) + if (s.isEmpty()) + return r; + else { + final A h = s.head(); + final Ordering i = ord.compare(a, h); + if (i == LT) { + r = some(h); + s = s.l(); + } + else + s = s.r(); + } + } + + /** + * Find largest element smaller or equal to the given one. + * + * @param a An element to compare with. + * @return Some largest element in this set smaller or equal to the given one, or None. + */ + public final Option lookupLE(final A a) { + Set s = this; + Option r = none(); + while (true) + if (s.isEmpty()) + return r; + else { + final A h = s.head(); + final Ordering i = ord.compare(a, h); + if (i == LT) + s = s.l(); + else if (i == GT) { + r = some(h); + s = s.r(); + } + else + return some(h); + } + } + + /** + * Find smallest element greater or equal to the given one. + * + * @param a An element to compare with. + * @return Some smallest element in this set greater or equal to the given one, or None. + */ + public final Option lookupGE(final A a) { + Set s = this; + Option r = none(); + while (true) + if (s.isEmpty()) + return r; + else { + final A h = s.head(); + final Ordering i = ord.compare(a, h); + if (i == LT) { + r = some(h); + s = s.l(); + } + else if (i == GT) + s = s.r(); + else + return some(h); + } + } + /** * Returns true if this set is a subset of the given set. * diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index f663ab09..e5a3f06f 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -129,8 +129,7 @@ public static TreeMap arrayTreeMap(final Ord keyOrd, final P2 get(final K k) { - final Option>> x = tree.split(p(k, Option.none()))._2(); - return x.bind(P2.__2()); + return tree.lookup(p(k, Option.none())).bind(P2::_2); } /** diff --git a/core/src/test/java/fj/data/SetTest.java b/core/src/test/java/fj/data/SetTest.java index 78084bb4..cdf2519c 100644 --- a/core/src/test/java/fj/data/SetTest.java +++ b/core/src/test/java/fj/data/SetTest.java @@ -2,6 +2,8 @@ import org.junit.Test; +import static fj.data.Option.none; +import static fj.data.Option.some; import static fj.Ord.intOrd; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; @@ -23,4 +25,18 @@ public void testString() { assertThat(s.toString(), equalTo("Set(1,2,3)")); } + @Test + public void testLookups() { + Set s = Set.set(intOrd, 5, 1, 7, 8); + assertThat(s.lookup(7), equalTo(some(7))); + assertThat(s.lookup(4), equalTo(none())); + assertThat(s.lookupLT(6), equalTo(some(5))); + assertThat(s.lookupLT(1), equalTo(none())); + assertThat(s.lookupGT(5), equalTo(some(7))); + assertThat(s.lookupGT(9), equalTo(none())); + assertThat(s.lookupLE(8), equalTo(some(8))); + assertThat(s.lookupLE(0), equalTo(none())); + assertThat(s.lookupGE(8), equalTo(some(8))); + assertThat(s.lookupGE(9), equalTo(none())); + } } From 443e01a12f2732e94f4b19d485dfb95cebd70075 Mon Sep 17 00:00:00 2001 From: siro-mateos Date: Mon, 12 Dec 2016 23:27:18 +0100 Subject: [PATCH 637/811] Force strict evaluation in 'TreeMap.map'. --- core/src/main/java/fj/data/TreeMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index e5a3f06f..cd111d06 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -359,7 +359,7 @@ public P3, Option, TreeMap> splitLookup(final K k) { */ @SuppressWarnings("unchecked") public TreeMap map(final F f) { - final F>, P2>> g = P2.map2_(F1Functions.mapOption(f)); + final F>, P2>> g = compose(p2 -> p(p2._1(), p2._2()), P2.map2_(F1Functions.mapOption(f))); final F>> coord = flip(P.>p2()).f(Option.none()); final Ord o = tree.ord().contramap(coord); return new TreeMap<>(tree.map(TreeMap.ord(o), g)); From dd8451dd26d5ca9406e173b1ebaae02a74ae03e6 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 27 Feb 2017 21:05:56 +0100 Subject: [PATCH 638/811] Fix typo. sofMemo -> softMemo --- core/src/main/java/fj/P.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index b0f3a31d..6d174ed7 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -61,7 +61,7 @@ public static P1 weakMemo(F0 f) { * and at each subsequent call if and only if the reference have been garbage collected * due of shortage of memory (ie. to avoid OutOfMemoryErrors). */ - public static P1 sofMemo(F0 f) { + public static P1 softMemo(F0 f) { return new P1.SoftReferenceMemo<>(f); } From 9ca5ce35e7f83bbedfd707e8d67f1c7fc477ffdf Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 12:47:20 +0200 Subject: [PATCH 639/811] Update to gradle 3.4 --- gradle/wrapper/gradle-wrapper.jar | Bin 53637 -> 54208 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 68 +++++++++++++---------- gradlew.bat | 14 ++--- props-core-scalacheck/build.gradle | 10 +--- 5 files changed, 48 insertions(+), 48 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 05ef575b0cd0173fc735f2857ce4bd594ce4f6bd..7f9251933fd4846b7f2c971bb2c5f6a575ad3e3a 100644 GIT binary patch delta 24962 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 F{|CS?UfTcw delta 24405 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 23175860..aa8a01af 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Dec 06 21:53:19 EST 2016 +#Mon Feb 27 21:23:04 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.4-bin.zip diff --git a/gradlew b/gradlew index 9d82f789..4453ccea 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index aec99730..e95643d6 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index 4d1a04e9..02f3652a 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -4,16 +4,12 @@ archivesBaseName = "${project.projectName}-${project.name}" apply plugin: 'scala' ext { - scalaVersion = "2.11.7" + scalaVersion = "2.11.8" scalacheckScalaVersion = "2.11" - scalacheckVersion = "1.12.4" + scalacheckVersion = "1.12.5" signModule = true } -tasks.withType(ScalaCompile) { - scalaCompileOptions.useAnt = false -} - dependencies { compile project(":core") compile "org.scala-lang:scala-library:$scalaVersion" @@ -22,8 +18,6 @@ dependencies { testCompile dependencyJunit } -sourceCompatibility = "1.7" - performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) From 6fa8bce2008c73d5995af20f6f41f60908e2ca6d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 23 Oct 2016 12:49:34 +0200 Subject: [PATCH 640/811] add "_1.8" suffix to artifact cross-built for java 8. Use JDK7 as retrolambda target --- .travis.yml | 1 - build.gradle | 8 ++++---- java-core/build.gradle | 2 ++ java8/build.gradle | 4 +++- lib.gradle | 2 ++ quickcheck/build.gradle | 4 ++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a7c9290..8f3091d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,6 @@ before_script: - sudo service x11-common stop || true script: - - jdk_switcher use openjdk6 && export JAVA6_HOME=$JAVA_HOME - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME - ./gradlew build coverage -s -i diff --git a/build.gradle b/build.gradle index 1ccd524a..5bedc102 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ ext { buildscript { ext { - uptodateVersion = "1.6.0" - retrolambdaPluginVersion = "3.2.5" + uptodateVersion = "1.6.2" + retrolambdaPluginVersion = "3.3.1" retrolambdaVersion = "2.3.0" } @@ -77,8 +77,8 @@ allprojects { displayCompilerWarnings = true newJdkEnvVar = "JAVA8_HOME" - oldJdkEnvVar = "JAVA6_HOME" - retroLambdaTarget = JavaVersion.VERSION_1_6 + oldJdkEnvVar = "JAVA7_HOME" + retroLambdaTarget = JavaVersion.VERSION_1_7 } repositories { diff --git a/java-core/build.gradle b/java-core/build.gradle index 88e9a25f..6a92cc28 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -1,5 +1,6 @@ archivesBaseName = "${project.projectName}-${project.name}" +configureAllRetroLambda() ext { signModule = true @@ -13,4 +14,5 @@ dependencies { performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) + uploadArchives.enabled = true diff --git a/java8/build.gradle b/java8/build.gradle index 88e9a25f..d6d4c485 100644 --- a/java8/build.gradle +++ b/java8/build.gradle @@ -13,4 +13,6 @@ dependencies { performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) -uploadArchives.enabled = true +if (!useRetroLambda) { + uploadArchives.enabled = true +} diff --git a/lib.gradle b/lib.gradle index 28be5e34..253ed251 100644 --- a/lib.gradle +++ b/lib.gradle @@ -94,6 +94,8 @@ void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String ol dependencies { retrolambdaConfig "net.orfjackal.retrolambda:retrolambda:$retrolambdaVersion" } + } else { + project.archivesBaseName = "${project.archivesBaseName}_1.8" } } diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 4d3a25be..45e379da 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -3,10 +3,10 @@ ext { signModule = true } -configureAllRetroLambda() - archivesBaseName = "${project.projectName}-${project.name}" +configureAllRetroLambda() + dependencies { compile project(":core") compile dependencyJunit From 3dcdf401182899611608537dd9862f06eed18062 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 27 Feb 2017 21:18:51 +0100 Subject: [PATCH 641/811] java-core module should be publish with retrolambda processing. --- java-core/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java-core/build.gradle b/java-core/build.gradle index 6a92cc28..032c2ca5 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -16,3 +16,5 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true + +configureAllRetroLambda() \ No newline at end of file From d1b15e16f8287b1265efc6516801aba29abdd290 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 27 Feb 2017 21:25:41 +0100 Subject: [PATCH 642/811] upgrade to latest retrolambda version. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 5bedc102..b9597063 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,8 @@ ext { buildscript { ext { uptodateVersion = "1.6.2" - retrolambdaPluginVersion = "3.3.1" - retrolambdaVersion = "2.3.0" + retrolambdaPluginVersion = "3.5.0" + retrolambdaVersion = "2.5.1" } repositories { From 0759750518cfbd920170d75c73c199d80b5bb49e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 17 Mar 2017 00:43:54 +1000 Subject: [PATCH 643/811] Added release notes for 4.7 --- etc/release-notes/release-notes-4.7.adoc | 44 ++++++++++++++++++++---- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/etc/release-notes/release-notes-4.7.adoc b/etc/release-notes/release-notes-4.7.adoc index 3c1b265f..6f5958de 100644 --- a/etc/release-notes/release-notes-4.7.adoc +++ b/etc/release-notes/release-notes-4.7.adoc @@ -1,28 +1,58 @@ = Release 4.7 -Proposed release: September 2016 +Released: unknown, potentially 25 March 2017 == Enhancements -* TODO. +* Added Hash Array Mapped Trie (#284). +* Improve performance of List#groupBy via a mutable buffer (#288). +* Avoid unnecessary wrapping of F0 into P1.lazy where applicable. Use static P factories for this (#284). +* Added semigroup constraint to List.traverseValidation (#287). +* Added first class fold for either (catamorphism) (#284). +* Added first class fold for Option (catamorphism) (#284). +* Added optimisable definitions for Equal (#284). +* Added uncurried version of foldRight, foldLeft and append to NonEmptyList (#284). +* Added optimisable definitions for Monoid and Semigroup (#284). +* Improved performance of List.minimum and maximum by using uncurried Ord.max and Ord.min (#284). +* Removed deprecation of Monoid, Ord and Semigroup constructors for non Java 8 versions (#284). +* Added safe List minimumOption and maximumOption and NonEmptyList minimum and maximum. +* Added Set.lookup, Set.lookupLT, Set.lookupGT, Set.lookupLE and Set.lookupGE from Haskell (#305). == Fixes -* TODO. +* Make Stream conversions respect laziness (#284). +* Fixed Ord#isGreaterThan(A)/isLesserThan(A) not using strict inequality (#293). +* Correctly convert Option.some(null) to Optional (#284). +* Fixed override in P.p(A) (#284). +* Avoid unnecessary currying in uncurried version of foldRight (#284). == Internal -* TODO. +* Deprecated unsafe Ord instance and List#groupBy without an Ord parameter (#290). +* Added tests for Strings class (#295). +* Use more method references (#284). +* Converted memoisation tests from JUnit to PropertyTestRunner (#284) for hard memoisation. +* Improved implementation of P1#_1 method (#284). +* Make use of weak memoisation explicit (#284). +* Enable backport of default methods using Retro Lambda (#284). +* Upgrade to Gradle 2.14.1 (#310). +* Switch from Coveralls to cover.io (#308). +* Force strict evaluation in TreeMap.map (#309). == Breaking Changes -* TODO. +* none. == Documentation -* TODO. +* none. == Contributors -* TODO. +* Jean-Baptiste Giradeau +* Mark Perry +* Gabor Liptak +* Shimi Bandiel +* Siro Mateos + From 1faf5b9184d82cca5929747f5cfb4e67100752ab Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 25 Mar 2017 18:12:58 +0100 Subject: [PATCH 644/811] Make retrolambda target java 6. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b9597063..6c417b5c 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ allprojects { newJdkEnvVar = "JAVA8_HOME" oldJdkEnvVar = "JAVA7_HOME" - retroLambdaTarget = JavaVersion.VERSION_1_7 + retroLambdaTarget = JavaVersion.VERSION_1_6 } repositories { From 4d36fcddcf9899191899d83ec80546e41c528bac Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 27 Mar 2017 20:58:13 +0200 Subject: [PATCH 645/811] Update gradle wrapper to 3.4.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 54208 -> 54208 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f9251933fd4846b7f2c971bb2c5f6a575ad3e3a..2dcd00d1ccd90b5b3d39e0da139893d5e7651ae4 100644 GIT binary patch delta 957 zcmYL{YeR2CHVzW+1q!^`jYJm-H7=RM~PJGfy7Cok7> zNeV)wQqo{Ew8@oH9vWZXgMDqKMn%VL(_E8?{Lh&9j3b{D5MBlRSSP@x63G?|LQ7=R zXym1+B#^RI@V5MX4V^6my6OdBhR2kT7)&kk9S8Qi$YUoQ2bx0 zV6pcgc*9!(zV=$cO(RyYd!z~!`6|IGAIm@X8BxppIw11RKJ7@MYKvt{go9-WoN4UqYjOBjCPNKHP86$Bs>NR6*{@nz*arSU)$7?a}Pt?i@jg-GC Ljc`HKKC%BF8^&kK delta 957 zcmYL{T}YEr7{|}{s#}wpQ-d_jR9Fd>C1N%Epig46HJg#8PIG48WDCbiFA}1gE>cfK z(WF3YBVkdCA`!H0x^Fj?KB-8hM7l}JEKurw|7Y06%kTF*=YJ08J?He>xPBWa*J-%8 zG(x0OB5TfVlPje>)UW4SX4;C&)6##KrcEO9KQrHy+h)t=1O!(Bzt#zG=80sB1ffN; zNiuISagU*j+I6ZxPFoDWlT5kMd z1vR)-*$Mn5OQaJY9$!r*gedq=rxA(M$ima0FI7N*TISV)6<#%H_m+UOUJbb0cM$CG zvHb5C^?t2zfV9i60>}IYa7Tc#Gf;|pHgFz19n^y_gGO*==oolCR0e(x)r0%Pr@-DY zo1Z*%0(H|+9XLM3a+=5?)b}GS_a|~3wK2*Vj#i;wGtB1Sijf;(54U!t7USMntsGTL O`KwY37ep Date: Mon, 27 Mar 2017 20:58:59 +0200 Subject: [PATCH 646/811] java-core build: remove duplicate call of configureAllRetroLambda() --- java-core/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/java-core/build.gradle b/java-core/build.gradle index 032c2ca5..3b636072 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -1,6 +1,5 @@ archivesBaseName = "${project.projectName}-${project.name}" -configureAllRetroLambda() ext { signModule = true From 8fb59b9f1ed3771296c4a164e5cde4439a4e82c4 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 27 Mar 2017 21:17:53 +0200 Subject: [PATCH 647/811] 4.7 release. --- README.adoc | 22 +++++++++++----------- build.gradle | 2 +- etc/release-notes/release-notes-4.7.adoc | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.adoc b/README.adoc index 418605de..6c5d3c1e 100644 --- a/README.adoc +++ b/README.adoc @@ -31,16 +31,16 @@ The recommended way to download and use the project is through your build tool. The Functional Java artifact is published to Maven Central using the group `org.functionaljava` with three published artifacts: -* the core library (`functionaljava`) +* the core library (`functionaljava` or `functionaljava_1.8` if you use Java 8+) * Java 8 specific support (`functionaljava-java8`) -* property based testing (`functionaljava-quickcheck`) +* property based testing (`functionaljava-quickcheck` or `functionaljava-quickcheck_1.8` if you use Java 8+) -The latest stable version is `4.6`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.7`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.6" -compile "org.functionaljava:functionaljava-java8:4.6" -compile "org.functionaljava:functionaljava-quickcheck:4.6" -compile "org.functionaljava:functionaljava-java-core:4.6" +compile "org.functionaljava:functionaljava:4.7" +compile "org.functionaljava:functionaljava-java8:4.7" +compile "org.functionaljava:functionaljava-quickcheck:4.7" +compile "org.functionaljava:functionaljava-java-core:4.7" ---- and in Maven: @@ -48,22 +48,22 @@ and in Maven: org.functionaljava functionaljava - 4.6 + 4.7 org.functionaljava functionaljava-java8 - 4.6 + 4.7 org.functionaljava functionaljava-quickcheck - 4.6 + 4.7 org.functionaljava functionaljava-java-core - 4.6 + 4.7 ---- diff --git a/build.gradle b/build.gradle index 6c417b5c..c0152d08 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.7" snapshotAppendix = "-SNAPSHOT" diff --git a/etc/release-notes/release-notes-4.7.adoc b/etc/release-notes/release-notes-4.7.adoc index 6f5958de..428a0726 100644 --- a/etc/release-notes/release-notes-4.7.adoc +++ b/etc/release-notes/release-notes-4.7.adoc @@ -1,7 +1,7 @@ = Release 4.7 -Released: unknown, potentially 25 March 2017 +Released: 27 March 2017 == Enhancements From 0ff3a9c27425736994f6f336aec68e40b6183884 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 27 Mar 2017 21:46:59 +0200 Subject: [PATCH 648/811] Prepare next iteration. --- build.gradle | 6 ++--- etc/release-notes/release-notes-4.8.adoc | 28 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 etc/release-notes/release-notes-4.8.adoc diff --git a/build.gradle b/build.gradle index c0152d08..04209664 100644 --- a/build.gradle +++ b/build.gradle @@ -46,12 +46,12 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.7" + isSnapshot = true + fjBaseVersion = "4.8" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.6" + fjConsumeVersion = "4.7" signModule = false useRetroLambda = false diff --git a/etc/release-notes/release-notes-4.8.adoc b/etc/release-notes/release-notes-4.8.adoc new file mode 100644 index 00000000..22dbc552 --- /dev/null +++ b/etc/release-notes/release-notes-4.8.adoc @@ -0,0 +1,28 @@ + += Release + +Proposed release: + +== Enhancements + +* TODO. + +== Fixes + +* TODO. + +== Internal + +* TODO. + +== Breaking Changes + +* TODO. + +== Documentation + +* TODO. + +== Contributors + +* TODO. From 07f94fa172d9465de69abea188ecbdbc73c09078 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Mon, 1 May 2017 21:44:09 -0500 Subject: [PATCH 649/811] Fixed a bug in the NonEmptyList Semigroup implementation that resulted in the same NonEmptyList appended to itself. --- core/src/main/java/fj/Semigroup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 74d7de9b..16b0d130 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -534,7 +534,7 @@ public static Semigroup> nonEmptyListSemigroup() { return semigroupDef(new Definition>() { @Override public NonEmptyList append(NonEmptyList a1, NonEmptyList a2) { - return a1.append(a1); + return a1.append(a2); } @Override From 405c3ec31351bf8518bfec8b91bf8be66056991b Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Mon, 1 May 2017 21:44:46 -0500 Subject: [PATCH 650/811] Added Scalacheck Arbitrary implementations for Natural and NonEmptyList. --- .../main/scala/fj/data/ArbitraryNatural.scala | 13 +++++++++++++ .../scala/fj/data/ArbitraryNonEmptyList.scala | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 props-core-scalacheck/src/main/scala/fj/data/ArbitraryNatural.scala create mode 100644 props-core-scalacheck/src/main/scala/fj/data/ArbitraryNonEmptyList.scala diff --git a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryNatural.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryNatural.scala new file mode 100644 index 00000000..4210eef7 --- /dev/null +++ b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryNatural.scala @@ -0,0 +1,13 @@ +package fj.data + +import org.scalacheck.Arbitrary + +/** + * A Scalacheck [[Arbitrary]] for [[Natural]]. + */ +object ArbitraryNatural { + + implicit def arbitraryNatural: Arbitrary[Natural] = + Arbitrary(Arbitrary.arbBigInt.arbitrary.map(_.abs).map(bi => Natural.natural(bi.bigInteger).some())) + +} diff --git a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryNonEmptyList.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryNonEmptyList.scala new file mode 100644 index 00000000..2258ba9b --- /dev/null +++ b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryNonEmptyList.scala @@ -0,0 +1,16 @@ +package fj.data + +import fj.data.NonEmptyList.nel +import org.scalacheck.Arbitrary.arbitrary +import org.scalacheck.{Arbitrary, Gen} + +/** + * A Scalacheck [[Arbitrary]] for [[NonEmptyList]]. + */ +object ArbitraryNonEmptyList { + implicit def arbitraryNonEmptyList[A](implicit a: Arbitrary[A]): Arbitrary[NonEmptyList[A]] = + Arbitrary(nelOf(arbitrary[A])) + + def nelOf[A](g: => Gen[A]): Gen[NonEmptyList[A]] = + Gen.nonEmptyListOf(g).map(l => l.tail.foldRight(nel(l.head))((x, n) => n.cons(x))) +} From ef811305b0e60e8b4dd5e42c601c8b3cbfed1fe7 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Tue, 2 May 2017 00:15:25 -0500 Subject: [PATCH 651/811] Added unit test coverage for Semigroup implementations. The StringBuffer and StringBuilder tests fail because both of those types are mutable. The IO test fails because the ArbitraryIO implementation does not implement equals. --- .../src/main/scala/fj/data/ArbitraryIO.scala | 22 +++ .../src/test/scala/fj/CheckSemigroup.scala | 152 ++++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala create mode 100644 props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala diff --git a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala new file mode 100644 index 00000000..7667840b --- /dev/null +++ b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala @@ -0,0 +1,22 @@ +package fj.data + +import org.scalacheck.Arbitrary + +/** + * + */ +object ArbitraryIO { + + implicit def arbitraryIO[T](implicit arbT: Arbitrary[T]): Arbitrary[IO[T]] = + Arbitrary(arbT.arbitrary.map(t => new IO[T]() { + + override def run(): T = t + + override def toString: String = t.toString + + override def hashCode(): Int = t.hashCode() + + override def equals(obj: scala.Any): Boolean = ??? + })) + +} diff --git a/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala b/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala new file mode 100644 index 00000000..933bedc6 --- /dev/null +++ b/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala @@ -0,0 +1,152 @@ +package fj + +import fj.ArbitraryP._ +import fj.ArbitraryUnit.arbitraryUnit +import fj.Ord.intOrd +import fj.data.ArbitraryArray.arbitraryArray +import fj.data.ArbitraryIO.arbitraryIO +import fj.data.ArbitraryList.arbitraryList +import fj.data.ArbitraryNatural.arbitraryNatural +import fj.data.ArbitraryNonEmptyList.arbitraryNonEmptyList +import fj.data.ArbitraryOption.arbitraryOption +import fj.data.ArbitrarySet.arbitrarySet +import fj.data.ArbitraryStream.arbitraryStream +import org.scalacheck.Arbitrary._ +import org.scalacheck.Prop._ +import org.scalacheck.{Arbitrary, Properties} + +/** + * Scalacheck [[Properties]] for [[Semigroup]] implementations. + * + * @param s a Semigroup implementation. + * @param desc a description of the Semigroup implementation. + * @param arbitrary a Scalacheck [[Arbitrary]] implementation for the Semigroup's type. + * @tparam T the type to which the Semigroup applies. + */ +case class SemigroupProperties[T](s: Semigroup[T], desc: String)(implicit val arbitrary: Arbitrary[T]) extends Properties(desc) { + + + property("sum(x,y)") = forAll((x: T, y: T, z: T) => + s.sum(s.sum(x, y), z) == s.sum(x, s.sum(y, z))) + + property("sum()") = forAll((x: T, y: T, z: T) => { + val sf = s.sum() + sf.f(sf.f(x).f(y)).f(z) == sf.f(x).f(sf.f(y).f(z)) + }) + + property("dual()") = forAll((x: T, y: T, z: T) => { + val sd = s.dual() + sd.sum(sd.sum(x, y), z) == sd.sum(x, sd.sum(y, z)) + }) + + property("sum(x)") = forAll((x: T, y: T) => + s.sum(x).f(y) == s.sum(x, y)) + +} + + +/** + * + */ +object CheckSemigroup extends Properties("Semigroup") { + + + def idInt(n: Int): java.lang.Integer = n + + implicit def oi: Ord[Int] = intOrd.contramap(idInt _) + + implicit lazy val arbJavaBigDecimal: Arbitrary[java.math.BigDecimal] = Arbitrary( + Arbitrary.arbLong.arbitrary.map(l => new java.math.BigDecimal(l)) + ) + + implicit lazy val arbJavaBigInteger: Arbitrary[java.math.BigInteger] = Arbitrary( + Arbitrary.arbBigInt.arbitrary.map(_.bigInteger) + ) + + implicit lazy val arbJavaInteger: Arbitrary[Integer] = Arbitrary( + Arbitrary.arbInt.arbitrary.map(i => i) + ) + + implicit lazy val arbJavaLong: Arbitrary[java.lang.Long] = Arbitrary( + Arbitrary.arbLong.arbitrary.map(i => i) + ) + + implicit lazy val arbJavaBoolean: Arbitrary[java.lang.Boolean] = Arbitrary( + Arbitrary.arbBool.arbitrary.map(b => b) + ) + + implicit lazy val arbStringBuilder: Arbitrary[java.lang.StringBuilder] = Arbitrary( + Arbitrary.arbString.arbitrary.map(new java.lang.StringBuilder(_)) + ) + + implicit lazy val arbStringBuffer: Arbitrary[StringBuffer] = Arbitrary( + Arbitrary.arbString.arbitrary.map(new StringBuffer(_)) + ) + + include(SemigroupProperties(Semigroup.arraySemigroup[Int](), "arraySemigroup()")) + + include(SemigroupProperties(Semigroup.bigdecimalAdditionSemigroup, "bigdecimalAdditionSemigroup")) + include(SemigroupProperties(Semigroup.bigdecimalMultiplicationSemigroup, "bigdecimalMultiplicationSemigroup")) + include(SemigroupProperties(Semigroup.bigDecimalMaximumSemigroup, "bigDecimalMaximumSemigroup")) + include(SemigroupProperties(Semigroup.bigDecimalMinimumSemigroup, "bigDecimalMinimumSemigroup")) + + include(SemigroupProperties(Semigroup.bigintAdditionSemigroup, "bigintAdditionSemigroup")) + include(SemigroupProperties(Semigroup.bigintMultiplicationSemigroup, "bigintMultiplicationSemigroup")) + include(SemigroupProperties(Semigroup.bigintMaximumSemigroup, "bigintMaximumSemigroup")) + include(SemigroupProperties(Semigroup.bigintMinimumSemigroup, "bigintMinimumSemigroup")) + + include(SemigroupProperties(Semigroup.conjunctionSemigroup, "conjunctionSemigroup")) + include(SemigroupProperties(Semigroup.disjunctionSemigroup, "disjunctionSemigroup")) + include(SemigroupProperties(Semigroup.exclusiveDisjunctionSemiGroup, "exclusiveDisjunctionSemiGroup")) + + include(SemigroupProperties(Semigroup.firstOptionSemigroup[Int](), "firstOptionSemigroup()")) + include(SemigroupProperties(Semigroup.firstSemigroup[Int](), "firstSemigroup()")) + + include(SemigroupProperties(Semigroup.intAdditionSemigroup, "intAdditionSemigroup")) + include(SemigroupProperties(Semigroup.intMultiplicationSemigroup, "intMultiplicationSemigroup")) + include(SemigroupProperties(Semigroup.intMaximumSemigroup, "intMaximumSemigroup")) + include(SemigroupProperties(Semigroup.intMinimumSemigroup, "intMinimumSemigroup")) + + include(SemigroupProperties(Semigroup.ioSemigroup[String](Semigroup.stringSemigroup), "ioSemigroup(Semigroup)")) + + include(SemigroupProperties(Semigroup.lastOptionSemigroup[Int](), "lastOptionSemigroup()")) + include(SemigroupProperties(Semigroup.lastSemigroup[Int](), "lastSemigroup()")) + + include(SemigroupProperties(Semigroup.longAdditionSemigroup, "longAdditionSemigroup")) + include(SemigroupProperties(Semigroup.longMultiplicationSemigroup, "longMultiplicationSemigroup")) + include(SemigroupProperties(Semigroup.longMaximumSemigroup, "longMaximumSemigroup")) + include(SemigroupProperties(Semigroup.longMinimumSemigroup, "longMinimumSemigroup")) + + + include(SemigroupProperties(Semigroup.listSemigroup[Int], "listSemigroup")) + + include(SemigroupProperties(Semigroup.naturalAdditionSemigroup, "naturalAdditionSemigroup")) + include(SemigroupProperties(Semigroup.naturalMaximumSemigroup, "naturalMaximumSemigroup")) + include(SemigroupProperties(Semigroup.naturalMinimumSemigroup, "naturalMinimumSemigroup")) + include(SemigroupProperties(Semigroup.naturalMultiplicationSemigroup, "naturalMultiplicationSemigroup")) + + include(SemigroupProperties(Semigroup.nonEmptyListSemigroup[Int], "nonEmptyListSemigroup")) + + include(SemigroupProperties(Semigroup.p1Semigroup(Semigroup.intAdditionSemigroup), "p1Semigroup(Semigroup)")) + include(SemigroupProperties(Semigroup.p2Semigroup(Semigroup.intAdditionSemigroup, Semigroup.stringSemigroup), "p2Semigroup(Semigroup,Semigroup)")) + + include(SemigroupProperties(Semigroup.semigroup[Int](new F2[Int, Int, Int] { + def f(x: Int, y: Int): Int = x + y + }), "semigroup(F)")) + + include(SemigroupProperties(Semigroup.semigroup[Int](new F[Int, F[Int, Int]] { + def f(x: Int): F[Int, Int] = (y: Int) => x + y + }), "semigroup(F>)")) + + include(SemigroupProperties(Semigroup.setSemigroup[Int](), "setSemigroup()")) + include(SemigroupProperties(Semigroup.streamSemigroup[Int](), "streamSemigroup")) + + include(SemigroupProperties(Semigroup.stringSemigroup, "stringSemigroup")) + include(SemigroupProperties(Semigroup.stringBufferSemigroup, "stringBufferSemigroup")) + include(SemigroupProperties(Semigroup.stringBuilderSemigroup, "stringBuilderSemigroup")) + + + include(SemigroupProperties(Semigroup.unitSemigroup, "unitSemigroup")) + + +} From a8e979fc78e0cdd4e33e86d32b0394edcc065e47 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Tue, 2 May 2017 22:51:29 -0500 Subject: [PATCH 652/811] Fixed the ArbitraryIO implementation and created a Properties object for testing the IO semigroup. --- .../src/main/scala/fj/data/ArbitraryIO.scala | 14 ++--- .../src/test/scala/fj/CheckSemigroup.scala | 57 ++++++++++++++++++- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala index 7667840b..aca5cbd1 100644 --- a/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala +++ b/props-core-scalacheck/src/main/scala/fj/data/ArbitraryIO.scala @@ -7,16 +7,12 @@ import org.scalacheck.Arbitrary */ object ArbitraryIO { - implicit def arbitraryIO[T](implicit arbT: Arbitrary[T]): Arbitrary[IO[T]] = - Arbitrary(arbT.arbitrary.map(t => new IO[T]() { - - override def run(): T = t - override def toString: String = t.toString + private case class ArbIO[T](value: T) extends IO[T] { + override def run(): T = value + } - override def hashCode(): Int = t.hashCode() - - override def equals(obj: scala.Any): Boolean = ??? - })) + implicit def arbitraryIO[T](implicit arbT: Arbitrary[T]): Arbitrary[IO[T]] = + Arbitrary(arbT.arbitrary.map(ArbIO(_))) } diff --git a/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala b/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala index 933bedc6..1305efe9 100644 --- a/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala +++ b/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala @@ -11,12 +11,13 @@ import fj.data.ArbitraryNonEmptyList.arbitraryNonEmptyList import fj.data.ArbitraryOption.arbitraryOption import fj.data.ArbitrarySet.arbitrarySet import fj.data.ArbitraryStream.arbitraryStream +import fj.data.IO import org.scalacheck.Arbitrary._ import org.scalacheck.Prop._ import org.scalacheck.{Arbitrary, Properties} /** - * Scalacheck [[Properties]] for [[Semigroup]] implementations. + * Scalacheck [[Properties]] parameterized for [[Semigroup]] implementations. * * @param s a Semigroup implementation. * @param desc a description of the Semigroup implementation. @@ -44,9 +45,59 @@ case class SemigroupProperties[T](s: Semigroup[T], desc: String)(implicit val ar } +/** + * A specialized Scalacheck [[Properties]] object for testing the [[Semigroup.ioSemigroup()]] method. + */ +object CheckIOSemigroup extends Properties("ioSemigroup") { + + val s = Semigroup.ioSemigroup(Semigroup.stringSemigroup) + + property("sum(x,y)") = forAll((x: IO[String], y: IO[String], z: IO[String]) => + s.sum(s.sum(x, y), z).run() == s.sum(x, s.sum(y, z)).run()) + + property("sum()") = forAll((x: IO[String], y: IO[String], z: IO[String]) => { + val sf = s.sum() + sf.f(sf.f(x).f(y)).f(z).run() == sf.f(x).f(sf.f(y).f(z)).run() + }) + + property("dual()") = forAll((x: IO[String], y: IO[String], z: IO[String]) => { + val sd = s.dual() + sd.sum(sd.sum(x, y), z).run() == sd.sum(x, sd.sum(y, z)).run() + }) + + property("sum(x)") = forAll((x: IO[String], y: IO[String]) => + s.sum(x).f(y).run() == s.sum(x, y).run()) + +} + +object CheckStringBuilder extends Properties("stringBuilderSemigroup") { + + val s: Semigroup[java.lang.StringBuilder] = Semigroup.stringBuilderSemigroup + + implicit def toStringBuilder(str: String): java.lang.StringBuilder = new java.lang.StringBuilder(str) + + property("sum(x,y)") = forAll((x: String, y: String, z: String) => + s.sum(s.sum(x, y), z).toString == s.sum(x, s.sum(y, z)).toString + ) + + property("sum()") = forAll((x: String, y: String, z: String) => { + val sf = s.sum() + sf.f(sf.f(x).f(y)).f(z).toString == sf.f(x).f(sf.f(y).f(z.toString)) + }) + + property("dual()") = forAll((x: String, y: String, z: String) => { + val sd = s.dual() + sd.sum(sd.sum(x, y), z).toString == sd.sum(x, sd.sum(y, z).toString) + }) + + property("sum(x)") = forAll((x: String, y: String) => + s.sum(x).f(y).toString == s.sum(x, y).toString) + +} + /** - * + * A Scalacheck [[Properties]] object that aggregates the tests for all [[Semigroup]] implementations. */ object CheckSemigroup extends Properties("Semigroup") { @@ -107,7 +158,7 @@ object CheckSemigroup extends Properties("Semigroup") { include(SemigroupProperties(Semigroup.intMaximumSemigroup, "intMaximumSemigroup")) include(SemigroupProperties(Semigroup.intMinimumSemigroup, "intMinimumSemigroup")) - include(SemigroupProperties(Semigroup.ioSemigroup[String](Semigroup.stringSemigroup), "ioSemigroup(Semigroup)")) + include(CheckIOSemigroup) include(SemigroupProperties(Semigroup.lastOptionSemigroup[Int](), "lastOptionSemigroup()")) include(SemigroupProperties(Semigroup.lastSemigroup[Int](), "lastSemigroup()")) From aa4de33faacb59c7dd24092fe3d3a65ca3a4c4d9 Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Tue, 9 May 2017 22:47:43 -0500 Subject: [PATCH 653/811] Added working tests coverage for the StringBuffer and StringBuilder semigroup implementations. Added the Semigroup tests to the list of Scalacheck test suite. --- .../src/test/scala/fj/CheckSemigroup.scala | 33 ++++++++++++------- .../src/test/scala/fj/Tests.scala | 30 +++++++++-------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala b/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala index 1305efe9..8c9fe547 100644 --- a/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala +++ b/props-core-scalacheck/src/test/scala/fj/CheckSemigroup.scala @@ -70,27 +70,36 @@ object CheckIOSemigroup extends Properties("ioSemigroup") { } -object CheckStringBuilder extends Properties("stringBuilderSemigroup") { - - val s: Semigroup[java.lang.StringBuilder] = Semigroup.stringBuilderSemigroup +/** + * A [[Properties]] implementation for testing [[Semigroup]] implementations that + * apply to mutable builder style classes such as [[java.lang.StringBuilder]] and + * [[java.lang.StringBuffer]]. + * + * @param s a Semigroup implementation to test. + * @param desc a description of the Semigroup implementation under test. + * @param conversion a function that converts a value of type T to a new instance of type S. + * @tparam T the type that the builder constructs. + * @tparam S the type to which the Semigroup applies. + */ +case class CheckMutableBuilder[S, T](s: Semigroup[S], desc: String, conversion: T => S)(implicit val arbitrary: Arbitrary[T]) extends Properties(desc) { - implicit def toStringBuilder(str: String): java.lang.StringBuilder = new java.lang.StringBuilder(str) + implicit def toBuilder(t: T): S = conversion(t) - property("sum(x,y)") = forAll((x: String, y: String, z: String) => + property("sum(x,y)") = forAll((x: T, y: T, z: T) => s.sum(s.sum(x, y), z).toString == s.sum(x, s.sum(y, z)).toString ) - property("sum()") = forAll((x: String, y: String, z: String) => { + property("sum()") = forAll((x: T, y: T, z: T) => { val sf = s.sum() - sf.f(sf.f(x).f(y)).f(z).toString == sf.f(x).f(sf.f(y).f(z.toString)) + sf.f(sf.f(x).f(y)).f(z).toString == sf.f(x).f(sf.f(y).f(z)).toString }) - property("dual()") = forAll((x: String, y: String, z: String) => { + property("dual()") = forAll((x: T, y: T, z: T) => { val sd = s.dual() - sd.sum(sd.sum(x, y), z).toString == sd.sum(x, sd.sum(y, z).toString) + sd.sum(sd.sum(x, y), z).toString == sd.sum(x, sd.sum(y, z)).toString }) - property("sum(x)") = forAll((x: String, y: String) => + property("sum(x)") = forAll((x: T, y: T) => s.sum(x).f(y).toString == s.sum(x, y).toString) } @@ -193,8 +202,8 @@ object CheckSemigroup extends Properties("Semigroup") { include(SemigroupProperties(Semigroup.streamSemigroup[Int](), "streamSemigroup")) include(SemigroupProperties(Semigroup.stringSemigroup, "stringSemigroup")) - include(SemigroupProperties(Semigroup.stringBufferSemigroup, "stringBufferSemigroup")) - include(SemigroupProperties(Semigroup.stringBuilderSemigroup, "stringBuilderSemigroup")) + include(CheckMutableBuilder(Semigroup.stringBufferSemigroup, "stringBufferSemigroup", (s: String) => new java.lang.StringBuffer(s))) + include(CheckMutableBuilder(Semigroup.stringBuilderSemigroup, "stringBuilderSemigroup", (s: String) => new java.lang.StringBuilder(s))) include(SemigroupProperties(Semigroup.unitSemigroup, "unitSemigroup")) diff --git a/props-core-scalacheck/src/test/scala/fj/Tests.scala b/props-core-scalacheck/src/test/scala/fj/Tests.scala index 60c2f009..d94661f9 100644 --- a/props-core-scalacheck/src/test/scala/fj/Tests.scala +++ b/props-core-scalacheck/src/test/scala/fj/Tests.scala @@ -1,8 +1,9 @@ package fj object Tests { - def tests = List ( + def tests = List( CheckP2.properties, + CheckSemigroup.properties, fj.data.CheckArray.properties, fj.data.CheckIO.properties, fj.data.CheckIteratee.properties, @@ -19,26 +20,27 @@ object Tests { def main(args: Array[String]) { run(tests) -// System.exit(0) + // System.exit(0) } - import org.scalacheck.Prop - import org.scalacheck.Test import org.scalacheck.Test.check + import org.scalacheck.{Prop, Test} def run(tests: List[(String, Prop)]) = tests foreach { case (name, p) => { - val c = check(new Test.Parameters.Default { override val maxSize = 20 }, p) - c.status match { - case Test.Passed => println("Passed " + name) - case Test.Proved(_) => println("Proved " + name) - case f @ Test.Failed(_, _) => sys.error(name + ": " + f) - case Test.Exhausted => println("Exhausted " + name) - case f @ Test.PropException(_, e, _) => { - e.printStackTrace - sys.error(name + ": " + f) - } + val c = check(new Test.Parameters.Default { + override val maxSize = 20 + }, p) + c.status match { + case Test.Passed => println("Passed " + name) + case Test.Proved(_) => println("Proved " + name) + case f@Test.Failed(_, _) => sys.error(name + ": " + f) + case Test.Exhausted => println("Exhausted " + name) + case f@Test.PropException(_, e, _) => { + e.printStackTrace + sys.error(name + ": " + f) } } } + } } From e834e8bfb87c394b0071e478a84445a1ca88834e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Wed, 9 Aug 2017 13:34:53 +0200 Subject: [PATCH 654/811] Enable upload of snapshot artifacts. --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8f3091d1..4a9f2d24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,3 +30,10 @@ script: after_success: - bash <(curl -s https://codecov.io/bash) + - '[ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ] + && ./gradlew uploadArchives' + +env: + global: + - secure: Bun+1FZ29Q3dR9gZ/5brxcSf+zcY5tWrsqOA4GUb5bYCMyORuXQB0FYXuhKR4wB1pFrk1a9EYwRwSu3GwRJVWb+UzF0CNOWF/QG5tGPx32IOXScwlL/KonI4Vhs7Oc0fF4Wdb7euNrT27BU61jbUugjJ642b3n0VBYFYDdquprU= + - secure: QAxhjqLRa+WHKIzgIJPZ/rM5a5uzqG7E5rsC0YvB25cO712oYXmzsYPia/oSp0chXlYLYMfk2UnLeQCSx2e6ogXRRRa977Q+B33Nt0Hd9SGLtduv6DBrbA2ehLU12Ib4DWe5VhF5eueAunycYcllTvqA5h+pzTtEVbd68ZHncM4= From 8330696120a4bcb744b1601600cb573dc176d0fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 9 Sep 2017 16:29:09 -0400 Subject: [PATCH 655/811] Upgrade Gradle version to 4.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- gradle/wrapper/gradle-wrapper.jar | Bin 54208 -> 54708 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 2dcd00d1ccd90b5b3d39e0da139893d5e7651ae4..7a3265ee94c0ab25cf079ac8ccdf87f41d455d42 100644 GIT binary patch delta 19176 zcmZ6yV{m3&w>2Ew?6_mwwr$(Cadpzk6(=3rwylnB+qRv&_j&H~)mP8?v1`rRHP^0M zRb!8-vHq5TH&%cnDanFEV1R(Yz<_{&2!q5Sk^f@|gK)(i$;9z$V5gtp+_~JkfP(xV zx6+>w|8bw7{C9n3{Lk9pK+OU9A1k4hVdpL(FvcSWu!X=@u3r5y z{&N>8=QoGFZncMeBZ+ejqAmiv=%4C)ob7te?`iRLT;nJRl6bo!fyRx8{r=D9z5UL4ODV`5f(yi zVZh^C*&pM4cV;SH4@jv65Rk`0EoM7JD!n6C7nwL2gybnT{qpPx;woxaqpvCQVns19 zyj75-x(>Mr4Lq2fY=ERe7^lzkr0QZ+cLlpQAE}LFT-d%x-hdBzvPhu8x?=fd%rDsD z*=7P2i=Xtv|Q=c`3^TFdX&KOq&?uixhEl zg8vOx(gsDXO~u<93tikV3LpC;;@dM7Ax*Hn_}5|^I%{EQI4H92)>UrBAhGD&Mr8cJ z0ywbB&p#+XiKv+-q=6Vn$r|>Znw}jK2SaabUtKQajD|Xn{bY--Xa$EV7Y@6iiQ#7*7;x)!8K}A8I^6 z@*xY4w>JpSvkIN8d#{iAVp{c3Kt6FiW(+m8ugSTs#EjIG-mW=$B8+Ltq!Uw*sJII0 zmD4G$Qq}+sQZFdF!YoeV1M0s~^XC?I3Jw_w1cU+~1cVqQL3sc(fe#M`z+h@;?CP4O z4R3_8?9Q*awuuuhL8Kv7Yjk7s7wZid?>9Yy1R5AbJc@_!j^nf4`b}QYdhUKJpi##jqon!q z$p6a!x!ZTT>$>~#xaaj0Fb%ds&G18Nr#;ZPQ>}l?((GP)wUaJG^Wco}U;fEJykI9bat@r9jdf}`4>IX1z{WcxAy>O!om434h)%QXG-V?c`Y` z*Ei2iFVLM1J4CnY1gtJcIR^@c39N?mH`6LFX`|J8w@$f-)nn+w2HHe-Kwbn0>Y|vZ>u_Ni33K3Fim)xjX9YAXMA6gbj(q+#rR%-O}J> zd)S#tB!k23phjCShrHeLKvjCHJP6oP?*57aU`(duvQfxu!IhEz!Qw-E{Wd{0`Pv8U zvA}c~ITmri1o?>whlrcvClut_n?B{GZj7LD5sODtV}TIBe)}a)6x@u{iLJhP zRZ@Co<|;FQ80EwheWBBs>U4!PtxbBJ*IK@KL3@LmmfhG}ntMtS>SL8mzRQ|DsVu*v z++usudHaOfA>AeG^gwQ?VO%+P!eEmo{6Wkh>hEM#n?L^gH6an+#C5t`2Qs;8^O|x4 z8f+OHb7N+rlJttT;OW70wc(U(D6(F9{qZ458Xi1=1)5;{37=NnoW-ErZkf1#(Q>YN znb-8#SXxriqPT=yqJ)S7~^ zqGthEB{*E#zfDNDDk9TqotB|28S82)$amE!r`t4>!yI<2W!ueVy=38*)3Nq_t_HP~ z*?nJHf@>|qsETH7&N00M+5?t~4mlEMyr0}6=Gt9t3pwq@^>P

    ;{uxCFdo17>QTVNzIrR=a?@u;vR$fngPL2ck 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
      9(Ta0+uZQM3v=vl(NR&l<6Sp%Q$O6-L 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7a57ac51..f16d2666 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Mon Mar 27 13:51:02 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip From 95c0d0d659a2dfa354aa549aa6197be7d12aba15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 9 Sep 2017 17:38:22 -0400 Subject: [PATCH 656/811] Bring dependencies current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- build.gradle | 2 +- core/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 04209664..6f8ecc5d 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ ext { buildscript { ext { - uptodateVersion = "1.6.2" + uptodateVersion = "1.6.3" retrolambdaPluginVersion = "3.5.0" retrolambdaVersion = "2.5.1" } diff --git a/core/build.gradle b/core/build.gradle index b3e1756e..e0c86f0c 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -7,8 +7,8 @@ archivesBaseName = project.projectName dependencies { testCompile dependencyJunit - testCompile 'com.h2database:h2:1.4.191' - testCompile 'commons-dbutils:commons-dbutils:1.6' + testCompile 'com.h2database:h2:1.4.196' + testCompile 'commons-dbutils:commons-dbutils:1.7' } performSigning(signingEnabled, signModule) From 6c6dabdb26b050c5d0e3a712fe4f28edd0e1ad57 Mon Sep 17 00:00:00 2001 From: l1cache Date: Mon, 11 Sep 2017 14:19:59 +0300 Subject: [PATCH 657/811] Equal: remove reference to static field of LazyString. Fix #321 Cause it could cause deadlock on parallel static initialization. --- core/src/main/java/fj/Equal.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index b64c758d..5e407a00 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -674,7 +674,7 @@ public static Equal> v8Equal(final Equal ea) { /** * An equal instance for lazy strings. */ - public static final Equal eq = streamEqual(charEqual).contramap(LazyString.toStream); + public static final Equal eq = streamEqual(charEqual).contramap(LazyString::toStream); /** * An equal instance for the empty heterogeneous list. From 065ed439303eacf90e3ac49c5403b1d62979b8f4 Mon Sep 17 00:00:00 2001 From: janbols Date: Mon, 6 Nov 2017 20:09:10 +0100 Subject: [PATCH 658/811] Add append methods to all Px classes. Fix #326 --- core/src/main/java/fj/P2.java | 63 ++++++++++++++++++++++++++++++++++- core/src/main/java/fj/P3.java | 52 +++++++++++++++++++++++++++++ core/src/main/java/fj/P4.java | 44 ++++++++++++++++++++++++ core/src/main/java/fj/P5.java | 30 +++++++++++++++++ core/src/main/java/fj/P6.java | 20 +++++++++++ core/src/main/java/fj/P7.java | 10 ++++++ 6 files changed, 218 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index e503ff40..b434a0da 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -178,7 +178,68 @@ public final P1 _2_() { return F1Functions.lazy(P2.__2()).f(this); } - /** + /** + * Creates a {@link P3} by adding the given element to the current {@link P2} + * + * @param el the element to append + * @return A {@link P3} containing the original {@link P2} with the extra element added at the end + */ + public final P3 append(C el) { + return P.p(_1(), _2(), el); + } + + /** + * Creates a {@link P4} by adding the given element to the current {@link P2} + * + * @param el the element to append + * @return A {@link P4} containing the original {@link P2} with the extra element added at the end + */ + public final P4 append(P2 el) { + return P.p(_1(), _2(), el._1(), el._2()); + } + + /** + * Creates a {@link P5} by adding the given element to the current {@link P2} + * + * @param el the element to append + * @return A {@link P5} containing the original {@link P2} with the extra element added at the end + */ + public final P5 append(P3 el) { + return P.p(_1(), _2(), el._1(), el._2(), el._3()); + } + + /** + * Creates a {@link P6} by adding the given element to the current {@link P2} + * + * @param el the element to append + * @return A {@link P6} containing the original {@link P2} with the extra element added at the end + */ + public final P6 append(P4 el) { + return P.p(_1(), _2(), el._1(), el._2(), el._3(), el._4()); + } + + /** + * Creates a {@link P7} by adding the given element to the current {@link P2} + * + * @param el the element to append + * @return A {@link P7} containing the original {@link P2} with the extra element added at the end + */ + public final P7 append(P5 el) { + return P.p(_1(), _2(), el._1(), el._2(), el._3(), el._4(), el._5()); + } + + /** + * Creates a {@link P8} by adding the given element to the current {@link P2} + * + * @param el the element to append + * @return A {@link P8} containing the original {@link P2} with the extra element added at the end + */ + public final P8 append(P6 el) { + return P.p(_1(), _2(), el._1(), el._2(), el._3(), el._4(), el._5(), el._6()); + } + + + /** * Provides a memoising P2 that remembers its values. * * @return A P2 that calls this P2 once for any given element and remembers the value for subsequent calls. diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index ec277346..fe980059 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -122,6 +122,58 @@ public final P1 _3_() { return F1Functions.lazy(P3.__3()).f(this); } + + /** + * Creates a {@link P4} by adding the given element to the current {@link P3} + * + * @param el the element to append + * @return A {@link P4} containing the original {@link P3} with the extra element added at the end + */ + public final P4 append(D el) { + return P.p(_1(), _2(), _3(), el); + } + + /** + * Creates a {@link P5} by adding the given element to the current {@link P3} + * + * @param el the element to append + * @return A {@link P5} containing the original {@link P3} with the extra element added at the end + */ + public final P5 append(P2 el) { + return P.p(_1(), _2(), _3(), el._1(), el._2()); + } + + /** + * Creates a {@link P6} by adding the given element to the current {@link P3} + * + * @param el the element to append + * @return A {@link P6} containing the original {@link P3} with the extra element added at the end + */ + public final P6 append(P3 el) { + return P.p(_1(), _2(), _3(), el._1(), el._2(), el._3()); + } + + /** + * Creates a {@link P7} by adding the given element to the current {@link P3} + * + * @param el the element to append + * @return A {@link P7} containing the original {@link P3} with the extra element added at the end + */ + public final P7 append(P4 el) { + return P.p(_1(), _2(), _3(), el._1(), el._2(), el._3(), el._4()); + } + + /** + * Creates a {@link P8} by adding the given element to the current {@link P3} + * + * @param el the element to append + * @return A {@link P8} containing the original {@link P3} with the extra element added at the end + */ + public final P8 append(P5 el) { + return P.p(_1(), _2(), _3(), el._1(), el._2(), el._3(), el._4(), el._5()); + } + + /** * Provides a memoising P3 that remembers its values. * diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 3f7236fe..a7bf8167 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -176,6 +176,50 @@ public final P1 _4_() { return F1Functions.lazy(P4.__4()).f(this); } + + /** + * Creates a {@link P5} by adding the given element to the current {@link P4} + * + * @param el the element to append + * @return A {@link P5} containing the original {@link P4} with the extra element added at the end + */ + public final P5 append(E el) { + return P.p(_1(), _2(), _3(), _4(), el); + } + + /** + * Creates a {@link P6} by adding the given element to the current {@link P4} + * + * @param el the element to append + * @return A {@link P6} containing the original {@link P4} with the extra element added at the end + */ + public final P6 append(P2 el) { + return P.p(_1(), _2(), _3(), _4(), el._1(), el._2()); + } + + /** + * Creates a {@link P7} by adding the given element to the current {@link P4} + * + * @param el the element to append + * @return A {@link P7} containing the original {@link P4} with the extra element added at the end + */ + public final P7 append(P3 el) { + return P.p(_1(), _2(), _3(), _4(), el._1(), el._2(), el._3()); + } + + /** + * Creates a {@link P8} by adding the given element to the current {@link P4} + * + * @param el the element to append + * @return A {@link P8} containing the original {@link P4} with the extra element added at the end + */ + public final P8 append(P4 el) { + return P.p(_1(), _2(), _3(), _4(), el._1(), el._2(), el._3(), el._4()); + } + + + + /** * Provides a memoising P4 that remembers its values. * diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 393b0632..69262327 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -238,6 +238,36 @@ public final P1 _5_() { return F1Functions.lazy(P5.__5()).f(this); } + /** + * Creates a {@link P6} by adding the given element to the current {@link P5} + * + * @param el the element to append + * @return A {@link P6} containing the original {@link P5} with the extra element added at the end + */ + public final P6 append(F el) { + return P.p(_1(), _2(), _3(), _4(), _5(), el); + } + + /** + * Creates a {@link P7} by adding the given element to the current {@link P5} + * + * @param el the element to append + * @return A {@link P7} containing the original {@link P5} with the extra element added at the end + */ + public final P7 append(P2 el) { + return P.p(_1(), _2(), _3(), _4(), _5(), el._1(), el._2()); + } + + /** + * Creates a {@link P8} by adding the given element to the current {@link P5} + * + * @param el the element to append + * @return A {@link P8} containing the original {@link P5} with the extra element added at the end + */ + public final P8 append(P3 el) { + return P.p(_1(), _2(), _3(), _4(), _5(), el._1(), el._2(), el._3()); + } + /** * Provides a memoising P5 that remembers its values. * diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 1e8c3055..fbf91948 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -309,6 +309,26 @@ public final P1 _6_() { return F1Functions.lazy(P6.__6()).f(this); } + /** + * Creates a {@link P7} by adding the given element to the current {@link P6} + * + * @param el the element to append + * @return A {@link P7} containing the original {@link P6} with the extra element added at the end + */ + public final P7 append(G el) { + return P.p(_1(), _2(), _3(), _4(), _5(), _6(), el); + } + + /** + * Creates a {@link P8} by adding the given element to the current {@link P6} + * + * @param el the element to append + * @return A {@link P8} containing the original {@link P6} with the extra element added at the end + */ + public final P8 append(P2 el) { + return P.p(_1(), _2(), _3(), _4(), _5(), _6(), el._1(), el._2()); + } + /** * Provides a memoising P6 that remembers its values. * diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index ca24b40e..b1c67b30 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -387,6 +387,16 @@ public final P1 _7_() { return F1Functions.lazy(P7.__7()).f(this); } + /** + * Creates a {@link P8} by adding the given element to the current {@link P7} + * + * @param el the element to append + * @return A {@link P8} containing the original {@link P7} with the extra element added at the end + */ + public final P8 append(H el) { + return P.p(_1(), _2(), _3(), _4(), _5(), _6(), _7(), el); + } + /** * Provides a memoising P7 that remembers its values. * From 34f2c176ac462596f22de81a70fd0bfdda8f6ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 9 Sep 2017 17:44:31 -0400 Subject: [PATCH 659/811] Bring ScalaCheck current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- props-core-scalacheck/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index 02f3652a..a395a586 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -4,9 +4,9 @@ archivesBaseName = "${project.projectName}-${project.name}" apply plugin: 'scala' ext { - scalaVersion = "2.11.8" + scalaVersion = "2.11.11" scalacheckScalaVersion = "2.11" - scalacheckVersion = "1.12.5" + scalacheckVersion = "1.12.6" signModule = true } From 98294fc3bdffe6c290818a6ffc04227e44ea3719 Mon Sep 17 00:00:00 2001 From: Iaroslav Zeigerman Date: Wed, 17 Jan 2018 08:51:51 -0500 Subject: [PATCH 660/811] Introduce the Eval monad a convenient wrapper around Trampoline and P1.hardMemo for stack-safe computation. --- core/src/main/java/fj/data/Eval.java | 238 +++++++++++++++++++++++ core/src/test/java/fj/data/EvalTest.java | 76 ++++++++ 2 files changed, 314 insertions(+) create mode 100644 core/src/main/java/fj/data/Eval.java create mode 100644 core/src/test/java/fj/data/EvalTest.java diff --git a/core/src/main/java/fj/data/Eval.java b/core/src/main/java/fj/data/Eval.java new file mode 100644 index 00000000..519070a1 --- /dev/null +++ b/core/src/main/java/fj/data/Eval.java @@ -0,0 +1,238 @@ +package fj.data; + +import fj.F; +import fj.F0; +import fj.P; +import fj.P1; +import fj.control.Trampoline; + +/** + * Eval is an abstraction over different models of evaluation. + * The data constructors: + *
        + *
      • Now - the value is evaluated immediately.
      • + *
      • Later - the value is evaluated only once when it's requested (lazy evaluation).
      • + *
      • Always - the value is evaluated every time when it's requested.
      • + *
      + * + * Both Later and Always are lazy computations, while Now is eager. + * + * + * @version %build.number% + */ +public abstract class Eval
      { + + /** + * Constructs an eager evaluation by wrapping the given value. + * + * @param a the evaluated value. + * @return an eval with computed value. + */ + public static Eval now(A a) { + return new Now<>(a); + } + + /** + * Constructs a lazy evaluation with caching. + * + * @param a the supplier that evaluates a value. + * @return a lazy evaluation. + */ + public static Eval later(F0 a) { + return new Later<>(a); + } + + /** + * Constructs a lazy evaluation without caching. + * + * @param a the supplier that evaluates a value. + * @return a lazy evaluation. + */ + public static Eval always(F0 a) { + return new Always<>(a); + } + + /** + * Constructs a lazy evaluation of an expression that produces Eval. + * This operation is stack-safe and can be used for recursive computations. + * + * @param a the supplier that produces an Eval. + * @return a lazily evaluated nested evaluation. + */ + public static Eval defer(F0> a) { + return new DeferEval<>(a); + } + + /** + * Evaluates the computation and return its result. + * Depending on whether the current instance is lazy or eager the + * computation may or may not happen at this point. + * + * @return a result of this computation. + */ + public abstract A value(); + + /** + * Transforms Eval into a Eval using + * the given function. + * + * Note: the computation of the given transformation is always lazy, + * even if it invoked for an eager Now instance. This computation + * is performed in O(1) stack space. + * + * @param f the transformation function. + * @return a transformed evaluation. + */ + public final Eval map(final F f) { + return bind(a -> now(f.f(a))); + } + + /** + * Alias for {@link #bind(F)}. + */ + public final Eval flatMap(final F> f) { + return bind(f); + } + + /** + * Transforms Eval into a Eval using + * the given function that directly produces Eval. + * + * Note: the computation of the given transformation is always lazy, + * even if it invoked for an eager Now instance. This computation + * is performed in O(1) stack space. + * + * @param f the transformation function. + * @return a transformed evaluation. + */ + public final Eval bind(final F> f) { + return new BindTrampolineEval<>(f, asTrampoline()); + } + + /** + * Transforms the current instance into a trampoline instance. + */ + abstract TrampolineEval asTrampoline(); + + /** + * Represents an eager computation. + */ + private static final class Now extends Eval { + private final A a; + + Now(A a) { + this.a = a; + } + + @Override + public final A value() { + return a; + } + + @Override + final TrampolineEval asTrampoline() { + return new PureTrampolineEval<>(this); + } + } + + /** + * Represents a lazy computation that is evaluated only once. + */ + private static final class Later extends Eval { + private final P1 memo; + + Later(F0 producer) { + this.memo = P.hardMemo(producer); + } + + @Override + public final A value() { + return memo._1(); + } + + @Override + final TrampolineEval asTrampoline() { + return new PureTrampolineEval<>(this); + } + } + + /** + * Represents a lazy computation that is evaluated every time when it's requested. + */ + private static final class Always extends Eval { + private final F0 supplier; + + Always(F0 supplier) { + this.supplier = supplier; + } + + @Override + public final A value() { + return supplier.f(); + } + + @Override + final TrampolineEval asTrampoline() { + return new PureTrampolineEval<>(this); + } + } + + /** + * A helper abstraction that allows to perform recursive lazy transformations in O(1) stack space. + */ + private static abstract class TrampolineEval extends Eval { + + protected abstract Trampoline trampoline(); + + @Override + public final A value() { + return trampoline().run(); + } + + @Override + final TrampolineEval asTrampoline() { + return this; + } + } + + private static final class PureTrampolineEval extends TrampolineEval { + private final Eval start; + + PureTrampolineEval(Eval start) { + this.start = start; + } + + @Override + protected final Trampoline trampoline() { + return Trampoline.suspend(P.lazy(() -> Trampoline.pure(start.value()))); + } + } + + private static final class BindTrampolineEval extends TrampolineEval { + private final TrampolineEval next; + private final F> f; + + BindTrampolineEval(F> f, TrampolineEval next) { + this.next = next; + this.f = f; + } + + @Override + protected final Trampoline trampoline() { + return Trampoline.suspend(P.lazy(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline()))); + } + } + + private static final class DeferEval extends TrampolineEval { + private final P1> memo; + + DeferEval(F0> producer) { + this.memo = P.hardMemo(producer); + } + + @Override + protected final Trampoline trampoline() { + return memo._1().asTrampoline().trampoline(); + } + } +} diff --git a/core/src/test/java/fj/data/EvalTest.java b/core/src/test/java/fj/data/EvalTest.java new file mode 100644 index 00000000..a604c873 --- /dev/null +++ b/core/src/test/java/fj/data/EvalTest.java @@ -0,0 +1,76 @@ +package fj.data; + +import fj.F0; +import org.junit.Assert; +import org.junit.Test; + +public class EvalTest { + + @Test + public void testNow() { + Eval eval = Eval.now(1); + Assert.assertEquals(eval.value().intValue(), 1); + Assert.assertEquals(eval.map(a -> a.toString()).value(), "1"); + Assert.assertEquals(eval.bind(a -> Eval.now(a * 3)).value().intValue(), 3); + } + + @Test + public void testLater() { + InvocationTrackingF tracker = new InvocationTrackingF<>(1); + Eval eval = Eval.later(tracker); + + Assert.assertEquals(tracker.getInvocationCounter(), 0); + Assert.assertEquals(eval.value().intValue(), 1); + Assert.assertEquals(tracker.getInvocationCounter(), 1); + eval.value(); + Assert.assertEquals(tracker.getInvocationCounter(), 1); + } + + @Test + public void testAlways() { + InvocationTrackingF tracker = new InvocationTrackingF<>(1); + Eval eval = Eval.always(tracker); + + Assert.assertEquals(tracker.getInvocationCounter(), 0); + Assert.assertEquals(eval.value().intValue(), 1); + Assert.assertEquals(tracker.getInvocationCounter(), 1); + eval.value(); + eval.value(); + Assert.assertEquals(tracker.getInvocationCounter(), 3); + } + + @Test + public void testDefer() { + // Make sure that a recursive computation is actually stack-safe. + Assert.assertEquals(even(200000).value(), "done"); + } + + private static Eval even(int n) { + return Eval.now(n <= 0).flatMap(b -> b ? Eval.now("done") : Eval.defer(() -> odd(n - 1))); + } + + private static Eval odd(int n) { + return Eval.defer(() -> even(n - 1)); + } + + private static class InvocationTrackingF implements F0 { + + private final A value; + private int invocationCounter; + + public InvocationTrackingF(A value) { + this.value = value; + this.invocationCounter = 0; + } + + @Override + public A f() { + invocationCounter++; + return value; + } + + public int getInvocationCounter() { + return invocationCounter; + } + } +} From e0f69dc368fe0df52531dc48c490a27ae143de2c Mon Sep 17 00:00:00 2001 From: Iaroslav Zeigerman Date: Thu, 18 Jan 2018 10:25:18 -0500 Subject: [PATCH 661/811] Fix a recursive trampoline call in the Eval Defer implementation (#329) --- core/src/main/java/fj/data/Eval.java | 2 +- core/src/test/java/fj/data/EvalTest.java | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/data/Eval.java b/core/src/main/java/fj/data/Eval.java index 519070a1..3e513075 100644 --- a/core/src/main/java/fj/data/Eval.java +++ b/core/src/main/java/fj/data/Eval.java @@ -232,7 +232,7 @@ private static final class DeferEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return memo._1().asTrampoline().trampoline(); + return Trampoline.suspend(P.lazy(() -> memo._1().asTrampoline().trampoline())); } } } diff --git a/core/src/test/java/fj/data/EvalTest.java b/core/src/test/java/fj/data/EvalTest.java index a604c873..a3302e55 100644 --- a/core/src/test/java/fj/data/EvalTest.java +++ b/core/src/test/java/fj/data/EvalTest.java @@ -1,9 +1,12 @@ package fj.data; import fj.F0; +import fj.F2; import org.junit.Assert; import org.junit.Test; +import java.util.Iterator; + public class EvalTest { @Test @@ -42,15 +45,19 @@ public void testAlways() { @Test public void testDefer() { // Make sure that a recursive computation is actually stack-safe. - Assert.assertEquals(even(200000).value(), "done"); - } - - private static Eval even(int n) { - return Eval.now(n <= 0).flatMap(b -> b ? Eval.now("done") : Eval.defer(() -> odd(n - 1))); + int targetValue = 200000; + Iterator it = Enumerator.intEnumerator.toStream(0).iterator(); + Eval result = foldRight(it, (v, acc) -> v == targetValue ? Eval.now(true) : acc, false); + Assert.assertTrue(result.value()); } - private static Eval odd(int n) { - return Eval.defer(() -> even(n - 1)); + private static Eval foldRight(Iterator iterator, + F2, Eval> f, + A zero) { + if (!iterator.hasNext()) { + return Eval.now(zero); + } + return f.f(iterator.next(), Eval.defer(() -> foldRight(iterator, f, zero))); } private static class InvocationTrackingF implements F0 { From 7a30ac7323670bb134b78e6ddbba4452b881af4f Mon Sep 17 00:00:00 2001 From: l1cache Date: Fri, 2 Feb 2018 11:46:12 -0800 Subject: [PATCH 662/811] Added some useful functions to Equal --- core/src/main/java/fj/Equal.java | 68 ++++++++++++++++++++++++++++ core/src/test/java/fj/EqualTest.java | 48 ++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 core/src/test/java/fj/EqualTest.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 5e407a00..07863acf 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -132,6 +132,74 @@ public boolean equal(B b1, B b2) { }); } + /** + * Constructs an equal instance, which tests equality of self and the mapped object in "and" manner + * + * @param f The function to map the original object + * @param eq Equality for the mapped object + * @return A new equal instance + */ + public final Equal andThen(final F f, final Equal eq) { + return and(eq.contramap(f)); + } + + /** + * An equal instance, which executes two Equality of self in "and" manner + * + * @param eq Another equality for self + * @return A new equal instance + */ + public final Equal and(final Equal eq) { + return equalDef((a1, a2) -> def.equal(a1, a2) && eq.def.equal(a1, a2)); + } + + /** + * An equal instance, which executes two Equality of self in "or" manner + * + * @param eq Another equality for self + * @return A new equal instance + */ + public final Equal or(final Equal eq) { + return equalDef((a1, a2) -> def.equal(a1, a2) || eq.def.equal(a1, a2)); + } + + /** + * An equal instance, which reverts equality for self + * + * @return A new equal instance + */ + public final Equal not() { + return equalDef((a1, a2) -> !def.equal(a1, a2)); + } + + /** + * Static version of {@link #contramap(F)} + */ + public static Equal contramap(final F f, final Equal eq) { + return eq.contramap(f); + } + + /** + * Static version of {@link #and(Equal)} + */ + public static Equal and(final Equal eq1, final Equal eq2) { + return eq1.and(eq2); + } + + /** + * Static version of {@link #or(Equal)} + */ + public static Equal or(final Equal eq1, final Equal eq2) { + return eq1.or(eq2); + } + + /** + * Static version of {@link #not()} + */ + public static Equal not(final Equal eq) { + return eq.not(); + } + /** * Constructs an equal instance from the given function. * diff --git a/core/src/test/java/fj/EqualTest.java b/core/src/test/java/fj/EqualTest.java new file mode 100644 index 00000000..776ccc57 --- /dev/null +++ b/core/src/test/java/fj/EqualTest.java @@ -0,0 +1,48 @@ +package fj; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +public class EqualTest { + @Test + public void contramapShouldWork() { + Equal equalByLength = Equal.contramap(String::length, Equal.intEqual); + + assertThat(equalByLength.eq("str1", "str2"), is(true)); + assertThat(equalByLength.eq("str1", "str11"), is(false)); + } + + @Test + public void andShouldWork() { + Equal equalByLengthAndLastDigit = Equal.and(Equal.contramap(String::length, Equal.intEqual), + Equal.contramap(s -> s.charAt(s.length() - 1), + Equal.charEqual)); + + assertThat(equalByLengthAndLastDigit.eq("str1", "spr1"), is(true)); + assertThat(equalByLengthAndLastDigit.eq("str1", "str2"), is(false)); + assertThat(equalByLengthAndLastDigit.eq("str1", "strr1"), is(false)); + } + + @Test + public void orShouldWork() { + Equal equalByLengthOrLastDigit = Equal.or(Equal.contramap(String::length, Equal.intEqual), + Equal.contramap(s -> s.charAt(s.length() - 1), + Equal.charEqual)); + + assertThat(equalByLengthOrLastDigit.eq("str1", "str2"), is(true)); + assertThat(equalByLengthOrLastDigit.eq("str1", "strr1"), is(true)); + assertThat(equalByLengthOrLastDigit.eq("str1", "strr2"), is(false)); + } + + @Test + public void thenShouldWork() { + Equal equalByLengthThenLastDigit = Equal.contramap(String::length, Equal.intEqual) + .andThen(s -> s.charAt(s.length() - 1), Equal.charEqual); + + assertThat(equalByLengthThenLastDigit.eq("str1", "spr1"), is(true)); + assertThat(equalByLengthThenLastDigit.eq("str1", "str2"), is(false)); + assertThat(equalByLengthThenLastDigit.eq("str1", "strr1"), is(false)); + } +} From dc0f405dc9ab62c97400ce0c88853027218fb211 Mon Sep 17 00:00:00 2001 From: l1cache Date: Fri, 2 Feb 2018 13:17:49 -0800 Subject: [PATCH 663/811] few useful function added to Ord class as well --- core/src/main/java/fj/Ord.java | 33 ++++++++++++++++++++++++++++++ core/src/test/java/fj/OrdTest.java | 18 ++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index a3e55edc..0b532ed1 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -287,6 +287,39 @@ public final Ord reverse() { return ordDef(def.dual()); } + /** + * Constructs an ord instance, which compares using self and if objects are equal compares using ord + * + * @param ord Ord for subsequent comparison + * @return A new equal instance + */ + public final Ord andThen(final Ord ord) { + return ordDef((a1, a2) -> { + final Ordering compareResult = compare(a1, a2); + if(compareResult == Ordering.EQ) + return ord.compare(a1, a2); + return compareResult; + }); + } + + /** + * Constructs an ord instance, which compares using self and if objects are equal compares the mapped objects + * + * @param f The function to map the original object + * @param ord Ord for the mapped object + * @return A new equal instance + */ + public final Ord andThen(final F f, final Ord ord) { + return andThen(ord.contramap(f)); + } + + /** + * Static version of {@link #contramap(F)} + */ + public static Ord contramap(final F f, final Ord ord) { + return ord.contramap(f); + } + /** * Returns an order instance that uses the given equality test and ordering function. * diff --git a/core/src/test/java/fj/OrdTest.java b/core/src/test/java/fj/OrdTest.java index d218387a..1dfa6223 100644 --- a/core/src/test/java/fj/OrdTest.java +++ b/core/src/test/java/fj/OrdTest.java @@ -24,4 +24,22 @@ public void isLessThan() { assertThat(pred.f(1L), is(false)); assertThat(pred.f(2L), is(false)); } + + @Test + public void contramapShouldWork() { + Ord lengthOrd = Ord.contramap(String::length, Ord.intOrd); + + assertThat(lengthOrd.compare("str", "rts"), is(Ordering.EQ)); + assertThat(lengthOrd.compare("strlong", "str"), is(Ordering.GT)); + } + + @Test + public void andThenShouldWork() { + Ord lengthThenLastDigitOrd = Ord.contramap(String::length, Ord.intOrd) + .andThen(s -> s.charAt(s.length() - 1), Ord.charOrd); + + assertThat(lengthThenLastDigitOrd.compare("str", "dyr"), is(Ordering.EQ)); + assertThat(lengthThenLastDigitOrd.compare("stt", "str"), is(Ordering.GT)); + assertThat(lengthThenLastDigitOrd.compare("str", "strr"), is(Ordering.LT)); + } } From c4f1f6830a7f6cf66efdffb9436676361af2ff25 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Tue, 20 Mar 2018 13:55:23 +0100 Subject: [PATCH 664/811] Move fluent Equal/Ord construction api to the Definition interfaces. Also remove Equal.or and Equal.and as there is no precise use case. --- core/src/main/java/fj/Equal.java | 111 +++++++++++++-------------- core/src/main/java/fj/Ord.java | 101 ++++++++++++++---------- core/src/test/java/fj/EqualTest.java | 26 +------ core/src/test/java/fj/OrdTest.java | 6 +- 4 files changed, 117 insertions(+), 127 deletions(-) diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 07863acf..f427849a 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -48,6 +48,39 @@ public interface Definition { default boolean equal(A a1, A a2) { return equal(a1).f(a2); } + + /** + * Refine this equal definition, to tests equality of self and the mapped object in "and" manner. + * @see #equal() + * + * @param f The function to map the original object + * @param eq Equality for the mapped object + * @return A new equal definition + */ + default Definition then(final F f, final Equal eq) { + Definition bEqDef = eq.def; + return new Definition() { + @Override + public F equal(A a1) { + F fa = Definition.this.equal(a1); + F fb = bEqDef.equal(f.f(a1)); + return a2 -> fa.f(a2) && fb.f(f.f(a2)); + } + + @Override + public boolean equal(A a1, A a2) { + return Definition.this.equal(a1, a2) && bEqDef.equal(f.f(a1), f.f(a2)); + } + }; + } + + /** + * Build an equal instance from this definition. + * to be called after some successive {@link #then(F, Equal)} calls. + */ + default Equal equal() { + return equalDef(this); + } } /** @@ -118,58 +151,31 @@ public F eq(final A a) { * @return A new equal. */ public Equal contramap(final F f) { - Definition eaDef = def; - return equalDef(new Definition(){ - @Override - public F equal(B b) { - return compose(eaDef.equal(f.f(b)), f); - } - - @Override - public boolean equal(B b1, B b2) { - return eaDef.equal(f.f(b1), f.f(b2)); - } - }); + return equalDef(contramapDef(f, def)); } /** - * Constructs an equal instance, which tests equality of self and the mapped object in "and" manner + * An equal instance, which reverts equality for self * - * @param f The function to map the original object - * @param eq Equality for the mapped object * @return A new equal instance */ - public final Equal andThen(final F f, final Equal eq) { - return and(eq.contramap(f)); + public final Equal not() { + return equalDef((a1, a2) -> !def.equal(a1, a2)); } - /** - * An equal instance, which executes two Equality of self in "and" manner - * - * @param eq Another equality for self - * @return A new equal instance - */ - public final Equal and(final Equal eq) { - return equalDef((a1, a2) -> def.equal(a1, a2) && eq.def.equal(a1, a2)); - } - /** - * An equal instance, which executes two Equality of self in "or" manner - * - * @param eq Another equality for self - * @return A new equal instance - */ - public final Equal or(final Equal eq) { - return equalDef((a1, a2) -> def.equal(a1, a2) || eq.def.equal(a1, a2)); - } + private static Definition contramapDef(F f, Definition aEqDef) { + return new Definition(){ + @Override + public F equal(B b) { + return compose(aEqDef.equal(f.f(b)), f); + } - /** - * An equal instance, which reverts equality for self - * - * @return A new equal instance - */ - public final Equal not() { - return equalDef((a1, a2) -> !def.equal(a1, a2)); + @Override + public boolean equal(B b1, B b2) { + return aEqDef.equal(f.f(b1), f.f(b2)); + } + }; } /** @@ -180,24 +186,11 @@ public static Equal contramap(final F f, final Equal eq) { } /** - * Static version of {@link #and(Equal)} - */ - public static Equal and(final Equal eq1, final Equal eq2) { - return eq1.and(eq2); - } - - /** - * Static version of {@link #or(Equal)} - */ - public static Equal or(final Equal eq1, final Equal eq2) { - return eq1.or(eq2); - } - - /** - * Static version of {@link #not()} + * Begin definition of an equal instance. + * @see Definition#then(F, Equal) */ - public static Equal not(final Equal eq) { - return eq.not(); + public static Definition on(final F f, final Equal eq) { + return contramapDef(f, eq.def); } /** diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 0b532ed1..0a778f4d 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -84,6 +84,42 @@ public Definition dual() { } }; } + + /** + * Refine this ord definition: compares using self and if objects are equal compares using given Ord. + * @see #ord() + * + * @param bOrd Ord for subsequent comparison + * @return A new ord definition. + */ + default Definition then(final F f, final Ord bOrd) { + Definition bOrdDef = bOrd.def; + return new Definition() { + @Override + public F compare(A a1) { + F fa = Definition.this.compare(a1); + F fb = bOrdDef.compare(f.f(a1)); + return a2 -> { + Ordering aOrdering = fa.f(a2); + return aOrdering != Ordering.EQ ? aOrdering : fb.f(f.f(a2)); + }; + } + + @Override + public Ordering compare(A a1, A a2) { + Ordering aOrdering = Definition.this.compare(a1, a2); + return aOrdering != Ordering.EQ ? aOrdering : bOrdDef.compare(f.f(a1), f.f(a2)); + } + }; + } + + /** + * Build an ord instance from this definition. + * to be called after some successive {@link #then(F, Ord)} calls. + */ + default Ord ord() { + return ordDef(this); + } } /** @@ -160,18 +196,7 @@ public Equal equal() { * @return A new ord. */ public Ord contramap(final F f) { - Definition selfDef = def; - return ordDef(new Definition() { - @Override - public F compare(B b) { - return compose(selfDef.compare(f.f(b)), f); - } - - @Override - public Ordering compare(B b1, B b2) { - return selfDef.compare(f.f(b1), f.f(b2)); - } - }); + return ordDef(contramapDef(f, def)); } /** @@ -288,36 +313,32 @@ public final Ord reverse() { } /** - * Constructs an ord instance, which compares using self and if objects are equal compares using ord - * - * @param ord Ord for subsequent comparison - * @return A new equal instance + * Begin definition of an ord instance. + * @see Definition#then(F, Equal) */ - public final Ord andThen(final Ord ord) { - return ordDef((a1, a2) -> { - final Ordering compareResult = compare(a1, a2); - if(compareResult == Ordering.EQ) - return ord.compare(a1, a2); - return compareResult; - }); - } - - /** - * Constructs an ord instance, which compares using self and if objects are equal compares the mapped objects - * - * @param f The function to map the original object - * @param ord Ord for the mapped object - * @return A new equal instance - */ - public final Ord andThen(final F f, final Ord ord) { - return andThen(ord.contramap(f)); + public static Definition on(final F f, final Ord ord) { + return contramapDef(f, ord.def); } /** * Static version of {@link #contramap(F)} */ public static Ord contramap(final F f, final Ord ord) { - return ord.contramap(f); + return ordDef(contramapDef(f, ord.def)); + } + + private static Definition contramapDef(F f, Definition def) { + return new Definition() { + @Override + public F compare(B b) { + return compose(def.compare(f.f(b)), f); + } + + @Override + public Ordering compare(B b1, B b2) { + return def.compare(f.f(b1), f.f(b2)); + } + }; } /** @@ -609,15 +630,15 @@ public static Ord> p1Ord(final Ord oa) { * @return An order instance for a product-2, with the first factor considered most significant. */ public static Ord> p2Ord(final Ord oa, final Ord ob) { - return ordDef((a, b) -> oa.eq(a._1(), b._1()) ? ob.compare(a._2(), b._2()) : oa.compare(a._1(), b._1())); + return on(P2.__1(), oa).then(P2.__2(), ob).ord(); } public static Ord> p2Ord1(Ord oa) { - return ordDef((p1, p2) -> oa.compare(p1._1(), p2._1())); + return on(P2.__1(), oa).ord(); } public static Ord> p2Ord2(Ord ob) { - return ordDef((p1, p2) -> ob.compare(p1._2(), p2._2())); + return on(P2.__2(), ob).ord(); } /** @@ -629,9 +650,7 @@ public static Ord> p2Ord2(Ord ob) { * @return An order instance for a product-3, with the first factor considered most significant. */ public static Ord> p3Ord(final Ord oa, final Ord ob, final Ord oc) { - return ordDef((a, b) -> oa.eq(a._1(), b._1()) ? - p2Ord(ob, oc).compare(P.p(a._2(), a._3()), P.p(b._2(), b._3())) - : oa.compare(a._1(), b._1())); + return on(P3.__1(), oa).then(P3.__2(), ob).then(P3.__3(), oc).ord(); } /** diff --git a/core/src/test/java/fj/EqualTest.java b/core/src/test/java/fj/EqualTest.java index 776ccc57..bacecc46 100644 --- a/core/src/test/java/fj/EqualTest.java +++ b/core/src/test/java/fj/EqualTest.java @@ -14,32 +14,10 @@ public void contramapShouldWork() { assertThat(equalByLength.eq("str1", "str11"), is(false)); } - @Test - public void andShouldWork() { - Equal equalByLengthAndLastDigit = Equal.and(Equal.contramap(String::length, Equal.intEqual), - Equal.contramap(s -> s.charAt(s.length() - 1), - Equal.charEqual)); - - assertThat(equalByLengthAndLastDigit.eq("str1", "spr1"), is(true)); - assertThat(equalByLengthAndLastDigit.eq("str1", "str2"), is(false)); - assertThat(equalByLengthAndLastDigit.eq("str1", "strr1"), is(false)); - } - - @Test - public void orShouldWork() { - Equal equalByLengthOrLastDigit = Equal.or(Equal.contramap(String::length, Equal.intEqual), - Equal.contramap(s -> s.charAt(s.length() - 1), - Equal.charEqual)); - - assertThat(equalByLengthOrLastDigit.eq("str1", "str2"), is(true)); - assertThat(equalByLengthOrLastDigit.eq("str1", "strr1"), is(true)); - assertThat(equalByLengthOrLastDigit.eq("str1", "strr2"), is(false)); - } - @Test public void thenShouldWork() { - Equal equalByLengthThenLastDigit = Equal.contramap(String::length, Equal.intEqual) - .andThen(s -> s.charAt(s.length() - 1), Equal.charEqual); + Equal equalByLengthThenLastDigit = Equal.on(String::length, Equal.intEqual) + .then(s -> s.charAt(s.length() - 1), Equal.charEqual).equal(); assertThat(equalByLengthThenLastDigit.eq("str1", "spr1"), is(true)); assertThat(equalByLengthThenLastDigit.eq("str1", "str2"), is(false)); diff --git a/core/src/test/java/fj/OrdTest.java b/core/src/test/java/fj/OrdTest.java index 1dfa6223..4addec65 100644 --- a/core/src/test/java/fj/OrdTest.java +++ b/core/src/test/java/fj/OrdTest.java @@ -34,9 +34,9 @@ public void contramapShouldWork() { } @Test - public void andThenShouldWork() { - Ord lengthThenLastDigitOrd = Ord.contramap(String::length, Ord.intOrd) - .andThen(s -> s.charAt(s.length() - 1), Ord.charOrd); + public void thenShouldWork() { + Ord lengthThenLastDigitOrd = Ord.on(String::length, Ord.intOrd) + .then(s -> s.charAt(s.length() - 1), Ord.charOrd).ord(); assertThat(lengthThenLastDigitOrd.compare("str", "dyr"), is(Ordering.EQ)); assertThat(lengthThenLastDigitOrd.compare("stt", "str"), is(Ordering.GT)); From bbc28c47a29d04724007192100edef79499078cc Mon Sep 17 00:00:00 2001 From: Sidney Quitorio Date: Tue, 3 Jul 2018 16:16:17 -0700 Subject: [PATCH 665/811] Fixes exception in Either.LeftProjection.traverseIO --- core/src/main/java/fj/data/Either.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index 7d8e0bb7..a9a746a9 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -316,7 +316,7 @@ public List> traverseList(final F> f) { * @return An either after traversing through this projection. */ public IO> traverseIO(final F> f) { - return e.isRight() ? + return e.isLeft() ? IOFunctions.map(f.f(value()), Either::left) : IOFunctions.unit(Either.right(e.right().value())); } From 8ff163c6bbcaf4888bde7dcef21a16137b4db5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Wed, 11 Jul 2018 21:24:12 -0400 Subject: [PATCH 666/811] Bring Gradle to 4.8.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f16d2666..717f0389 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip diff --git a/gradlew b/gradlew index 4453ccea..cccdd3d5 100755 --- a/gradlew +++ b/gradlew @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -155,7 +155,7 @@ if $cygwin ; then fi # Escape application args -save ( ) { +save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } From 4b6536110719689dad7e784ac389db05a0959af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Wed, 11 Jul 2018 21:43:15 -0400 Subject: [PATCH 667/811] Bring dependencies current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- build.gradle | 2 +- core/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 6f8ecc5d..e1fed096 100644 --- a/build.gradle +++ b/build.gradle @@ -72,7 +72,7 @@ allprojects { sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" - dependencyJunit = "junit:junit:4.12" + dependencyJunit = "org.junit.vintage:junit-vintage-engine:5.2.0" displayCompilerWarnings = true diff --git a/core/build.gradle b/core/build.gradle index e0c86f0c..71dae913 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -7,7 +7,7 @@ archivesBaseName = project.projectName dependencies { testCompile dependencyJunit - testCompile 'com.h2database:h2:1.4.196' + testCompile 'com.h2database:h2:1.4.197' testCompile 'commons-dbutils:commons-dbutils:1.7' } From 7576f6f65537cbb7f059d683d96425860b306213 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 21 Jul 2018 09:21:05 +0200 Subject: [PATCH 668/811] use openjdk7, remove oracle installer, try sudo false --- .travis.yml | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a9f2d24..539e7a45 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,13 @@ -language: java +# Use faster, Docker-based container (instead of OpenVZ) +sudo: false -sudo: required +language: java jdk: - oraclejdk8 -addons: - apt: - packages: - - oracle-java8-installer - -before_script: - - sudo service postgresql stop || true - - sudo service mysql stop || true - - sudo service memcached stop || true - - sudo service bootlogd stop || true - - sudo service elasticsearch stop || true - - sudo service mongodb stop || true - - sudo service neo4j stop || true - - sudo service cassandra stop || true - - sudo service riak stop || true - - sudo service rsync stop || true - - sudo service x11-common stop || true - script: - - jdk_switcher use oraclejdk7 && export JAVA7_HOME=$JAVA_HOME + - jdk_switcher use openjdk7 && export JAVA7_HOME=$JAVA_HOME - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME - ./gradlew build coverage -s -i From b280c531debd92885ca6b7998cb2aa485a0fd955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Thu, 26 Jul 2018 18:48:45 -0400 Subject: [PATCH 669/811] Add IOFunctions tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/IOTest.java | 30 -------- .../test/java/fj/data/IOFunctionsTest.java | 69 +++++++++++++++++-- 2 files changed, 63 insertions(+), 36 deletions(-) delete mode 100644 core/src/test/java/fj/IOTest.java diff --git a/core/src/test/java/fj/IOTest.java b/core/src/test/java/fj/IOTest.java deleted file mode 100644 index f965204c..00000000 --- a/core/src/test/java/fj/IOTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package fj; - -import fj.data.IO; -import fj.data.IOFunctions; -import org.junit.Test; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - - -public class IOTest { - - @Test - public void testLift() throws IOException { - final IO readName = () -> new BufferedReader(new StringReader("foo")).readLine(); - final F> upperCaseAndPrint = F1Functions., String>o(this::println).f(String::toUpperCase); - final IO readAndPrintUpperCasedName = IOFunctions.bind(readName, upperCaseAndPrint); - assertThat(readAndPrintUpperCasedName.run(), is("FOO")); - } - - public IO println(final String s) { - return () -> { - return s; - }; - } -} diff --git a/core/src/test/java/fj/data/IOFunctionsTest.java b/core/src/test/java/fj/data/IOFunctionsTest.java index dcafc221..b943db36 100644 --- a/core/src/test/java/fj/data/IOFunctionsTest.java +++ b/core/src/test/java/fj/data/IOFunctionsTest.java @@ -1,7 +1,6 @@ package fj.data; -import fj.Unit; -import org.hamcrest.core.Is; +import fj.*; import org.junit.Assert; import org.junit.Test; @@ -9,6 +8,10 @@ import java.io.Reader; import java.util.concurrent.atomic.AtomicBoolean; +import static fj.data.IOFunctions.*; +import static fj.data.Stream.cons; +import static fj.data.Stream.nil_; +import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.*; public class IOFunctionsTest { @@ -30,8 +33,8 @@ public void close() { r -> () -> new BufferedReader(r).readLine() ); - Assert.assertThat(bracketed.run(), Is.is("Read OK")); - Assert.assertThat(closed.get(), Is.is(true)); + Assert.assertThat(bracketed.run(), is("Read OK")); + Assert.assertThat(closed.get(), is(true)); } @Test @@ -56,9 +59,63 @@ public void close() { bracketed.run(); fail("Exception expected"); } catch (IllegalArgumentException e) { - Assert.assertThat(e.getMessage(), Is.is("OoO")); + Assert.assertThat(e.getMessage(), is("OoO")); } - Assert.assertThat(closed.get(), Is.is(true)); + Assert.assertThat(closed.get(), is(true)); + } + + @Test + public void testTraverseIO() throws IOException { + String[] as = {"foo1", "bar2", "foobar3"}; + Stream stream = Stream.arrayStream(as); + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + PrintStream originalOut = System.out; + System.setOut(new PrintStream(outContent)); + stream.traverseIO(IOFunctions::stdoutPrint).run(); + System.setOut(originalOut); + assertThat(outContent.toString(), is("foobar3bar2foo1")); + } + + @Test + public void testSequenceWhile() throws IOException { + BufferedReader r = new BufferedReader(new StringReader("foo1\nbar2\nfoobar3")); + Stream> s1 = Stream.repeat(() -> r.readLine()); + IO> io = sequenceWhile(s1, s -> !s.equals("foobar3")); + assertThat(io.run(), is(cons("foo1", () -> cons("bar2", () -> Stream.nil())))); + } + + @Test + public void testForeach() throws IOException { + Stream> s1 = Stream.repeat(() -> "foo1"); + IO> io = sequence(s1.take(2)); + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + PrintStream originalOut = System.out; + System.setOut(new PrintStream(outContent)); + runSafe(io).foreach(s -> runSafe(stdoutPrint(s))); + System.setOut(originalOut); + assertThat(outContent.toString(), is("foo1foo1")); + } + + + @Test + public void testReplicateM() throws IOException { + final IO is = () -> new BufferedReader(new StringReader("foo")).readLine(); + assertThat(replicateM(is, 3).run(), is(List.list("foo", "foo", "foo"))); + } + + + @Test + public void testLift() throws IOException { + final IO readName = () -> new BufferedReader(new StringReader("foo")).readLine(); + final F> upperCaseAndPrint = F1Functions., String>o(this::println).f(String::toUpperCase); + final IO readAndPrintUpperCasedName = IOFunctions.bind(readName, upperCaseAndPrint); + assertThat(readAndPrintUpperCasedName.run(), is("FOO")); + } + + private IO println(final String s) { + return () -> { + return s; + }; } } \ No newline at end of file From be646621a7be6dc7dfe5a10bb9fd26fd3d04c6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 29 Jul 2018 08:47:35 -0400 Subject: [PATCH 670/811] Add Stream tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/data/StreamTest.java | 75 ++++++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index a37764c2..49840b78 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -1,16 +1,16 @@ package fj.data; +import fj.Equal; +import fj.Ord; +import fj.P2; +import fj.control.parallel.Strategy; import org.junit.Test; -import java.io.IOException; -import java.util.ArrayList; import java.util.ConcurrentModificationException; -import static fj.data.IOFunctions.stdinReadLine; -import static java.lang.System.out; +import static fj.data.Stream.*; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; /** @@ -21,7 +21,7 @@ public class StreamTest { @Test public void infiniteStream() { Stream s = Stream.forever(Enumerator.intEnumerator, 0).bind(Stream::single); - assertEquals(List.range(0, 5), s.take(5).toList()); + assertThat(List.range(0, 5), is(s.take(5).toList())); } @Test @@ -48,5 +48,68 @@ public void iterableStreamWithStructureUpdate() { x = s2.head(); } + @Test(expected=Error.class) + public void testCycleNil(){ + cycle(Stream.nil()); + } + + @Test + public void testCycle() { + Stream s = stream(new Character[]{'a', 'b'}); + assertThat(cycle(s).take(5), + is(stream(new Character[]{'a', 'b', 'a', 'b', 'a'}))); + } + + @Test + public void testIterate() { + assertThat(iterate(a -> 2 * a + 1, 1).take(5), + is(stream(new Integer[]{1, 3, 7, 15, 31}))); + } + + @Test + public void testArrayStreamEmpty() { + assertThat(arrayStream(new Integer[]{}), is(Stream.nil())); + } + + @Test(expected=Error.class) + public void testNilHead() { + Stream.nil().head(); + } + @Test(expected=Error.class) + public void testNilTail() { + Stream.nil().tail(); + } + + @Test + public void testArray() { + Character[] a = new Character[]{'a', 'b', 'c'}; + Stream s = stream(a); + assertThat(s.array(Character[].class), is(a)); + } + + @Test + public void testZipIndex() { + Character[] a = new Character[]{'a', 'b', 'c'}; + P2, Stream> p = unzip(stream(a).zipIndex().drop(1)); + assertThat(p._1(), is(stream(new Character[]{'b', 'c'}))); + assertThat(p._2(), is(stream(new Integer[]{1, 2}))); + } + + @Test + public void testMinus() { + Character[] a1 = new Character[]{'a', 'b', 'c', 'd', 'e'}; + Stream s1 = stream(a1); + Character[] a2 = new Character[]{'b', 'e'}; + Stream s2 = stream(a2); + assertThat(s1.minus(Equal.charEqual, s2), + is(stream(new Character[]{'a', 'c', 'd'}))); + } + + @Test + public void testSort() { + Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + assertThat(s.sort(Ord.intOrd, Strategy.seqStrategy()), + is(s.sort(Ord.intOrd))); + } } From 99a7642a5fbae7e90e5ce80bbe44842acc8f524b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 29 Jul 2018 21:20:43 +0200 Subject: [PATCH 671/811] Update to latest retrolambda --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e1fed096..08d3e946 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,8 @@ ext { buildscript { ext { uptodateVersion = "1.6.3" - retrolambdaPluginVersion = "3.5.0" - retrolambdaVersion = "2.5.1" + retrolambdaPluginVersion = "3.7.0" + retrolambdaVersion = "2.5.4" } repositories { From 3fc4ab2994d942c121d79be37bda672e9a2a8262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 29 Jul 2018 17:01:47 -0400 Subject: [PATCH 672/811] Exclude paths in codecov.io MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- codecov.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..8c7fd5e4 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,3 @@ +ignore: + - "demo/.*" + - "performance/.*" \ No newline at end of file From fa322e27df3c491d2e771a540894f9073d95f6eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 30 Jul 2018 15:45:03 -0400 Subject: [PATCH 673/811] Bring Gradle Jacoco current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index e1fed096..1cc8078e 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,7 @@ allprojects { jacoco { -// toolVersion = "0.7.1.201405082137" - toolVersion = "0.7.6.201602180812" + toolVersion = "0.8.1" } From e9fd4eca665bf392c6b1a72176e476ff6bae1289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 30 Jul 2018 15:22:45 -0400 Subject: [PATCH 674/811] Add tests for Try, F, FW, Digit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/F8Functions.java | 1 - core/src/test/java/fj/DigitTest.java | 30 ++++++++ core/src/test/java/fj/FFunctionsTest.java | 25 +++++++ core/src/test/java/fj/FWFunctionsTest.java | 24 ++++++ core/src/test/java/fj/ShowTest.java | 6 -- core/src/test/java/fj/TryEffectTest.java | 82 +++++++++++++++++++++ core/src/test/java/fj/TryTest.java | 50 +++++++++++++ core/src/test/java/fj/data/JavaTest.java | 4 +- core/src/test/java/fj/data/OptionTest.java | 1 - core/src/test/java/fj/data/SeqTest.java | 5 +- core/src/test/java/fj/data/StreamTest.java | 9 ++- core/src/test/java/fj/data/TreeMapTest.java | 11 --- 12 files changed, 226 insertions(+), 22 deletions(-) create mode 100644 core/src/test/java/fj/DigitTest.java create mode 100644 core/src/test/java/fj/FFunctionsTest.java create mode 100644 core/src/test/java/fj/FWFunctionsTest.java create mode 100644 core/src/test/java/fj/TryEffectTest.java create mode 100644 core/src/test/java/fj/TryTest.java diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java index 071cb6bc..8b9883a3 100644 --- a/core/src/main/java/fj/F8Functions.java +++ b/core/src/main/java/fj/F8Functions.java @@ -11,7 +11,6 @@ private F8Functions() { /** * Partial application. * - * @param a The A to which to apply this function. * @return The function partially applied to the given argument. */ public static F7 f(final F8 func, final A a) { diff --git a/core/src/test/java/fj/DigitTest.java b/core/src/test/java/fj/DigitTest.java new file mode 100644 index 00000000..9fc98d4c --- /dev/null +++ b/core/src/test/java/fj/DigitTest.java @@ -0,0 +1,30 @@ +package fj; + +import fj.data.Option; +import org.junit.Test; + +import static fj.data.Array.range; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class DigitTest { + @Test + public void testInteger() { + for (Integer i: range(0, 10)) { + assertThat(Digit.fromLong(i).toLong(), is(i.longValue())); + } + } + + @Test + public void testChar() { + for (Integer i: range(0, 10)) { + Character c = Character.forDigit(i, 10); + assertThat(Digit.fromChar(c).some().toChar(), is(c)); + } + } + + @Test + public void testCharNone() { + assertThat(Digit.fromChar('x'), is(Option.none())); + } +} diff --git a/core/src/test/java/fj/FFunctionsTest.java b/core/src/test/java/fj/FFunctionsTest.java new file mode 100644 index 00000000..9d38e1f5 --- /dev/null +++ b/core/src/test/java/fj/FFunctionsTest.java @@ -0,0 +1,25 @@ +package fj; + +import org.junit.Test; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class FFunctionsTest { + @Test + public void testApply() { + F8 f8 = + (i1, i2, i3, i4, i5, i6, i7, i8) -> + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8; + F7 f7 = F8Functions.f(f8, 8); + F6 f6 = + F7Functions.f(f7, 7); + F5 f5 = F6Functions.f(f6, 6); + F4 f4 = F5Functions.f(f5, 5); + F3 f3 = F4Functions.f(f4, 4); + F2 f2 = F3Functions.f(f3, 3); + F f1 = F2Functions.f(f2, 2); + assertThat(F1Functions.f(f1, 1).f(), is(36)); + } +} diff --git a/core/src/test/java/fj/FWFunctionsTest.java b/core/src/test/java/fj/FWFunctionsTest.java new file mode 100644 index 00000000..b9ce65d5 --- /dev/null +++ b/core/src/test/java/fj/FWFunctionsTest.java @@ -0,0 +1,24 @@ +package fj; + +import org.junit.Test; + +import fj.F1W; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class FWFunctionsTest { + @Test + public void testLift1() { + F f = i -> i + 1; + F1W f1w = F1W.lift(f); + assertThat(f1w.f(1), is(2)); + } + + @Test + public void testLift2() { + F2 f2 = (i, j) -> i + j; + F2W f2w = F2W.lift(f2); + assertThat(f2w.f(1, 2), is(3)); + } + +} diff --git a/core/src/test/java/fj/ShowTest.java b/core/src/test/java/fj/ShowTest.java index e271f5a1..c516c0df 100644 --- a/core/src/test/java/fj/ShowTest.java +++ b/core/src/test/java/fj/ShowTest.java @@ -10,16 +10,10 @@ * Created by MarkPerry on 4/06/2015. */ public class ShowTest { - - - @Test public void arrayShow() { Array a = array(3, 5, 7); String s = Show.arrayShow(Show.intShow).showS(a); - System.out.println(s); assertTrue(s.equals("Array(3,5,7)")); - } - } diff --git a/core/src/test/java/fj/TryEffectTest.java b/core/src/test/java/fj/TryEffectTest.java new file mode 100644 index 00000000..bb684fc6 --- /dev/null +++ b/core/src/test/java/fj/TryEffectTest.java @@ -0,0 +1,82 @@ +package fj; + +import fj.data.Validation; +import fj.function.TryEffect0; +import fj.function.TryEffect1; +import org.junit.Test; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class TryEffectTest { + + @Test + public void testTryEffect0Success() { + F> f = + TryEffect.f(TryEffect0::f); + Validation v = f.f(new AlwaysSucceed0()); + assertThat(v.isSuccess(), is(true)); + assertThat(v.success(), is(Unit.unit())); + } + + @Test + public void testTryEffect0Fail() { + F> f = + TryEffect.f(TryEffect0::f); + Validation v = f.f(new AlwaysFail0()); + assertThat(v.isFail(), is(true)); + assertThat(v.fail(), is(new TryEffectException())); + } + + @Test + public void testTryEffect1Success() { + F2, Integer, Validation> f = + TryEffect.f(TryEffect1::f); + Validation v = f.f(new AlwaysSucceed1(), 1); + assertThat(v.isSuccess(), is(true)); + assertThat(v.success(), is(Unit.unit())); + } + + @Test + public void testTryEffect1Fail() { + F2, Integer, Validation> f = + TryEffect.f(TryEffect1::f); + Validation v = f.f(new AlwaysFail1(), 1); + assertThat(v.isFail(), is(true)); + assertThat(v.fail(), is(new TryEffectException())); + } + + class AlwaysSucceed0 implements TryEffect0 { + @Override + public void f() throws TryEffectException { + // SUCCESS + } + } + + class AlwaysSucceed1 implements TryEffect1 { + @Override + public void f(Integer i) throws TryEffectException { + // SUCCESS; + } + } + + class AlwaysFail0 implements TryEffect0 { + @Override + public void f() throws TryEffectException { + throw new TryEffectException(); + } + } + + class AlwaysFail1 implements TryEffect1 { + @Override + public void f(Integer i) throws TryEffectException { + throw new TryEffectException(); + } + } + + class TryEffectException extends Exception { + @Override + public boolean equals (Object obj) { + return (obj instanceof TryEffectException); + } + } +} diff --git a/core/src/test/java/fj/TryTest.java b/core/src/test/java/fj/TryTest.java new file mode 100644 index 00000000..bd94e986 --- /dev/null +++ b/core/src/test/java/fj/TryTest.java @@ -0,0 +1,50 @@ +package fj; + +import fj.data.Validation; +import fj.function.Try0; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class TryTest { + + @Test + public void testTrySuccess() { + F, Validation> f = + Try.f(Try0::f); + Validation v = f.f(new AlwaysSucceed()); + assertThat(v.isSuccess(), is(true)); + assertThat(v.success(), is(99)); + } + + @Test + public void testTryFail() { + F, Validation> f = + Try.f(Try0::f); + Validation v = f.f(new AlwaysFail()); + assertThat(v.isFail(), is(true)); + assertThat(v.fail(), is(new TryException())); + } + + class AlwaysSucceed implements Try0 { + @Override + public Integer f() throws TryException { + return 99; + } + } + + class AlwaysFail implements Try0 { + @Override + public Integer f() throws TryException { + throw new TryException(); + } + } + + class TryException extends Exception { + @Override + public boolean equals (Object obj) { + return (obj instanceof TryException); + } + } +} diff --git a/core/src/test/java/fj/data/JavaTest.java b/core/src/test/java/fj/data/JavaTest.java index 3b5a5785..2a9b6bfd 100644 --- a/core/src/test/java/fj/data/JavaTest.java +++ b/core/src/test/java/fj/data/JavaTest.java @@ -6,6 +6,8 @@ import java.util.EnumSet; import static fj.Show.listShow; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; /** * Created by MarkPerry on 14/07/2014. @@ -16,7 +18,7 @@ public class JavaTest { public void test1() { // #33: Fixes ClassCastException final List colors = Java.EnumSet_List().f(EnumSet.allOf(Colors.class)); - listShow(Show.anyShow()).print(colors); + assertThat(listShow(Show.anyShow()).showS(colors), is("List(red,green,blue)")); } enum Colors { diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index 5d2778e5..3eeed489 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -23,7 +23,6 @@ public void traverseList() { int max = 3; List> actual = some(max).traverseList(a -> List.range(1, a + 1)); List> expected = List.range(1, max + 1).map(i -> some(i)); - System.out.println(String.format("actual: %s, expected: %s", actual.toString(), expected.toString())); assertTrue(actual.equals(expected)); } diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java index 27ec26e2..a7c85175 100644 --- a/core/src/test/java/fj/data/SeqTest.java +++ b/core/src/test/java/fj/data/SeqTest.java @@ -3,6 +3,8 @@ import fj.P2; import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -40,7 +42,8 @@ public void convertToString() { @Test public void test() { P2, Seq> p2 = Seq.single(1).split(5); - System.out.println(p2); + assertThat(p2._1(), is(Seq.single(1))); + assertThat(p2._2(), is(Seq.empty())); } } diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index 49840b78..b65e115c 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -107,9 +107,16 @@ public void testMinus() { } @Test - public void testSort() { + public void testSortSeq() { Stream s = range(Enumerator.intEnumerator, 99, -99, -1); assertThat(s.sort(Ord.intOrd, Strategy.seqStrategy()), is(s.sort(Ord.intOrd))); } + + @Test + public void testSortThread() { + Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + assertThat(s.sort(Ord.intOrd, Strategy.simpleThreadStrategy()), + is(s.sort(Ord.intOrd))); + } } diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index d3e60936..96cb95b2 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -38,10 +38,6 @@ public void split() { Show> ss = Show.setShow(Show.stringShow); Show> so = Show.optionShow(Show.stringShow); Show, Option, Set>> sp3 = Show.p3Show(ss, so, ss); - if (true) { - st.println(m2); - sp3.println(p); - } // assert equals Equal> seq = Equal.setEqual(Equal.stringEqual); @@ -70,13 +66,6 @@ public void splitLookup() { List rightList = List.range(pivot + 1, max + 1); TreeMap rightMap = iterableTreeMap(Ord.intOrd, rightList.zip(rightList.map(i -> i.toString()))); - // debug info - if (true) { - Show> st = Show.treeMapShow(Show.intShow, Show.stringShow); - Show, Option, TreeMap>> sp3 = Show.p3Show(st, Show.optionShow(Show.stringShow), st); - sp3.println(p3); - } - // do the assert Equal> tme = Equal.treeMapEqual(Equal.intEqual, Equal.stringEqual); Equal, Option, TreeMap>> eq = Equal.p3Equal(tme, Equal.optionEqual(Equal.stringEqual), tme); From ae70d20b6370531dca2efcd576eefbeb3e03228a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 29 Jul 2018 14:07:30 -0400 Subject: [PATCH 675/811] Implement Zipper Eq and Hash and add tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/Equal.java | 30 +++--- core/src/main/java/fj/Hash.java | 20 ++++ core/src/main/java/fj/data/Zipper.java | 23 +++-- core/src/test/java/fj/data/ZipperTest.java | 110 +++++++++++++++++++++ 4 files changed, 157 insertions(+), 26 deletions(-) create mode 100644 core/src/test/java/fj/data/ZipperTest.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index f427849a..9cf2a72a 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -1,19 +1,6 @@ package fj; -import fj.data.Array; -import fj.data.Either; -import fj.data.LazyString; -import fj.data.List; -import fj.data.Natural; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Seq; -import fj.data.Set; -import fj.data.Stream; -import fj.data.Tree; -import fj.data.TreeMap; -import fj.data.Validation; -import fj.data.Writer; +import fj.data.*; import fj.data.hamt.BitSet; import fj.data.hlist.HList; import fj.data.vector.V2; @@ -455,6 +442,21 @@ public static Equal> streamEqual(final Equal ea) { }); } + /** + * An equal instance for the {@link Zipper} type. + * + * @param ea Equality across the elements of the zipper. + * @return An equal instance for the {@link Zipper} type. + */ + public static Equal> zipperEqual(final Equal ea) { + Equal> se = Equal.streamEqual(ea); + return equalDef((a1, a2) -> + se.eq(a1.lefts(), a2.lefts()) && + ea.eq(a1.focus(), a2.focus()) && + se.eq(a1.rights(), a2.rights()) + ); + } + /** * An equal instance for the {@link Array} type. * diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 14f8a9d7..708fe853 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -262,6 +262,26 @@ public static Hash> arrayHash(final Hash ha) { }); } + /** + * A hash instance for the {@link Zipper} type. + * + * @param ha A hash for the elements of the zipper. + * @return A hash instance for the {@link Zipper} type. + */ + public static Hash> zipperHash(final Hash ha) { + Hash> sh = streamHash(ha); + return hash(as -> { + final int p = 419; + int r = 239; + + r = p * r + sh.hash(as.lefts()); + r = p * r + ha.hash(as.focus()); + r = p * r + sh.hash(as.rights()); + + return r; + }); + } + /** * A hash instance for the {@link Tree} type. * diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index 24414ed2..2514d8e2 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -1,17 +1,6 @@ package fj.data; -import fj.Equal; -import fj.F; -import fj.F2; -import fj.F2Functions; -import fj.F3; -import fj.Function; -import fj.Ord; -import fj.P; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.Show; +import fj.*; import fj.function.Integers; import java.util.Iterator; @@ -106,6 +95,16 @@ public static Ord> ord(final Ord o) { return Ord.p3Ord(so, o, so).contramap(Zipper.p_()); } + @Override + public final boolean equals(Object other) { + return Equal.equals0(Zipper.class, this, other, () -> Equal.zipperEqual(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.zipperHash(Hash.anyHash()).hash(this); + } + /** * An Equal instance for Zippers. * diff --git a/core/src/test/java/fj/data/ZipperTest.java b/core/src/test/java/fj/data/ZipperTest.java new file mode 100644 index 00000000..51c7b4ea --- /dev/null +++ b/core/src/test/java/fj/data/ZipperTest.java @@ -0,0 +1,110 @@ +package fj.data; + +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class ZipperTest { + @Test + public void testZipper() { + Zipper z = Zipper.zipper(Stream.nil(), 0, Stream.range(1, 9)); + assertThat(z.map(i -> i + 13).toStream(), is(Stream.range(13, 22))); + } + + @Test + public void testNext() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.single(3)); + z = z.next().some(); + assertThat(z.lefts(), is(Stream.arrayStream(new Integer[]{2, 1}))); + assertThat(z.focus(), is(3)); + assertThat(z.rights(), is(Stream.nil())); + } + + @Test + public void testNextNone() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.nil()); + assertThat(z.next().isNone(), is(true)); + } + + @Test + public void testCycleNext() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.single(3)); + assertThat(z.cycleNext(), is(z.next().some())); + } + + @Test + public void testCycleNextLast() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.nil()); + z = z.cycleNext(); + assertThat(z.lefts(), is(Stream.nil())); + assertThat(z.focus(), is(1)); + assertThat(z.rights(), is(Stream.single(2))); + } + + @Test + public void testPrevious() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.single(3)); + z = z.previous().some(); + assertThat(z.lefts(), is(Stream.nil())); + assertThat(z.focus(), is(1)); + assertThat(z.rights(), is(Stream.arrayStream(new Integer[]{2, 3}))); + } + + @Test + public void testPreviousNone() { + Zipper z = Zipper.zipper(Stream.nil(), 2, Stream.single(3)); + assertThat(z.previous().isNone(), is(true)); + } + + @Test + public void testCyclePrevious() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.single(3)); + assertThat(z.cyclePrevious(), is(z.previous().some())); + } + + @Test + public void testCyclePreviousFirst() { + Zipper z = Zipper.zipper(Stream.nil(), 1, Stream.single(2)); + z = z.cyclePrevious(); + assertThat(z.lefts(), is(Stream.single(1))); + assertThat(z.focus(), is(2)); + assertThat(z.rights(), is(Stream.nil())); + } + + @Test + public void testInsertLeft() { + Zipper z = Zipper.single(2); + z = z.insertLeft(1); + assertThat(z.lefts(), is(Stream.nil())); + assertThat(z.focus(), is(1)); + assertThat(z.rights(), is(Stream.single(2))); + } + + @Test + public void testInsertRight() { + Zipper z = Zipper.single(2); + z = z.insertRight(3); + assertThat(z.lefts(), is(Stream.single(2))); + assertThat(z.focus(), is(3)); + assertThat(z.rights(), is(Stream.nil())); + } + + @Test + public void testDeleteOthers() { + Zipper z = Zipper.zipper(Stream.single(1), 2, Stream.single(3)); + z = z.deleteOthers(); + assertThat(z.lefts(), is(Stream.nil())); + assertThat(z.focus(), is(2)); + assertThat(z.rights(), is(Stream.nil())); + } + + @Test + public void testFind() { + Zipper z = Zipper.zipper(Stream.nil(), 0, Stream.range(1)); + z = z.find(i -> i == 4).some(); + assertThat(z.lefts(), is(Stream.arrayStream(new Integer[]{3, 2, 1, 0}))); + assertThat(z.focus(), is(4)); + assertThat(z.rights().take(3), is(Stream.range(5, 8))); + } +} From 954a12b31c7430fe4af0aecb0492f02960cc0796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Thu, 2 Aug 2018 17:26:56 -0400 Subject: [PATCH 676/811] Add Vector tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/data/vector/VTest.java | 62 ++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 core/src/test/java/fj/data/vector/VTest.java diff --git a/core/src/test/java/fj/data/vector/VTest.java b/core/src/test/java/fj/data/vector/VTest.java new file mode 100644 index 00000000..027b8407 --- /dev/null +++ b/core/src/test/java/fj/data/vector/VTest.java @@ -0,0 +1,62 @@ +package fj.data.vector; + +import fj.P; +import fj.P2; +import fj.P3; +import fj.P4; +import fj.P5; +import fj.P6; +import fj.P7; +import fj.P8; +import fj.data.Array; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class VTest { + @Test + public void testVectorUp(){ + final P2 p2 = P.p(2, 1); + final V2 v2 = V2.p(p2); + final V3 v3 = V3.cons(P.p(3), v2); + final V4 v4 = V4.cons(P.p(4), v3); + final V5 v5 = V5.cons(P.p(5), v4); + final V6 v6 = V6.cons(P.p(6), v5); + final V7 v7 = V7.cons(P.p(7), v6); + final V8 v8 = V8.cons(P.p(8), v7); + assertThat(v8.toArray(), is(Array.range(1, 9).reverse())); + } + + @Test + public void testVectorP(){ + final P2 p2 = P.p(1, 2); + final V2 v2 = V2.p(p2); + assertThat(v2.toArray(), is(Array.range(1, 3))); + assertThat(v2.p(), is(p2)); + final P3 p3 = p2.append(3); + final V3 v3 = V3.p(p3); + assertThat(v3.toArray(), is(Array.range(1, 4))); + assertThat(v3.p(), is(p3)); + final P4 p4 = p3.append(4); + final V4 v4 = V4.p(p4); + assertThat(v4.toArray(), is(Array.range(1, 5))); + assertThat(v4.p(), is(p4)); + final P5 p5 = p4.append(5); + final V5 v5 = V5.p(p5); + assertThat(v5.toArray(), is(Array.range(1, 6))); + assertThat(v5.p(), is(p5)); + final P6 p6 = p5.append(6); + final V6 v6 = V6.p(p6); + assertThat(v6.toArray(), is(Array.range(1, 7))); + assertThat(v6.p(), is(p6)); + final P7 p7 = p6.append(7); + final V7 v7 = V7.p(p7); + assertThat(v7.toArray(), is(Array.range(1, 8))); + assertThat(v7.p(), is(p7)); + final P8 p8 = p7.append(8); + final V8 v8 = V8.p(p8); + assertThat(v8.toArray(), is(Array.range(1, 9))); + assertThat(v8.p(), is(p8)); + } +} From ba27e71970287988d0ca5125d7316439dd7dd1ef Mon Sep 17 00:00:00 2001 From: Gabor Liptak Date: Thu, 2 Aug 2018 20:41:08 -0400 Subject: [PATCH 677/811] Add Optic tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/data/optic/IsoTest.java | 43 ++++++ .../src/test/java/fj/data/optic/LensTest.java | 123 ++++++++++++++++++ .../test/java/fj/data/optic/OptionalTest.java | 29 +++++ .../test/java/fj/data/optic/PrismTest.java | 29 +++++ .../java/fj/data/optic/TraversalTest.java | 23 ++++ 5 files changed, 247 insertions(+) create mode 100644 core/src/test/java/fj/data/optic/IsoTest.java create mode 100644 core/src/test/java/fj/data/optic/LensTest.java create mode 100644 core/src/test/java/fj/data/optic/OptionalTest.java create mode 100644 core/src/test/java/fj/data/optic/PrismTest.java create mode 100644 core/src/test/java/fj/data/optic/TraversalTest.java diff --git a/core/src/test/java/fj/data/optic/IsoTest.java b/core/src/test/java/fj/data/optic/IsoTest.java new file mode 100644 index 00000000..6cace533 --- /dev/null +++ b/core/src/test/java/fj/data/optic/IsoTest.java @@ -0,0 +1,43 @@ +package fj.data.optic; + +import fj.P; +import fj.P2; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class IsoTest { + @Test + public void testIso() { + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Iso> addressIso = Iso.iso(p -> P.p(p.number, p.street), + p -> new Address(p._1(), p._2())); + final Address a = addressIso.reverseGet(addressIso.get(oldAddress)); + assertThat(a.number, is(oldAddress.number)); + assertThat(a.street, is(oldAddress.street)); + } + + static final class Person { + String name; + Address address; + + Person(String name, Address address) { + this.name = name; + this.address = address; + } + } + + static final class Address { + int number; + String street; + + public Address(int number, String street) { + this.number = number; + this.street = street; + } + } + +} diff --git a/core/src/test/java/fj/data/optic/LensTest.java b/core/src/test/java/fj/data/optic/LensTest.java new file mode 100644 index 00000000..d78fa0d0 --- /dev/null +++ b/core/src/test/java/fj/data/optic/LensTest.java @@ -0,0 +1,123 @@ +package fj.data.optic; + +import fj.F; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class LensTest { + @Test + public void testLensPersonGet() { + final String oldName = "Joe"; + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Person oldPerson = new Person(oldName, oldAddress); + final Lens personNameLens = Lens.lens(p -> p.name, s -> p -> new Person(s, p.address)); + final Lens personAddressLens = Lens.lens(p -> p.address, a -> p -> new Person(p.name, a)); + final Lens addressNumberLens = Lens.lens(a -> a.number, n -> a -> new Address(n, a.street)); + final Lens addressStreetLens = Lens.lens(a -> a.street, s -> a -> new Address(a.number, s)); + final Lens personNumberLens = personAddressLens.composeLens(addressNumberLens); + final Lens personStreetLens = personAddressLens.composeLens(addressStreetLens); + assertThat(personNameLens.get(oldPerson), is(oldName)); + assertThat(personNumberLens.get(oldPerson), is(oldNumber)); + assertThat(personStreetLens.get(oldPerson), is(oldStreet)); + } + + @Test + public void testLensPersonSetName() { + final String oldName = "Joe"; + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Person oldPerson = new Person(oldName, oldAddress); + final Lens personNameLens = Lens.lens(p -> p.name, s -> p -> new Person(s, p.address)); + String newName = "Bill"; + Person p = personNameLens.set(newName).f(oldPerson); + assertThat(p.name, is(newName)); + assertThat(p.address, is(oldPerson.address)); + } + + @Test + public void testLensPersonSetNumber() { + final String oldName = "Joe"; + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Person oldPerson = new Person(oldName, oldAddress); + final Lens personAddressLens = Lens.lens(p -> p.address, a -> p -> new Person(p.name, a)); + final Lens addressNumberLens = Lens.lens(a -> a.number, n -> a -> new Address(n, a.street)); + final Lens personNumberLens = personAddressLens.composeLens(addressNumberLens); + int newNumber = 20; + Person p = personNumberLens.set(newNumber).f(oldPerson); + assertThat(p.name, is(oldName)); + assertThat(p.address.number, is(newNumber)); + assertThat(p.address.street, is(oldStreet)); + } + + @Test + public void testLensPersonSetStreet() { + final String oldName = "Joe"; + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Person oldPerson = new Person(oldName, oldAddress); + final Lens personAddressLens = Lens.lens(p -> p.address, a -> p -> new Person(p.name, a)); + final Lens addressNumberLens = Lens.lens(a -> a.number, n -> a -> new Address(n, a.street)); + final Lens addressStreetLens = Lens.lens(a -> a.street, s -> a -> new Address(a.number, s)); + final Lens personStreetLens = personAddressLens.composeLens(addressStreetLens); + String newStreet = "First St"; + Person p = personStreetLens.set(newStreet).f(oldPerson); + assertThat(p.name, is(oldName)); + assertThat(p.address.number, is(oldPerson.address.number)); + assertThat(p.address.street, is(newStreet)); + } + + @Test + public void testLensPersonSetter() { + final String oldName = "Joe"; + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Person oldPerson = new Person(oldName, oldAddress); + final Lens personNameLens = Lens.lens(p -> p.name, s -> p -> new Person(s, p.address)); + String newName = "Bill"; + F setter = personNameLens.asSetter().set(newName); + Person p = setter.f(oldPerson); + assertThat(p.name, is(newName)); + assertThat(p.address, is(oldPerson.address)); + } + + @Test + public void testLensPersonGetter() { + final String oldName = "Joe"; + final int oldNumber = 10; + final String oldStreet = "Main St"; + final Address oldAddress = new Address(oldNumber, oldStreet); + final Person oldPerson = new Person(oldName, oldAddress); + final Lens personNameLens = Lens.lens(p -> p.name, s -> p -> new Person(s, p.address)); + assertThat(personNameLens.asGetter().get(oldPerson), is(oldName)); + } + + static final class Person { + String name; + Address address; + + Person(String name, Address address) { + this.name = name; + this.address = address; + } + } + + static final class Address { + int number; + String street; + + public Address(int number, String street) { + this.number = number; + this.street = street; + } + } + +} diff --git a/core/src/test/java/fj/data/optic/OptionalTest.java b/core/src/test/java/fj/data/optic/OptionalTest.java new file mode 100644 index 00000000..07c3f79a --- /dev/null +++ b/core/src/test/java/fj/data/optic/OptionalTest.java @@ -0,0 +1,29 @@ +package fj.data.optic; + +import fj.data.Option; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class OptionalTest { + @Test + public void testOptionalSome() { + Optional o = Optional.optional(this::decode, i -> s -> s); + assertThat(o.getOption("18"), is(Option.some(18))); + } + + @Test + public void testOptionalNone() { + Optional o = Optional.optional(this::decode, i -> s -> s); + assertThat(o.getOption("Z"), is(Option.none())); + } + + private Option decode(String s) { + try { + return Option.some(Integer.decode(s)); + } catch (NumberFormatException nfe) { + return Option.none(); + } + } +} diff --git a/core/src/test/java/fj/data/optic/PrismTest.java b/core/src/test/java/fj/data/optic/PrismTest.java new file mode 100644 index 00000000..da128d72 --- /dev/null +++ b/core/src/test/java/fj/data/optic/PrismTest.java @@ -0,0 +1,29 @@ +package fj.data.optic; + +import fj.data.Option; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class PrismTest { + @Test + public void testPrismSome() { + Prism prism = Prism.prism(s -> decode(s), i -> i.toString()); + assertThat(prism.getOption("18"), is(Option.some(18))); + } + + @Test + public void testPrismNone() { + Prism prism = Prism.prism(s -> decode(s), i -> i.toString()); + assertThat(prism.getOption("Z"), is(Option.none())); + } + + private Option decode(String s) { + try { + return Option.some(Integer.decode(s)); + } catch (NumberFormatException nfe) { + return Option.none(); + } + } +} diff --git a/core/src/test/java/fj/data/optic/TraversalTest.java b/core/src/test/java/fj/data/optic/TraversalTest.java new file mode 100644 index 00000000..cadd6ccf --- /dev/null +++ b/core/src/test/java/fj/data/optic/TraversalTest.java @@ -0,0 +1,23 @@ +package fj.data.optic; + +import fj.Monoid; +import fj.data.Either; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class TraversalTest { + @Test + public void testTraversalLeft() { + final Traversal, Integer> t = Traversal.codiagonal(); + assertThat(t.fold(Monoid.intMinMonoid).f(Either.left(3)), is(3)); + } + + @Test + public void testTraversalRight() { + final Traversal, Integer> t = Traversal.codiagonal(); + assertThat(t.fold(Monoid.intMinMonoid).f(Either.right(2)), is(2)); + } + +} From 22cf4b4a06298c79701e61384fa5baffb0eb34a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Fri, 3 Aug 2018 21:03:45 -0400 Subject: [PATCH 678/811] Add Parser tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/Equal.java | 8 +++ core/src/main/java/fj/Hash.java | 20 ++++++++ core/src/main/java/fj/Show.java | 14 ++++++ core/src/main/java/fj/parser/Result.java | 19 +++++++ core/src/test/java/fj/parser/ParserTest.java | 52 ++++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 core/src/test/java/fj/parser/ParserTest.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 9cf2a72a..a798a736 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -10,6 +10,7 @@ import fj.data.vector.V6; import fj.data.vector.V7; import fj.data.vector.V8; +import fj.parser.Result; import java.math.BigDecimal; import java.math.BigInteger; @@ -355,6 +356,13 @@ public static Equal> eitherEqual(final Equal ea, final Eq )); } + public static Equal> resultEqual(final Equal ea, final Equal ei) { + Definition eaDef = ea.def; + Definition eiDef= ei.def; + return equalDef((r1, r2) -> eaDef.equal(r1.value(), r2.value()) && eiDef.equal(r1.rest(), r2.rest())); + } + + /** * An equal instance for the {@link Validation} type. * diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 708fe853..da443ab2 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -10,6 +10,7 @@ import fj.data.vector.V6; import fj.data.vector.V7; import fj.data.vector.V8; +import fj.parser.Result; import java.math.BigDecimal; import java.math.BigInteger; @@ -162,6 +163,25 @@ public static Hash> eitherHash(final Hash ha, final Hash< return hash(e -> e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value())); } + /** + * A hash instance for the {@link Result} type. + * + * @param ha Hash the Result value. + * @param hi Hash the Result remainder. + * @return A hash instance for the {@link Result} type. + */ + public static Hash> resultHash(Hash ha, Hash hi) { + return hash(res -> { + final int p = 419; + int r = 239; + + r = p * r + ha.hash(res.value()); + r = p * r + hi.hash(res.rest()); + + return r; + }); + } + /** * A hash instance for the {@link Validation} type. * diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 2d2c4707..cd57897b 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -12,6 +12,7 @@ import fj.data.vector.V6; import fj.data.vector.V7; import fj.data.vector.V8; +import fj.parser.Result; import java.math.BigDecimal; import java.math.BigInteger; @@ -255,6 +256,19 @@ public static Show> eitherShow(final Show sa, final Show< fromString("Right(").append(sb.f.f(e.right().value())).append(single(')'))); } + /** + * A show instance for the {@link Result} type. + * + * @param sa Show for the {@link Result} value. + * @param si Show for the {@link Result} remainder. + * @return A show instance for the {@link Result} type. + */ + public static Show> resultShow(Show sa, Show si) { + return show(res -> + fromString("Result(").append(sa.f.f(res.value())) + .append(single(',')).append(si.f.f(res.rest())).append(single(')'))); + } + /** * A show instance for the {@link Validation} type. * diff --git a/core/src/main/java/fj/parser/Result.java b/core/src/main/java/fj/parser/Result.java index 51e115f6..b8acc6c4 100644 --- a/core/src/main/java/fj/parser/Result.java +++ b/core/src/main/java/fj/parser/Result.java @@ -1,6 +1,9 @@ package fj.parser; +import fj.Equal; import fj.F; +import fj.Hash; +import fj.Show; import static fj.Function.curry; @@ -21,6 +24,22 @@ private Result(final I i, final A a) { this.a = a; } + @Override + public final int hashCode() { + return Hash.resultHash(Hash.anyHash(), Hash.anyHash()).hash(this); + } + + @Override + public final String toString() { + return Show.resultShow(Show.anyShow(), Show.anyShow()).showS(this); + } + + @Override + public final boolean equals(Object other) { + return Equal.equals0(Result.class, this, other, () -> Equal.resultEqual(Equal.anyEqual(), Equal.anyEqual())); + } + + /** * The remainder of the parse input. * diff --git a/core/src/test/java/fj/parser/ParserTest.java b/core/src/test/java/fj/parser/ParserTest.java new file mode 100644 index 00000000..a3f623f5 --- /dev/null +++ b/core/src/test/java/fj/parser/ParserTest.java @@ -0,0 +1,52 @@ +package fj.parser; + +import fj.F; +import fj.F0; +import fj.data.Stream; +import fj.data.Validation; +import org.junit.Test; + +import static fj.parser.Result.result; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class ParserTest { + @Test + public void testParserFail() { + final Parser fail = Parser.fail(new ParseException()); + assertThat(fail.parse("").fail(), is(new ParseException())); + } + + @Test + public void testParserValue() { + final Parser p = Parser.parser(s -> s.isEmpty() ? + Validation.fail(new ParseException()) : + Validation.success(result(s.substring(1), s.substring(0, 1))) + ); + final Result r = p.parse("abc").success(); + assertThat(r.value(), is("a")); + assertThat(r.rest(), is("bc")); + } + + @Test + public void testParserBind() { + final Parser p = Parser.value("a"); + final Parser fail = Parser.fail(new ParseException()); + assertThat(p.bind(o -> fail).parse("aaaa").fail(), is(new ParseException())); + } + + @Test + public void testParserStream() { + Stream s = Stream.fromString("abc"); + Result, Character> r = Parser.CharsParser.character('a').parse(s).success(); + assertThat(r, is(Result.result(Stream.fromString("bc"), 'a'))); + } + + class ParseException extends Exception { + @Override + public boolean equals (Object obj) { + return (obj instanceof ParseException); + } + } + +} From ca67637f62aba38fc84056378601b9e88bb69a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 4 Aug 2018 15:24:14 -0400 Subject: [PATCH 679/811] Implement Vector equals MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/data/vector/V2.java | 10 ++++ core/src/main/java/fj/data/vector/V3.java | 10 ++++ core/src/main/java/fj/data/vector/V4.java | 10 ++++ core/src/main/java/fj/data/vector/V5.java | 10 ++++ core/src/main/java/fj/data/vector/V6.java | 10 ++++ core/src/main/java/fj/data/vector/V7.java | 10 ++++ core/src/main/java/fj/data/vector/V8.java | 10 ++++ core/src/test/java/fj/data/vector/VTest.java | 60 +++++++++++++++++--- 8 files changed, 122 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/data/vector/V2.java b/core/src/main/java/fj/data/vector/V2.java index fdab115c..d1ec5e74 100644 --- a/core/src/main/java/fj/data/vector/V2.java +++ b/core/src/main/java/fj/data/vector/V2.java @@ -23,6 +23,16 @@ private V2(final P2 inner) { this.inner = inner; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V2.class, this, other, () -> Equal.v2Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v2Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-2 from a homogeneous product-2. * diff --git a/core/src/main/java/fj/data/vector/V3.java b/core/src/main/java/fj/data/vector/V3.java index 9b25258f..523c08ae 100644 --- a/core/src/main/java/fj/data/vector/V3.java +++ b/core/src/main/java/fj/data/vector/V3.java @@ -23,6 +23,16 @@ private V3(final P1 head, final V2 tail) { this.tail = tail; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V3.class, this, other, () -> Equal.v3Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v3Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-3 from a homogeneous product-3. * diff --git a/core/src/main/java/fj/data/vector/V4.java b/core/src/main/java/fj/data/vector/V4.java index 1f39346b..808e7bab 100644 --- a/core/src/main/java/fj/data/vector/V4.java +++ b/core/src/main/java/fj/data/vector/V4.java @@ -23,6 +23,16 @@ private V4(final P1 head, final V3 tail) { this.tail = tail; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V4.class, this, other, () -> Equal.v4Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v4Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-4 from a homogeneous product-4. * diff --git a/core/src/main/java/fj/data/vector/V5.java b/core/src/main/java/fj/data/vector/V5.java index 0119dcf9..8f0583a3 100644 --- a/core/src/main/java/fj/data/vector/V5.java +++ b/core/src/main/java/fj/data/vector/V5.java @@ -23,6 +23,16 @@ private V5(final P1 head, final V4 tail) { this.tail = tail; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V5.class, this, other, () -> Equal.v5Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v5Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-5 from a homogeneous product-5. * diff --git a/core/src/main/java/fj/data/vector/V6.java b/core/src/main/java/fj/data/vector/V6.java index 47a0c4e7..880deaff 100644 --- a/core/src/main/java/fj/data/vector/V6.java +++ b/core/src/main/java/fj/data/vector/V6.java @@ -23,6 +23,16 @@ private V6(final P1 head, final V5 tail) { this.tail = tail; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V6.class, this, other, () -> Equal.v6Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v6Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-6 from a homogeneous product-6. * diff --git a/core/src/main/java/fj/data/vector/V7.java b/core/src/main/java/fj/data/vector/V7.java index c0dfa4b6..2127d5f4 100644 --- a/core/src/main/java/fj/data/vector/V7.java +++ b/core/src/main/java/fj/data/vector/V7.java @@ -23,6 +23,16 @@ private V7(final P1 head, final V6 tail) { this.tail = tail; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V7.class, this, other, () -> Equal.v7Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v7Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-7 from a homogeneous product-7. * diff --git a/core/src/main/java/fj/data/vector/V8.java b/core/src/main/java/fj/data/vector/V8.java index f01dc2fe..9ca7b618 100644 --- a/core/src/main/java/fj/data/vector/V8.java +++ b/core/src/main/java/fj/data/vector/V8.java @@ -23,6 +23,16 @@ private V8(final P1 head, final V7 tail) { this.tail = tail; } + @Override + public final boolean equals(Object other) { + return Equal.equals0(V8.class, this, other, () -> Equal.v8Equal(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.v8Hash(Hash.anyHash()).hash(this); + } + /** * Creates a vector-8 from a homogeneous product-8. * diff --git a/core/src/test/java/fj/data/vector/VTest.java b/core/src/test/java/fj/data/vector/VTest.java index 027b8407..9a3709ac 100644 --- a/core/src/test/java/fj/data/vector/VTest.java +++ b/core/src/test/java/fj/data/vector/VTest.java @@ -1,13 +1,6 @@ package fj.data.vector; -import fj.P; -import fj.P2; -import fj.P3; -import fj.P4; -import fj.P5; -import fj.P6; -import fj.P7; -import fj.P8; +import fj.*; import fj.data.Array; import org.junit.Test; @@ -59,4 +52,55 @@ public void testVectorP(){ assertThat(v8.toArray(), is(Array.range(1, 9))); assertThat(v8.p(), is(p8)); } + + @Test + public void testVectorFunc2() { + V2 v2 = V.v(() -> 2, () -> 1); + F2> fv2 = V.v2(); + V2 vf2 = fv2.f(2, 1); + assertThat(vf2, is(v2)); + } + + @Test + public void testVectorFunc3() { + V3 v3 = V.v(P.p(3), () -> 2, () -> 1); + F3> fv3 = V.v3(); + V3 vf3 = fv3.f(3, 2, 1); + assertThat(vf3, is(v3)); + } + + @Test + public void testVectorFunc4() { + V4 v4 = V.v(P.p(4), P.p(3), () -> 2, () -> 1); + F4> fv4 = V.v4(); + V4 vf4 = fv4.f(4, 3, 2, 1); + assertThat(vf4, is(v4)); + } + + @Test + public void testVectorFunc5() { + V5 v5 = V.v(P.p(5), P.p(4), P.p(3), () -> 2, () -> 1); + F5> fv5 = V.v5(); + V5 vf5 = fv5.f(5, 4, 3, 2, 1); + assertThat(vf5, is(v5)); + } + + @Test + public void testVectorMap() { + final V2 v2 = V.v(() -> 2, () -> 1); + assertThat(v2, is(v2.map(i -> i * 1))); + final V3 v3 = V3.cons(P.p(3), v2); + assertThat(v3, is(v3.map(i -> i * 1))); + final V4 v4 = V4.cons(P.p(4), v3); + assertThat(v4, is(v4.map(i -> i * 1))); + final V5 v5 = V5.cons(P.p(5), v4); + assertThat(v5, is(v5.map(i -> i * 1))); + final V6 v6 = V6.cons(P.p(6), v5); + assertThat(v6, is(v6.map(i -> i * 1))); + final V7 v7 = V7.cons(P.p(7), v6); + assertThat(v7, is(v7.map(i -> i * 1))); + final V8 v8 = V8.cons(P.p(8), v7); + assertThat(v8, is(v8.map(i -> i * 1))); + } + } From 7e149a63b478ce943b4e8c5d2cd5c7c909a71eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 11 Aug 2018 19:42:46 -0400 Subject: [PATCH 680/811] Add FingerTree tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/FWFunctionsTest.java | 1 - .../fj/data/fingertrees/FingerTreeTest.java | 37 ++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/core/src/test/java/fj/FWFunctionsTest.java b/core/src/test/java/fj/FWFunctionsTest.java index b9ce65d5..c1f69718 100644 --- a/core/src/test/java/fj/FWFunctionsTest.java +++ b/core/src/test/java/fj/FWFunctionsTest.java @@ -2,7 +2,6 @@ import org.junit.Test; -import fj.F1W; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index 2a64b44b..57e1fae6 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -1,19 +1,19 @@ package fj.data.fingertrees; +import fj.Function; import fj.P; import fj.P2; -import fj.Show; import fj.data.List; -import fj.data.Stream; +import fj.data.Option; import org.junit.Test; -import static fj.P.p; -import static fj.Show.intShow; -import static fj.test.Property.prop; -import static fj.test.Property.property; -import static java.lang.System.out; +import static fj.Monoid.intAdditionMonoid; +import static fj.Monoid.intMinMonoid; +import static fj.data.fingertrees.FingerTree.measured; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; +import static org.hamcrest.core.Is.is; + /** * Created by MarkPerry on 10/10/2015. @@ -24,18 +24,35 @@ public class FingerTreeTest { @Test public void size() { - validateSize(List.list(-92, 68, 54, -77, -18, 67)); - validateSize(List.list(-92, 68, 54, -77, -18, 67, -60, 23, -70, 99, 66, -79, -5)); + validateOperations(List.list(-92, 68, 54, -77, -18, 67)); + validateOperations(List.list(-92, 68, 54, -77, -18, 67, -60, 23, -70, 99, 66, -79, -5)); } - void validateSize(List list) { + void validateOperations(List list) { FingerTree ft = list.foldLeft( (acc, i) -> acc.snoc(i), FingerTree.emptyIntAddition() ); assertThat(ft.measure(), equalTo(list.length())); + assertThat(ft.foldLeft((s, i) -> s + 1, 0), equalTo(list.length())); + assertThat(ft.foldRight((i, s) -> 1 + s, 0), equalTo(list.length())); + assertThat(ft.filter(e -> e.equals(-77)).head(), equalTo(-77)); assertThat(ft.length(), equalTo(list.length())); } + @Test + public void testHeadOption() { + assertThat(Empty.emptyIntAddition().headOption(), is(Option.none())); + FingerTree ft = new MakeTree(measured(intAdditionMonoid, Function.constant(1))).single(1); + assertThat(ft.headOption(), is(Option.some(1))); + } + + @Test + public void testUncons() { + assertThat(Empty.emptyIntAddition().uncons(0, (h, t) -> h), is(0)); + FingerTree ft = new MakeTree(measured(intAdditionMonoid, Function.constant(1))).single(1); + assertThat(ft.uncons(0, (h, t) -> h), is(1)); + } + public FingerTree midSeq() { FingerTree ft = FingerTree.emptyIntAddition(); return List.range(1, SIZE).foldLeft(ft2 -> i -> ft2.snoc(i), ft); From c2392a12e6e4a4f61508a2fd0f9e905bd5d65c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 13 Aug 2018 16:40:27 -0400 Subject: [PATCH 681/811] Add Reader/Writer tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- props-core/src/test/java/fj/data/ReaderTest.java | 16 +++++++++++++++- props-core/src/test/java/fj/data/WriterTest.java | 14 ++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index 8494336e..87e2b52a 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -11,6 +11,8 @@ import static fj.test.Cogen.cogenInteger; import static fj.test.Property.prop; import static fj.test.Property.property; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; /** @@ -24,7 +26,6 @@ public void testMap() { // example taken from http://learnyouahaskell.com/for-a-few-monads-more int x = Reader.unit((Integer i) -> i + 3).map(i -> i * 5).f(8); assertTrue(x == 55); -// System.out.println(x); // 55 } @Test @@ -108,6 +109,19 @@ public void testAssociativity() { PropertyAssert.assertResult(p); } + @Test + public void testAndThen() { + final int y = Reader.unit((Integer i) -> i * 2).andThen(i -> i + 10).f(10); + assertThat(y, is(30)); + } + + @Test + public void testBind() { + final int y = Reader.unit((Integer i) -> i * 2) + .bind(a -> Reader.unit(i -> a + i + 11)).f(10); + assertThat(y, is(41)); + } + public Gen> arbReader() { return Arbitrary.arbReader(cogenInteger, arbInteger); } diff --git a/props-core/src/test/java/fj/data/WriterTest.java b/props-core/src/test/java/fj/data/WriterTest.java index 5f0ac122..25f99b22 100644 --- a/props-core/src/test/java/fj/data/WriterTest.java +++ b/props-core/src/test/java/fj/data/WriterTest.java @@ -2,8 +2,7 @@ import fj.Equal; import fj.F; -import fj.data.test.PropertyAssert; -import fj.test.Arbitrary; +import fj.P; import fj.test.Gen; import fj.test.Property; import org.junit.Assert; @@ -14,7 +13,8 @@ import static fj.test.Cogen.cogenInteger; import static fj.test.Property.prop; import static fj.test.Property.property; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; /** * Created by MarkPerry on 17/12/2014. @@ -107,7 +107,13 @@ public void testAssociativity() { assertResult(p); } - + @Test + public void testUnit() { + Writer w = Writer.unit("+").tell("foo").tell("bar"); + assertThat(w.run(), is(P.p("foobar", "+"))); + assertThat(w.log(), is("foobar")); + assertThat(w.value(), is("+")); + } } From 69fbd1d451d3382aee4e5bca5bd775b6631fc0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 12 Aug 2018 13:04:21 -0400 Subject: [PATCH 682/811] Add TreeZipper tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/Equal.java | 20 ++++++++++++ core/src/main/java/fj/Hash.java | 26 ++++++++++++++- core/src/main/java/fj/data/TreeZipper.java | 25 +++++++++++++-- core/src/test/java/fj/FFunctionsTest.java | 18 +++++++++++ .../src/test/java/fj/data/TreeZipperTest.java | 32 +++++++++++++++++++ 5 files changed, 117 insertions(+), 4 deletions(-) create mode 100644 core/src/test/java/fj/data/TreeZipperTest.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index a798a736..5cd31aeb 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -3,6 +3,7 @@ import fj.data.*; import fj.data.hamt.BitSet; import fj.data.hlist.HList; +import fj.data.optic.Traversal; import fj.data.vector.V2; import fj.data.vector.V3; import fj.data.vector.V4; @@ -466,6 +467,25 @@ public static Equal> zipperEqual(final Equal ea) { } /** + * An equal instance for the {@link TreeZipper} type. + * + * @param ea Equality across the elements of the tree zipper. + * @return An equal instance for the {@link TreeZipper} type. + */ + public static Equal> treeZipperEqual(final Equal ea) { + final Equal> te = Equal.treeEqual(ea); + final Equal>> st = streamEqual(Equal.treeEqual(ea)); + final Equal>, A, Stream>>>> sp = + streamEqual(p3Equal(streamEqual(treeEqual(ea)), ea, streamEqual(treeEqual(ea)))); + return equalDef((a1, a2) -> + te.eq(a1.focus(), a2.focus()) && + st.eq(a1.lefts(), a2.lefts()) && + st.eq(a1.rights(), a2.rights()) && + sp.eq(a1.parents(), a2.parents()) + ); + } + + /** * An equal instance for the {@link Array} type. * * @param ea Equality across the elements of the array. diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index da443ab2..8d0a4e4c 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -302,7 +302,31 @@ public static Hash> zipperHash(final Hash ha) { }); } - /** + /** + * A hash instance for the {@link TreeZipper} type. + * + * @param ha A hash for the elements of the tree zipper. + * @return A hash instance for the {@link TreeZipper} type. + */ + public static Hash> treeZipperHash(final Hash ha) { + Hash> th = treeHash(ha); + Hash>> sth = streamHash(treeHash(ha)); + Hash>, A, Stream>>>> tsp = + streamHash(p3Hash(streamHash(treeHash(ha)), ha, streamHash(treeHash(ha)))); + return hash(as -> { + final int p = 419; + int r = 239; + + r = p * r + th.hash(as.focus()); + r = p * r + sth.hash(as.lefts()); + r = p * r + sth.hash(as.rights()); + r = p * r + tsp.hash(as.parents()); + + return r; + }); + } + + /** * A hash instance for the {@link Tree} type. * * @param ha A hash for the elements of the tree. diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index c94287cf..46392d20 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -54,7 +54,17 @@ private TreeZipper(final Tree tree, this.parents = parents; } - /** + @Override + public final boolean equals(Object other) { + return Equal.equals0(TreeZipper.class, this, other, () -> Equal.treeZipperEqual(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.treeZipperHash(Hash.anyHash()).hash(this); + } + + /** * Creates a new tree zipper given a currently selected tree, a forest on the left, a forest on the right, * and a stream of parent contexts. * @@ -341,8 +351,17 @@ public Stream> lefts() { * @return the right siblings of the currently focused node. */ public Stream> rights() { - return rights; - } + return rights; + } + + /** + * Returns the parents of the currently focused node. + * + * @return the parents of the currently focused node. + */ + public Stream>, A, Stream>>> parents() { + return parents; + } /** * Indicates whether the current node is at the top of the tree. diff --git a/core/src/test/java/fj/FFunctionsTest.java b/core/src/test/java/fj/FFunctionsTest.java index 9d38e1f5..e13b1f2b 100644 --- a/core/src/test/java/fj/FFunctionsTest.java +++ b/core/src/test/java/fj/FFunctionsTest.java @@ -1,5 +1,7 @@ package fj; +import fj.data.Tree; +import fj.data.TreeZipper; import org.junit.Test; import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; @@ -22,4 +24,20 @@ public void testApply() { F f1 = F2Functions.f(f2, 2); assertThat(F1Functions.f(f1, 1).f(), is(36)); } + + @Test + public void testTreeK() { + final Tree t1 = F1Functions.treeK(Function.identity()).f(1); + final Tree t2 = F1Functions.treeK(Function.identity()).f(2); + assertThat(F1Functions.mapTree(i -> i + 1).f(t1), + is(F1Functions.mapTree(i -> i * 1).f(t2))); + } + + @Test + public void testTreeZipperK() { + final TreeZipper tz1 = F1Functions.treeZipperK(Function.identity()).f(1); + final TreeZipper tz2 = F1Functions.treeZipperK(Function.identity()).f(2); + assertThat(F1Functions.mapTreeZipper(i -> i + 1).f(tz1), + is(F1Functions.mapTreeZipper(i -> i * 1).f(tz2))); + } } diff --git a/core/src/test/java/fj/data/TreeZipperTest.java b/core/src/test/java/fj/data/TreeZipperTest.java new file mode 100644 index 00000000..c52f4111 --- /dev/null +++ b/core/src/test/java/fj/data/TreeZipperTest.java @@ -0,0 +1,32 @@ +package fj.data; + +import org.junit.Test; + +import static fj.data.Option.none; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class TreeZipperTest { + @Test + public void testDelete() { + final Tree t = Tree.node(1, List.single(Tree.leaf(2))); + final TreeZipper tz = TreeZipper.fromTree(t); + assertThat(tz.delete(), is(none())); + } + + @Test + public void testDeleteForest() { + final Tree t = Tree.node(1, List.single(Tree.leaf(2))); + final TreeZipper tz = TreeZipper.fromForest(Stream.single(t)).some(); + assertThat(tz.delete(), is(none())); + + } + + @Test + public void testHash() { + final Tree t = Tree.node(1, List.single(Tree.leaf(2))); + final TreeZipper tz1 = TreeZipper.fromForest(Stream.single(t)).some(); + final TreeZipper tz2 = TreeZipper.fromForest(Stream.single(t)).some(); + assertThat(tz1.hashCode(), is(tz2.hashCode())); + } +} From 02d05ebaa451c33a1c0eedbcc1408e35eec7ad60 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 18 Aug 2018 22:41:08 +0200 Subject: [PATCH 683/811] ChangeLog of 4.8 release. --- .changelogged.yaml | 14 ++++++++++++++ ChangeLog.md | 33 +++++++++++++++++++++++++++++++++ build.gradle | 4 ++-- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 .changelogged.yaml create mode 100644 ChangeLog.md diff --git a/.changelogged.yaml b/.changelogged.yaml new file mode 100644 index 00000000..46180488 --- /dev/null +++ b/.changelogged.yaml @@ -0,0 +1,14 @@ +changelogs: + - changelog: ChangeLog.md + + ignore_files: + - "*ChangeLog*.md" + - .changelogged.yaml + + ignore_commits: [] + +branch: upstream/master + +entry_format: " - %message% (see [%link%](%id%));" + +editor_command: "nano -EiT 2" diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 00000000..24276f35 --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,33 @@ +4.8 +--- + +### Enhancements + +- Enable upload of snapshot artifacts. (see [`e834e8b`](https://github.com/functionaljava/functionaljava/commit/e834e8b)); +- Add append methods to all Px classes. Fix #326 (see [`065ed43`](https://github.com/functionaljava/functionaljava/commit/065ed43)); +- Introduce the Eval monad (see [`98294fc`](https://github.com/functionaljava/functionaljava/commit/98294fc)); +- Fluent Equal/Ord construction (see [#333](https://github.com/functionaljava/functionaljava/pull/333)); +- Implement Zipper Eq and Hash and add tests (see [#343](https://github.com/functionaljava/functionaljava/pull/343)); +- Implement Vector equals (see [#350](https://github.com/functionaljava/functionaljava/pull/350)); + +### Fixes + +- Fixed a bug in the NonEmptyList Semigroup implementation that resulted in the same NonEmptyList appended to itself. (Regression in 4.7, see [`07f94fa`](https://github.com/functionaljava/functionaljava/commit/07f94fa)); +- Fixes #334: exception in Either.LeftProjection.traverseIO (see [#335](https://github.com/functionaljava/functionaljava/pull/335)); + +### Internal + +- Added Scalacheck Arbitrary implementations for Natural and NonEmptyList. (see [`405c3ec`](https://github.com/functionaljava/functionaljava/commit/405c3ec)); +- Added unit test coverage for Semigroup implementations. The StringBuffer and StringBuilder tests fail because both of those types are mutable. The IO test fails because the ArbitraryIO implementation does not implement equals. (see [`ef81130`](https://github.com/functionaljava/functionaljava/commit/ef81130)); +- Fixed the ArbitraryIO implementation and created a Properties object for testing the IO semigroup. (see [`a8e979f`](https://github.com/functionaljava/functionaljava/commit/a8e979f)); +- Added working tests coverage for the StringBuffer and StringBuilder semigroup implementations. Added the Semigroup tests to the list of Scalacheck test suite. (see [`aa4de33`](https://github.com/functionaljava/functionaljava/commit/aa4de33)); +- Equal: remove reference to static field of LazyString. Fix #321 (see [`6c6dabd`](https://github.com/functionaljava/functionaljava/commit/6c6dabd)); +- Add IOFunctions tests (see [#340](https://github.com/functionaljava/functionaljava/pull/340)); +- Add Stream tests (see [#341](https://github.com/functionaljava/functionaljava/pull/341)); +- Add tests for Try, F, FW, Digit (see [#346](https://github.com/functionaljava/functionaljava/pull/346)); +- Add Vector tests (see [#347](https://github.com/functionaljava/functionaljava/pull/347)); +- Add Optic tests (see [#348](https://github.com/functionaljava/functionaljava/pull/348)); +- Add Parser tests (see [#349](https://github.com/functionaljava/functionaljava/pull/349)); +- Add FingerTree tests (see [#351](https://github.com/functionaljava/functionaljava/pull/351)); +- Add TreeZipper tests (see [#352](https://github.com/functionaljava/functionaljava/pull/352)); +- Add Reader/Writer tests (see [#353](https://github.com/functionaljava/functionaljava/pull/353)); \ No newline at end of file diff --git a/build.gradle b/build.gradle index a1098cbb..9410f205 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.8" snapshotAppendix = "-SNAPSHOT" @@ -53,7 +53,7 @@ allprojects { fjConsumeVersion = "4.7" signModule = false - useRetroLambda = false + useRetroLambda = true projectTitle = "Functional Java" projectName = "functionaljava" From 8cce3ee2d3c221a67b06e48f616532ecfa58b122 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 18 Aug 2018 23:29:19 +0200 Subject: [PATCH 684/811] Update readme. Prepare next iteration. --- README.adoc | 18 +++++++++--------- build.gradle | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.adoc b/README.adoc index 6c5d3c1e..a7e2d3a4 100644 --- a/README.adoc +++ b/README.adoc @@ -35,12 +35,12 @@ The Functional Java artifact is published to Maven Central using the group `org. * Java 8 specific support (`functionaljava-java8`) * property based testing (`functionaljava-quickcheck` or `functionaljava-quickcheck_1.8` if you use Java 8+) -The latest stable version is `4.7`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.8`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.7" -compile "org.functionaljava:functionaljava-java8:4.7" -compile "org.functionaljava:functionaljava-quickcheck:4.7" -compile "org.functionaljava:functionaljava-java-core:4.7" +compile "org.functionaljava:functionaljava:4.8" +compile "org.functionaljava:functionaljava-java8:4.8" +compile "org.functionaljava:functionaljava-quickcheck:4.8" +compile "org.functionaljava:functionaljava-java-core:4.8" ---- and in Maven: @@ -48,22 +48,22 @@ and in Maven: org.functionaljava functionaljava - 4.7 + 4.8 org.functionaljava functionaljava-java8 - 4.7 + 4.8 org.functionaljava functionaljava-quickcheck - 4.7 + 4.8 org.functionaljava functionaljava-java-core - 4.7 + 4.8 ---- diff --git a/build.gradle b/build.gradle index 9410f205..fe81f484 100644 --- a/build.gradle +++ b/build.gradle @@ -44,16 +44,16 @@ allprojects { defaultTasks "build" - ext { - isSnapshot = false - fjBaseVersion = "4.8" + ext { + isSnapshot = true + fjBaseVersion = "4.9" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.7" + fjConsumeVersion = "4.8" signModule = false - useRetroLambda = true + useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" From fd9b337abe0927bc8d2f5b149198bc84a77c0b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 18 Aug 2018 18:23:40 -0400 Subject: [PATCH 685/811] Add Visitor tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .../test/java/fj/function/VisitorTest.java | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 core/src/test/java/fj/function/VisitorTest.java diff --git a/core/src/test/java/fj/function/VisitorTest.java b/core/src/test/java/fj/function/VisitorTest.java new file mode 100644 index 00000000..54efcf24 --- /dev/null +++ b/core/src/test/java/fj/function/VisitorTest.java @@ -0,0 +1,80 @@ +package fj.function; + +import fj.Equal; +import fj.F; +import fj.P; +import fj.P1; +import fj.data.List; +import org.junit.Test; + +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.function.Visitor.*; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class VisitorTest { + @Test + public void testFindFirst() { + assertThat(findFirst(List.list(none(), some(1), none()), () -> -1), is(1)); + } + + @Test + public void testFindFirstDef() { + assertThat(findFirst(List.list(none(), none(), none()), () -> -1), is(-1)); + } + + @Test + public void testNullableFindFirst() { + assertThat(nullablefindFirst(List.list(null, 1, null), () -> -1), is(1)); + } + + @Test + public void testNullableFindFirstDef() { + assertThat(nullablefindFirst(List.list(null, null, null), () -> -1), is(-1)); + } + + @Test + public void testVisitor() { + assertThat(visitor(List.list(i -> some(2 * i)), () -> -1, 10), is(20)); + } + + @Test + public void testVisitorDef() { + assertThat(visitor(List.list(i -> none()), () -> "foo", 10), is("foo")); + } + + @Test + public void testNullableVisitor() { + assertThat(nullableVisitor(List.list(i -> 2 * i), () -> -1, 10), is(20)); + } + + @Test + public void testNullableVisitorDef() { + assertThat(nullableVisitor(List.list(i -> null), () -> "foo", 10), is("foo")); + } + + @Test + public void testAssociation() { + final F> a = association(List.list(P.p(1, "one"), P.p(2, "two")), Equal.intEqual); + assertThat(a.f("foo").f(2), is("two")); + } + + @Test + public void testAssociationDef() { + final F> a = association(List.list(P.p(1, "one"), P.p(2, "two")), Equal.intEqual); + assertThat(a.f("foo").f(3), is("foo")); + } + + @Test + public void testAssociationLazy() { + final F, F> a = associationLazy(List.list(P.p(1, "one"), P.p(2, "two")), Equal.intEqual); + assertThat(a.f(P.p("foo")).f(2), is("two")); + } + + @Test + public void testAssociationLazyDef() { + final F, F> a = associationLazy(List.list(P.p(1, "one"), P.p(2, "two")), Equal.intEqual); + assertThat(a.f(P.p("foo")).f(3), is("foo")); + } +} From f1801d3c4fa3b8c8bdfddd185b7e20bb4ce65860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 20 Aug 2018 20:01:15 -0400 Subject: [PATCH 686/811] Add DList tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/data/DListTest.java | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 core/src/test/java/fj/data/DListTest.java diff --git a/core/src/test/java/fj/data/DListTest.java b/core/src/test/java/fj/data/DListTest.java new file mode 100644 index 00000000..6846ca2d --- /dev/null +++ b/core/src/test/java/fj/data/DListTest.java @@ -0,0 +1,31 @@ +package fj.data; + +import org.junit.Test; + +import static fj.data.DList.*; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class DListTest { + @Test + public void testConsSnoc() { + assertThat(nil().snoc(2).cons(1).toJavaList(), is(single(1).snoc(2).toJavaList())); + } + + @Test + public void testListDList() { + DList d = listDList(List.range(0, 1000)); + assertThat(d.toJavaList(), is(List.range(0, 1000).toJavaList())); + } + + @Test + public void testArrayDList() { + DList d = arrayDList(Array.range(0, 1000).array(Integer[].class)); + assertThat(d.toJavaList(), is(Array.range(0, 1000).toJavaList())); + } + @Test + public void testIter() { + DList d = iteratorDList(List.range(0, 1000).iterator()); + assertThat(d.toJavaList(), is(List.range(0, 1000).toJavaList())); + } +} From 58e0b4b556b870507dc6d7b788101b60f328f8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Thu, 23 Aug 2018 10:05:41 -0400 Subject: [PATCH 687/811] Exclude consume/ from coverage --- codecov.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 8c7fd5e4..b7ddeec5 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,3 +1,4 @@ ignore: - "demo/.*" - - "performance/.*" \ No newline at end of file + - "consume/.*" + - "performance/.*" From 33d5e8338f9c6a90a44882e61e821632be996990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Mon, 27 Aug 2018 21:25:41 -0400 Subject: [PATCH 688/811] Add P tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/test/java/fj/PTest.java | 159 +++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 core/src/test/java/fj/PTest.java diff --git a/core/src/test/java/fj/PTest.java b/core/src/test/java/fj/PTest.java new file mode 100644 index 00000000..2a97303f --- /dev/null +++ b/core/src/test/java/fj/PTest.java @@ -0,0 +1,159 @@ +package fj; + +import org.junit.Test; + +import static fj.Function.identity; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class PTest { + @Test + public void testPF(){ + final F> p1f = P.p1(); + final P1 p1 = p1f.f(1); + F>> p2f = P.p2(); + final P2 p2 = p2f.f(1).f(2); + assertThat(P2.__1().f(p2), is(P1.__1().f(p1))); + final F>>> p3f = P.p3(); + final P3 p3 = p3f.f(1).f(2).f(3); + assertThat(P3.__1().f(p3), is(P2.__1().f(p2))); + assertThat(P3.__2().f(p3), is(P2.__2().f(p2))); + final F>>>> p4f = P.p4(); + final P4 p4 = p4f.f(1).f(2).f(3).f(4); + assertThat(P4.__1().f(p4), is(P3.__1().f(p3))); + assertThat(P4.__2().f(p4), is(P3.__2().f(p3))); + assertThat(P4.__3().f(p4), is(P3.__3().f(p3))); + final F>>>>> p5f = P.p5(); + final P5 p5 = p5f.f(1).f(2).f(3).f(4).f(5); + assertThat(P5.__1().f(p5), is(P4.__1().f(p4))); + assertThat(P5.__2().f(p5), is(P4.__2().f(p4))); + assertThat(P5.__3().f(p5), is(P4.__3().f(p4))); + assertThat(P5.__4().f(p5), is(P4.__4().f(p4))); + final F>>>>>> p6f = P.p6(); + final P6 p6 = p6f.f(1).f(2).f(3).f(4).f(5).f(6); + assertThat(P6.__1().f(p6), + is(P5.__1().f(p5))); + assertThat(P6.__2().f(p6), + is(P5.__2().f(p5))); + assertThat(P6.__3().f(p6), + is(P5.__3().f(p5))); + assertThat(P6.__4().f(p6), + is(P5.__4().f(p5))); + assertThat(P6.__5().f(p6), + is(P5.__5().f(p5))); + final F>>>>>>> p7f = P.p7(); + final P7 p7 = + p7f.f(1).f(2).f(3).f(4).f(5).f(6).f(7); + assertThat(P7.__1().f(p7), + is(P6.__1().f(p6))); + assertThat(P7.__2().f(p7), + is(P6.__2().f(p6))); + assertThat(P7.__3().f(p7), + is(P6.__3().f(p6))); + assertThat(P7.__4().f(p7), + is(P6.__4().f(p6))); + assertThat(P7.__5().f(p7), + is(P6.__5().f(p6))); + assertThat(P7.__6().f(p7), + is(P6.__6().f(p6))); + final F>>>>>>>> p8f = P.p8(); + final P8 p8 = + p8f.f(1).f(2).f(3).f(4).f(5).f(6).f(7).f(8); + assertThat(P8.__1().f(p8), + is(P7.__1().f(p7))); + assertThat(P8.__2().f(p8), + is(P7.__2().f(p7))); + assertThat(P8.__3().f(p8), + is(P7.__3().f(p7))); + assertThat(P8.__4().f(p8), + is(P7.__4().f(p7))); + assertThat(P8.__5().f(p8), + is(P7.__5().f(p7))); + assertThat(P8.__6().f(p8), + is(P7.__6().f(p7))); + assertThat(P8.__7().f(p8), + is(P7.__7().f(p7))); + assertThat(P8.__8().f(p8), is(8)); + } + + @Test + public void testPProject1() { + final P1 p1 = P.p(1); + assertThat(p1.map(identity()), is(p1)); + } + + @Test + public void testPProject2() { + final P2 p2 = P.p(1, 2); + assertThat(p2.map1(identity()), is(p2)); + assertThat(p2.map2(identity()), is(p2)); + } + + @Test + public void testPProject3() { + final P3 p3 = P.p(1, 2, 3); + assertThat(p3.map1(identity()), is(p3)); + assertThat(p3.map2(identity()), is(p3)); + assertThat(p3.map3(identity()), is(p3)); + } + + @Test + public void testPProject4() { + final P4 p4 = P.p(1, 2, 3, 4); + assertThat(p4.map1(identity()), is(p4)); + assertThat(p4.map2(identity()), is(p4)); + assertThat(p4.map3(identity()), is(p4)); + assertThat(p4.map4(identity()), is(p4)); + } + + @Test + public void testPProject5() { + final P5 p5 = P.p(1, 2, 3, 4, 5); + assertThat(p5.map1(identity()), is(p5)); + assertThat(p5.map2(identity()), is(p5)); + assertThat(p5.map3(identity()), is(p5)); + assertThat(p5.map4(identity()), is(p5)); + assertThat(p5.map5(identity()), is(p5)); + } + + @Test + public void testPProject6() { + final P6 p6 = P.p(1, 2, 3, 4, 5, 6); + assertThat(p6.map1(identity()), is(p6)); + assertThat(p6.map2(identity()), is(p6)); + assertThat(p6.map3(identity()), is(p6)); + assertThat(p6.map4(identity()), is(p6)); + assertThat(p6.map5(identity()), is(p6)); + assertThat(p6.map6(identity()), is(p6)); + } + + @Test + public void testPProject7() { + final P7 p7 = + P.p(1, 2, 3, 4, 5, 6, 7); + assertThat(p7.map1(identity()), is(p7)); + assertThat(p7.map2(identity()), is(p7)); + assertThat(p7.map3(identity()), is(p7)); + assertThat(p7.map4(identity()), is(p7)); + assertThat(p7.map5(identity()), is(p7)); + assertThat(p7.map6(identity()), is(p7)); + assertThat(p7.map7(identity()), is(p7)); + } + + @Test + public void testPProject8() { + final P8 p8 = + P.p(1, 2, 3, 4, 5, 6, 7, 8); + assertThat(p8.map1(identity()), is(p8)); + assertThat(p8.map2(identity()), is(p8)); + assertThat(p8.map3(identity()), is(p8)); + assertThat(p8.map4(identity()), is(p8)); + assertThat(p8.map5(identity()), is(p8)); + assertThat(p8.map6(identity()), is(p8)); + assertThat(p8.map7(identity()), is(p8)); + assertThat(p8.map8(identity()), is(p8)); + } +} From ebdceaa7653780d8c896ad08687a22b934538aa5 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 25 Aug 2018 21:16:44 +0200 Subject: [PATCH 689/811] Fix compile under jdk11. Enable jdk11 travis build. --- .travis.yml | 21 +- build.gradle | 13 +- core/src/main/java/fj/data/$.java | 6 - core/src/main/java/fj/data/IOFunctions.java | 234 +++++++++--------- core/src/main/java/fj/data/Java.java | 22 +- core/src/main/java/fj/data/TreeZipper.java | 17 +- demo/build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 3 +- java-core/build.gradle | 2 +- props-core-scalacheck/build.gradle | 4 +- .../src/main/java/fj/test/Arbitrary.java | 174 +++++-------- quickcheck/src/main/java/fj/test/Arg.java | 9 +- .../src/main/java/fj/test/CheckResult.java | 18 +- quickcheck/src/main/java/fj/test/Cogen.java | 7 +- quickcheck/src/main/java/fj/test/Gen.java | 2 +- .../src/main/java/fj/test/Property.java | 30 +-- quickcheck/src/main/java/fj/test/Shrink.java | 5 +- .../src/main/java/fj/test/reflect/Check.java | 8 +- .../java/fj/test/reflect/CheckParams.java | 1 + .../src/main/java/fj/test/reflect/Main.java | 3 - .../fj/test/runner/PropertyTestRunner.java | 9 +- .../src/test/java/fj/data/test/TestCheck.java | 12 +- .../src/test/java/fj/data/test/TestNull.java | 10 +- quickcheck/src/test/java/fj/test/GenTest.java | 18 +- 24 files changed, 247 insertions(+), 383 deletions(-) diff --git a/.travis.yml b/.travis.yml index 539e7a45..7c55b120 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,17 +4,22 @@ sudo: false language: java jdk: - - oraclejdk8 + - openjdk11 + +matrix: + + include: + - jdk: openjdk8 + script: + - ./gradlew build coverage -s -i + after_success: + - bash <(curl -s https://codecov.io/bash) + - '[ "$TRAVIS_BRANCH" = "series/4.x" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ] + && ./gradlew uploadArchives' script: - - jdk_switcher use openjdk7 && export JAVA7_HOME=$JAVA_HOME - - jdk_switcher use oraclejdk8 && export JAVA8_HOME=$JAVA_HOME - - ./gradlew build coverage -s -i + - ./gradlew clean test -after_success: - - bash <(curl -s https://codecov.io/bash) - - '[ "$TRAVIS_BRANCH" = "master" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ] - && ./gradlew uploadArchives' env: global: diff --git a/build.gradle b/build.gradle index fe81f484..9d98d2b3 100644 --- a/build.gradle +++ b/build.gradle @@ -23,8 +23,6 @@ buildscript { } } -apply plugin: "jacoco" - if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { @@ -35,11 +33,10 @@ if (JavaVersion.current().isJava8Compatible()) { allprojects { - + apply plugin: "jacoco" jacoco { - toolVersion = "0.8.1" - + toolVersion = "0.8.2" } defaultTasks "build" @@ -100,8 +97,6 @@ subprojects { } } - apply plugin: "jacoco" - apply from: "$rootDir/lib.gradle" apply plugin: "java" apply plugin: "eclipse" @@ -123,9 +118,13 @@ subprojects { } jacocoTestReport { + additionalSourceDirs = files(sourceSets.main.allSource.srcDirs) + sourceDirectories = files(sourceSets.main.allSource.srcDirs) + classDirectories = files(sourceSets.main.output) reports { html.enabled = true xml.enabled = true + csv.enabled = false } } diff --git a/core/src/main/java/fj/data/$.java b/core/src/main/java/fj/data/$.java index 17b2ac9e..a1aa77bf 100644 --- a/core/src/main/java/fj/data/$.java +++ b/core/src/main/java/fj/data/$.java @@ -17,14 +17,8 @@ public final class $ extends P1 { /** * Returns a function that given an argument, returns a function that ignores its argument. - * @deprecated JDK 8 warns '_' may not be supported after SE 8. As of release 4.4, use {@link #constant} (note the synonym {@link #__}). * @return A function that given an argument, returns a function that ignores its argument. */ - @Deprecated - public static $ _(final B b) { - return constant(b); - } - public static $ __(final B b) { return constant(b); } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 92263d09..2ea15dfb 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -1,8 +1,19 @@ package fj.data; -import static fj.Bottom.errorF; -import static fj.Function.constant; -import static fj.Function.partialApply2; +import fj.F; +import fj.F0; +import fj.F1Functions; +import fj.F2; +import fj.Function; +import fj.P; +import fj.P1; +import fj.P2; +import fj.Try; +import fj.Unit; +import fj.data.Iteratee.Input; +import fj.data.Iteratee.IterV; +import fj.function.Try0; +import fj.function.Try1; import java.io.BufferedReader; import java.io.Closeable; @@ -14,11 +25,9 @@ import java.nio.charset.Charset; import java.util.Arrays; -import fj.*; -import fj.data.Iteratee.Input; -import fj.data.Iteratee.IterV; -import fj.function.Try0; -import fj.function.Try1; +import static fj.Bottom.errorF; +import static fj.Function.constant; +import static fj.Function.partialApply2; /** * IO monad for processing files, with main methods {@link #enumFileLines }, @@ -170,38 +179,37 @@ public static SafeIO lazySafe(final F0 f) { * A function that feeds an iteratee with lines read from a {@link BufferedReader}. */ public static F, IO>>> lineReader() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); - } - }; - - return r -> new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return () -> { - IterV i = it; - while (!isDone.f(i)) { - final String s = r.readLine(); - if (s == null) { - return i; - } - final Input input = Input.el(s); - final F, IterV>, P1>> cont = F1Functions.lazy(Function.apply(input)); - i = i.fold(done, cont)._1(); + return LineReader::new; + } + + private static class LineReader implements F, IO>> { + + private final BufferedReader r; + + private final F, Boolean> isDone = i -> i.fold(constant(P.p(true)), constant(P.p(false)))._1(); + private final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + + private LineReader(BufferedReader r) { + this.r = r; + } + + @Override + public IO> f(IterV it) { + // use loop instead of recursion because of missing TCO + return () -> { + IterV i = it; + while (!isDone.f(i)) { + final String s = r.readLine(); + if (s == null) { + return i; } - return i; - }; - } - }; + final Input input = Input.el(s); + final F, IterV>, P1>> cont = F1Functions.lazy(Function.apply(input)); + i = i.fold(done, cont)._1(); + } + return i; + }; + } } /** @@ -209,91 +217,91 @@ public IO> f(final IterV it) { * (char[] of size {@link #DEFAULT_BUFFER_SIZE}). */ public static F, IO>>> charChunkReader() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); + return CharChunkReader::new; + } + + private static class CharChunkReader implements F, IO>> { + + private final Reader r; + + private final F, Boolean> isDone = i -> i.fold(constant(P.p(true)), constant(P.p(false)))._1(); + private final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ + + CharChunkReader(Reader r) { + this.r = r; + } + + @Override + public IO> f(IterV it) { + // use loop instead of recursion because of missing TCO + return () -> { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { + return i; } - }; - - return r -> new F, IO>>() { - final F>, P1>> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return () -> { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { - return i; - } - if (numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - final Input input = Input.el(buffer); - final F, IterV>, P1>> cont = - F1Functions.lazy(Function.apply(input)); - i = i.fold(done, cont)._1(); + if (numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); } - return i; - }; - } - }; + final Input input = Input.el(buffer); + final F, IterV>, P1>> cont = + F1Functions.lazy(Function.apply(input)); + i = i.fold(done, cont)._1(); + } + return i; + }; + } } + + /** * A function that feeds an iteratee with characters read from a {@link Reader} * (chars are read in chunks of size {@link #DEFAULT_BUFFER_SIZE}). */ public static F, IO>>> charChunkReader2() { - final F, Boolean> isDone = - new F, Boolean>() { - final F>, P1> done = constant(P.p(true)); - final F, IterV>, P1> cont = constant(P.p(false)); - - @Override - public Boolean f(final IterV i) { - return i.fold(done, cont)._1(); + return CharChunkReader2::new; + } + + private static class CharChunkReader2 implements F, IO>> { + + private final Reader r; + + private final F, Boolean> isDone = i -> i.fold(constant(P.p(true)), constant(P.p(false)))._1(); + private final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ + + CharChunkReader2(Reader r) { + this.r = r; + } + + @Override + public IO> f(IterV it) { + // use loop instead of recursion because of missing TCO + return () -> { + + IterV i = it; + while (!isDone.f(i)) { + char[] buffer = new char[DEFAULT_BUFFER_SIZE]; + final int numRead = r.read(buffer); + if (numRead == -1) { + return i; } - }; - - return r -> new F, IO>>() { - final F>, IterV> done = errorF("iteratee is done"); //$NON-NLS-1$ - - @Override - public IO> f(final IterV it) { - // use loop instead of recursion because of missing TCO - return () -> { - - IterV i = it; - while (!isDone.f(i)) { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - final int numRead = r.read(buffer); - if (numRead == -1) { - return i; - } - if (numRead < buffer.length) { - buffer = Arrays.copyOfRange(buffer, 0, numRead); - } - for (char c : buffer) { - final Input input = Input.el(c); - final F, IterV>, IterV> cont = - Function.apply(input); - i = i.fold(done, cont); - } + if (numRead < buffer.length) { + buffer = Arrays.copyOfRange(buffer, 0, numRead); } - return i; - }; - } - }; + for (char c : buffer) { + final Input input = Input.el(c); + final F, IterV>, IterV> cont = + Function.apply(input); + i = i.fold(done, cont); + } + } + return i; + }; + } } public static IO map(final IO io, final F f) { diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 487e9703..80a5ec43 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -404,27 +404,7 @@ public static F, SynchronousQueue> Array_SynchronousQueue(final * @return A function that converts streams to iterable. */ public static F, Iterable> Stream_Iterable() { - return as -> () -> new Iterator() { - private Stream x = as; - - public boolean hasNext() { - return x.isNotEmpty(); - } - - public A next() { - if (x.isEmpty()) - throw new NoSuchElementException("Empty iterator"); - else { - final A a = x.head(); - x = x.tail()._1(); - return a; - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - }; + return as -> as; } /** diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 46392d20..9ffad4f4 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -628,21 +628,8 @@ private Stream>> uf(final F, Option F, P2, P1>>>> dwn() { - return tz -> P.p(tz, new P1>>() { - private F>, Option, Option>>>> fwd() { - return o -> { - Option, Option>>> r = none(); - for (final TreeZipper c : o) { - r = some(P.p(c, c.right())); - } - return r; - }; - } - - public Stream> _1() { - return unfold(fwd(), tz.firstChild()); - } - }); + F>, Option, Option>>>> fwd = o -> o.map(c -> P.p(c, c.right())); + return tz -> P.p(tz, P.lazy(() -> unfold(fwd, tz.firstChild()))); } /** diff --git a/demo/build.gradle b/demo/build.gradle index 41841cfa..b79cb246 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -17,4 +17,4 @@ test { jacoco { enabled = false } -} \ No newline at end of file +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 717f0389..72c40576 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sat Aug 25 14:20:05 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip diff --git a/java-core/build.gradle b/java-core/build.gradle index 3b636072..b5ee71ec 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -16,4 +16,4 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true -configureAllRetroLambda() \ No newline at end of file +configureAllRetroLambda() diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index a395a586..10e494c9 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -4,7 +4,7 @@ archivesBaseName = "${project.projectName}-${project.name}" apply plugin: 'scala' ext { - scalaVersion = "2.11.11" + scalaVersion = "2.11.12" scalacheckScalaVersion = "2.11" scalacheckVersion = "1.12.6" signModule = true @@ -20,5 +20,3 @@ dependencies { performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) - - diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index df922af2..95bdedca 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -1,8 +1,6 @@ package fj.test; -import fj.Equal; import fj.F; -import fj.F1Functions; import fj.F2; import fj.F3; import fj.F4; @@ -13,7 +11,6 @@ import fj.Function; import fj.Bottom; -import static fj.Equal.longEqual; import static fj.Function.compose; import static fj.P.p; @@ -30,22 +27,14 @@ import fj.LcgRng; import fj.Ord; -import static fj.data.Either.left; -import static fj.data.Either.right; import static fj.data.Enumerator.charEnumerator; import static fj.data.List.asString; import static fj.data.List.list; -import static fj.data.Option.some; import fj.data.List; import fj.data.Set; -import fj.data.TreeMap; -import fj.function.Booleans; -import fj.function.Effect1; -import fj.function.Longs; import static fj.data.Stream.range; -import static fj.function.Booleans.not; import static fj.test.Gen.choose; import static fj.test.Gen.elements; import static fj.test.Gen.fail; @@ -95,11 +84,7 @@ public final class Arbitrary { * @return An arbitrary for functions. */ public static Gen> arbF(final Cogen c, final Gen a) { - return promote(new F>() { - public Gen f(final A x) { - return c.cogen(x, a); - } - }); + return promote(x -> c.cogen(x, a)); } public static Gen> arbReader(Cogen aa, Gen ab) { @@ -389,19 +374,14 @@ public static Gen> arbF4Invariant(final Gen * max, min, max - 1, min + 1) with a frequency of 1% each then generates from {@link * #arbInteger} the remainder of the time (93%). */ - public static final Gen arbIntegerBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value(0)), - p(1, value(1)), - p(1, value(-1)), - p(1, value(Integer.MAX_VALUE)), - p(1, value(Integer.MIN_VALUE)), - p(1, value(Integer.MAX_VALUE - 1)), - p(1, value(Integer.MIN_VALUE + 1)), - p(93, arbInteger))); - } - }); + public static final Gen arbIntegerBoundaries = sized(i -> frequency(list(p(1, value(0)), + p(1, value(1)), + p(1, value(-1)), + p(1, value(Integer.MAX_VALUE)), + p(1, value(Integer.MIN_VALUE)), + p(1, value(Integer.MAX_VALUE - 1)), + p(1, value(Integer.MIN_VALUE + 1)), + p(93, arbInteger)))); /** * An arbitrary implementation for long values. @@ -414,19 +394,14 @@ public Gen f(final Integer i) { * min, max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbLong} * the remainder of the time (93%). */ - public static final Gen arbLongBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value(0L)), - p(1, value(1L)), - p(1, value(-1L)), - p(1, value(Long.MAX_VALUE)), - p(1, value(Long.MIN_VALUE)), - p(1, value(Long.MAX_VALUE - 1L)), - p(1, value(Long.MIN_VALUE + 1L)), - p(93, arbLong))); - } - }); + public static final Gen arbLongBoundaries = sized(i -> frequency(list(p(1, value(0L)), + p(1, value(1L)), + p(1, value(-1L)), + p(1, value(Long.MAX_VALUE)), + p(1, value(Long.MIN_VALUE)), + p(1, value(Long.MAX_VALUE - 1L)), + p(1, value(Long.MIN_VALUE + 1L)), + p(93, arbLong)))); /** * An arbitrary implementation for byte values. @@ -438,19 +413,14 @@ public Gen f(final Integer i) { * min, max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbByte} * the remainder of the time (93%). */ - public static final Gen arbByteBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value((byte) 0)), - p(1, value((byte) 1)), - p(1, value((byte) -1)), - p(1, value(Byte.MAX_VALUE)), - p(1, value(Byte.MIN_VALUE)), - p(1, value((byte) (Byte.MAX_VALUE - 1))), - p(1, value((byte) (Byte.MIN_VALUE + 1))), - p(93, arbByte))); - } - }); + public static final Gen arbByteBoundaries = sized(i -> frequency(list(p(1, value((byte) 0)), + p(1, value((byte) 1)), + p(1, value((byte) -1)), + p(1, value(Byte.MAX_VALUE)), + p(1, value(Byte.MIN_VALUE)), + p(1, value((byte) (Byte.MAX_VALUE - 1))), + p(1, value((byte) (Byte.MIN_VALUE + 1))), + p(93, arbByte)))); /** * An arbitrary implementation for short values. @@ -462,19 +432,14 @@ public Gen f(final Integer i) { * min, max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbShort} * the remainder of the time (93%). */ - public static final Gen arbShortBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value((short) 0)), - p(1, value((short) 1)), - p(1, value((short) -1)), - p(1, value(Short.MAX_VALUE)), - p(1, value(Short.MIN_VALUE)), - p(1, value((short) (Short.MAX_VALUE - 1))), - p(1, value((short) (Short.MIN_VALUE + 1))), - p(93, arbShort))); - } - }); + public static final Gen arbShortBoundaries = sized(i -> frequency(list(p(1, value((short) 0)), + p(1, value((short) 1)), + p(1, value((short) -1)), + p(1, value(Short.MAX_VALUE)), + p(1, value(Short.MIN_VALUE)), + p(1, value((short) (Short.MAX_VALUE - 1))), + p(1, value((short) (Short.MIN_VALUE + 1))), + p(93, arbShort)))); /** * An arbitrary implementation for character values. @@ -486,16 +451,11 @@ public Gen f(final Integer i) { * max - 1, min + 1) with a frequency of 1% each then generates from {@link #arbCharacter} * the remainder of the time (96%). */ - public static final Gen arbCharacterBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value(Character.MIN_VALUE)), - p(1, value((char) (Character.MIN_VALUE + 1))), - p(1, value(Character.MAX_VALUE)), - p(1, value((char) (Character.MAX_VALUE - 1))), - p(95, arbCharacter))); - } - }); + public static final Gen arbCharacterBoundaries = sized(i -> frequency(list(p(1, value(Character.MIN_VALUE)), + p(1, value((char) (Character.MIN_VALUE + 1))), + p(1, value(Character.MAX_VALUE)), + p(1, value((char) (Character.MAX_VALUE - 1))), + p(95, arbCharacter)))); /** * An arbitrary implementation for double values. @@ -507,21 +467,16 @@ public Gen f(final Integer i) { * min, min (normal), NaN, -infinity, infinity, max - 1) with a frequency of 1% each then * generates from {@link #arbDouble} the remainder of the time (91%). */ - public static final Gen arbDoubleBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value(0D)), - p(1, value(1D)), - p(1, value(-1D)), - p(1, value(Double.MAX_VALUE)), - p(1, value(Double.MIN_VALUE)), - p(1, value(Double.NaN)), - p(1, value(Double.NEGATIVE_INFINITY)), - p(1, value(Double.POSITIVE_INFINITY)), - p(1, value(Double.MAX_VALUE - 1D)), - p(91, arbDouble))); - } - }); + public static final Gen arbDoubleBoundaries = sized(i -> frequency(list(p(1, value(0D)), + p(1, value(1D)), + p(1, value(-1D)), + p(1, value(Double.MAX_VALUE)), + p(1, value(Double.MIN_VALUE)), + p(1, value(Double.NaN)), + p(1, value(Double.NEGATIVE_INFINITY)), + p(1, value(Double.POSITIVE_INFINITY)), + p(1, value(Double.MAX_VALUE - 1D)), + p(91, arbDouble)))); /** * An arbitrary implementation for float values. @@ -533,21 +488,16 @@ public Gen f(final Integer i) { * min, NaN, -infinity, infinity, max - 1) with a frequency of 1% each then generates from * {@link #arbFloat} the remainder of the time (91%). */ - public static final Gen arbFloatBoundaries = sized(new F>() { - @SuppressWarnings("unchecked") - public Gen f(final Integer i) { - return frequency(list(p(1, value(0F)), - p(1, value(1F)), - p(1, value(-1F)), - p(1, value(Float.MAX_VALUE)), - p(1, value(Float.MIN_VALUE)), - p(1, value(Float.NaN)), - p(1, value(Float.NEGATIVE_INFINITY)), - p(1, value(Float.POSITIVE_INFINITY)), - p(1, value(Float.MAX_VALUE - 1F)), - p(91, arbFloat))); - } - }); + public static final Gen arbFloatBoundaries = sized(i -> frequency(list(p(1, value(0F)), + p(1, value(1F)), + p(1, value(-1F)), + p(1, value(Float.MAX_VALUE)), + p(1, value(Float.MIN_VALUE)), + p(1, value(Float.NaN)), + p(1, value(Float.NEGATIVE_INFINITY)), + p(1, value(Float.POSITIVE_INFINITY)), + p(1, value(Float.MAX_VALUE - 1F)), + p(91, arbFloat)))); /** * An arbitrary implementation for string values. @@ -670,7 +620,7 @@ public static Gen> arbNonEmptyList(final Gen aa) { * Returns an arbitrary Validation for the given arbitrary parameters. */ public static Gen> arbValidation(final Gen aa, final Gen ab) { - return arbBoolean.bind(bool -> bool ? ab.map(Validation::success) : aa.map(Validation::fail)); + return arbBoolean.bind(bool -> bool ? ab.map(Validation::success) : aa.map(Validation::fail)); } /** @@ -690,7 +640,7 @@ public static Gen> arbStream(final Gen aa) { * @return An arbitrary implementation for arrays. */ public static Gen> arbArray(final Gen aa) { - return arbList(aa).map(List::toArray); + return arbList(aa).map(List::toArray); } /** @@ -1029,8 +979,8 @@ public static Gen> arbWeakHashMap(final Gen ak, fina */ public static Gen> arbArrayBlockingQueue(final Gen aa) { return arbArray(aa).bind(arbInteger, arbBoolean, - a -> capacity -> fair -> new ArrayBlockingQueue(a.length() + abs(capacity), - fair, a.asJavaList())); + a -> capacity -> fair -> new ArrayBlockingQueue<>(a.length() + abs(capacity), + fair, a.asJavaList())); } /** diff --git a/quickcheck/src/main/java/fj/test/Arg.java b/quickcheck/src/main/java/fj/test/Arg.java index 4187c15d..71df9e2d 100644 --- a/quickcheck/src/main/java/fj/test/Arg.java +++ b/quickcheck/src/main/java/fj/test/Arg.java @@ -1,6 +1,5 @@ package fj.test; -import fj.F; import fj.Show; import static fj.Show.anyShow; @@ -52,10 +51,6 @@ public int shrinks() { /** * The rendering of an argument (uses {@link Object#toString()} for the argument value). */ - public static final Show> argShow = showS(new F, String>() { - public String f(final Arg arg) { - return anyShow().showS(arg.value) + - (arg.shrinks > 0 ? " (" + arg.shrinks + " shrink" + (arg.shrinks == 1 ? "" : 's') + ')' : ""); - } - }); + public static final Show> argShow = showS(arg -> anyShow().showS(arg.value) + + (arg.shrinks > 0 ? " (" + arg.shrinks + " shrink" + (arg.shrinks == 1 ? "" : 's') + ')' : "")); } diff --git a/quickcheck/src/main/java/fj/test/CheckResult.java b/quickcheck/src/main/java/fj/test/CheckResult.java index c9c0a2fe..784fe4e9 100644 --- a/quickcheck/src/main/java/fj/test/CheckResult.java +++ b/quickcheck/src/main/java/fj/test/CheckResult.java @@ -286,16 +286,14 @@ else if (r.isPropException()) { * the result is a failure (falsified, property exception or generator exception). */ public static Show summaryEx(final Show> sa) { - return showS(new F() { - public String f(final CheckResult r) { - final String s = summary(sa).showS(r); - if (r.isProven() || r.isPassed() || r.isExhausted()) - return s; - else if (r.isFalsified() || r.isPropException() || r.isGenException()) - throw new Error(s); - else - throw decons(r.getClass()); - } + return showS(r -> { + final String s = summary(sa).showS(r); + if (r.isProven() || r.isPassed() || r.isExhausted()) + return s; + else if (r.isFalsified() || r.isPropException() || r.isGenException()) + throw new Error(s); + else + throw decons(r.getClass()); }); } } diff --git a/quickcheck/src/main/java/fj/test/Cogen.java b/quickcheck/src/main/java/fj/test/Cogen.java index c4c3b0a0..5770ea21 100644 --- a/quickcheck/src/main/java/fj/test/Cogen.java +++ b/quickcheck/src/main/java/fj/test/Cogen.java @@ -7,7 +7,6 @@ import fj.data.*; -import static fj.data.Array.array; import static fj.data.Array.iterableArray; import static fj.data.List.fromString; import static fj.data.List.nil; @@ -501,11 +500,7 @@ public Gen cogen(final Array as, final Gen g) { * @return A cogen for throwables. */ public static Cogen cogenThrowable(final Cogen cs) { - return cs.contramap(new F() { - public String f(final Throwable t) { - return t.getMessage(); - } - }); + return cs.contramap(Throwable::getMessage); } /** diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 5b0a98bc..a5e30a9d 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -275,7 +275,7 @@ public Gen bind(final Gen gb, final Gen gc, final Gen g * @return A new generator after function application. */ public Gen apply(final Gen> gf) { - return gf.bind(f1 -> map(f1)); + return gf.bind(this::map); } /** diff --git a/quickcheck/src/main/java/fj/test/Property.java b/quickcheck/src/main/java/fj/test/Property.java index 0f77f85e..2a327ebc 100644 --- a/quickcheck/src/main/java/fj/test/Property.java +++ b/quickcheck/src/main/java/fj/test/Property.java @@ -501,11 +501,7 @@ public static Property property(final Gen aa, final F f) { * application of its arguments. */ public static Property propertyP(final Gen aa, final Gen ab, final Shrink sa, final Shrink sb, final F>> f) { - return property(aa, sa, a -> { - return propertyP(ab, sb, b -> { - return f.f(a).f(b); - }); - }); + return property(aa, sa, a -> propertyP(ab, sb, b -> f.f(a).f(b))); } /** @@ -633,9 +629,7 @@ public static Property property(final Gen aa, final Shrink sb, final Shrink sc, final F>> f) { - return property(aa, ab, sa, sb, a -> b -> property(ac, sc, c -> { - return f.f(a).f(b).f(c); - })); + return property(aa, ab, sa, sb, a -> b -> property(ac, sc, c -> f.f(a).f(b).f(c))); } /** @@ -723,9 +717,7 @@ public static Property property(final Gen aa, final Shrink sc, final Shrink sd, final F>>> f) { - return property(aa, ab, ac, sa, sb, sc, a -> b -> c -> property(ad, sd, d -> { - return f.f(a).f(b).f(c).f(d); - })); + return property(aa, ab, ac, sa, sb, sc, a -> b -> c -> property(ad, sd, d -> f.f(a).f(b).f(c).f(d))); } /** @@ -825,9 +817,7 @@ public static Property property(final Gen aa, final Shrink sd, final Shrink se, final F>>>> f) { - return property(aa, ab, ac, ad, sa, sb, sc, sd, a -> b -> c -> d -> property(ae, se, e -> { - return f.f(a).f(b).f(c).f(d).f(e); - })); + return property(aa, ab, ac, ad, sa, sb, sc, sd, a -> b -> c -> d -> property(ae, se, e -> f.f(a).f(b).f(c).f(d).f(e))); } /** @@ -939,9 +929,7 @@ public static Property property(final Gen aa, final Shrink se, final Shrink sf, final F>>>>> f) { - return property(aa, ab, ac, ad, ae, sa, sb, sc, sd, se, a -> b -> c -> d -> e -> property(af, sf, f$ -> { - return f.f(a).f(b).f(c).f(d).f(e).f(f$); - })); + return property(aa, ab, ac, ad, ae, sa, sb, sc, sd, se, a -> b -> c -> d -> e -> property(af, sf, f$ -> f.f(a).f(b).f(c).f(d).f(e).f(f$))); } /** @@ -1065,9 +1053,7 @@ public static Property property(final Gen aa, final Shrink sf, final Shrink sg, final F>>>>>> f) { - return property(aa, ab, ac, ad, ae, af, sa, sb, sc, sd, se, sf, a -> b -> c -> d -> e -> f$ -> property(ag, sg, g -> { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g); - })); + return property(aa, ab, ac, ad, ae, af, sa, sb, sc, sd, se, sf, a -> b -> c -> d -> e -> f$ -> property(ag, sg, g -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g))); } /** @@ -1203,9 +1189,7 @@ public static Property property(final Gen aa, final Shrink sg, final Shrink sh, final F>>>>>>> f) { - return property(aa, ab, ac, ad, ae, af, ag, sa, sb, sc, sd, se, sf, sg, a -> b -> c -> d -> e -> f$ -> g -> property(ah, sh, h -> { - return f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h); - })); + return property(aa, ab, ac, ad, ae, af, ag, sa, sb, sc, sd, se, sf, sg, a -> b -> c -> d -> e -> f$ -> g -> property(ah, sh, h -> f.f(a).f(b).f(c).f(d).f(e).f(f$).f(g).f(h))); } /** diff --git a/quickcheck/src/main/java/fj/test/Shrink.java b/quickcheck/src/main/java/fj/test/Shrink.java index 77c95381..483293e8 100644 --- a/quickcheck/src/main/java/fj/test/Shrink.java +++ b/quickcheck/src/main/java/fj/test/Shrink.java @@ -23,7 +23,7 @@ import static fj.Primitive.Long_Integer; import static fj.Primitive.Long_Short; import static fj.Primitive.Short_Long; -import static fj.data.Array.array; + import fj.data.Conversions; import static fj.data.List.isNotEmpty_; import fj.data.Array; @@ -38,7 +38,6 @@ import static fj.data.Stream.iterate; import static fj.data.Stream.nil; -import static java.lang.System.arraycopy; import static java.math.BigInteger.ZERO; import java.math.BigDecimal; @@ -683,7 +682,7 @@ public static Shrink> shrinkSynchronousQueue(final Shrin final Stream is = cons(ZERO, () -> iterate(x -> x.divide(two), i) .takeWhile(x2 -> eq.notEq(x2, ZERO)) - .map(i::subtract)); + .map(x2 -> i.subtract(x2))); return Ord.bigintOrd.isLessThan(i, ZERO) ? cons(i.negate(), () -> is) : is; } diff --git a/quickcheck/src/main/java/fj/test/reflect/Check.java b/quickcheck/src/main/java/fj/test/reflect/Check.java index eb865e04..a1eea79b 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Check.java +++ b/quickcheck/src/main/java/fj/test/reflect/Check.java @@ -1,6 +1,5 @@ package fj.test.reflect; -import fj.Class; import static fj.Class.clas; import fj.F; import fj.Function; @@ -24,8 +23,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; + import static java.lang.reflect.Modifier.isStatic; /** @@ -177,7 +175,7 @@ public static List> check(final java.lang.Class c */ public static List>> properties(final java.lang.Class c, final String... categories) { //noinspection ClassEscapesDefinedScope - final Array>> propFields = properties(array(c.getDeclaredFields()).map((F) f -> new PropertyMember() { + final Array>> propFields = properties(array(c.getDeclaredFields()).map(f -> new PropertyMember() { public java.lang.Class type() { return f.getType(); } @@ -205,7 +203,7 @@ public boolean isProperty() { }), c, categories); //noinspection ClassEscapesDefinedScope - final Array>> propMethods = properties(array(c.getDeclaredMethods()).map((F) m -> { + final Array>> propMethods = properties(array(c.getDeclaredMethods()).map(m -> { //noinspection ProhibitedExceptionDeclared return new PropertyMember() { public java.lang.Class type() { diff --git a/quickcheck/src/main/java/fj/test/reflect/CheckParams.java b/quickcheck/src/main/java/fj/test/reflect/CheckParams.java index 8c8445c1..7951b40e 100644 --- a/quickcheck/src/main/java/fj/test/reflect/CheckParams.java +++ b/quickcheck/src/main/java/fj/test/reflect/CheckParams.java @@ -1,5 +1,6 @@ package fj.test.reflect; +import fj.F0; import fj.test.Property; import java.lang.annotation.Documented; diff --git a/quickcheck/src/main/java/fj/test/reflect/Main.java b/quickcheck/src/main/java/fj/test/reflect/Main.java index 5f6f3dfc..b07997c2 100644 --- a/quickcheck/src/main/java/fj/test/reflect/Main.java +++ b/quickcheck/src/main/java/fj/test/reflect/Main.java @@ -1,10 +1,7 @@ package fj.test.reflect; -import fj.P2; import static fj.data.Array.array; -import fj.function.Effect1; -import fj.test.CheckResult; import static fj.test.CheckResult.summary; import static fj.test.reflect.Check.check; diff --git a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java index 876dbff1..8b90d57c 100644 --- a/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java +++ b/quickcheck/src/main/java/fj/test/runner/PropertyTestRunner.java @@ -58,11 +58,10 @@ private static String getLabel(Description d) { } private static CheckResult checkProperty(Property prop, Option params) { - for (CheckParams ps : params) { - return prop.check(ps.minSuccessful(), ps.maxDiscarded(), ps.minSize(), ps.maxSize()); - } - - return prop.check(); + return params.option( + prop::check, + ps -> prop.check(ps.minSuccessful(), ps.maxDiscarded(), ps.minSize(), ps.maxSize()) + ); } @Override diff --git a/quickcheck/src/test/java/fj/data/test/TestCheck.java b/quickcheck/src/test/java/fj/data/test/TestCheck.java index 935f1127..3a4e6a80 100644 --- a/quickcheck/src/test/java/fj/data/test/TestCheck.java +++ b/quickcheck/src/test/java/fj/data/test/TestCheck.java @@ -1,16 +1,10 @@ package fj.data.test; -import fj.F2; -import fj.F3; -import fj.data.List; -import fj.test.Arbitrary; import fj.test.CheckResult; import fj.test.Gen; import fj.test.Property; import org.junit.*; -import static fj.Function.compose; -import static fj.test.Arbitrary.arbLong; import static fj.test.Property.prop; import static fj.test.Property.property; import static org.junit.Assert.*; @@ -19,13 +13,11 @@ public class TestCheck { @Test(timeout=5000 /*ms*/) public void testExceptionsThrownFromGeneratorsArePropagated() { - Gen failingGen = Gen.value(0).map((i) -> { + Gen failingGen = Gen.value(0).map((i) -> { throw new RuntimeException("test failure"); }); - Property p = property(failingGen, (Integer i) -> { - return prop(i == 0); - }); + Property p = property(failingGen, (Integer i) -> prop(i == 0)); CheckResult res = p.check( 1, /*minSuccessful*/ diff --git a/quickcheck/src/test/java/fj/data/test/TestNull.java b/quickcheck/src/test/java/fj/data/test/TestNull.java index 0fd44c6a..fe9dc843 100644 --- a/quickcheck/src/test/java/fj/data/test/TestNull.java +++ b/quickcheck/src/test/java/fj/data/test/TestNull.java @@ -1,16 +1,10 @@ package fj.data.test; -import fj.F2; -import fj.F3; -import fj.data.List; -import fj.test.Arbitrary; import fj.test.CheckResult; import fj.test.Gen; import fj.test.Property; import org.junit.Test; -import static fj.Function.compose; -import static fj.test.Arbitrary.arbLong; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -21,9 +15,7 @@ public class TestNull { @Test public void testShowNullParameters() { - Property p = property(Gen.value(null), (Integer i) -> { - return prop(i != null); - }); + Property p = property(Gen.value(null), (Integer i) -> prop(i != null)); CheckResult.summary.println(p.check()); } diff --git a/quickcheck/src/test/java/fj/test/GenTest.java b/quickcheck/src/test/java/fj/test/GenTest.java index 3bb723b8..900369a7 100644 --- a/quickcheck/src/test/java/fj/test/GenTest.java +++ b/quickcheck/src/test/java/fj/test/GenTest.java @@ -22,9 +22,7 @@ public final class GenTest { @Test public void testCombinationOf_none() { Gen> instance = combinationOf(0, AS); - testPick(100, instance, actual -> { - assertTrue(actual.isEmpty()); - }); + testPick(100, instance, actual -> assertTrue(actual.isEmpty())); } @Test @@ -59,9 +57,7 @@ public void testCombinationOf_three() { @Test public void testSelectionOf_none() { Gen> instance = selectionOf(0, AS); - testPick(100, instance, actual -> { - assertTrue(actual.isEmpty()); - }); + testPick(100, instance, actual -> assertTrue(actual.isEmpty())); } @Test @@ -106,9 +102,7 @@ public void testSelectionOf_four() { @Test public void testPermutationOf_none() { Gen> instance = permutationOf(0, AS); - testPick(100, instance, actual -> { - assertTrue(actual.isEmpty()); - }); + testPick(100, instance, actual -> assertTrue(actual.isEmpty())); } @Test @@ -142,9 +136,7 @@ public void testPermutationOf_three() { @Test public void testWordOf_none() { Gen> instance = wordOf(0, AS); - testPick(100, instance, actual -> { - assertTrue(actual.isEmpty()); - }); + testPick(100, instance, actual -> assertTrue(actual.isEmpty())); } @Test @@ -184,7 +176,7 @@ public void testWordOf_four() { } private static void testPick(int n, Gen> instance, Effect1> test) { - range(0, n).map(ignore -> instance.gen(0, standard)).foreachDoEffect(test::f); + range(0, n).map(ignore -> instance.gen(0, standard)).foreachDoEffect(test); } } From 5b6b88979c717c03d47d9d3977912df9b7f72153 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sat, 25 Aug 2018 21:16:44 +0200 Subject: [PATCH 690/811] Initiate 5.x series: build with jdk11 by default. Move java8 to core. --- .travis.yml | 11 +++-- build.gradle | 22 ++++----- core/build.gradle | 2 - .../src/main/java/fj/data/Collectors.java | 0 .../src/main/java/fj/data/Java8.java | 22 ++++----- demo/build.gradle | 2 - java-core/build.gradle | 2 - java8/build.gradle | 18 ------- java8/src/test/java/fj/EmptyTest.java | 17 ------- lib.gradle | 24 ---------- performance/build.gradle | 2 - props-core/build.gradle | 2 - quickcheck/build.gradle | 2 - .../src/main/java/fj/test/Arbitrary.java | 48 +++++++++---------- settings.gradle | 2 +- 15 files changed, 52 insertions(+), 124 deletions(-) rename {java8 => core}/src/main/java/fj/data/Collectors.java (100%) rename {java8 => core}/src/main/java/fj/data/Java8.java (97%) delete mode 100644 java8/build.gradle delete mode 100644 java8/src/test/java/fj/EmptyTest.java diff --git a/.travis.yml b/.travis.yml index 7c55b120..bbe5966b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,19 +4,24 @@ sudo: false language: java jdk: - - openjdk11 + - openjdk10 + - openjdk-ea matrix: include: - - jdk: openjdk8 + - jdk: openjdk11 script: - ./gradlew build coverage -s -i after_success: - bash <(curl -s https://codecov.io/bash) - - '[ "$TRAVIS_BRANCH" = "series/4.x" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ] + - '[ "$TRAVIS_BRANCH" = "series/5.x" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ] && ./gradlew uploadArchives' + allow_failures: + - jdk: openjdk10 + - jdk: openjdk-ea + script: - ./gradlew clean test diff --git a/build.gradle b/build.gradle index 9d98d2b3..b386b5d3 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,6 @@ ext { buildscript { ext { uptodateVersion = "1.6.3" - retrolambdaPluginVersion = "3.7.0" - retrolambdaVersion = "2.5.4" } repositories { @@ -19,7 +17,6 @@ buildscript { dependencies { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" - classpath "me.tatarka:gradle-retrolambda:$retrolambdaPluginVersion" } } @@ -43,14 +40,13 @@ allprojects { ext { isSnapshot = true - fjBaseVersion = "4.9" + fjBaseVersion = "5.0" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") fjConsumeVersion = "4.8" signModule = false - useRetroLambda = false projectTitle = "Functional Java" projectName = "functionaljava" @@ -71,10 +67,6 @@ allprojects { dependencyJunit = "org.junit.vintage:junit-vintage-engine:5.2.0" displayCompilerWarnings = true - - newJdkEnvVar = "JAVA8_HOME" - oldJdkEnvVar = "JAVA7_HOME" - retroLambdaTarget = JavaVersion.VERSION_1_6 } repositories { @@ -111,11 +103,13 @@ subprojects { } } - if (displayCompilerWarnings) { - tasks.withType(JavaCompile) { + + tasks.withType(JavaCompile) { + options.compilerArgs.addAll(['--release', '10']) + if (displayCompilerWarnings) { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" - } - } + } + } jacocoTestReport { additionalSourceDirs = files(sourceSets.main.allSource.srcDirs) @@ -136,7 +130,7 @@ task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { dependsOn = subprojects.coverage executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec") // We only care about coverage of: - def projectForFoverage = ["core", "java8", "quickcheck", "java-core"] + def projectForFoverage = ["core", "quickcheck", "java-core"] classDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.output) sourceDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs) diff --git a/core/build.gradle b/core/build.gradle index 71dae913..13d06114 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -15,5 +15,3 @@ performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) uploadArchives.enabled = true - -configureAllRetroLambda() diff --git a/java8/src/main/java/fj/data/Collectors.java b/core/src/main/java/fj/data/Collectors.java similarity index 100% rename from java8/src/main/java/fj/data/Collectors.java rename to core/src/main/java/fj/data/Collectors.java diff --git a/java8/src/main/java/fj/data/Java8.java b/core/src/main/java/fj/data/Java8.java similarity index 97% rename from java8/src/main/java/fj/data/Java8.java rename to core/src/main/java/fj/data/Java8.java index e41f0958..46c5ca2a 100644 --- a/java8/src/main/java/fj/data/Java8.java +++ b/core/src/main/java/fj/data/Java8.java @@ -1,14 +1,5 @@ package fj.data; -import java.util.Iterator; -import java.util.Optional; -import java.util.Spliterators; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.StreamSupport; - import fj.F; import fj.F2; import fj.P; @@ -19,6 +10,15 @@ import fj.function.Try1; import fj.function.Try2; +import java.util.Iterator; +import java.util.Optional; +import java.util.Spliterators; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.StreamSupport; + /** * Created by mperry on 3/06/2014. */ @@ -134,7 +134,7 @@ public static F Consumer_F(final Consumer c) { }; } - public static java.util.stream.Stream Stream_JavaStream(final fj.data.Stream s) { + public static java.util.stream.Stream Stream_JavaStream(final Stream s) { return Iterable_JavaStream(s); } @@ -146,7 +146,7 @@ public static java.util.stream.Stream Iterator_JavaStream(final Iterator< return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, 0), false); } - public static F, java.util.stream.Stream> Stream_JavaStream() { + public static F, java.util.stream.Stream> Stream_JavaStream() { return Java8::Stream_JavaStream; } diff --git a/demo/build.gradle b/demo/build.gradle index b79cb246..e97f94b8 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -5,8 +5,6 @@ mainClassName = "fj.demo.euler.Problem2" archivesBaseName = "${project.projectName}-${project.name}" -configureAllRetroLambda() - dependencies { compile project(":core") compile project(":quickcheck") diff --git a/java-core/build.gradle b/java-core/build.gradle index b5ee71ec..22bf8970 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -15,5 +15,3 @@ configureUpload(signingEnabled, signModule) uploadArchives.enabled = true - -configureAllRetroLambda() diff --git a/java8/build.gradle b/java8/build.gradle deleted file mode 100644 index d6d4c485..00000000 --- a/java8/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ - -archivesBaseName = "${project.projectName}-${project.name}" - -ext { - signModule = true -} - -dependencies { - compile project(":core") - testCompile dependencyJunit -} - -performSigning(signingEnabled, signModule) -configureUpload(signingEnabled, signModule) - -if (!useRetroLambda) { - uploadArchives.enabled = true -} diff --git a/java8/src/test/java/fj/EmptyTest.java b/java8/src/test/java/fj/EmptyTest.java deleted file mode 100644 index e187cccb..00000000 --- a/java8/src/test/java/fj/EmptyTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package fj; - -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -/** - * Created by MarkPerry on 30/08/2015. - */ -public class EmptyTest { - - @Ignore @Test - public void missing() { - Assert.fail("not implemented"); - - } -} diff --git a/lib.gradle b/lib.gradle index 253ed251..39ce7a7e 100644 --- a/lib.gradle +++ b/lib.gradle @@ -77,33 +77,9 @@ void configureUpload(String signingEnabled, Boolean signModule) { } } -void configureAllRetroLambda() { - configureRetroLambda(useRetroLambda, newJdkEnvVar, oldJdkEnvVar, retroLambdaTarget) -} - -void configureRetroLambda(boolean useRetroLambda, String newJdkEnvVar, String oldJdkEnvVar, JavaVersion retroLambdaTarget) { - - if (useRetroLambda) { - apply plugin: 'me.tatarka.retrolambda' - retrolambda { - jdk System.getenv(newJdkEnvVar) - oldJdk System.getenv(oldJdkEnvVar) - javaVersion retroLambdaTarget - defaultMethods true - } - dependencies { - retrolambdaConfig "net.orfjackal.retrolambda:retrolambda:$retrolambdaVersion" - } - } else { - project.archivesBaseName = "${project.archivesBaseName}_1.8" - } -} - ext { findJavaCommand = this.&findJavaCommand doSigning = this.&doSigning performSigning = this.&performSigning configureUpload = this.&configureUpload - configureRetroLambda = this.&configureRetroLambda - configureAllRetroLambda = this.&configureAllRetroLambda } diff --git a/performance/build.gradle b/performance/build.gradle index b5bc2916..cac2f584 100644 --- a/performance/build.gradle +++ b/performance/build.gradle @@ -1,6 +1,4 @@ -configureAllRetroLambda() - dependencies { compile project(":core") testCompile dependencyJunit diff --git a/props-core/build.gradle b/props-core/build.gradle index d697cff5..181ae5b2 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -1,8 +1,6 @@ archivesBaseName = "${project.projectName}-${project.name}" -configureAllRetroLambda() - dependencies { compile project(":quickcheck") testCompile dependencyJunit diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 45e379da..b477e26a 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -5,8 +5,6 @@ ext { archivesBaseName = "${project.projectName}-${project.name}" -configureAllRetroLambda() - dependencies { compile project(":core") compile dependencyJunit diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 95bdedca..8e5461fd 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -260,13 +260,13 @@ public static Gen> arbF4Invariant(final Gen * @return An arbitrary for function-6. */ public static Gen> arbF6Invariant(final Gen a) { - return a.map(compose(Function.uncurryF6(), - compose(Function.>>>>>constant(), - compose(Function.>>>>constant(), - compose(Function.>>>constant(), - compose(Function.>>constant(), - compose(Function.>constant(), - Function.constant()))))))); + return a.map(compose(Function.uncurryF6(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + Function.constant()))))))); } /** @@ -301,14 +301,14 @@ public static Gen> arbF4Invariant(final Gen * @return An arbitrary for function-7. */ public static Gen> arbF7Invariant(final Gen a) { - return a.map(compose(Function.uncurryF7(), - compose(Function.>>>>>>constant(), - compose(Function.>>>>>constant(), - compose(Function.>>>>constant(), - compose(Function.>>>constant(), - compose(Function.>>constant(), - compose(Function.>constant(), - Function.constant())))))))); + return a.map(compose(Function.uncurryF7(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), + Function.constant())))))))); } /** @@ -346,17 +346,17 @@ public static Gen> arbF4Invariant(final Gen */ public static Gen> arbF8Invariant( final Gen a) { - return a.map(compose(Function.uncurryF8(), - compose(Function.>>>>>>>constant(), - compose(Function.>>>>>>constant(), - compose(Function.>>>>>constant(), + return a.map(compose(Function.uncurryF8(), + compose(Function.constant(), + compose(Function.constant(), + compose(Function.constant(), compose( - Function.>>>>constant(), - compose(Function.>>>constant(), + Function.constant(), + compose(Function.constant(), compose( - Function.>>constant(), - compose(Function.>constant(), - Function.constant()))))))))); + Function.constant(), + compose(Function.constant(), + Function.constant()))))))))); } /** diff --git a/settings.gradle b/settings.gradle index d231d998..f1a6bd56 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ rootProject.name = "functionaljava" -include "core", "demo", "consume", "java8", "quickcheck", "props-core", "props-core-scalacheck", "java-core", "performance" +include "core", "demo", "consume", "quickcheck", "props-core", "props-core-scalacheck", "java-core", "performance" From 2e1f2c57176a2bf8974ef0725e681e9042cff9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 23 Sep 2018 14:28:40 -0400 Subject: [PATCH 691/811] Add Strategy tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .../fj/control/parallel/StrategyTest.java | 61 +++++++++++++++++++ core/src/test/java/fj/data/StreamTest.java | 16 ----- 2 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 core/src/test/java/fj/control/parallel/StrategyTest.java diff --git a/core/src/test/java/fj/control/parallel/StrategyTest.java b/core/src/test/java/fj/control/parallel/StrategyTest.java new file mode 100644 index 00000000..ee3b30df --- /dev/null +++ b/core/src/test/java/fj/control/parallel/StrategyTest.java @@ -0,0 +1,61 @@ +package fj.control.parallel; + +import fj.Ord; +import fj.P; +import fj.P1; +import fj.data.Enumerator; +import fj.data.List; +import fj.data.Stream; +import org.junit.Test; + +import java.util.concurrent.*; + +import static fj.control.parallel.Callables.callable; +import static fj.control.parallel.Strategy.*; +import static fj.data.Stream.range; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class StrategyTest { + + @Test + public void testStrategySeq() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + assertThat(s.sort(Ord.intOrd, seqStrategy()), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyThread() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + assertThat(s.sort(Ord.intOrd, simpleThreadStrategy()), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyExecutor() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + final ExecutorService es = Executors.newFixedThreadPool(10); + assertThat(s.sort(Ord.intOrd, executorStrategy(es)), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyCompletion() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + final ExecutorService es = Executors.newFixedThreadPool(10); + final CompletionService cs = new ExecutorCompletionService(es); + assertThat(s.sort(Ord.intOrd, completionStrategy(cs)), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyMergeAll() { + final List l = List.range(0, 100); + final List> p1s = mergeAll(l.map(x -> CompletableFuture.supplyAsync(() -> x))); + assertThat(P1.sequence(p1s)._1(), is(l)); + } + + @Test + public void testStrategyCallables() throws Exception { + final Strategy> s = strategy(c -> c); + final Strategy> cs = callableStrategy(s); + assertThat(callableStrategy(s).par(P.p(callable(1)))._1().call(), is(1)); + } +} diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index b65e115c..999a3a3e 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -1,9 +1,7 @@ package fj.data; import fj.Equal; -import fj.Ord; import fj.P2; -import fj.control.parallel.Strategy; import org.junit.Test; import java.util.ConcurrentModificationException; @@ -105,18 +103,4 @@ public void testMinus() { assertThat(s1.minus(Equal.charEqual, s2), is(stream(new Character[]{'a', 'c', 'd'}))); } - - @Test - public void testSortSeq() { - Stream s = range(Enumerator.intEnumerator, 99, -99, -1); - assertThat(s.sort(Ord.intOrd, Strategy.seqStrategy()), - is(s.sort(Ord.intOrd))); - } - - @Test - public void testSortThread() { - Stream s = range(Enumerator.intEnumerator, 99, -99, -1); - assertThat(s.sort(Ord.intOrd, Strategy.simpleThreadStrategy()), - is(s.sort(Ord.intOrd))); - } } From 9893314de654075a46f53f6aa6edb4e0426228bd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 11:13:26 +0200 Subject: [PATCH 692/811] Fix regression in lifted semigroup sum. Move lifted definition in Monoid. --- core/src/main/java/fj/Monoid.java | 31 +++++++++++++++++++++++++++ core/src/main/java/fj/Semigroup.java | 24 +-------------------- core/src/test/java/fj/MonoidTest.java | 19 ++++++++++++++++ 3 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 core/src/test/java/fj/MonoidTest.java diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 3fcf1775..cdb8e746 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -17,6 +17,7 @@ import static fj.data.List.nil; import static fj.data.Natural.natural; import static fj.data.Option.none; +import static fj.data.Option.some; import static fj.data.Stream.iterableStream; import java.math.BigInteger; @@ -867,6 +868,36 @@ public List sum(F0>> as) { }); } + /** + * Lift a {@code Semigroup} for A to a {@code Monoid>}, using Option.none() as zero. + * + * @return A monoid for option. + */ + public static Monoid> optionMonoid(Semigroup aSemigroup) { + return monoidDef(new Monoid.Definition>() { + @Override + public Option empty() { + return none(); + } + + @Override + public Option append(Option a1, Option a2) { + return a1.liftM2(a2, aSemigroup::sum).orElse(a1).orElse(a2); + } + + @Override + public Option multiply(int n, Option oa) { + return n > 0 ? oa.map(a -> aSemigroup.multiply1p(n - 1, a)) : none(); + } + + @Override + public Option sum(F0>> oas) { + Stream as = oas.f().bind(Option::toStream); + return as.uncons(none(), h -> tail -> some(aSemigroup.sumStream(h, tail::_1))); + } + }); + } + /** * A monoid for options. * @deprecated since 4.7. Use {@link #firstOptionMonoid()}. diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 16b0d130..f626ded7 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -172,29 +172,7 @@ public Semigroup dual() { * Lifts the semigroup to obtain a trivial monoid. */ public Monoid> lift() { - Definition def = this.def; - return monoidDef(new Monoid.Definition>() { - @Override - public Option empty() { - return none(); - } - - @Override - public Option append(Option a1, Option a2) { - return a1.liftM2(a1, def::append).orElse(a1).orElse(a2); - } - - @Override - public Option multiply(int n, Option oa) { - return n > 0 ? oa.map(a -> def.multiply1p(n - 1, a)) : none(); - } - - @Override - public Option sum(F0>> oas) { - Stream as = oas.f().bind(Option::toStream); - return as.uncons(none(), h -> tail -> some(def.sum(h, tail::_1))); - } - }); + return Monoid.optionMonoid(this); } /** diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java new file mode 100644 index 00000000..8bab5315 --- /dev/null +++ b/core/src/test/java/fj/MonoidTest.java @@ -0,0 +1,19 @@ +package fj; + +import fj.data.Option; +import fj.data.Stream; +import org.junit.Test; + +import static fj.data.Option.some; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class MonoidTest { + + @Test + public void lifted_sum_of_two_numbers() { + Monoid> optionMonoid = Semigroup.intAdditionSemigroup.lift(); + assertThat(optionMonoid.sum(some(3), some(5)), is(some(8))); + assertThat(optionMonoid.sumLeft(Stream.arrayStream(some(3), some(5))), is(some(8))); + } +} From d3d876c28b31b5ad210302614abdd2e8c7b3165f Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 11:25:47 +0200 Subject: [PATCH 693/811] Add Trampoline.suspend(final F0> a). --- core/src/main/java/fj/control/Trampoline.java | 17 ++++++++++++++--- core/src/main/java/fj/data/DList.java | 2 +- core/src/main/java/fj/data/Eval.java | 6 +++--- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/State.java | 3 +-- quickcheck/src/main/java/fj/test/Gen.java | 5 ++--- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 37491c3b..0b6060b1 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -46,7 +46,7 @@ public R fold(final F, R> n, // The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the // continuations. public Trampoline bind(final F> f) { - return codense(sub, o -> suspend(P.lazy(() -> cont.f(o).bind(f)))); + return codense(sub, o -> suspend(() -> cont.f(o).bind(f))); } // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result @@ -126,6 +126,16 @@ public static Trampoline pure(final A a) { return new Pure<>(a); } + /** + * Suspends the given computation in a thunk. + * + * @param a A trampoline suspended in a thunk. + * @return A trampoline whose next step runs the given thunk. + */ + public static Trampoline suspend(final F0> a) { + return new Suspend<>(P.lazy(a)); + } + /** * Suspends the given computation in a thunk. * @@ -136,6 +146,7 @@ public static Trampoline suspend(final P1> a) { return new Suspend<>(a); } + /** * @return The first-class version of `suspend`. */ @@ -255,7 +266,7 @@ public final Trampoline zipWith(final Trampoline b, final F2>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.lazy(() -> ta.zipWith(tb, f)))))); + return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(() -> ta.zipWith(tb, f))))); } for (final B y : eb.right()) { return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); @@ -263,7 +274,7 @@ public final Trampoline zipWith(final Trampoline b, final F2 pure(f.f(x, y)))); + return suspend(() -> pure(f.f(x, y))); } for (final P1> y : eb.left()) { return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index af9d68b0..597b6dda 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -126,6 +126,6 @@ public DList append(DList other) { } private static F> kleisliTrampCompose(F> bc, F> ab) { - return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(P.lazy(() -> bc.f(b)))); + return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(() -> bc.f(b))); } } diff --git a/core/src/main/java/fj/data/Eval.java b/core/src/main/java/fj/data/Eval.java index 3e513075..5d09f913 100644 --- a/core/src/main/java/fj/data/Eval.java +++ b/core/src/main/java/fj/data/Eval.java @@ -204,7 +204,7 @@ private static final class PureTrampolineEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return Trampoline.suspend(P.lazy(() -> Trampoline.pure(start.value()))); + return Trampoline.suspend(() -> Trampoline.pure(start.value())); } } @@ -219,7 +219,7 @@ private static final class BindTrampolineEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return Trampoline.suspend(P.lazy(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline()))); + return Trampoline.suspend(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline())); } } @@ -232,7 +232,7 @@ private static final class DeferEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return Trampoline.suspend(P.lazy(() -> memo._1().asTrampoline().trampoline())); + return Trampoline.suspend(() -> memo._1().asTrampoline().trampoline()); } } } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index f58fd73f..e0e12877 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -736,7 +736,7 @@ public final B foldRight(final F2 f, final B b) { * @return A Trampoline containing the final result after the right-fold reduction. */ public final Trampoline foldRightC(final F2 f, final B b) { - return Trampoline.suspend(P.lazy(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head())))); + return Trampoline.suspend(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head()))); } /** diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 1b30a55e..f29d55d7 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -5,7 +5,6 @@ import fj.Unit; import fj.control.Trampoline; -import static fj.P.lazy; import static fj.P.p; import static fj.control.Trampoline.suspend; import static fj.data.List.cons; @@ -75,7 +74,7 @@ public static State> traverse(List list, F State suspended(F>> runF) { - return new State<>(s -> suspend(lazy(() -> runF.f(s)))); + return new State<>(s -> suspend(() -> runF.f(s))); } private final F>> runF; diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index a5e30a9d..323995e1 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -16,7 +16,6 @@ import static fj.Function.flip; import static fj.Monoid.intAdditionMonoid; import static fj.Ord.intOrd; -import static fj.P.lazy; import static fj.P2.__1; import static fj.control.Trampoline.pure; import static fj.control.Trampoline.suspend; @@ -551,7 +550,7 @@ final class Tramp { // Picks elements in constant stack space private Trampoline> tramp(List remainAs, int remainN, int remainALength) { - return suspend(lazy(() -> + return suspend(() -> (remainN == 0) ? // We have picked N elements; stop pure(nil()) : @@ -559,7 +558,7 @@ private Trampoline> tramp(List remainAs, int remainN, int remainALeng (r.choose(0, remainALength - 1) < remainN) ? tramp(remainAs.tail(), remainN - 1, remainALength - 1) .map(pickedTail -> cons(remainAs.head(), pickedTail)) : - tramp(remainAs.tail(), remainN, remainALength - 1))); + tramp(remainAs.tail(), remainN, remainALength - 1)); } } From cf1188acafd62d60f1736a0d945790771029079b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 11:13:26 +0200 Subject: [PATCH 694/811] Fix regression in lifted semigroup sum. Move lifted definition in Monoid. --- core/src/main/java/fj/Monoid.java | 31 +++++++++++++++++++++++++++ core/src/main/java/fj/Semigroup.java | 24 +-------------------- core/src/test/java/fj/MonoidTest.java | 19 ++++++++++++++++ 3 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 core/src/test/java/fj/MonoidTest.java diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 3fcf1775..cdb8e746 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -17,6 +17,7 @@ import static fj.data.List.nil; import static fj.data.Natural.natural; import static fj.data.Option.none; +import static fj.data.Option.some; import static fj.data.Stream.iterableStream; import java.math.BigInteger; @@ -867,6 +868,36 @@ public List sum(F0>> as) { }); } + /** + * Lift a {@code Semigroup} for A to a {@code Monoid>}, using Option.none() as zero. + * + * @return A monoid for option. + */ + public static Monoid> optionMonoid(Semigroup aSemigroup) { + return monoidDef(new Monoid.Definition>() { + @Override + public Option empty() { + return none(); + } + + @Override + public Option append(Option a1, Option a2) { + return a1.liftM2(a2, aSemigroup::sum).orElse(a1).orElse(a2); + } + + @Override + public Option multiply(int n, Option oa) { + return n > 0 ? oa.map(a -> aSemigroup.multiply1p(n - 1, a)) : none(); + } + + @Override + public Option sum(F0>> oas) { + Stream as = oas.f().bind(Option::toStream); + return as.uncons(none(), h -> tail -> some(aSemigroup.sumStream(h, tail::_1))); + } + }); + } + /** * A monoid for options. * @deprecated since 4.7. Use {@link #firstOptionMonoid()}. diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 16b0d130..f626ded7 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -172,29 +172,7 @@ public Semigroup dual() { * Lifts the semigroup to obtain a trivial monoid. */ public Monoid> lift() { - Definition def = this.def; - return monoidDef(new Monoid.Definition>() { - @Override - public Option empty() { - return none(); - } - - @Override - public Option append(Option a1, Option a2) { - return a1.liftM2(a1, def::append).orElse(a1).orElse(a2); - } - - @Override - public Option multiply(int n, Option oa) { - return n > 0 ? oa.map(a -> def.multiply1p(n - 1, a)) : none(); - } - - @Override - public Option sum(F0>> oas) { - Stream as = oas.f().bind(Option::toStream); - return as.uncons(none(), h -> tail -> some(def.sum(h, tail::_1))); - } - }); + return Monoid.optionMonoid(this); } /** diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java new file mode 100644 index 00000000..8bab5315 --- /dev/null +++ b/core/src/test/java/fj/MonoidTest.java @@ -0,0 +1,19 @@ +package fj; + +import fj.data.Option; +import fj.data.Stream; +import org.junit.Test; + +import static fj.data.Option.some; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class MonoidTest { + + @Test + public void lifted_sum_of_two_numbers() { + Monoid> optionMonoid = Semigroup.intAdditionSemigroup.lift(); + assertThat(optionMonoid.sum(some(3), some(5)), is(some(8))); + assertThat(optionMonoid.sumLeft(Stream.arrayStream(some(3), some(5))), is(some(8))); + } +} From c3ea5d36dd7869e8e4da411b4d9b926a44fb4bcd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 11:25:47 +0200 Subject: [PATCH 695/811] Add Trampoline.suspend(final F0> a). --- core/src/main/java/fj/control/Trampoline.java | 17 ++++++++++++++--- core/src/main/java/fj/data/DList.java | 2 +- core/src/main/java/fj/data/Eval.java | 6 +++--- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/State.java | 3 +-- quickcheck/src/main/java/fj/test/Gen.java | 5 ++--- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 37491c3b..0b6060b1 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -46,7 +46,7 @@ public R fold(final F, R> n, // The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the // continuations. public Trampoline bind(final F> f) { - return codense(sub, o -> suspend(P.lazy(() -> cont.f(o).bind(f)))); + return codense(sub, o -> suspend(() -> cont.f(o).bind(f))); } // The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result @@ -126,6 +126,16 @@ public static Trampoline pure(final A a) { return new Pure<>(a); } + /** + * Suspends the given computation in a thunk. + * + * @param a A trampoline suspended in a thunk. + * @return A trampoline whose next step runs the given thunk. + */ + public static Trampoline suspend(final F0> a) { + return new Suspend<>(P.lazy(a)); + } + /** * Suspends the given computation in a thunk. * @@ -136,6 +146,7 @@ public static Trampoline suspend(final P1> a) { return new Suspend<>(a); } + /** * @return The first-class version of `suspend`. */ @@ -255,7 +266,7 @@ public final Trampoline zipWith(final Trampoline b, final F2>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.lazy(() -> ta.zipWith(tb, f)))))); + return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(() -> ta.zipWith(tb, f))))); } for (final B y : eb.right()) { return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); @@ -263,7 +274,7 @@ public final Trampoline zipWith(final Trampoline b, final F2 pure(f.f(x, y)))); + return suspend(() -> pure(f.f(x, y))); } for (final P1> y : eb.left()) { return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); diff --git a/core/src/main/java/fj/data/DList.java b/core/src/main/java/fj/data/DList.java index af9d68b0..597b6dda 100644 --- a/core/src/main/java/fj/data/DList.java +++ b/core/src/main/java/fj/data/DList.java @@ -126,6 +126,6 @@ public DList append(DList other) { } private static F> kleisliTrampCompose(F> bc, F> ab) { - return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(P.lazy(() -> bc.f(b)))); + return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(() -> bc.f(b))); } } diff --git a/core/src/main/java/fj/data/Eval.java b/core/src/main/java/fj/data/Eval.java index 3e513075..5d09f913 100644 --- a/core/src/main/java/fj/data/Eval.java +++ b/core/src/main/java/fj/data/Eval.java @@ -204,7 +204,7 @@ private static final class PureTrampolineEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return Trampoline.suspend(P.lazy(() -> Trampoline.pure(start.value()))); + return Trampoline.suspend(() -> Trampoline.pure(start.value())); } } @@ -219,7 +219,7 @@ private static final class BindTrampolineEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return Trampoline.suspend(P.lazy(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline()))); + return Trampoline.suspend(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline())); } } @@ -232,7 +232,7 @@ private static final class DeferEval extends TrampolineEval { @Override protected final Trampoline trampoline() { - return Trampoline.suspend(P.lazy(() -> memo._1().asTrampoline().trampoline())); + return Trampoline.suspend(() -> memo._1().asTrampoline().trampoline()); } } } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index f58fd73f..e0e12877 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -736,7 +736,7 @@ public final B foldRight(final F2 f, final B b) { * @return A Trampoline containing the final result after the right-fold reduction. */ public final Trampoline foldRightC(final F2 f, final B b) { - return Trampoline.suspend(P.lazy(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head())))); + return Trampoline.suspend(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head()))); } /** diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index 1b30a55e..f29d55d7 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -5,7 +5,6 @@ import fj.Unit; import fj.control.Trampoline; -import static fj.P.lazy; import static fj.P.p; import static fj.control.Trampoline.suspend; import static fj.data.List.cons; @@ -75,7 +74,7 @@ public static State> traverse(List list, F State suspended(F>> runF) { - return new State<>(s -> suspend(lazy(() -> runF.f(s)))); + return new State<>(s -> suspend(() -> runF.f(s))); } private final F>> runF; diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index a5e30a9d..323995e1 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -16,7 +16,6 @@ import static fj.Function.flip; import static fj.Monoid.intAdditionMonoid; import static fj.Ord.intOrd; -import static fj.P.lazy; import static fj.P2.__1; import static fj.control.Trampoline.pure; import static fj.control.Trampoline.suspend; @@ -551,7 +550,7 @@ final class Tramp { // Picks elements in constant stack space private Trampoline> tramp(List remainAs, int remainN, int remainALength) { - return suspend(lazy(() -> + return suspend(() -> (remainN == 0) ? // We have picked N elements; stop pure(nil()) : @@ -559,7 +558,7 @@ private Trampoline> tramp(List remainAs, int remainN, int remainALeng (r.choose(0, remainALength - 1) < remainN) ? tramp(remainAs.tail(), remainN - 1, remainALength - 1) .map(pickedTail -> cons(remainAs.head(), pickedTail)) : - tramp(remainAs.tail(), remainN, remainALength - 1))); + tramp(remainAs.tail(), remainN, remainALength - 1)); } } From e1a0983a365ca6a934dccf14a181a9ba486ccdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 23 Sep 2018 20:28:40 +0200 Subject: [PATCH 696/811] Add Strategy tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták (cherry picked from commit 2e1f2c57176a2bf8974ef0725e681e9042cff9ec) --- .../fj/control/parallel/StrategyTest.java | 61 +++++++++++++++++++ core/src/test/java/fj/data/StreamTest.java | 16 ----- 2 files changed, 61 insertions(+), 16 deletions(-) create mode 100644 core/src/test/java/fj/control/parallel/StrategyTest.java diff --git a/core/src/test/java/fj/control/parallel/StrategyTest.java b/core/src/test/java/fj/control/parallel/StrategyTest.java new file mode 100644 index 00000000..ee3b30df --- /dev/null +++ b/core/src/test/java/fj/control/parallel/StrategyTest.java @@ -0,0 +1,61 @@ +package fj.control.parallel; + +import fj.Ord; +import fj.P; +import fj.P1; +import fj.data.Enumerator; +import fj.data.List; +import fj.data.Stream; +import org.junit.Test; + +import java.util.concurrent.*; + +import static fj.control.parallel.Callables.callable; +import static fj.control.parallel.Strategy.*; +import static fj.data.Stream.range; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class StrategyTest { + + @Test + public void testStrategySeq() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + assertThat(s.sort(Ord.intOrd, seqStrategy()), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyThread() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + assertThat(s.sort(Ord.intOrd, simpleThreadStrategy()), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyExecutor() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + final ExecutorService es = Executors.newFixedThreadPool(10); + assertThat(s.sort(Ord.intOrd, executorStrategy(es)), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyCompletion() { + final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); + final ExecutorService es = Executors.newFixedThreadPool(10); + final CompletionService cs = new ExecutorCompletionService(es); + assertThat(s.sort(Ord.intOrd, completionStrategy(cs)), is(s.sort(Ord.intOrd))); + } + + @Test + public void testStrategyMergeAll() { + final List l = List.range(0, 100); + final List> p1s = mergeAll(l.map(x -> CompletableFuture.supplyAsync(() -> x))); + assertThat(P1.sequence(p1s)._1(), is(l)); + } + + @Test + public void testStrategyCallables() throws Exception { + final Strategy> s = strategy(c -> c); + final Strategy> cs = callableStrategy(s); + assertThat(callableStrategy(s).par(P.p(callable(1)))._1().call(), is(1)); + } +} diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index b65e115c..999a3a3e 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -1,9 +1,7 @@ package fj.data; import fj.Equal; -import fj.Ord; import fj.P2; -import fj.control.parallel.Strategy; import org.junit.Test; import java.util.ConcurrentModificationException; @@ -105,18 +103,4 @@ public void testMinus() { assertThat(s1.minus(Equal.charEqual, s2), is(stream(new Character[]{'a', 'c', 'd'}))); } - - @Test - public void testSortSeq() { - Stream s = range(Enumerator.intEnumerator, 99, -99, -1); - assertThat(s.sort(Ord.intOrd, Strategy.seqStrategy()), - is(s.sort(Ord.intOrd))); - } - - @Test - public void testSortThread() { - Stream s = range(Enumerator.intEnumerator, 99, -99, -1); - assertThat(s.sort(Ord.intOrd, Strategy.simpleThreadStrategy()), - is(s.sort(Ord.intOrd))); - } } From 7b3cdae5e9d708904d72afffe039710ed8a9ad28 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 20:00:44 +0200 Subject: [PATCH 697/811] Add missing @Deprecated annotations (previously only on javadoc). --- core/src/main/java/fj/P1.java | 3 ++- core/src/main/java/fj/Semigroup.java | 3 ++- core/src/main/java/fj/data/Java.java | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 555a28ae..5e627403 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -42,10 +42,11 @@ public static F, A> __1() { /** * Promote any function to a transformation between P1s. * - * @deprecated As of release 4.5, use {@link #map_} + * @deprecated As of release 4.5, use {@link #map_} * @param f A function to promote to a transformation between P1s. * @return A function promoted to operate on P1s. */ + @Deprecated public static F, P1> fmap(final F f) { return map_(f); } diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index f626ded7..075dfeda 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -527,8 +527,9 @@ public NonEmptyList sum(NonEmptyList nea, F0>> neas * A semigroup for optional values. * @deprecated since 4.7. Use {@link #firstOptionSemigroup()}. * - ** @return A semigroup for optional values. + * @return A semigroup for optional values. */ + @Deprecated public static Semigroup> optionSemigroup() { return firstOptionSemigroup(); } diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 80a5ec43..ae7fcf6a 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1420,6 +1420,7 @@ public static F, List> ArrayList_List() { * * @return A function that converts Java lists to lists. */ + @Deprecated public static F, List> JUList_List() { return Java::JavaList_List; } From 9f489c9428ff06ea39400239faa929eae9d78bba Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 21:08:42 +0200 Subject: [PATCH 698/811] Fix compile warnings. --- core/src/test/java/fj/FWFunctionsTest.java | 4 ++-- core/src/test/java/fj/TryEffectTest.java | 6 ++---- core/src/test/java/fj/control/parallel/StrategyTest.java | 3 ++- props-core/src/test/java/fj/MemoisationTest.java | 9 +++++---- .../test/java/fj/data/fingertrees/FingerTreeTest.java | 6 ++++-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/core/src/test/java/fj/FWFunctionsTest.java b/core/src/test/java/fj/FWFunctionsTest.java index c1f69718..1c034ab9 100644 --- a/core/src/test/java/fj/FWFunctionsTest.java +++ b/core/src/test/java/fj/FWFunctionsTest.java @@ -9,14 +9,14 @@ public class FWFunctionsTest { @Test public void testLift1() { F f = i -> i + 1; - F1W f1w = F1W.lift(f); + F1W f1w = F1W.lift(f); assertThat(f1w.f(1), is(2)); } @Test public void testLift2() { F2 f2 = (i, j) -> i + j; - F2W f2w = F2W.lift(f2); + F2W f2w = F2W.lift(f2); assertThat(f2w.f(1, 2), is(3)); } diff --git a/core/src/test/java/fj/TryEffectTest.java b/core/src/test/java/fj/TryEffectTest.java index bb684fc6..ea92b8f2 100644 --- a/core/src/test/java/fj/TryEffectTest.java +++ b/core/src/test/java/fj/TryEffectTest.java @@ -11,8 +11,7 @@ public class TryEffectTest { @Test public void testTryEffect0Success() { - F> f = - TryEffect.f(TryEffect0::f); + F, Validation> f = TryEffect.f(TryEffect0::f); Validation v = f.f(new AlwaysSucceed0()); assertThat(v.isSuccess(), is(true)); assertThat(v.success(), is(Unit.unit())); @@ -20,8 +19,7 @@ public void testTryEffect0Success() { @Test public void testTryEffect0Fail() { - F> f = - TryEffect.f(TryEffect0::f); + F, Validation> f = TryEffect.f(TryEffect0::f); Validation v = f.f(new AlwaysFail0()); assertThat(v.isFail(), is(true)); assertThat(v.fail(), is(new TryEffectException())); diff --git a/core/src/test/java/fj/control/parallel/StrategyTest.java b/core/src/test/java/fj/control/parallel/StrategyTest.java index ee3b30df..8475b35a 100644 --- a/core/src/test/java/fj/control/parallel/StrategyTest.java +++ b/core/src/test/java/fj/control/parallel/StrategyTest.java @@ -3,6 +3,7 @@ import fj.Ord; import fj.P; import fj.P1; +import fj.Unit; import fj.data.Enumerator; import fj.data.List; import fj.data.Stream; @@ -41,7 +42,7 @@ public void testStrategyExecutor() { public void testStrategyCompletion() { final Stream s = range(Enumerator.intEnumerator, 99, -99, -1); final ExecutorService es = Executors.newFixedThreadPool(10); - final CompletionService cs = new ExecutorCompletionService(es); + final CompletionService cs = new ExecutorCompletionService<>(es); assertThat(s.sort(Ord.intOrd, completionStrategy(cs)), is(s.sort(Ord.intOrd))); } diff --git a/props-core/src/test/java/fj/MemoisationTest.java b/props-core/src/test/java/fj/MemoisationTest.java index 65fa83fc..865f76a3 100644 --- a/props-core/src/test/java/fj/MemoisationTest.java +++ b/props-core/src/test/java/fj/MemoisationTest.java @@ -6,6 +6,7 @@ import org.junit.runner.RunWith; import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbString; import static fj.test.CheckResult.summary; import static fj.test.Property.prop; import static fj.test.Property.property; @@ -25,16 +26,16 @@ public Property test1() { } public Property test1_hardMemo() { - return property(arbInteger, a -> { - P1 t = P.hardMemo(() -> new Integer(a)); + return property(arbString, a -> { + P1 t = P.hardMemo(() -> new String(a)); return prop(t._1() == t._1()).and(prop(t._1().equals(a))); }); } @Test public Property test2() { - return property(arbInteger, arbInteger, (a, b) -> { - P2 t = P.lazy(u -> new Integer(a), u -> new Integer(b)).memo(); + return property(arbString, arbString, (a, b) -> { + P2 t = P.lazy(u -> new String(a), u -> new String(b)).memo(); return prop(t._1().equals(t._1()) && t._1().equals(a) && t._2().equals(t._2()) && t._2().equals(b) ); }); } diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index 57e1fae6..b25fff51 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -42,14 +42,16 @@ void validateOperations(List list) { @Test public void testHeadOption() { assertThat(Empty.emptyIntAddition().headOption(), is(Option.none())); - FingerTree ft = new MakeTree(measured(intAdditionMonoid, Function.constant(1))).single(1); + FingerTree ft = new MakeTree(measured(intAdditionMonoid, Function.constant(1))) + .single(1); assertThat(ft.headOption(), is(Option.some(1))); } @Test public void testUncons() { assertThat(Empty.emptyIntAddition().uncons(0, (h, t) -> h), is(0)); - FingerTree ft = new MakeTree(measured(intAdditionMonoid, Function.constant(1))).single(1); + FingerTree ft = new MakeTree(measured(intAdditionMonoid, Function.constant(1))) + .single(1); assertThat(ft.uncons(0, (h, t) -> h), is(1)); } From 4c93bae8c23385b9d9acc0e2358073384a10ae03 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 21:09:17 +0200 Subject: [PATCH 699/811] Update gradle. Fix gradle warnings. --- build.gradle | 24 ++++++++--------------- gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 56177 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 9d98d2b3..bc292a82 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,11 @@ buildscript { classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" classpath "me.tatarka:gradle-retrolambda:$retrolambdaPluginVersion" } + + wrapper { + gradleVersion = "4.10.2" + distributionType = Wrapper.DistributionType.ALL + } } if (JavaVersion.current().isJava8Compatible()) { @@ -117,23 +122,10 @@ subprojects { } } - jacocoTestReport { - additionalSourceDirs = files(sourceSets.main.allSource.srcDirs) - sourceDirectories = files(sourceSets.main.allSource.srcDirs) - classDirectories = files(sourceSets.main.output) - reports { - html.enabled = true - xml.enabled = true - csv.enabled = false - } - } - - task coverage(dependsOn: ["test", "jacocoTestReport"]) << {} - } task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { - dependsOn = subprojects.coverage + dependsOn = subprojects*.test executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec") // We only care about coverage of: def projectForFoverage = ["core", "java8", "quickcheck", "java-core"] @@ -192,7 +184,7 @@ configure(subprojects.findAll { it.name != "props-core" }) { } // Output MANIFEST.MF statically so eclipse can see it for plugin development - task eclipsePluginManifest(dependsOn: jar) << { + task eclipsePluginManifest(dependsOn: jar) doLast { file("META-INF").mkdirs() jar.manifest.writeTo(file("META-INF/MANIFEST.MF")) } @@ -200,6 +192,6 @@ configure(subprojects.findAll { it.name != "props-core" }) { eclipseProject.dependsOn eclipsePluginManifest } -task env << { +task env doLast { println System.getenv() } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..29953ea141f55e3b8fc691d31b5ca8816d89fa87 100644 GIT binary patch delta 50157 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 *SW$u63w9|gi(C$5HMvX&ZbF|8 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 HXWjn;W&S@( delta 48671 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 p-JqCdbEt2u3x<%@f8MG(Y}9d{||T4^I-r0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 72c40576..d76b502e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat Aug 25 14:20:05 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip From b797968ae46d5eafd951b03c68d649b9aae8f654 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Sun, 7 Oct 2018 21:52:42 +0200 Subject: [PATCH 700/811] Fix javadoc warnings. --- core/src/main/java/fj/Function.java | 28 +++++++++---------- core/src/main/java/fj/Monoid.java | 2 +- core/src/main/java/fj/Semigroup.java | 2 +- core/src/main/java/fj/control/Trampoline.java | 12 ++++---- core/src/main/java/fj/data/Enumerator.java | 16 +++++------ core/src/main/java/fj/data/Tree.java | 4 ++- core/src/main/java/fj/data/hlist/HPre.java | 4 +-- core/src/main/java/fj/data/optic/Iso.java | 4 +-- core/src/main/java/fj/data/optic/PIso.java | 16 +++++------ core/src/main/java/fj/data/optic/PLens.java | 26 +++++++++-------- .../main/java/fj/data/optic/POptional.java | 18 ++++++------ core/src/main/java/fj/data/optic/PPrism.java | 17 ++++++----- core/src/main/java/fj/data/optic/PSetter.java | 14 ++++++---- .../main/java/fj/data/optic/PTraversal.java | 6 ++-- quickcheck/src/main/java/fj/test/Gen.java | 12 ++++---- 15 files changed, 96 insertions(+), 85 deletions(-) diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index f95b1c87..995c179d 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -778,11 +778,11 @@ public static F join(final F> f) { /** * Partial application of the second argument to the supplied function to get a function of type - * A -> C. Same as flip(f).f(b). + * {@code A -> C}. Same as {@code flip(f).f(b)}. * * @param f The function to partially apply. * @param b The value to apply to the function. - * @return A new function based on f with its second argument applied. + * @return A new function based on {@code f} with its second argument applied. */ public static F partialApply2(final F> f, final B b) { return a -> uncurryF2(f).f(a, b); @@ -790,11 +790,11 @@ public static F partialApply2(final F> f, final B b) /** * Partial application of the third argument to the supplied function to get a function of type - * A -> B -> D. + * {@code A -> B -> D}. * * @param f The function to partially apply. * @param c The value to apply to the function. - * @return A new function based on f with its third argument applied. + * @return A new function based on {@code f} with its third argument applied. */ public static F> partialApply3(final F>> f, final C c) { return a -> b -> uncurryF3(f).f(a, b, c); @@ -802,11 +802,11 @@ public static F> partialApply3(final F>> /** * Partial application of the fourth argument to the supplied function to get a function of type - * A -> B -> C -> E. + * {@code A -> B -> C -> E}. * * @param f The function to partially apply. * @param d The value to apply to the function. - * @return A new function based on f with its fourth argument applied. + * @return A new function based on {@code f} with its fourth argument applied. */ public static F>> partialApply4(final F>>> f, final D d) { return a -> b -> c -> uncurryF4(f).f(a, b, c, d); @@ -814,11 +814,11 @@ public static F>> partialApply4(final FA -> B -> C -> D -> F$. + * {@code A -> B -> C -> D -> F$}. * * @param f The function to partially apply. * @param e The value to apply to the function. - * @return A new function based on f with its fifth argument applied. + * @return A new function based on {@code f} with its fifth argument applied. */ public static F>>> partialApply5(final F>>>> f, final E e) { @@ -827,11 +827,11 @@ public static F>> partialApply4(final FA -> B -> C -> D -> E -> G. + * {@code A -> B -> C -> D -> E -> G}. * * @param f The function to partially apply. * @param f$ The value to apply to the function. - * @return A new function based on f with its sixth argument applied. + * @return A new function based on {@code f} with its sixth argument applied. */ public static F>>>> partialApply6( final F>>>>> f, final F$ f$) { @@ -840,11 +840,11 @@ public static F>> partialApply4(final FA -> B -> C -> D -> E -> F$ -> H. + * {@code A -> B -> C -> D -> E -> F$ -> H}. * * @param f The function to partially apply. * @param g The value to apply to the function. - * @return A new function based on f with its seventh argument applied. + * @return A new function based on {@code f} with its seventh argument applied. */ public static F>>>>> partialApply7( final F>>>>>> f, final G g) { @@ -853,11 +853,11 @@ public static F>> partialApply4(final FA -> B -> C -> D -> E -> F$ -> G -> I. + * {@code A -> B -> C -> D -> E -> F$ -> G -> I}. * * @param f The function to partially apply. * @param h The value to apply to the function. - * @return A new function based on f with its eigth argument applied. + * @return A new function based on {@code f} with its eigth argument applied. */ public static F>>>>>> partialApply8( final F>>>>>>> f, final H h) { diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index cdb8e746..0c09b558 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -246,7 +246,7 @@ public A zero() { /** * Returns a value summed n times (a + a + ... + a). * The default definition uses peasant multiplication, exploiting - * associativity to only require `O(log n)` uses of + * associativity to only require {@code O(log n)} uses of * {@link #sum(Object, Object)}. * * @param n multiplier diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 075dfeda..42f05f5b 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -134,7 +134,7 @@ public F> sum() { /** * Returns a value summed n + 1 times ( * a + a + ... + a) The default definition uses peasant - * multiplication, exploiting associativity to only require `O(log n)` uses of + * multiplication, exploiting associativity to only require {@code O(log n)} uses of * {@link #sum(Object, Object)}. * * @param n multiplier diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 0b6060b1..47fd282b 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -43,7 +43,7 @@ public R fold(final F, R> n, return gs.f(this); } - // The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the + // The monadic bind constructs a new Codense whose subcomputation is still {@code sub}, and Kleisli-composes the // continuations. public Trampoline bind(final F> f) { return codense(sub, o -> suspend(() -> cont.f(o).bind(f))); @@ -110,7 +110,7 @@ private static Codense codense(final Normal a, final F F> pure() { return Trampoline::pure; @@ -148,7 +148,7 @@ public static Trampoline suspend(final P1> a) { /** - * @return The first-class version of `suspend`. + * @return The first-class version of {@code suspend}. */ public static F>, Trampoline> suspend_() { return Trampoline::suspend; @@ -175,21 +175,21 @@ public final Trampoline map(final F f) { } /** - * @return The first-class version of `bind`. + * @return The first-class version of {@code bind}. */ public static F>, F, Trampoline>> bind_() { return f -> a -> a.bind(f); } /** - * @return The first-class version of `map`. + * @return The first-class version of {@code map}. */ public static F, F, Trampoline>> map_() { return f -> a -> a.map(f); } /** - * @return The first-class version of `resume`. + * @return The first-class version of {@code resume}. */ public static F, Either>, A>> resume_() { return Trampoline::resume; diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index 1666d7b2..94f1b2cd 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -18,18 +18,18 @@ /** * Abstracts over a type that may have a successor and/or predecessor value. This implies ordering for that type. A user - * may construct an enumerator with an optimised version for plus, otherwise a default is implemented using + * may construct an enumerator with an optimised version for {@code plus}, otherwise a default is implemented using * the given successor/predecessor implementations. *

      * For any enumerator e, the following laws must satisfy: *

        - *
      • forall a. e.successor(a).forall(\t -> e.predecessor(t).forall(\z -> z == a))
      • - *
      • forall a. e.predecessor(a).forall(\t -> e.successor(t).forall(\z -> z == a))
      • - *
      • e.max().forall(\t -> e.successor(t).isNone)
      • - *
      • e.min().forall(\t -> e.predecessor(t).isNone)
      • - *
      • forall a n. e.plus(a, 0) == Some(a)
      • - *
      • forall a n | n > 0. e.plus(a, n) == e.plus(a, n - 1)
      • - *
      • forall a n | n < 0. e.plus(a, n) == e.plus(a, n + 1)
      • + *
      • {@code forall a. e.successor(a).forall(\t -> e.predecessor(t).forall(\z -> z == a))}
      • + *
      • {@code forall a. e.predecessor(a).forall(\t -> e.successor(t).forall(\z -> z == a))}
      • + *
      • {@code e.max().forall(\t -> e.successor(t).isNone)}
      • + *
      • {@code e.min().forall(\t -> e.predecessor(t).isNone)}
      • + *
      • {@code forall a n. e.plus(a, 0) == Some(a)}
      • + *
      • {@code forall a n | n > 0. e.plus(a, n) == e.plus(a, n - 1)}
      • + *
      • {@code forall a n | n < 0. e.plus(a, n) == e.plus(a, n + 1)}
      • *
      * * @version %build.number% diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 4b0ce7eb..9eebb932 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -134,8 +134,10 @@ public Stream
      f(final Tree t, final P1> xs) { } /** + *
      {@code
          * flatten :: Tree a -> [a]
          * flatten t = squish t []
      +   * }
      * where squish (Node x ts) xs = x:Prelude.foldr squish xs ts * Puts the elements of the tree into a Stream, in pre-order. * @@ -346,4 +348,4 @@ public int length() { return 1 + subForest._1().map(Tree::length).foldLeft((acc, i) -> acc + i, 0); } -} \ No newline at end of file +} diff --git a/core/src/main/java/fj/data/hlist/HPre.java b/core/src/main/java/fj/data/hlist/HPre.java index 6a2556de..6c6174a4 100644 --- a/core/src/main/java/fj/data/hlist/HPre.java +++ b/core/src/main/java/fj/data/hlist/HPre.java @@ -57,7 +57,7 @@ public static HFalse hFalse() { } /** - * Type-level boolean conjunction. A value of this type represents evidence that AB -> C + * Type-level boolean conjunction. A value of this type represents evidence that {@code AB -> C} * * @param
      A boolean * @param A boolean @@ -92,7 +92,7 @@ public static HAnd hAnd(final HTrue a, final HTrue b) { } /** - * Type-level boolean disjunction. A value of this type represents evidence that A+B -> C + * Type-level boolean disjunction. A value of this type represents evidence that {@code A+B -> C} * * @param A boolean * @param A boolean diff --git a/core/src/main/java/fj/data/optic/Iso.java b/core/src/main/java/fj/data/optic/Iso.java index ea9babac..4b41b1ad 100644 --- a/core/src/main/java/fj/data/optic/Iso.java +++ b/core/src/main/java/fj/data/optic/Iso.java @@ -119,10 +119,10 @@ public static Iso iso(final F get, final F reverseGet) * create an {@link Iso} between any type and itself. id is the zero element of optics composition, for all optics o of type O * (e.g. Lens, Iso, Prism, ...): * - *
      +   * 
      {@code
          *  o composeIso Iso.id == o
          *  Iso.id composeO o == o
      -   * 
      + * }
      * * (replace composeO by composeLens, composeIso, composePrism, ...) */ diff --git a/core/src/main/java/fj/data/optic/PIso.java b/core/src/main/java/fj/data/optic/PIso.java index e10b47bb..b97b416f 100644 --- a/core/src/main/java/fj/data/optic/PIso.java +++ b/core/src/main/java/fj/data/optic/PIso.java @@ -21,18 +21,18 @@ /** * A {@link PIso} defines an isomorphism between types S, A and B, T: * - *
      + * 
      {@code
        *              get                           reverse.get
        *     -------------------->             -------------------->
        *   S                       A         T                       B
        *     <--------------------             <--------------------
        *       reverse.reverseGet                   reverseGet
      - * 
      + * }
      * - * In addition, if f and g forms an isomorphism between `A` and `B`, i.e. if `f . g = id` and `g . f = id`, then a {@link PIso} - * defines an isomorphism between `S` and `T`: + * In addition, if f and g forms an isomorphism between {@code A} and {@code B}, i.e. if {@code f . g = id} and {@code g . f = id}, then a {@link PIso} + * defines an isomorphism between {@code S} and {@code T}: * - *
      + * 
      {@code
        *     S           T                                   S           T
        *     |           |                                   |           |
        *     |           |                                   |           |
      @@ -40,7 +40,7 @@
        *     |           |                                   |           |
        *     |     f     |                                   |     g     |
        *     A --------> B                                   A <-------- B
      - * 
      + * }
      * * A {@link PIso} is also a valid {@link Getter}, {@link Fold}, {@link PLens}, {@link PPrism}, {@link POptional}, * {@link PTraversal} and {@link PSetter} @@ -552,10 +552,10 @@ public PIso reverse() { * create a {@link PIso} between any type and itself. id is the zero element of optics composition, for all optics o of type O * (e.g. Lens, Iso, Prism, ...): * - *
      +   * 
      {@code
          *  o composeIso Iso.id == o
          *  Iso.id composeO o == o
      -   * 
      + * }
      * * (replace composeO by composeLens, composeIso, composePrism, ...) */ diff --git a/core/src/main/java/fj/data/optic/PLens.java b/core/src/main/java/fj/data/optic/PLens.java index 971f76ff..4dcad20b 100644 --- a/core/src/main/java/fj/data/optic/PLens.java +++ b/core/src/main/java/fj/data/optic/PLens.java @@ -17,18 +17,20 @@ import fj.data.vector.V2; /** - * A {@link PLens} can be seen as a pair of functions: - `get: S => A` i.e. from an `S`, we can extract an `A` - `set: (B, S) => - * T` i.e. if we replace an `A` by a `B` in an `S`, we obtain a `T` - * - * A {@link PLens} could also be defined as a weaker {@link PIso} where set requires an additional parameter than reverseGet. - * - * {@link PLens} stands for Polymorphic Lens as it set and modify methods change a type `A` to `B` and `S` to `T`. {@link Lens} - * is a {@link PLens} restricted to monomoprhic updates. - * - * A {@link PLens} is also a valid {@link Getter}, {@link Fold}, {@link POptional}, {@link PTraversal} and {@link PSetter} - * + * A {@link PLens} can be seen as a pair of functions:
        + *
      • {@code get: S => A} i.e. from an {@code S}, we can extract an {@code A}
      • + *
      • {@code set: (B, S) => T} i.e. if we replace an {@code A} by a {@code B} in an {@code S}, we obtain a {@code T}
      • + *
      + *

      + * A {@link PLens} could also be defined as a weaker {@link PIso} where set requires an additional parameter than reverseGet.

      + *

      + * {@link PLens} stands for Polymorphic Lens as it set and modify methods change a type {@code A} to {@code B} and {@code S} to {@code T}. {@link Lens} + * is a {@link PLens} restricted to monomoprhic updates.

      + *

      + * A {@link PLens} is also a valid {@link Getter}, {@link Fold}, {@link POptional}, {@link PTraversal} and {@link PSetter}

      + *

      * Typically a {@link PLens} or {@link Lens} can be defined between a Product (e.g. case class, tuple, HList) and one of it is - * component. + * component.

      * * @param the source of a {@link PLens} * @param the modified source of a {@link PLens} @@ -500,4 +502,4 @@ public F modify(final F f) { } }; } -} \ No newline at end of file +} diff --git a/core/src/main/java/fj/data/optic/POptional.java b/core/src/main/java/fj/data/optic/POptional.java index d35979d8..c70aa4c1 100644 --- a/core/src/main/java/fj/data/optic/POptional.java +++ b/core/src/main/java/fj/data/optic/POptional.java @@ -20,13 +20,15 @@ import fj.data.vector.V2; /** - * A {@link POptional} can be seen as a pair of functions: - `getOrModify: S => T \/ A` - `set : (B, S) => T` - * - * A {@link POptional} could also be defined as a weaker {@link PLens} and weaker {@link PPrism} - * - * {@link POptional} stands for Polymorphic Optional as it set and modify methods change a type `A` to `B` and `S` to `T`. - * {@link Optional} is a {@link POptional} restricted to monomoprhic updates: {{{ type Optional[S, A] = POptional[S, S, A, A] - * }}} + * A {@link POptional} can be seen as a pair of functions:
        + *
      • {@code getOrModify: S => T \/ A}
      • + *
      • {@code set : (B, S) => T}
      • + *
      + *

      + * A {@link POptional} could also be defined as a weaker {@link PLens} and weaker {@link PPrism}

      + *

      + * {@link POptional} stands for Polymorphic Optional as it set and modify methods change a type {@code A} to {@code B} and {@code S} to {@code T}. + * {@link Optional} is a {@link POptional} restricted to monomoprhic updates: {@code type Optional[S, A] = POptional[S, S, A, A]}

      * * @param the source of a {@link POptional} * @param the modified source of a {@link POptional} @@ -479,4 +481,4 @@ public F modify(final F f) { }; } -} \ No newline at end of file +} diff --git a/core/src/main/java/fj/data/optic/PPrism.java b/core/src/main/java/fj/data/optic/PPrism.java index c4a65a68..ffa87ba6 100644 --- a/core/src/main/java/fj/data/optic/PPrism.java +++ b/core/src/main/java/fj/data/optic/PPrism.java @@ -19,14 +19,17 @@ import fj.data.vector.V2; /** - * A {@link PPrism} can be seen as a pair of functions: - `getOrModify: S => T \/ A` - `reverseGet : B => T` - * - * A {@link PPrism} could also be defined as a weaker {@link PIso} where get can fail. - * + * A {@link PPrism} can be seen as a pair of functions:
        + *
      • {@code getOrModify: S => T \/ A}
      • + *
      • {@code reverseGet : B => T}
      • + *
      + *

      + * A {@link PPrism} could also be defined as a weaker {@link PIso} where get can fail.

      + *

      * Typically a {@link PPrism} or {@link Prism} encodes the relation between a Sum or CoProduct type (e.g. sealed trait) and one - * of it is element. + * of it is element.

      * - * {@link PPrism} stands for Polymorphic Prism as it set and modify methods change a type `A` to `B` and `S` to `T`. + * {@link PPrism} stands for Polymorphic Prism as it set and modify methods change a type {@code A} to {@code B} and {@code S} to {@code T}. * {@link Prism} is a {@link PPrism} where the type of target cannot be modified. * * A {@link PPrism} is also a valid {@link Fold}, {@link POptional}, {@link PTraversal} and {@link PSetter} @@ -436,4 +439,4 @@ public Option
      getOption(final S s) { }; } -} \ No newline at end of file +} diff --git a/core/src/main/java/fj/data/optic/PSetter.java b/core/src/main/java/fj/data/optic/PSetter.java index 012920cb..13be7739 100644 --- a/core/src/main/java/fj/data/optic/PSetter.java +++ b/core/src/main/java/fj/data/optic/PSetter.java @@ -5,12 +5,14 @@ import fj.data.Either; /** - * A {@link PSetter} is a generalisation of Functor map: - `map: (A => B) => F[A] => F[B]` - `modify: (A => B) => S => - * T` - * - * {@link PSetter} stands for Polymorphic Setter as it set and modify methods change a type `A` to `B` and `S` to `T`. - * - * {@link PTraversal}, {@link POptional}, {@link PPrism}, {@link PLens} and {@link PIso} are valid {@link PSetter} + * A {@link PSetter} is a generalisation of Functor map:
        + *
      • {@code map: (A => B) => F[A] => F[B]}
      • + *
      • {@code modify: (A => B) => S => T}
      • + *
      + *

      + * {@link PSetter} stands for Polymorphic Setter as it set and modify methods change a type {@code A} to {@code B} and {@code S} to {@code T}.

      + *

      + * {@link PTraversal}, {@link POptional}, {@link PPrism}, {@link PLens} and {@link PIso} are valid {@link PSetter}

      * * @param the source of a {@link PSetter} * @param the modified source of a {@link PSetter} diff --git a/core/src/main/java/fj/data/optic/PTraversal.java b/core/src/main/java/fj/data/optic/PTraversal.java index ee16760f..6087f707 100644 --- a/core/src/main/java/fj/data/optic/PTraversal.java +++ b/core/src/main/java/fj/data/optic/PTraversal.java @@ -24,9 +24,9 @@ /** * A {@link PTraversal} can be seen as a {@link POptional} generalised to 0 to n targets where n can be infinite. - * - * {@link PTraversal} stands for Polymorphic Traversal as it set and modify methods change a type `A` to `B` and `S` to `T`. - * {@link Traversal} is a {@link PTraversal} restricted to monomoprhic updates. + *

      + * {@link PTraversal} stands for Polymorphic Traversal as it set and modify methods change a type {@code A} to {@code B} and {@code S} to {@code T}. + * {@link Traversal} is a {@link PTraversal} restricted to monomoprhic updates.

      * * @param the source of a {@link PTraversal} * @param the modified source of a {@link PTraversal} diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 323995e1..c375874d 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -33,7 +33,7 @@ * allowing various forms of composition of generators.

      A user typically creates an {@link * Arbitrary arbitrary} to return a generator using the 'combinator methods' below. For example, * suppose a class Person: -

      +
      {@code
       class Person {
         final int age;
         final String name;
      @@ -45,23 +45,23 @@ class Person {
           this.male = male;
         }
       }
      -
      +}
      *

      In a case like this one, a user may create a generator over Person by * invoking the {@link #bind(F)} methods — in this case, {@link #bind(Gen , Gen , F)} the one * that takes two generator arguments}, since the class has one more than two fields (the bind * method is invoked on a generator adding the extra one to the count as they are composed). The * class fields are of types for which there exist generators (on {@link Gen} so those can be * used to compose a generator for Person:

      -
      +
      {@code
       static Gen<Person> personArbitrary() {
         return arbInteger.bind(arbString(), arbBoolean(),
             // compose the generators
             {int age => {String name => {boolean male => new Person(age, name, male)}}};
       }
      -
      +}
      *

      * The example above uses Java 7 closure syntax. Here is the same example using objects instead: -

      +
      {@code
       static Gen<Person> personArbitrary() {
         return arbInteger.bind(arbString, arbBoolean,
             // compose the generators
      @@ -79,7 +79,7 @@ public Person f(final Boolean male) {
               }
             });
       }
      -
      +}
      * * @version %build.number% */ From 6dd03d708f5d04c4f3c0fe4ba25eab39cd075073 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 8 Oct 2018 14:21:40 +0200 Subject: [PATCH 701/811] html5 javadoc --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 6104c093..c070903d 100644 --- a/build.gradle +++ b/build.gradle @@ -140,6 +140,10 @@ configure(subprojects.findAll { it.name != "props-core" }) { sourceCompatibility = "1.8" + javadoc { + options.addBooleanOption('html5', true) + } + task javadocJar(type: Jar, dependsOn: "javadoc") { classifier = 'javadoc' from "build/docs/javadoc" From cd201cce91343302d928f72d31ead35021261de9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 8 Oct 2018 17:35:49 +0200 Subject: [PATCH 702/811] 4.8.1 release. --- README.adoc | 18 +++++++++--------- build.gradle | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.adoc b/README.adoc index a7e2d3a4..8a3ad347 100644 --- a/README.adoc +++ b/README.adoc @@ -35,12 +35,12 @@ The Functional Java artifact is published to Maven Central using the group `org. * Java 8 specific support (`functionaljava-java8`) * property based testing (`functionaljava-quickcheck` or `functionaljava-quickcheck_1.8` if you use Java 8+) -The latest stable version is `4.8`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.8.1`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.8" -compile "org.functionaljava:functionaljava-java8:4.8" -compile "org.functionaljava:functionaljava-quickcheck:4.8" -compile "org.functionaljava:functionaljava-java-core:4.8" +compile "org.functionaljava:functionaljava:4.8.1" +compile "org.functionaljava:functionaljava-java8:4.8.1" +compile "org.functionaljava:functionaljava-quickcheck:4.8.1" +compile "org.functionaljava:functionaljava-java-core:4.8.1" ---- and in Maven: @@ -48,22 +48,22 @@ and in Maven: org.functionaljava functionaljava - 4.8 + 4.8.1 org.functionaljava functionaljava-java8 - 4.8 + 4.8.1 org.functionaljava functionaljava-quickcheck - 4.8 + 4.8.1 org.functionaljava functionaljava-java-core - 4.8 + 4.8.1 ---- diff --git a/build.gradle b/build.gradle index bc292a82..d6c26032 100644 --- a/build.gradle +++ b/build.gradle @@ -47,8 +47,8 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true - fjBaseVersion = "4.9" + isSnapshot = false + fjBaseVersion = "4.8.1" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") From e32fbfdfee3b0f939ec3a9a83cb2c2d094ff3f64 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 8 Oct 2018 17:39:52 +0200 Subject: [PATCH 703/811] Set version to 4.9-SNAPSHOT --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index d6c26032..67d8cd15 100644 --- a/build.gradle +++ b/build.gradle @@ -47,12 +47,12 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "4.8.1" + isSnapshot = true + fjBaseVersion = "4.9" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.8" + fjConsumeVersion = "4.8.1" signModule = false useRetroLambda = false From fcff9d1dc166943906aaa837b26478e74814bfd9 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Giraudeau Date: Mon, 8 Oct 2018 18:11:11 +0200 Subject: [PATCH 704/811] Update changelog with 4.8.1 changes. --- ChangeLog.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 24276f35..acdbedea 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,23 @@ +4.8.1 +----- + +### Enhancements + +- Add Trampoline.suspend(final F0> a). (see [#367](https://github.com/functionaljava/functionaljava/pull/367)); + +### Fixes + +- Fix regression in lifted semigroup sum. Fix #365 (see [#366](https://github.com/functionaljava/functionaljava/pull/366)); + +### Internal + +- Fix compile under jdk11. Enable jdk11 travis build. (see [#361](https://github.com/functionaljava/functionaljava/pull/361)); +- Fix warnings (see [#369](https://github.com/functionaljava/functionaljava/pull/369)); +- Add P tests (see [#360](https://github.com/functionaljava/functionaljava/pull/360)); +- Exclude consume/ from coverage (see [#357](https://github.com/functionaljava/functionaljava/pull/357)); +- Add DList tests (see [#356](https://github.com/functionaljava/functionaljava/pull/356)); +- Add Visitor tests (see [#354](https://github.com/functionaljava/functionaljava/pull/354)); + 4.8 --- @@ -20,7 +40,6 @@ - Added Scalacheck Arbitrary implementations for Natural and NonEmptyList. (see [`405c3ec`](https://github.com/functionaljava/functionaljava/commit/405c3ec)); - Added unit test coverage for Semigroup implementations. The StringBuffer and StringBuilder tests fail because both of those types are mutable. The IO test fails because the ArbitraryIO implementation does not implement equals. (see [`ef81130`](https://github.com/functionaljava/functionaljava/commit/ef81130)); - Fixed the ArbitraryIO implementation and created a Properties object for testing the IO semigroup. (see [`a8e979f`](https://github.com/functionaljava/functionaljava/commit/a8e979f)); -- Added working tests coverage for the StringBuffer and StringBuilder semigroup implementations. Added the Semigroup tests to the list of Scalacheck test suite. (see [`aa4de33`](https://github.com/functionaljava/functionaljava/commit/aa4de33)); - Equal: remove reference to static field of LazyString. Fix #321 (see [`6c6dabd`](https://github.com/functionaljava/functionaljava/commit/6c6dabd)); - Add IOFunctions tests (see [#340](https://github.com/functionaljava/functionaljava/pull/340)); - Add Stream tests (see [#341](https://github.com/functionaljava/functionaljava/pull/341)); @@ -30,4 +49,4 @@ - Add Parser tests (see [#349](https://github.com/functionaljava/functionaljava/pull/349)); - Add FingerTree tests (see [#351](https://github.com/functionaljava/functionaljava/pull/351)); - Add TreeZipper tests (see [#352](https://github.com/functionaljava/functionaljava/pull/352)); -- Add Reader/Writer tests (see [#353](https://github.com/functionaljava/functionaljava/pull/353)); \ No newline at end of file +- Add Reader/Writer tests (see [#353](https://github.com/functionaljava/functionaljava/pull/353)); From 86dabd508306a2cc78fbb692994e158420926c8d Mon Sep 17 00:00:00 2001 From: SoundharyaKamaraj Date: Thu, 25 Oct 2018 12:37:50 -0400 Subject: [PATCH 705/811] #371: fixed failing property test (#373) --- .../src/test/java/fj/data/hamt/BitSetProperties.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java index f3527972..6c3f91a9 100644 --- a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java +++ b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java @@ -156,15 +156,19 @@ Property rangeTest() { int h = list.index(2); int m = Math.max(l, Math.min(list.index(1), h - 1)); int vh = list.index(3); - + BitSet bs1 = longBitSet(x); BitSet bs2 = bs1.range(l, h); + if(l==h){ + return prop(true); + } boolean b = - bs1.isSet(m) == bs2.isSet(m - l) && + bs1.isSet(m) == bs2.isSet(m - l) && bs2.isSet(vh - l) == false; return prop(b); }); } + Property setTest() { return property(arbNaturalLong, arbBitSetSize, (l, i) -> prop(longBitSet(l).set(i).isSet(i))); From c0f0fdbc6ba6e0dd1043fe63d07af4cac6a0c5a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 15 Dec 2018 22:21:15 -0500 Subject: [PATCH 706/811] Add Validation tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/data/Validation.java | 8 +- .../src/test/java/fj/data/ValidationTest.java | 244 ++++++++++++++++++ 2 files changed, 248 insertions(+), 4 deletions(-) create mode 100644 core/src/test/java/fj/data/ValidationTest.java diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 58aa5e9c..0b939e57 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -783,7 +783,7 @@ public final Validation, D> accumulate(Validation v2, Va public final Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { - List list = fails(list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5, v6)); if (!list.isEmpty()) { return fail(list); } else { @@ -792,7 +792,7 @@ public final Validation, D> accumulate(Validation v2, Va } public final Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { - List list = fails(list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5, v6, v7)); if (!list.isEmpty()) { return fail(list); } else { @@ -801,7 +801,7 @@ public final Validation, D> accumulate(Validation v2, Va } public final Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { - List list = fails(list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5, v6, v7, v8)); if (!list.isEmpty()) { return fail(list); } else { @@ -860,7 +860,7 @@ public static List fails(List> list) { return list.filter(Validation::isFail).map(v -> v.fail()); } - public static List
      successes(List> list) { + public static List successes(List> list) { return list.filter(Validation::isSuccess).map(v -> v.success()); } diff --git a/core/src/test/java/fj/data/ValidationTest.java b/core/src/test/java/fj/data/ValidationTest.java new file mode 100644 index 00000000..2d90c9e4 --- /dev/null +++ b/core/src/test/java/fj/data/ValidationTest.java @@ -0,0 +1,244 @@ +package fj.data; + +import org.junit.Test; + +import static fj.data.Validation.*; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; +import fj.*; + +public class ValidationTest { + @Test + public void testParseShort() { + final List> l = + List.list(parseShort("10"), parseShort("x"), parseShort("20")); + assertThat(successes(l).foldLeft1((s, a) -> (short)(s + a)), is((short)30)); + } + + @Test + public void testParseLong() { + final List> l = + List.list(parseLong("10"), parseLong("x"), parseLong("20")); + P2, List> p2 = partition(l); + assertThat(p2._1().length(), is(1)); + assertThat(p2._2().length(), is(2)); + } + + @Test + public void testParseInt() { + final List> l = + List.list(parseInt("10"), parseInt("x"), parseInt("20")); + assertThat(l.map(v -> v.validation(e -> 0, i -> 1)).foldLeft1((s, a) -> s + a), + is(2)); + } + + @Test + public void testParseFloat() { + final List> l = + List.list(parseFloat("2.0"), parseFloat("x"), parseFloat("3.0")); + assertThat(l.map(v -> v.validation(e -> 0, i -> 1)).foldLeft1((s, a) -> s + a), + is(2)); + } + + @Test + public void testParseByte() { + final List> l = + List.list(parseByte("10"), parseByte("x"), parseByte("-10")); + assertThat(l.map(v -> v.validation(e -> 0, i -> 1)).foldLeft1((s, a) -> s + a), + is(2)); + } + + @Test + public void testAccumulate1() { + final Validation, Double> v = + parseDouble("10.0").accumulate( + f1 -> f1); + assertThat(v.success(), is(10.0)); + } + + @Test + public void testAccumulate1Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + f1 -> f1); + assertThat(v.fail().length(), is(1)); + } + + @Test + public void testAccumulate2() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + (f1, f2) -> f1 + f2); + assertThat(v.success(), is(3.0)); + } + + @Test + public void testAccumulate2Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("y"), + (f1, f2) -> f1 + f2); + assertThat(v.fail().length(), is(2)); + } + + @Test + public void testAccumulate3() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + (f1, f2, f3) -> f1 + f2 + f3); + assertThat(v.success(), is(6.0)); + } + + @Test + public void testAccumulate3Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("2.0"), + parseDouble("y"), + (f1, f2, f3) -> f1 + f2 + f3); + assertThat(v.fail().length(), is(2)); + } + + @Test + public void testAccumulate4() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + (f1, f2, f3, f4) -> f1 + f2 + f3 + f4); + assertThat(v.success(), is(10.0)); + } + + @Test + public void testAccumulate4Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("y"), + (f1, f2, f3, f4) -> f1 + f2 + f3 + f4); + assertThat(v.fail().length(), is(2)); + } + + @Test + public void testAccumulate5() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + (f1, f2, f3, f4, f5) -> f1 + f2 + f3 + f4 + f5); + assertThat(v.success(), is(15.0)); + } + + @Test + public void testAccumulate5Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("y"), + (f1, f2, f3, f4, f5) -> f1 + f2 + f3 + f4 + f5); + assertThat(v.fail().length(), is(2)); + } + + @Test + public void testAccumulate6() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + parseDouble("6.0"), + (f1, f2, f3, f4, f5, f6) -> f1 + f2 + f3 + f4 + f5 + f6); + assertThat(v.success(), is(21.0)); + } + + @Test + public void testAccumulate6Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + parseDouble("y"), + (f1, f2, f3, f4, f5, f6) -> f1 + f2 + f3 + f4 + f5 + f6); + assertThat(v.fail().length(), is(2)); + } + + @Test + public void testAccumulate7() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + parseDouble("6.0"), + parseDouble("7.0"), + (f1, f2, f3, f4, f5, f6, f7) -> f1 + f2 + f3 + f4 + f5 + f6 + f7); + assertThat(v.success(), is(28.0)); + } + + @Test + public void testAccumulate7Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + parseDouble("6.0"), + parseDouble("y"), + (f1, f2, f3, f4, f5, f6, f7) -> f1 + f2 + f3 + f4 + f5 + f6 + f7); + assertThat(v.fail().length(), is(2)); + } + + @Test + public void testAccumulate8() { + final Validation, Double> v = + parseDouble("1.0").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + parseDouble("6.0"), + parseDouble("7.0"), + parseDouble("8.0"), + (f1, f2, f3, f4, f5, f6, f7, f8) -> f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8); + assertThat(v.success(), is(36.0)); + } + + @Test + public void testAccumulate8Fail() { + final Validation, Double> v = + parseDouble("x").accumulate( + parseDouble("2.0"), + parseDouble("3.0"), + parseDouble("4.0"), + parseDouble("5.0"), + parseDouble("6.0"), + parseDouble("7.0"), + parseDouble("y"), + (f1, f2, f3, f4, f5, f6, f7, f8) -> f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8); + assertThat(v.fail().length(), is(2)); + } + + @Test(expected = Error.class) + public void testSuccess() { + parseShort("x").success(); + } + + @Test(expected = Error.class) + public void testFail() { + parseShort("12").fail(); + } +} From 0e8e15232f4953a9396e7b30e5664dc1fb513a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 16 Dec 2018 13:35:39 -0500 Subject: [PATCH 707/811] Additional Validation tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .../src/test/java/fj/data/ValidationTest.java | 76 ++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/core/src/test/java/fj/data/ValidationTest.java b/core/src/test/java/fj/data/ValidationTest.java index 2d90c9e4..2f438e5c 100644 --- a/core/src/test/java/fj/data/ValidationTest.java +++ b/core/src/test/java/fj/data/ValidationTest.java @@ -1,11 +1,12 @@ package fj.data; +import fj.P2; import org.junit.Test; +import static fj.Semigroup.firstSemigroup; import static fj.data.Validation.*; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; -import fj.*; public class ValidationTest { @Test @@ -232,6 +233,47 @@ public void testAccumulate8Fail() { assertThat(v.fail().length(), is(2)); } + @Test + public void testAccumulate8s() { + final Validation v1 = parseInt("1"); + final Validation v2 = parseInt("2"); + final Validation v3 = parseInt("3"); + final Validation v4 = parseInt("4"); + final Validation v5 = parseInt("5"); + final Validation v6 = parseInt("6"); + final Validation v7 = parseInt("7"); + final Validation v8 = parseInt("8"); + final Option on2 = v1.accumulate(firstSemigroup(), v2); + assertThat(on2, is(Option.none())); + final Option on3 = v1.accumulate(firstSemigroup(), v2, v3); + assertThat(on3, is(Option.none())); + final Option on4 = v1.accumulate(firstSemigroup(), v2, v3, v4); + assertThat(on4, is(Option.none())); + final Option on5 = v1.accumulate(firstSemigroup(), v2, v3, v4, v5); + assertThat(on5, is(Option.none())); + final Option on6 = v1.accumulate(firstSemigroup(), v2, v3, v4, v5, v6); + assertThat(on6, is(Option.none())); + final Option on7 = v1.accumulate(firstSemigroup(), v2, v3, v4, v5, v6, v7); + assertThat(on7, is(Option.none())); + final Option on8 = v1.accumulate(firstSemigroup(), v2, v3, v4, v5, v6, v7, v8); + assertThat(on8, is(Option.none())); + } + + @Test + public void testAccumulate8sFail() { + final Option on = + parseInt("x").accumulate( + firstSemigroup(), + parseInt("2"), + parseInt("3"), + parseInt("4"), + parseInt("5"), + parseInt("6"), + parseInt("7"), + parseInt("y")); + assertThat(on.some().getMessage(), is("For input string: \"x\"")); + } + @Test(expected = Error.class) public void testSuccess() { parseShort("x").success(); @@ -241,4 +283,36 @@ public void testSuccess() { public void testFail() { parseShort("12").fail(); } + + @Test + public void testCondition() { + final Validation one = condition(true, "not 1", "one"); + assertThat(one.success(), is("one")); + final Validation fail = condition(false, "not 1", "one"); + assertThat(fail.fail(), is("not 1")); + } + + @Test + public void testNel() { + assertThat(Validation.success("success").nel().success(), is("success")); + assertThat(Validation.fail("fail").nel().fail().head(), is("fail")); + } + + @Test + public void testFailNEL() { + Validation, Integer> v = failNEL(new Exception("failed")); + assertThat(v.isFail(), is(true)); + } + + @Test + public void testEither() { + assertThat(either().f(Validation.success("success")).right().value(), is("success")); + assertThat(either().f(Validation.fail("fail")).left().value(), is("fail")); + } + + @Test + public void testValidation() { + assertThat(validation().f(Either.right("success")).success(), is("success")); + assertThat(validation().f(Either.left("fail")).fail(), is("fail")); + } } From 148eab718a81bfd90e5fd8176fb6c4435602da3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sun, 16 Dec 2018 14:12:00 -0500 Subject: [PATCH 708/811] Bring Gradle current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- build.gradle | 4 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 56177 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index c070903d..37a7b7c3 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { } wrapper { - gradleVersion = "4.10.2" + gradleVersion = "4.10.3" distributionType = Wrapper.DistributionType.ALL } } @@ -69,7 +69,7 @@ allprojects { sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" - dependencyJunit = "org.junit.vintage:junit-vintage-engine:5.2.0" + dependencyJunit = "org.junit.vintage:junit-vintage-engine:5.3.2" displayCompilerWarnings = true } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 29953ea141f55e3b8fc691d31b5ca8816d89fa87..94336fcae912db8a11d55634156fa011f4686124 100644 GIT binary patch delta 75 zcmeykjrrp?<_YF3{B|p=CR)d^elGf0#5nPQ^v3PRCxzG;0=(Hd{+{0VNQ{AjK?H~= bKR6{bS>lv7Sp8=AQ}+Z|K+=;nZ+id$gFGJ; delta 75 zcmeykjrrp?<_YF3`^8VXPqdC<{aEy|h;iZp>5bcsPYN+H1bDM^WdGhdRg8gwK?H~= bKR6{bS>lv7Sp8=AQ}+Z|K+=;nZ+id$ib5We diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d76b502e..ae45383b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From f85a3698a2b2838c0cc6462c85817a4c06c829d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Thu, 28 Feb 2019 20:29:08 -0500 Subject: [PATCH 709/811] Bring Gradle to 5.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- build.gradle | 5 +++-- consume/build.gradle | 3 ++- core/build.gradle | 3 ++- demo/build.gradle | 3 ++- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 55190 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- gradlew.bat | 2 +- java-core/build.gradle | 3 ++- performance/build.gradle | 3 ++- props-core-scalacheck/build.gradle | 3 ++- props-core/build.gradle | 5 +++-- quickcheck/build.gradle | 2 +- 13 files changed, 22 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 37a7b7c3..b206336a 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { } wrapper { - gradleVersion = "4.10.3" + gradleVersion = "5.2.1" distributionType = Wrapper.DistributionType.ALL } } @@ -69,7 +69,8 @@ allprojects { sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" - dependencyJunit = "org.junit.vintage:junit-vintage-engine:5.3.2" + junitCompile = "junit:junit:4.12" + junitRuntime = "org.junit.vintage:junit-vintage-engine:5.3.2" displayCompilerWarnings = true } diff --git a/consume/build.gradle b/consume/build.gradle index ff92a601..370ebfbf 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -4,5 +4,6 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { compile("$group:$projectName:$fjConsumeVersion") - testCompile dependencyJunit + testCompile junitCompile + testRuntime junitRuntime } diff --git a/core/build.gradle b/core/build.gradle index 13d06114..767904e0 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -6,7 +6,8 @@ ext { archivesBaseName = project.projectName dependencies { - testCompile dependencyJunit + testCompile junitCompile + testRuntime junitRuntime testCompile 'com.h2database:h2:1.4.197' testCompile 'commons-dbutils:commons-dbutils:1.7' } diff --git a/demo/build.gradle b/demo/build.gradle index e97f94b8..f19e765f 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -8,7 +8,8 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { compile project(":core") compile project(":quickcheck") - testCompile dependencyJunit + testCompile junitCompile + testRuntime junitRuntime } test { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 94336fcae912db8a11d55634156fa011f4686124..87b738cbd051603d91cc39de6cb000dd98fe6b02 100644 GIT binary patch delta 46897 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 delta 47854 zcmY(KQ*DWo<_WjQ}7Y{XRz3dwMVU4-Q zn%}IHTCm#|FbG8%FmSZ^JoI=RR8%w&kni6?KtO~*5c$i!g#T3<@q%*b#-shs8K>Ad zr`Y#Sw@%+c{`&~&xBr}5L;ue^5&RoI=KuWw38x$_I|K*_BMb-#ePSFbMxy*Te87D{ z9O*B{gu1cl_hD#GL1RfGHwO0Nq?DkNU&Lg);5Z^>(8W|w>&T-Ht)1=jBnuC$yK|!S;vP}>MV^c_r5GVcLs=nH^?rC-*=KA7NJXV?cuDb zS0XP*_AqA;t}qDGK_~w2gbd*IVL+s@XEB%-ar>e_Id-a96hu9C?RXo?piLW%$X3{o z6thF_ILtq7nlQ%HZieLF;a5y`uYWPL6cf4i#ThY!$5@7#D=@tn--Z8>zpi^Ws~JMrK>!OEzJ*l%TcY-YNr$DuvZ&5SeAQcQ`&2vpVPD^i~w>A3>y#3 zrPkuZ>hzg9iEw`#R+-_3Qs!3{ajlg#qK%nNbTX8(T*x!hvzA@>&khT<#UkpOqnSiz z;kisws8VZ&2jH@6o|>$cp12n3Ug>#?E03JkRqwNcke`G4t`38PU9zR|7?hS{!i;3} zY$eEqVL$O&H70pQ46^-)U;*x#H7N~=l&#8xMtrDfSdx&zk=RUwu;t7hXv^|m9!t5~+VRoN)j*{uEY6gE+W6zvCY z4#_@qY<5c#W_iWMD6M)YpLH%QD~Zvgm&QqmFBty5yi})XlHatyTj=KBRr@Snbo(%05sx7WMs$AydwDW?C

      ohmj(wKVBMg2V`Or6Dh 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae45383b..1b2b07cf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d5..af6708ff 100755 --- a/gradlew +++ b/gradlew @@ -28,7 +28,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" diff --git a/gradlew.bat b/gradlew.bat index e95643d6..0f8d5937 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/java-core/build.gradle b/java-core/build.gradle index 22bf8970..e7b40bb9 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -7,7 +7,8 @@ ext { dependencies { compile project(":core") - testCompile dependencyJunit + testCompile junitCompile + testRuntime junitRuntime } performSigning(signingEnabled, signModule) diff --git a/performance/build.gradle b/performance/build.gradle index cac2f584..c6f4c8a6 100644 --- a/performance/build.gradle +++ b/performance/build.gradle @@ -1,5 +1,6 @@ dependencies { compile project(":core") - testCompile dependencyJunit + testCompile junitCompile + testRuntime junitRuntime } diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index 10e494c9..5207bf50 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -15,7 +15,8 @@ dependencies { compile "org.scala-lang:scala-library:$scalaVersion" compile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - testCompile dependencyJunit + testCompile junitCompile + testRuntime junitRuntime } performSigning(signingEnabled, signModule) diff --git a/props-core/build.gradle b/props-core/build.gradle index 181ae5b2..b991bd47 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -2,6 +2,7 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { - compile project(":quickcheck") - testCompile dependencyJunit + compile project(":quickcheck") + testCompile junitCompile + testRuntime junitRuntime } diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index b477e26a..2e5dbe4c 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -7,7 +7,7 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { compile project(":core") - compile dependencyJunit + compile junitCompile } performSigning(signingEnabled, signModule) From c718d06f8320b56084b507b3d5b2d13a6f51ac3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Wed, 13 Mar 2019 18:00:24 -0400 Subject: [PATCH 710/811] Correct Either.iif Javadoc --- core/src/main/java/fj/data/Either.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index a9a746a9..dcc950f2 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -898,7 +898,7 @@ public static A reduce(final Either e) { } /** - * If the condition satisfies, return the given A in left, otherwise, return the given B in right. + * If the condition satisfies, return the given B in right, otherwise, return the given A in left. * * @param c The condition to test. * @param right The right value to use if the condition satisfies. From 68625ac4f1a40c65b2fb0ad4c24cacbe9288e6bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Fri, 15 Mar 2019 22:17:33 -0400 Subject: [PATCH 711/811] Add Integers tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .../test/java/fj/function/IntegersTest.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 core/src/test/java/fj/function/IntegersTest.java diff --git a/core/src/test/java/fj/function/IntegersTest.java b/core/src/test/java/fj/function/IntegersTest.java new file mode 100644 index 00000000..985afba9 --- /dev/null +++ b/core/src/test/java/fj/function/IntegersTest.java @@ -0,0 +1,62 @@ +package fj.function; + +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import static fj.data.List.list; +import static fj.data.Option.none; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class IntegersTest { + + @Test + public void testSum() { + assertThat(Integers.sum(list(3, 4, 5)), is(12)); + } + + @Test + public void testProduct() { + assertThat(Integers.product(list(3, 4, 5)), is(60)); + } + + @Test + public void testAdd() { + assertThat(Integers.add.f(10).f(20), is(30)); + } + + @Test + public void testMultiply() { + assertThat(Integers.multiply.f(3).f(5), is(15)); + } + + @Test + public void testAbs() { + assertThat(Integers.abs.f(-5), is(5)); + } + + @Test + public void testFromString() { + assertThat(Integers.fromString().f("-123").some(), is(-123)); + } + + @Test + public void testFromStringFail() { + assertThat(Integers.fromString().f("w"), is(none())); + } + + @Test + public void testCannotInstantiate() throws NoSuchMethodException, IllegalAccessException, InstantiationException { + Constructor constructor = Integers.class.getDeclaredConstructor(); + constructor.setAccessible(true); + try { + constructor.newInstance(); + fail("expected InvocationTargetException"); + } catch (InvocationTargetException ite) { + assertTrue(ite.getCause() instanceof UnsupportedOperationException); + } + } + +} From d2319f14e9b7b3293532454e110f6f0f675b26db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 6 Apr 2019 15:22:51 -0400 Subject: [PATCH 712/811] Add openjdk12 to Travis MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bbe5966b..8e7c52c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,13 @@ language: java jdk: - openjdk10 + - openjdk11 - openjdk-ea matrix: include: - - jdk: openjdk11 + - jdk: openjdk12 script: - ./gradlew build coverage -s -i after_success: From 40ef6c620aade5633e720f0401991bcfd9f18745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 6 Apr 2019 16:42:41 -0400 Subject: [PATCH 713/811] Add Longs tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- core/src/main/java/fj/function/Longs.java | 39 ++++++++++++ core/src/test/java/fj/function/LongsTest.java | 62 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 core/src/test/java/fj/function/LongsTest.java diff --git a/core/src/main/java/fj/function/Longs.java b/core/src/main/java/fj/function/Longs.java index 18667699..0989e8c0 100644 --- a/core/src/main/java/fj/function/Longs.java +++ b/core/src/main/java/fj/function/Longs.java @@ -1,11 +1,16 @@ package fj.function; import fj.F; +import fj.Monoid; +import fj.data.List; +import fj.data.Option; import static fj.Function.curry; import static fj.Semigroup.longAdditionSemigroup; import static fj.Semigroup.longMultiplicationSemigroup; +import static fj.data.Option.none; +import static fj.data.Option.some; import static java.lang.Math.abs; /** @@ -48,4 +53,38 @@ private Longs() { */ public static final F> remainder = curry((a, b) -> a % b); + /** + * Sums a list of longs. + * + * @param longs A list of longs to sum. + * @return The sum of the longs in the list. + */ + public static long sum(final List longs) { + return Monoid.longAdditionMonoid.sumLeft(longs); + } + + /** + * Returns the product of a list of integers. + * + * @param longs A list of longs to multiply together. + * @return The product of the longs in the list. + */ + public static long product(final List longs) { + return Monoid.longMultiplicationMonoid.sumLeft(longs); + } + + /** + * A function that converts strings to integers. + * + * @return A function that converts strings to integers. + */ + public static F> fromString() { + return s -> { + try { return some(Long.valueOf(s)); } + catch (final NumberFormatException ignored) { + return none(); + } + }; + } + } diff --git a/core/src/test/java/fj/function/LongsTest.java b/core/src/test/java/fj/function/LongsTest.java new file mode 100644 index 00000000..d59fc07c --- /dev/null +++ b/core/src/test/java/fj/function/LongsTest.java @@ -0,0 +1,62 @@ +package fj.function; + +import org.junit.Test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import static fj.data.List.list; +import static fj.data.Option.none; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class LongsTest { + + @Test + public void testSum() { + assertThat(Longs.sum(list(3L, 4L, 5L)), is(12L)); + } + + @Test + public void testProduct() { + assertThat(Longs.product(list(3L, 4L, 5L)), is(60L)); + } + + @Test + public void testAdd() { + assertThat(Longs.add.f(10L).f(20L), is(30L)); + } + + @Test + public void testMultiply() { + assertThat(Longs.multiply.f(3L).f(5L), is(15L)); + } + + @Test + public void testAbs() { + assertThat(Longs.abs.f(-5L), is(5L)); + } + + @Test + public void testFromString() { + assertThat(Longs.fromString().f("-123").some(), is(-123L)); + } + + @Test + public void testFromStringFail() { + assertThat(Longs.fromString().f("w"), is(none())); + } + + @Test + public void testCannotInstantiate() throws NoSuchMethodException, IllegalAccessException, InstantiationException { + Constructor constructor = Longs.class.getDeclaredConstructor(); + constructor.setAccessible(true); + try { + constructor.newInstance(); + fail("expected InvocationTargetException"); + } catch (InvocationTargetException ite) { + assertTrue(ite.getCause() instanceof UnsupportedOperationException); + } + } + +} From 0b8b7f083ce5cac932467e3a839357a568ef6dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Sat, 12 Oct 2019 13:25:44 -0400 Subject: [PATCH 714/811] Bring Gradle to 5.6.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- build.gradle | 6 +++--- core/build.gradle | 2 +- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 22 +++++++++++++++++++--- gradlew.bat | 18 +++++++++++++++++- 6 files changed, 41 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index b206336a..69c01425 100644 --- a/build.gradle +++ b/build.gradle @@ -20,7 +20,7 @@ buildscript { } wrapper { - gradleVersion = "5.2.1" + gradleVersion = "5.6.2" distributionType = Wrapper.DistributionType.ALL } } @@ -49,7 +49,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.8" + fjConsumeVersion = "4.8.1" signModule = false @@ -70,7 +70,7 @@ allprojects { primaryEmail = "functionaljava@googlegroups.com" junitCompile = "junit:junit:4.12" - junitRuntime = "org.junit.vintage:junit-vintage-engine:5.3.2" + junitRuntime = "org.junit.vintage:junit-vintage-engine:5.5.2" displayCompilerWarnings = true } diff --git a/core/build.gradle b/core/build.gradle index 767904e0..cbdad60b 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,7 +8,7 @@ archivesBaseName = project.projectName dependencies { testCompile junitCompile testRuntime junitRuntime - testCompile 'com.h2database:h2:1.4.197' + testCompile 'com.h2database:h2:1.4.199' testCompile 'commons-dbutils:commons-dbutils:1.7' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 3320 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 Date: Sun, 20 Oct 2019 17:28:54 +0300 Subject: [PATCH 715/811] define base bounded interface --- core/src/main/java/fj/Bounded.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 core/src/main/java/fj/Bounded.java diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java new file mode 100644 index 00000000..aea5da25 --- /dev/null +++ b/core/src/main/java/fj/Bounded.java @@ -0,0 +1,10 @@ +package fj; + +public class Bounded { + + public interface Definition { + A min(); + + A max(); + } +} From 78b3f7600f102b2cee62e0a3a300b38131fc3b5e Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 17:38:53 +0300 Subject: [PATCH 716/811] implement bounded with factory methods --- core/src/main/java/fj/Bounded.java | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java index aea5da25..9c64a0b7 100644 --- a/core/src/main/java/fj/Bounded.java +++ b/core/src/main/java/fj/Bounded.java @@ -2,9 +2,41 @@ public class Bounded { + private final Definition def; + public interface Definition { A min(); A max(); } + + private Bounded(Definition definition) { + this.def = definition; + } + + public A min() { + return def.min(); + } + + public A max() { + return def.max(); + } + + public static Bounded boundedDef(Definition def) { + return new Bounded<>(def); + } + + public static Bounded bounded(A min, A max) { + return boundedDef(new Definition() { + @Override + public A min() { + return min; + } + + @Override + public A max() { + return max; + } + }); + } } From 0083c800a32140c7fcdb6dadb793f0cdd07b8dba Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 17:46:40 +0300 Subject: [PATCH 717/811] add bounded for integers --- core/src/main/java/fj/Bounded.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java index 9c64a0b7..57827589 100644 --- a/core/src/main/java/fj/Bounded.java +++ b/core/src/main/java/fj/Bounded.java @@ -39,4 +39,7 @@ public A max() { } }); } + + public static final Bounded integerBounded = bounded(Integer.MIN_VALUE, Integer.MAX_VALUE); + } From 68828d3b8d72c8a481974902090f36b80e12bbd8 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 18:49:01 +0300 Subject: [PATCH 718/811] create tests for set monoid fabric methods --- core/src/test/java/fj/MonoidTest.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index 8bab5315..99ad5b5e 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -1,6 +1,8 @@ package fj; +import fj.data.Enumerator; import fj.data.Option; +import fj.data.Set; import fj.data.Stream; import org.junit.Test; @@ -16,4 +18,26 @@ public void lifted_sum_of_two_numbers() { assertThat(optionMonoid.sum(some(3), some(5)), is(some(8))); assertThat(optionMonoid.sumLeft(Stream.arrayStream(some(3), some(5))), is(some(8))); } + + @Test + public void intersection_monoid_test() { + Bounded integersBounded = Bounded.bounded(0, 10); + Monoid> intersectionMonoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator, Ord.intOrd); + Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); + Set zero = intersectionMonoid.zero(); + Set actual = intersectionMonoid.sum(intersectionMonoid.sum(zero, first), second); + assertThat(actual, is(Set.set(Ord.intOrd, 3, 4))); + } + + @Test + public void union_monoid_test() { + Monoid> intersectionMonoid = Monoid.setMonoid(Ord.intOrd); + Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); + Set zero = intersectionMonoid.zero(); + Set actual = intersectionMonoid.sum(intersectionMonoid.sum(zero, first), second); + assertThat(actual, is(Set.set(Ord.intOrd, 1, 2, 3, 4, 5, 6))); + } + } From 73c31ac71a0605cf36936396f5e3d3646df37abc Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 18:58:16 +0300 Subject: [PATCH 719/811] implement to stream with bounded function in enumerator --- core/src/main/java/fj/data/Enumerator.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index 94f1b2cd..85b8377f 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -1,16 +1,12 @@ package fj.data; -import fj.F; +import fj.*; import static fj.Function.*; import static fj.data.Option.none; import static fj.data.Option.some; -import fj.Function; -import fj.Ord; - import static fj.Ord.*; -import fj.Ordering; import static fj.Ordering.*; import java.math.BigDecimal; @@ -185,6 +181,18 @@ public Stream toStream(final A a) { return Stream.fromFunction(this, id, a); } + /** + * Returns a stream of the values from this enumerator, + * starting at the min of given Bounded, ending at the max, counting up. + * + * @param bounded A value at which to begin the stream. + * @return a stream of the values from this enumerator, cut by bounded, counting up. + */ + public Stream toStream(final Bounded bounded) { + final F id = identity(); + return Stream.fromFunction(this, id, bounded.min()).takeWhile(item -> !item.equals(bounded.max())); + } + /** * Create a new enumerator with the given minimum value. * From fce0df7b4f6fdc01489536c08da9906d406296ac Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 18:59:38 +0300 Subject: [PATCH 720/811] implement intersection monoid for sets --- core/src/main/java/fj/Monoid.java | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 0c09b558..e66a812f 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -2,14 +2,7 @@ import static fj.F1Functions.dimap; -import fj.data.Array; -import fj.data.DList; -import fj.data.List; -import fj.data.IO; -import fj.data.Natural; -import fj.data.Option; -import fj.data.Set; -import fj.data.Stream; +import fj.data.*; import static fj.Function.*; import static fj.Semigroup.semigroupDef; @@ -1109,6 +1102,20 @@ public Set append(Set a1, Set a2) { }); } + public static Monoid> setIntersectionMonoid(final Bounded bounded, final Enumerator enumerator, final Ord o) { + return monoidDef(new Definition>() { + @Override + public Set empty() { + return Set.iteratorSet(o, enumerator.toStream(bounded).iterator()); + } + + @Override + public Set append(Set a1, Set a2) { + return a1.intersect(a2); + } + }); + } + /** * A monoid for the maximum of elements with ordering o. * @deprecated since 4.7. Use {@link Ord#maxMonoid(Object)} From b550ca45e4bed28153bac587201ac570118df638 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 19:05:28 +0300 Subject: [PATCH 721/811] fix set monoid method docs --- core/src/main/java/fj/Monoid.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index e66a812f..02bba94a 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -1083,7 +1083,7 @@ public Unit append(Unit a1, Unit a2) { }); /** - * A monoid for sets. + * A union monoid for sets. * * @param o An order for set elements. * @return A monoid for sets whose elements have the given order. From 3c4e35fb9cb32ab3584cdf49fde27fe7d8987049 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 19:05:49 +0300 Subject: [PATCH 722/811] add docs for intersection set monoid --- core/src/main/java/fj/Monoid.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 02bba94a..2b3400c0 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -1102,6 +1102,14 @@ public Set append(Set a1, Set a2) { }); } + /** + * A intersection monoid for sets. + * + * @param bounded A bound for all possible elements + * @param enumerator An enumerator for all possible elements + * @param o An order for set elements. + * @return A monoid for sets whose elements have the given order. + */ public static Monoid> setIntersectionMonoid(final Bounded bounded, final Enumerator enumerator, final Ord o) { return monoidDef(new Definition>() { @Override From b602a2c2c598615b7ceb305d6ca79253449a36e5 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 19:50:53 +0300 Subject: [PATCH 723/811] add docs for bounded --- core/src/main/java/fj/Bounded.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java index 57827589..22d59ef5 100644 --- a/core/src/main/java/fj/Bounded.java +++ b/core/src/main/java/fj/Bounded.java @@ -1,9 +1,16 @@ package fj; +/** + * The Bounded class is used to name the upper and lower limits of a type. + * Ord is not a superclass of Bounded since types that are not totally ordered may also have upper and lower bounds. + */ public class Bounded { private final Definition def; + /** + * Minimal definition of Bounded + */ public interface Definition { A min(); From ea6fcc7127219874ba550005d3de20ea76d789b3 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 19:51:11 +0300 Subject: [PATCH 724/811] remove integer bounded implementation --- core/src/main/java/fj/Bounded.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java index 22d59ef5..980ba9a3 100644 --- a/core/src/main/java/fj/Bounded.java +++ b/core/src/main/java/fj/Bounded.java @@ -47,6 +47,4 @@ public A max() { }); } - public static final Bounded integerBounded = bounded(Integer.MIN_VALUE, Integer.MAX_VALUE); - } From 4b25bf8797258361c8ce0624a1f9f4a2721e3384 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 20:01:36 +0300 Subject: [PATCH 725/811] rename monoid variable in union monoid test --- core/src/test/java/fj/MonoidTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index 99ad5b5e..35e71c28 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -32,11 +32,11 @@ public void intersection_monoid_test() { @Test public void union_monoid_test() { - Monoid> intersectionMonoid = Monoid.setMonoid(Ord.intOrd); + Monoid> unionMonoid = Monoid.setMonoid(Ord.intOrd); Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); - Set zero = intersectionMonoid.zero(); - Set actual = intersectionMonoid.sum(intersectionMonoid.sum(zero, first), second); + Set zero = unionMonoid.zero(); + Set actual = unionMonoid.sum(unionMonoid.sum(zero, first), second); assertThat(actual, is(Set.set(Ord.intOrd, 1, 2, 3, 4, 5, 6))); } From 606f1e72803937b578e03aaca3f2c4dfd99c7c4c Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 20:01:59 +0300 Subject: [PATCH 726/811] add tests for set semigroup --- core/src/test/java/fj/SemigroupTest.java | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 core/src/test/java/fj/SemigroupTest.java diff --git a/core/src/test/java/fj/SemigroupTest.java b/core/src/test/java/fj/SemigroupTest.java new file mode 100644 index 00000000..20ecb2cb --- /dev/null +++ b/core/src/test/java/fj/SemigroupTest.java @@ -0,0 +1,26 @@ +package fj; + +import fj.data.Set; +import org.junit.Test; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.MatcherAssert.assertThat; + +public class SemigroupTest { + + @Test + public void intersection_semigroup_test() { + Semigroup> intersectionSemigroup = Semigroup.setIntersectionSemigroup(); + Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); + assertThat(intersectionSemigroup.sum(first, second), is(Set.set(Ord.intOrd, 3, 4))); + } + + @Test + public void union_semigroup_test() { + Semigroup> unionSemigroup = Semigroup.setSemigroup(); + Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); + assertThat(unionSemigroup.sum(first, second), is(Set.set(Ord.intOrd, 1, 2, 3, 4, 5, 6))); + } +} From b710672ec4586752c6d3265e3c8b80994d860ff1 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 20 Oct 2019 20:02:16 +0300 Subject: [PATCH 727/811] implement intersection semigroup --- core/src/main/java/fj/Semigroup.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 42f05f5b..c512e383 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -629,4 +629,8 @@ public static Semigroup> setSemigroup() { return semigroupDef(Set::union); } + public static Semigroup> setIntersectionSemigroup() { + return semigroupDef(Set::intersect); + } + } From a6a0d21d6accc1e3b7b19f142e1f492b40845f1c Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Mon, 21 Oct 2019 19:25:49 +0300 Subject: [PATCH 728/811] add tests for zero elements of monoids --- core/src/test/java/fj/MonoidTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index 35e71c28..721903b4 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -40,4 +40,21 @@ public void union_monoid_test() { assertThat(actual, is(Set.set(Ord.intOrd, 1, 2, 3, 4, 5, 6))); } + @Test + public void intersection_monoid_zero_test() { + Bounded integersBounded = Bounded.bounded(0, 10); + Monoid> monoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator, Ord.intOrd); + Set set = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set zero = monoid.zero(); + assertThat(monoid.sum(zero, set), is(set)); + } + + @Test + public void union_monoid_zero_test() { + Monoid> monoid = Monoid.setMonoid(Ord.intOrd); + Set set = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set zero = monoid.zero(); + assertThat(monoid.sum(zero, set), is(set)); + } + } From 226c84a74316d7d425610899eed2d0ef22d49599 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Mon, 21 Oct 2019 19:27:41 +0300 Subject: [PATCH 729/811] remove zero from monoids tests --- core/src/test/java/fj/MonoidTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index 721903b4..d61da72f 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -25,8 +25,7 @@ public void intersection_monoid_test() { Monoid> intersectionMonoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator, Ord.intOrd); Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); - Set zero = intersectionMonoid.zero(); - Set actual = intersectionMonoid.sum(intersectionMonoid.sum(zero, first), second); + Set actual = intersectionMonoid.sum(first, second); assertThat(actual, is(Set.set(Ord.intOrd, 3, 4))); } @@ -35,8 +34,7 @@ public void union_monoid_test() { Monoid> unionMonoid = Monoid.setMonoid(Ord.intOrd); Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); - Set zero = unionMonoid.zero(); - Set actual = unionMonoid.sum(unionMonoid.sum(zero, first), second); + Set actual = unionMonoid.sum(first, second); assertThat(actual, is(Set.set(Ord.intOrd, 1, 2, 3, 4, 5, 6))); } From 1a40c67f5502980a1c18fa4e54bc56a0ad9d8362 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Mon, 21 Oct 2019 19:29:31 +0300 Subject: [PATCH 730/811] add docs for semigroups --- core/src/main/java/fj/Semigroup.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index c512e383..ef8029b3 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -621,7 +621,7 @@ public static Semigroup> ioSemigroup(final Semigroup sa) { public static final Semigroup unitSemigroup = unitMonoid.semigroup(); /** - * A semigroup for sets. + * A union semigroup for sets. * * @return a semigroup for sets. */ @@ -629,6 +629,11 @@ public static Semigroup> setSemigroup() { return semigroupDef(Set::union); } + /** + * A intersection semigroup for sets. + * + * @return a semigroup for sets. + */ public static Semigroup> setIntersectionSemigroup() { return semigroupDef(Set::intersect); } From 854d1958fffa8dedc56db0a2a2650f591949d983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Mon, 28 Oct 2019 17:44:16 +0100 Subject: [PATCH 731/811] Basic JPMS (modules) support through 'Automatic-Module-Name' --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 67d8cd15..91bd5433 100644 --- a/build.gradle +++ b/build.gradle @@ -181,6 +181,7 @@ configure(subprojects.findAll { it.name != "props-core" }) { buildCommand 'org.eclipse.pde.ManifestBuilder' buildCommand 'org.eclipse.pde.SchemaBuilder' } + instruction 'Automatic-Module-Name', "functionaljava${project.name == 'core' ? '' : "-$project.name"}" } // Output MANIFEST.MF statically so eclipse can see it for plugin development From 1fed6abe362ee3a3931b11947570dd76baad9986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Tue, 29 Oct 2019 12:10:05 +0100 Subject: [PATCH 732/811] Fix previous commit --- build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index 91bd5433..2ac9a9c0 100644 --- a/build.gradle +++ b/build.gradle @@ -169,9 +169,10 @@ configure(subprojects.findAll { it.name != "props-core" }) { instruction 'Signature-Version', project.fjVersion instruction 'Bundle-ActivationPolicy', 'lazy' instruction 'Bundle-Vendor', 'functionaljava.org' - if(project.name != "core") { - instruction 'Require-Bundle', 'org.functionaljava;bundle-version="'+project.fjBaseVersion+'"' - } + if(project.name != "core") { + instruction 'Require-Bundle', 'org.functionaljava;bundle-version="'+project.fjBaseVersion+'"' + } + instruction 'Automatic-Module-Name', "functionaljava${project.name == 'core' ? '' : "-$project.name"}" } } @@ -181,7 +182,6 @@ configure(subprojects.findAll { it.name != "props-core" }) { buildCommand 'org.eclipse.pde.ManifestBuilder' buildCommand 'org.eclipse.pde.SchemaBuilder' } - instruction 'Automatic-Module-Name', "functionaljava${project.name == 'core' ? '' : "-$project.name"}" } // Output MANIFEST.MF statically so eclipse can see it for plugin development From 57699342be52381724ac34cf2b867cbd1d4ff407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Neuville?= Date: Tue, 29 Oct 2019 12:29:34 +0100 Subject: [PATCH 733/811] Dash character isn't allowed in modules names --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 2ac9a9c0..c9d8be40 100644 --- a/build.gradle +++ b/build.gradle @@ -172,7 +172,7 @@ configure(subprojects.findAll { it.name != "props-core" }) { if(project.name != "core") { instruction 'Require-Bundle', 'org.functionaljava;bundle-version="'+project.fjBaseVersion+'"' } - instruction 'Automatic-Module-Name', "functionaljava${project.name == 'core' ? '' : "-$project.name"}" + instruction 'Automatic-Module-Name', "functionaljava${project.name == 'core' ? '' : ".$project.name"}" } } From 6cadc81f9b651b90cfb3e2d79c99a3b70caddbe8 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 3 Nov 2019 15:58:10 +0300 Subject: [PATCH 734/811] remove ord parameter and provide it from enumerator --- core/src/main/java/fj/Monoid.java | 5 ++--- core/src/test/java/fj/MonoidTest.java | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 2b3400c0..490dc9d6 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -1107,14 +1107,13 @@ public Set append(Set a1, Set a2) { * * @param bounded A bound for all possible elements * @param enumerator An enumerator for all possible elements - * @param o An order for set elements. * @return A monoid for sets whose elements have the given order. */ - public static Monoid> setIntersectionMonoid(final Bounded bounded, final Enumerator enumerator, final Ord o) { + public static Monoid> setIntersectionMonoid(final Bounded bounded, final Enumerator enumerator) { return monoidDef(new Definition>() { @Override public Set empty() { - return Set.iteratorSet(o, enumerator.toStream(bounded).iterator()); + return Set.iteratorSet(enumerator.order(), enumerator.toStream(bounded).iterator()); } @Override diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index d61da72f..f185a124 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -22,7 +22,7 @@ public void lifted_sum_of_two_numbers() { @Test public void intersection_monoid_test() { Bounded integersBounded = Bounded.bounded(0, 10); - Monoid> intersectionMonoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator, Ord.intOrd); + Monoid> intersectionMonoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator); Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); Set second = Set.set(Ord.intOrd, 3, 4, 5, 6); Set actual = intersectionMonoid.sum(first, second); @@ -41,7 +41,7 @@ public void union_monoid_test() { @Test public void intersection_monoid_zero_test() { Bounded integersBounded = Bounded.bounded(0, 10); - Monoid> monoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator, Ord.intOrd); + Monoid> monoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator); Set set = Set.set(Ord.intOrd, 1, 2, 3, 4); Set zero = monoid.zero(); assertThat(monoid.sum(zero, set), is(set)); From fe19604e96855faaa6005aeda6b71c24bcb66a53 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 3 Nov 2019 16:03:31 +0300 Subject: [PATCH 735/811] fix missing max value of bounded --- core/src/main/java/fj/data/Enumerator.java | 2 +- core/src/test/java/fj/MonoidTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/Enumerator.java b/core/src/main/java/fj/data/Enumerator.java index 85b8377f..2fa96a6f 100644 --- a/core/src/main/java/fj/data/Enumerator.java +++ b/core/src/main/java/fj/data/Enumerator.java @@ -190,7 +190,7 @@ public Stream toStream(final A a) { */ public Stream toStream(final Bounded bounded) { final F id = identity(); - return Stream.fromFunction(this, id, bounded.min()).takeWhile(item -> !item.equals(bounded.max())); + return Stream.fromFunction(this, id, bounded.min()).takeWhile(item -> order.isLessThanOrEqualTo(item, bounded.max())); } /** diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index f185a124..a54bf672 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -29,7 +29,7 @@ public void intersection_monoid_test() { assertThat(actual, is(Set.set(Ord.intOrd, 3, 4))); } - @Test + @Test public void union_monoid_test() { Monoid> unionMonoid = Monoid.setMonoid(Ord.intOrd); Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); @@ -42,7 +42,7 @@ public void union_monoid_test() { public void intersection_monoid_zero_test() { Bounded integersBounded = Bounded.bounded(0, 10); Monoid> monoid = Monoid.setIntersectionMonoid(integersBounded, Enumerator.intEnumerator); - Set set = Set.set(Ord.intOrd, 1, 2, 3, 4); + Set set = Set.set(Ord.intOrd, 7, 8, 9, 10); Set zero = monoid.zero(); assertThat(monoid.sum(zero, set), is(set)); } From 5b6fafccb10c433f52dbcc0aff375e0aef89aaa3 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 3 Nov 2019 16:04:52 +0300 Subject: [PATCH 736/811] make bounded class final --- core/src/main/java/fj/Bounded.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Bounded.java b/core/src/main/java/fj/Bounded.java index 980ba9a3..e100b6d6 100644 --- a/core/src/main/java/fj/Bounded.java +++ b/core/src/main/java/fj/Bounded.java @@ -4,7 +4,7 @@ * The Bounded class is used to name the upper and lower limits of a type. * Ord is not a superclass of Bounded since types that are not totally ordered may also have upper and lower bounds. */ -public class Bounded { +public final class Bounded { private final Definition def; From dc9e0a9de8b897cd3ff53bf5c154494786b9dd98 Mon Sep 17 00:00:00 2001 From: Yaroslav Atroshenko Date: Sun, 3 Nov 2019 16:10:18 +0300 Subject: [PATCH 737/811] code clean up --- core/src/test/java/fj/MonoidTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index a54bf672..1156e729 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -29,7 +29,7 @@ public void intersection_monoid_test() { assertThat(actual, is(Set.set(Ord.intOrd, 3, 4))); } - @Test + @Test public void union_monoid_test() { Monoid> unionMonoid = Monoid.setMonoid(Ord.intOrd); Set first = Set.set(Ord.intOrd, 1, 2, 3, 4); From ac4819d9a71dd82f888db4663f47ab3e39c80cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Fri, 13 Dec 2019 09:11:52 -0500 Subject: [PATCH 738/811] Switch to gradle-versions-plugin --- build.gradle | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 69c01425..5fbad7bc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,9 @@ defaultTasks 'build' -ext { -} +apply plugin: "com.github.ben-manes.versions" buildscript { - ext { - uptodateVersion = "1.6.3" - } - repositories { mavenLocal() jcenter() @@ -16,7 +11,7 @@ buildscript { } dependencies { - classpath "com.ofg:uptodate-gradle-plugin:$uptodateVersion" + classpath "com.github.ben-manes:gradle-versions-plugin:0.27.0" } wrapper { @@ -98,7 +93,6 @@ subprojects { apply from: "$rootDir/lib.gradle" apply plugin: "java" apply plugin: "eclipse" - apply plugin: "com.ofg.uptodate" repositories { mavenLocal() From 560db2e6d9deaf2bb24bea21d65ab7c410977bce Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Tue, 19 May 2020 20:29:26 -0400 Subject: [PATCH 739/811] Add fj.test.Gen.streamOf(Gen), similar to fj.test.Gen.listOf(Gen, int); returns a generator of streams whose values come from the given generator. --- quickcheck/src/main/java/fj/test/Gen.java | 13 +++++++++++++ quickcheck/src/test/java/fj/test/GenTest.java | 16 ++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index c375874d..527d620c 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -9,6 +9,7 @@ import fj.data.Array; import fj.data.List; import fj.data.Option; +import fj.data.Stream; import fj.function.Effect1; import static fj.Bottom.error; @@ -497,6 +498,18 @@ public static Gen> listOf1(final Gen g) { return listOf(g, 1); } + /** + * Returns a generator of streams whose values come from the given generator. + * + * @param g the generator to produce values from for the returned generator + * @param the type of the generator + * + * @return A generator of streams whose values come from the given generator. + */ + public static Gen> streamOf(final Gen g) { + return gen(i -> r -> Stream.cons(g.gen(i, r), () -> streamOf(g).gen(i, r))); + } + /** * Returns a generator that picks one element from the given list. If the given list is empty, then the * returned generator will never produce a value. diff --git a/quickcheck/src/test/java/fj/test/GenTest.java b/quickcheck/src/test/java/fj/test/GenTest.java index 900369a7..9ec0ec79 100644 --- a/quickcheck/src/test/java/fj/test/GenTest.java +++ b/quickcheck/src/test/java/fj/test/GenTest.java @@ -1,16 +1,19 @@ package fj.test; import fj.data.List; +import fj.data.Stream; import fj.function.Effect1; import org.junit.Test; import static fj.Ord.charOrd; import static fj.data.List.list; import static fj.data.List.range; -import static fj.test.Gen.selectionOf; import static fj.test.Gen.combinationOf; -import static fj.test.Gen.wordOf; import static fj.test.Gen.permutationOf; +import static fj.test.Gen.pickOne; +import static fj.test.Gen.selectionOf; +import static fj.test.Gen.streamOf; +import static fj.test.Gen.wordOf; import static fj.test.Rand.standard; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -175,6 +178,15 @@ public void testWordOf_four() { }); } + @Test + public void testStreamOf() { + final Gen> instance = streamOf(pickOne(AS)); + testPick(100, instance.map(stream -> stream.take(4).toList()), actual -> { + assertEquals(4, actual.length()); + assertTrue(actual.forall(actualA -> AS.exists(a -> a.equals(actualA)))); + }); + } + private static void testPick(int n, Gen> instance, Effect1> test) { range(0, n).map(ignore -> instance.gen(0, standard)).foreachDoEffect(test); } From e98db344df3023beb0898688a682fe73e2c134ec Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Wed, 20 May 2020 19:16:19 -0400 Subject: [PATCH 740/811] Add fj.data.Option.sequence(Validation>). --- core/src/main/java/fj/data/Option.java | 16 +++++++++++--- core/src/test/java/fj/data/OptionTest.java | 25 +++++++++++++++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 54b4bb01..1a170c2c 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -372,11 +372,11 @@ public final Option> bindProduct(final Option ob) { public final Option> bindProduct(final Option ob, final Option oc) { return bind(ob, oc, P.p3()); } - + public final Option> bindProduct(final Option ob, final Option oc, final Option od) { return bind(ob, oc, od, P.p4()); } - + public final Option> bindProduct(final Option ob, final Option oc, final Option od, final Option oe) { return bind(ob, oc, od, oe, P.p5()); @@ -712,7 +712,7 @@ public static Option join(final Option> o) { } /** - * Sequence through the option monad. + * Sequence a list through the option monad. * * @param a The list of option to sequence. * @return The option of list after sequencing. @@ -723,6 +723,16 @@ public static Option> sequence(final List> a) { a.head().bind(aa -> sequence(a.tail()).map(cons_(aa))); } + /** + * Sequence a validation through the option monad. + * + * @param a The validation of option to sequence. + * @return The option of validation after sequencing. + */ + public static Option> sequence(final Validation> a) { + return a.traverseOption(identity()); + } + /** * Returns an optional value that has a value of the given argument, if the given predicate holds * on that argument, otherwise, returns no value. diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index 3eeed489..0966ece0 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -1,9 +1,15 @@ package fj.data; -import org.junit.Assert; import org.junit.Test; +import static fj.data.List.arrayList; +import static fj.data.List.nil; +import static fj.data.Option.none; +import static fj.data.Option.sequence; import static fj.data.Option.some; +import static fj.data.Validation.fail; +import static fj.data.Validation.success; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** @@ -26,4 +32,21 @@ public void traverseList() { assertTrue(actual.equals(expected)); } + @Test + public void sequenceListTest() { + assertEquals(some(nil()), sequence(nil())); + assertEquals(none(), sequence(arrayList(none()))); + assertEquals(some(arrayList(1)), sequence(arrayList(some(1)))); + assertEquals(none(), sequence(arrayList(none(), none()))); + assertEquals(none(), sequence(arrayList(some(1), none()))); + assertEquals(none(), sequence(arrayList(none(), some(2)))); + assertEquals(some(arrayList(1, 2)), sequence(arrayList(some(1), some(2)))); + } + + @Test + public void sequenceValidationTest() { + assertEquals(some(fail(1)), sequence(Validation.>fail(1))); + assertEquals(none(), sequence(Validation.>success(none()))); + assertEquals(some(success("string")), sequence(Validation.>success(some("string")))); + } } From 0a50e8b02c8dd00f7039d40f10eeefc10bfb3547 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Mon, 20 Jul 2020 21:55:04 -0400 Subject: [PATCH 741/811] Fixes #401. Add fj.test.Gen.sequence(Validation>). --- quickcheck/src/main/java/fj/test/Gen.java | 14 ++++++++++++++ quickcheck/src/test/java/fj/test/GenTest.java | 19 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index 527d620c..dabaf9a6 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -10,6 +10,7 @@ import fj.data.List; import fj.data.Option; import fj.data.Stream; +import fj.data.Validation; import fj.function.Effect1; import static fj.Bottom.error; @@ -319,6 +320,19 @@ public static Gen> sequenceN(final int n, final Gen g) { return sequence(replicate(n, g)); } + /** + * Transform a validation for a generator into a generator of validations: if the given validation is a failure, the + * generator produces that failure value; if the given validation is a success, the generator produces success values. + * + * @param gv The validation for a generator. + * @param the type of the value + * @param the type of the failure + * @return if the given validation is a failure, the generator produces that failure value; if the given validation is a success, the generator produces success values. + */ + public static Gen> sequence(final Validation> gv) { + return gen(i -> r -> gv.map(g -> g.gen(i, r))); + } + /** * Constructs a generator that can access its construction arguments — size and random * generator. diff --git a/quickcheck/src/test/java/fj/test/GenTest.java b/quickcheck/src/test/java/fj/test/GenTest.java index 9ec0ec79..c13480a1 100644 --- a/quickcheck/src/test/java/fj/test/GenTest.java +++ b/quickcheck/src/test/java/fj/test/GenTest.java @@ -1,17 +1,27 @@ package fj.test; +import fj.Equal; import fj.data.List; +import fj.data.NonEmptyList; +import fj.data.Option; import fj.data.Stream; +import fj.data.Validation; import fj.function.Effect1; import org.junit.Test; import static fj.Ord.charOrd; import static fj.data.List.list; import static fj.data.List.range; +import static fj.data.NonEmptyList.nel; +import static fj.data.Option.somes; +import static fj.data.Validation.fail; +import static fj.data.Validation.success; import static fj.test.Gen.combinationOf; +import static fj.test.Gen.listOf; import static fj.test.Gen.permutationOf; import static fj.test.Gen.pickOne; import static fj.test.Gen.selectionOf; +import static fj.test.Gen.sequence; import static fj.test.Gen.streamOf; import static fj.test.Gen.wordOf; import static fj.test.Rand.standard; @@ -187,6 +197,15 @@ public void testStreamOf() { }); } + @Test + public void testSequenceValidation() { + final Gen, Character>>> success = listOf(sequence(success(pickOne(AS))), 4); + testPick(100, success, list -> assertEquals(list.length(),somes(list.map(v -> Option.sequence(v.map(c -> AS.elementIndex(Equal.anyEqual(), c))))).length())); + + final Gen, Gen>>> failure = listOf(sequence(fail(nel(new Exception()))), 4); + testPick(100, failure, list -> assertTrue(list.forall(a -> a.isFail()))); + } + private static void testPick(int n, Gen> instance, Effect1> test) { range(0, n).map(ignore -> instance.gen(0, standard)).foreachDoEffect(test); } From b8c309374065364ae5922244795efbe8e40adffe Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Thu, 23 Jul 2020 13:42:30 -0400 Subject: [PATCH 742/811] Fixes #403. Add fj.data.Validation.sequence*, fj.data.Validation.traverse*. --- core/src/main/java/fj/data/Validation.java | 358 ++++++++++++++++-- .../src/test/java/fj/data/ValidationTest.java | 209 ++++++++++ 2 files changed, 530 insertions(+), 37 deletions(-) create mode 100644 core/src/test/java/fj/data/ValidationTest.java diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 58aa5e9c..2afb91f3 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -1,17 +1,18 @@ package fj.data; import fj.*; +import fj.control.Trampoline; import fj.function.Effect1; -import static fj.Function.curry; -import static fj.P.p; +import java.util.Iterator; -import static fj.Unit.unit; import static fj.Bottom.error; +import static fj.Function.*; +import static fj.P.p; +import static fj.Unit.unit; +import static fj.data.Either.*; import static fj.data.List.list; -import java.util.Iterator; - /** * Isomorphic to {@link Either} but has renamed functions and represents failure on the left and success on the right. * This type also has accumulating functions that accept a {@link Semigroup} for binding computation while keeping error @@ -825,44 +826,327 @@ public static Validation, List> sequenceNonCumulative(List List> traverseList(F> f){ - return isSuccess() ? - f.f(success()).map(Validation::success) : - List.iterableList(fail(e.left().value())); - } + /** + * Sequence the given validation and collect the output on the left side of an either. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either, R> sequenceEitherLeft(final Validation> validation) { + return validation.traverseEitherLeft(identity()); + } - public final Stream> traverseStream(F> f){ - return isSuccess() ? - f.f(success()).map(Validation::success) : - Stream.iterableStream(fail(e.left().value())); - } + /** + * Sequence the given validation and collect the output on the right side of an either. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either> sequenceEitherRight(final Validation> validation) { + return validation.traverseEitherRight(identity()); + } - public final Option> traverseOption(F> f){ - return isSuccess() ? - f.f(success()).map(Validation::success) : - Option.some(fail(e.left().value())); - } + /** + * Sequence the given validation and collect the output as a function. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of input value + * @param the type of output value + * @return the function + */ + public static final F> sequenceF(final Validation> validation) { + return validation.traverseF(identity()); + } - public final IO> traverseIO(F> f){ - return isSuccess() ? - IOFunctions.map(f.f(success()), Validation::success) : - IOFunctions.unit(fail(e.left().value())); - } + /** + * Sequence the given validation and collect the output as an IO. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the IO value + * @return the IO + */ + public static final IO> sequenceIO(final Validation> validation) { + return validation.traverseIO(identity()); + } - public final P1> traverseP1(F> f){ - return isSuccess() ? - f.f(success()).map(Validation::success) : - p(fail(e.left().value())); - } + /** + * Sequence the given validation and collect the output as a list. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the list value + * @return the list + */ + public static final List> sequenceList(final Validation> validation) { + return validation.traverseList(identity()); + } + + /** + * Sequence the given validation and collect the output as an option. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the option value + * @return the option + */ + public static final Option> sequenceOption(final Validation> validation) { + return validation.traverseOption(identity()); + } + /** + * Sequence the given validation and collect the output as a P1. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the P1 value + * @return the P1 + */ + public static final P1> sequenceP1(final Validation> validation) { + return validation.traverseP1(identity()); + } - public static List fails(List> list) { - return list.filter(Validation::isFail).map(v -> v.fail()); - } + /** + * Sequence the given validation and collect the output as a seq. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the seq value + * @return the seq + */ + public static final Seq> sequenceSeq(final Validation> validation) { + return validation.traverseSeq(identity()); + } - public static List successes(List> list) { - return list.filter(Validation::isSuccess).map(v -> v.success()); - } + /** + * Sequence the given validation and collect the output as a set. + * + * @param ordE the given failure value ord + * @param ordC the given success value ord + * @param validation the given validation + * @param the type of the failure value + * @param the type of the set value + * @return the set + */ + public static final Set> sequenceSet(final Ord ordE, final Ord ordC, final Validation> validation) { + return validation.traverseSet(ordE, ordC, identity()); + } + + /** + * Sequence the given validation and collect the output as a stream. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the stream value + * @return the stream + */ + public static final Stream> sequenceStream(final Validation> validation) { + return validation.traverseStream(identity()); + } + + /** + * Sequence the given validation and collect the output as a trampoline. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the trampoline value + * @return the trampoline + */ + public static final Trampoline> sequenceTrampoline(final Validation> validation) { + return validation.traverseTrampoline(identity()); + } + + /** + * Sequence the given validation and collect the output as a validation. + * + * @param validation the given validation + * @param the type of the failure value + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static final Validation> sequenceValidation(final Validation> validation) { + return validation.traverseValidation(identity()); + } + + /** + * Traverse this validation with the given function and collect the output on the left side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the list + */ + public final Either, R> traverseEitherLeft(final F> f) { + return validation( + failure -> left(fail(failure)), + success -> f.f(success).left().map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the list + */ + public final Either> traverseEitherRight(final F> f) { + return validation( + failure -> right(fail(failure)), + success -> f.f(success).right().map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a function. + * + * @param f the given function + * @param the type of the input value + * @param the type of the output value + * @return the function + */ + public final F> traverseF(final F> f) { + return validation( + failure -> constant(fail(failure)), + success -> andThen(f.f(success), Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as an IO. + * + * @param f the given function + * @param the type of the IO value + * @return the IO + */ + public final IO> traverseIO(final F> f) { + return validation( + failure -> IOFunctions.unit(fail(failure)), + success -> IOFunctions.map(f.f(success), Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a list. + * + * @param f the given function + * @param the type of the list value + * @return the list + */ + public final List> traverseList(final F> f) { + return validation( + failure -> List.single(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as an option. + * + * @param f the given function + * @param the type of the option value + * @return the option + */ + public final Option> traverseOption(F> f) { + return validation( + failure -> Option.some(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a P1. + * + * @param f the given function + * @param the type of the P1 value + * @return the P1 + */ + public final P1> traverseP1(final F> f) { + return validation( + failure -> p(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a seq. + * + * @param f the given function + * @param the type of the seq value + * @return the seq + */ + public final Seq> traverseSeq(final F> f) { + return validation( + failure -> Seq.single(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a set; use the given success and failure value ords to order the set. + * + * @param ordE the given failure value ord + * @param ordC the given success value ord + * @param f the given function + * @param the type of the set value + * @return the set + */ + public final Set> traverseSet(final Ord ordE, final Ord ordC, final F> f) { + final Ord> ord = Ord.validationOrd(ordE, ordC); + return validation( + failure -> Set.single(ord, fail(failure)), + success -> f.f(success).map(ord, Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a stream. + * + * @param f the given function + * @param the type of the stream value + * @return the stream + */ + public final Stream> traverseStream(final F> f) { + return validation( + failure -> Stream.single(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a trampoline. + * + * @param f the given function + * @param the type of the trampoline value + * @return the trampoline + */ + public final Trampoline> traverseTrampoline(final F> f) { + return validation( + failure -> Trampoline.pure(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + /** + * Traverse this validation with the given function and collect the output as a validation. + * + * @param f the given function + * @param the type of the failure value + * @param the type of the seq value + * @return the validation + */ + public final Validation> traverseValidation(final F> f) { + return validation( + failure -> success(fail(failure)), + success -> f.f(success).map(Validation::success)); + } + + + public static List fails(List> list) { + return list.filter(Validation::isFail).map(v -> v.fail()); + } + + public static List successes(List> list) { + return list.filter(Validation::isSuccess).map(v -> v.success()); + } /** * A failing projection of a validation. @@ -1268,7 +1552,7 @@ public static Validation parseShort(final String s } /** - * A function that parses a string into a short. + * A function that parses a string into a short. */ public static final F> parseShort = Validation::parseShort; diff --git a/core/src/test/java/fj/data/ValidationTest.java b/core/src/test/java/fj/data/ValidationTest.java new file mode 100644 index 00000000..0f1f3216 --- /dev/null +++ b/core/src/test/java/fj/data/ValidationTest.java @@ -0,0 +1,209 @@ +package fj.data; + +import fj.control.Trampoline; +import org.junit.Test; + +import java.io.IOException; + +import static fj.Function.constant; +import static fj.Ord.*; +import static fj.P.p; +import static fj.data.Either.*; +import static fj.data.Option.*; +import static fj.data.Validation.sequenceEitherLeft; +import static fj.data.Validation.sequenceEitherRight; +import static fj.data.Validation.sequenceF; +import static fj.data.Validation.sequenceIO; +import static fj.data.Validation.sequenceList; +import static fj.data.Validation.sequenceOption; +import static fj.data.Validation.sequenceP1; +import static fj.data.Validation.sequenceSeq; +import static fj.data.Validation.sequenceSet; +import static fj.data.Validation.sequenceStream; +import static fj.data.Validation.sequenceTrampoline; +import static fj.data.Validation.sequenceValidation; +import static fj.data.Validation.*; +import static org.junit.Assert.assertEquals; + +public class ValidationTest { + + @Test + public void testSequenceEitherLeft() { + assertEquals(left(fail("zero")), sequenceEitherLeft(fail("zero"))); + assertEquals(left(success("zero")), sequenceEitherLeft(success(left("zero")))); + assertEquals(right("zero"), sequenceEitherLeft(success(right("zero")))); + } + + @Test + public void testSequenceEitherRight() { + assertEquals(right(fail("zero")), sequenceEitherRight(fail("zero"))); + assertEquals(right(success("zero")), sequenceEitherRight(success(right("zero")))); + assertEquals(left("zero"), sequenceEitherRight(success(left("zero")))); + } + + @Test + public void testSequenceF() { + assertEquals(constant(fail("zero")).f(1), sequenceF(fail("zero")).f(1)); + assertEquals(constant(success("zero")).f(1), sequenceF(success(constant("zero"))).f(1)); + } + + @Test + public void testSequenceIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(fail("zero"))).run(), sequenceIO(fail("zero")).run()); + assertEquals(IOFunctions.lazy(constant(success("zero"))).run(), sequenceIO(success(IOFunctions.lazy(constant("zero")))).run()); + } + + @Test + public void testSequenceList() { + assertEquals(List.single(fail("zero")), sequenceList(fail("zero"))); + assertEquals(List.nil(), sequenceList(success(List.nil()))); + assertEquals(List.single(success("zero")), sequenceList(success(List.single("zero")))); + assertEquals(List.arrayList(success("zero"), success("one")), sequenceList(success(List.arrayList("zero", "one")))); + } + + @Test + public void testSequenceOption() { + assertEquals(some(fail("zero")), sequenceOption(fail("zero"))); + assertEquals(none(), sequenceOption(success(none()))); + assertEquals(some(success("zero")), sequenceOption(success(some("zero")))); + } + + @Test + public void testSequenceP1() { + assertEquals(p(fail("zero")), sequenceP1(fail("zero"))); + assertEquals(p(success("zero")), sequenceP1(success(p("zero")))); + } + + @Test + public void testSequenceSeq() { + assertEquals(Seq.single(fail("zero")), sequenceSeq(fail("zero"))); + assertEquals(Seq.empty(), sequenceSeq(success(Seq.empty()))); + assertEquals(Seq.single(success("zero")), sequenceSeq(success(Seq.single("zero")))); + assertEquals(Seq.arraySeq(success("zero"), success("one")), sequenceSeq(success(Seq.arraySeq("zero", "one")))); + } + + @Test + public void testSequenceSet() { + assertEquals(Set.single(validationOrd(stringOrd, intOrd), fail("zero")), sequenceSet(stringOrd, intOrd, fail("zero"))); + assertEquals(Set.empty(validationOrd(stringOrd, intOrd)), sequenceSet(stringOrd, intOrd, success(Set.empty(intOrd)))); + assertEquals(Set.single(validationOrd(intOrd, stringOrd), success("zero")), sequenceSet(intOrd, stringOrd, success(Set.single(stringOrd, "zero")))); + assertEquals(Set.arraySet(validationOrd(intOrd, stringOrd), success("zero"), success("one")), sequenceSet(intOrd, stringOrd, Validation.success(Set.arraySet(stringOrd, "zero", "one")))); + } + + @Test + public void testSequenceStream() { + assertEquals(Stream.single(fail("zero")), sequenceStream(fail("zero"))); + assertEquals(Stream.nil(), sequenceStream(success(Stream.nil()))); + assertEquals(Stream.single(success("zero")), sequenceStream(success(Stream.single("zero")))); + assertEquals(Stream.arrayStream(success("zero"), success("one")), sequenceStream(success(Stream.arrayStream("zero", "one")))); + } + + @Test + public void testSequenceTrampoline() { + assertEquals(Trampoline.pure(fail("zero")).run(), sequenceTrampoline(fail("zero")).run()); + assertEquals(Trampoline.pure(success(0)).run(), sequenceTrampoline(success(Trampoline.pure(0))).run()); + } + + @Test + public void testSequenceValidation() { + assertEquals(success(fail("zero")), sequenceValidation(fail("zero"))); + assertEquals(fail("zero"), sequenceValidation(success(fail("zero")))); + assertEquals(success(success(0)), sequenceValidation(success(success(0)))); + } + + @Test + public void testTraverseEitherLeft() { + assertEquals(left(fail("zero")), fail("zero").traverseEitherLeft(constant(left(0)))); + assertEquals(left(success(0)), success("zero").traverseEitherLeft(constant(left(0)))); + assertEquals(left(fail("zero")), fail("zero").traverseEitherLeft(constant(right(0)))); + assertEquals(right(0), success("zero").traverseEitherLeft(constant(right(0)))); + } + + @Test + public void testTraverseEitherRight() { + assertEquals(right(fail("zero")), fail("zero").traverseEitherRight(constant(right(0)))); + assertEquals(right(success(0)), success("zero").traverseEitherRight(constant(right(0)))); + assertEquals(right(fail("zero")), fail("zero").traverseEitherRight(constant(left(0)))); + assertEquals(left(0), success("zero").traverseEitherRight(constant(left(0)))); + } + + @Test + public void testTraverseF() { + assertEquals(constant(fail("zero")).f(1), fail("zero").traverseF(constant(constant(0))).f(1)); + assertEquals(constant(success(0)).f(1), success("zero").traverseF(constant(constant(0))).f(1)); + } + + @Test + public void testTraverseIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(fail("zero"))).run(), fail("zero").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(IOFunctions.lazy(constant(success(0))).run(), success("zero").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseList() { + assertEquals(List.single(fail("zero")), fail("zero").traverseList(constant(List.nil()))); + assertEquals(List.nil(), success("zero").traverseList(constant(List.nil()))); + assertEquals(List.single(fail("zero")), fail("zero").traverseList(constant(List.single(0)))); + assertEquals(List.single(success(0)), success("zero").traverseList(constant(List.single(0)))); + assertEquals(List.single(fail("zero")), fail("zero").traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.arrayList(success(0), success(1)), success("zero").traverseList(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseOption() { + assertEquals(some(fail("zero")), fail("zero").traverseOption(constant(none()))); + assertEquals(none(), success("zero").traverseOption(constant(none()))); + assertEquals(some(fail("zero")), fail("zero").traverseOption(constant(some(0)))); + assertEquals(some(success(0)), success("zero").traverseOption(constant(some(0)))); + } + + @Test + public void testTraverseP1() { + assertEquals(p(fail("zero")), fail("zero").traverseP1(constant(p(0)))); + assertEquals(p(success(0)), success("zero").traverseP1(constant(p(0)))); + } + + @Test + public void testTraverseSeq() { + assertEquals(Seq.single(fail("zero")), fail("zero").traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.empty(), success("zero").traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.single(fail("zero")), fail("zero").traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(success(0)), success("zero").traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(fail("zero")), fail("zero").traverseSeq(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.arraySeq(success(0), success(1)), success("zero").traverseSeq(constant(Seq.arraySeq(0, 1)))); + } + + @Test + public void testTraverseSet() { + assertEquals(Set.single(validationOrd(stringOrd, intOrd), fail("zero")), fail("zero").traverseSet(stringOrd, intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.empty(validationOrd(stringOrd, intOrd)), Validation.success("zero").traverseSet(stringOrd, intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.single(validationOrd(stringOrd, intOrd), fail("zero")), fail("zero").traverseSet(stringOrd, intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(validationOrd(stringOrd, intOrd), success(0)), Validation.success("zero").traverseSet(stringOrd, intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(validationOrd(stringOrd, intOrd), fail("zero")), fail("zero").traverseSet(stringOrd, intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + assertEquals(Set.arraySet(validationOrd(stringOrd, intOrd), success(0), success(1)), Validation.success("zero").traverseSet(stringOrd, intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.single(fail("zero")), fail("zero").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.nil(), success("zero").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(fail("zero")), fail("zero").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(success(0)), success("zero").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(fail("zero")), fail("zero").traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.arrayStream(success(0), success(1)), success("zero").traverseStream(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testTraverseTrampoline() { + assertEquals(Trampoline.pure(fail("zero")).run(), fail("zero").traverseTrampoline(constant(Trampoline.pure(0))).run()); + assertEquals(Trampoline.pure(success(0)).run(), success("zero").traverseTrampoline(constant(Trampoline.pure(0))).run()); + } + + @Test + public void testTraverseValidation() { + assertEquals(Validation.>success(fail("zero")), Validation.fail("zero").traverseValidation(constant(Validation.fail(0)))); + assertEquals(Validation.>fail(0), Validation.success("zero").traverseValidation(constant(Validation.fail(0)))); + assertEquals(Validation.>success(fail("zero")), Validation.fail("zero").traverseValidation(constant(Validation.success(0)))); + assertEquals(Validation.>success(success(0)), Validation.success("zero").traverseValidation(constant(Validation.success(0)))); + } +} From cb99e095a2fbc2bcf9f527dbe1d272515c715b0c Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Thu, 23 Jul 2020 12:04:17 -0400 Subject: [PATCH 743/811] Fixes #403. Add fj.data.Option.sequence*, fj.data.Option.traverse*. --- core/src/main/java/fj/data/Option.java | 351 +++++++++++++++++---- core/src/test/java/fj/data/OptionTest.java | 242 ++++++++++++-- 2 files changed, 515 insertions(+), 78 deletions(-) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 1a170c2c..6b62d2cf 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -1,43 +1,24 @@ package fj.data; -import static fj.Bottom.error; -import fj.F; -import fj.F0; -import fj.F2; -import fj.P; -import fj.P1; -import fj.P2; -import fj.P3; -import fj.P4; -import fj.P5; -import fj.P6; -import fj.P7; -import fj.P8; -import fj.Unit; -import fj.Show; +import fj.*; +import fj.control.Trampoline; +import fj.data.optic.*; import fj.function.Effect1; -import fj.Equal; -import fj.Ord; -import fj.Hash; -import fj.data.optic.Prism; -import fj.data.optic.PPrism; + +import java.lang.Class; +import java.util.*; + +import static fj.Bottom.error; import static fj.Function.*; import static fj.P.p; +import static fj.Show.optionShow; import static fj.Unit.unit; -import static fj.data.List.cons; -import static fj.data.List.cons_; -import static fj.data.Validation.parseByte; -import static fj.data.Validation.parseDouble; -import static fj.data.Validation.parseFloat; -import static fj.data.Validation.parseInt; -import static fj.data.Validation.parseLong; -import static fj.data.Validation.parseShort; -import static fj.data.optic.Prism.prism; +import static fj.control.Trampoline.pure; +import static fj.data.Either.*; +import static fj.data.List.*; +import static fj.data.Validation.*; import static fj.data.optic.PPrism.pPrism; -import static fj.Show.optionShow; - -import java.util.Collection; -import java.util.Iterator; +import static fj.data.optic.Prism.prism; /** * An optional value that may be none (no value) or some (a value). This type is a replacement for @@ -411,45 +392,307 @@ public final Option sequence(final Option o) { return bind(c); } - public final Either> traverseEither(F> f) { - return map(a -> f.f(a).right().map(Option::some)).orSome(Either.right(none())); + /** + * Sequence the given option and collect the output on the right side of an either. + * + * @param option the given option + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either, R> sequenceEitherLeft(final Option> option) { + return option.traverseEitherLeft(identity()); + } + + /** + * Sequence the given option and collect the output on the left side of an either. + * + * @param option the given option + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either> sequenceEitherRight(final Option> option) { + return option.traverseEitherRight(identity()); + } + + /** + * Sequence the given option and collect the output as a function. + * + * @param option the given option + * @param the type of the input value + * @param the type of the output value + * @return the either + */ + public static final F> sequenceF(final Option> option) { + return option.traverseF(identity()); + } + + /** + * Sequence the given option and collect the output as an IO. + * + * @param option the given option + * @param the type of the IO value + * @return the IO + */ + public static final IO> sequenceIO(final Option> option) { + return option.traverseIO(identity()); + } + + /** + * Sequence the given option and collect the output as an list. + * + * @param option the given option + * @param the type of the list value + * @return the list + */ + public static final List> sequenceList(final Option> option) { + return option.traverseList(identity()); } - public final IO> traverseIO(F> f) { - return map(a -> IOFunctions.map(f.f(a), Option::some)).orSome(IOFunctions.lazy(Option::none)); + /** + * Sequence the given option and collect the output as an option. + * + * @param option the given option + * @param the type of the option value + * @return the option + */ + public static final Option> sequenceOption(final Option> option) { + return option.traverseOption(identity()); } - public final List> traverseList(F> f) { - return map(a -> f.f(a).map(Option::some)).orSome(List.list()); + /** + * Sequence the given option and collect the output as a P1. + * + * @param option the given option + * @param the type of the P1 value + * @return the P1 + */ + public static final P1> sequenceP1(final Option> option) { + return option.traverseP1(identity()); } - public final Option> traverseOption(F> f) { - return map(f); + /** + * Sequence the given option and collect the output as a seq. + * + * @param option the given option + * @param the type of the seq value + * @return the seq + */ + public static final Seq> sequenceSeq(final Option> option) { + return option.traverseSeq(identity()); } - public final Stream> traverseStream(F> f) { - return map(a -> f.f(a).map(Option::some)).orSome(Stream.nil()); + /** + * Sequence the given option and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param option the given option + * @param the type of the set value + * @return the either + */ + public static final Set> sequenceSet(final Ord ord, final Option> option) { + return option.traverseSet(ord, identity()); } - public final P1> traverseP1(F> f) { - return map(a -> f.f(a).map(Option::some)).orSome(p(none())); + /** + * Sequence the given option and collect the output as a stream. + * + * @param option the given option + * @param the type of the stream value + * @return the stream + */ + public static final Stream> sequenceStream(final Option> option) { + return option.traverseStream(identity()); } - public final Seq> traverseSeq(F> f) { - return map(a -> f.f(a).map(Option::some)).orSome(Seq.empty()); + /** + * Sequence the given option and collect the output as a trampoline. + * + * @param option the given trampoline + * @param the type of the stream value + * @return the stream + */ + public static final Trampoline> sequenceTrampoline(final Option> option) { + return option.traverseTrampoline(identity()); } - public final Set> traverseSet(Ord ord, F> f) { - Ord> optOrd = Ord.optionOrd(ord); - return map(a -> f.f(a).map(optOrd, Option::some)).orSome(Set.empty(optOrd)); + /** + * Sequence the given option and collect the output as a validation. + * + * @param option the given option + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static final Validation> sequenceValidation(final Option> option) { + return option.traverseValidation(identity()); } - public final F2, F>, Set>> traverseSet() { - return this::traverseSet; + /** + * Traverse this option with the given function and collect the output on the left side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public final Either, R> traverseEitherLeft(final F> f) { + return option( + left(none()), + a -> f.f(a).left().map(Option::some)); } - public final Validation> traverseValidation(F> f) { - return map(a -> f.f(a).map(Option::some)).orSome(Validation.success(none())); + /** + * Traverse this option with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public final Either> traverseEitherRight(final F> f) { + return option( + right(none()), + a -> f.f(a).right().map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a function. + * + * @param f the given function + * @param the type of the input value + * @param the type of the output value + * @return the function + */ + public final F> traverseF(final F> f) { + return option( + constant(none()), + a -> andThen(f.f(a), Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as an IO. + * + * @param f the given function + * @param the type of the IO value + * @return the IO + */ + public final IO> traverseIO(final F> f) { + return option( + IOFunctions.lazy(Option::none), + a -> IOFunctions.map(f.f(a), Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a list. + * + * @param f the given function + * @param the type of the list value + * @return the list + */ + public final List> traverseList(final F> f) { + return option( + List.single(none()), + a -> f.f(a).map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as an option. + * + * @param f the given function + * @param the type of the option value + * @return the option + */ + public final Option> traverseOption(final F> f) { + return option( + some(none()), + a -> f.f(a).map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a P1. + * + * @param f the given function + * @param the type of the P1 value + * @return the P1 + */ + public final P1> traverseP1(final F> f) { + return option( + p(none()), + (F>>) a -> f.f(a).map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output a seq. + * + * @param f the given function + * @param the type of the seq value + * @return the seq + */ + public final Seq> traverseSeq(final F> f) { + return option( + Seq.single(none()), + a -> f.f(a).map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param f the given function + * @param the type of the set value + * @return the set + */ + public final Set> traverseSet(final Ord ord, final F> f) { + final Ord> ordOption = Ord.optionOrd(ord); + return option( + Set.single(ordOption, none()), + a -> f.f(a).map(ordOption, Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a stream. + * + * @param f the given function + * @param the type of the stream value + * @return the stream + */ + public final Stream> traverseStream(final F> f) { + return option( + Stream.single(none()), + a -> f.f(a).map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a trampoline. + * + * @param f the given function + * @param the type of the trampoline value + * @return the trampoline + */ + public final Trampoline> traverseTrampoline(final F> f) { + return option( + pure(none()), + a -> f.f(a).map(Option::some)); + } + + /** + * Traverse this option with the given function and collect the output as a validation. + * + * @param f the given function + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public final Validation> traverseValidation(final F> f) { + return option( + success(none()), + a -> f.f(a).map(Option::some)); + } + + public final F2, F>, Set>> traverseSet() { + return this::traverseSet; } /** diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index 0966ece0..403cbbd1 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -1,21 +1,35 @@ package fj.data; +import fj.control.Trampoline; import org.junit.Test; -import static fj.data.List.arrayList; -import static fj.data.List.nil; -import static fj.data.Option.none; +import java.io.IOException; + +import static fj.Function.constant; +import static fj.Ord.*; +import static fj.P.p; +import static fj.data.Either.*; +import static fj.data.List.*; import static fj.data.Option.sequence; -import static fj.data.Option.some; +import static fj.data.Option.sequenceF; +import static fj.data.Option.sequenceIO; +import static fj.data.Option.sequenceList; +import static fj.data.Option.sequenceOption; +import static fj.data.Option.sequenceP1; +import static fj.data.Option.sequenceSeq; +import static fj.data.Option.sequenceSet; +import static fj.data.Option.sequenceStream; +import static fj.data.Option.sequenceTrampoline; +import static fj.data.Option.sequenceValidation; +import static fj.data.Option.*; import static fj.data.Validation.fail; -import static fj.data.Validation.success; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static fj.data.Validation.*; +import static org.junit.Assert.*; /** * Created by MarkPerry on 15/01/2015. */ -public class OptionTest { +public final class OptionTest { @Test public void equals() { @@ -32,21 +46,201 @@ public void traverseList() { assertTrue(actual.equals(expected)); } - @Test - public void sequenceListTest() { - assertEquals(some(nil()), sequence(nil())); - assertEquals(none(), sequence(arrayList(none()))); - assertEquals(some(arrayList(1)), sequence(arrayList(some(1)))); - assertEquals(none(), sequence(arrayList(none(), none()))); - assertEquals(none(), sequence(arrayList(some(1), none()))); - assertEquals(none(), sequence(arrayList(none(), some(2)))); - assertEquals(some(arrayList(1, 2)), sequence(arrayList(some(1), some(2)))); - } + @Test + public void sequenceListTest() { + assertEquals(some(nil()), sequence(nil())); + assertEquals(none(), sequence(arrayList(none()))); + assertEquals(some(arrayList(1)), sequence(arrayList(some(1)))); + assertEquals(none(), sequence(arrayList(none(), none()))); + assertEquals(none(), sequence(arrayList(some(1), none()))); + assertEquals(none(), sequence(arrayList(none(), some(2)))); + assertEquals(some(arrayList(1, 2)), sequence(arrayList(some(1), some(2)))); + } - @Test - public void sequenceValidationTest() { - assertEquals(some(fail(1)), sequence(Validation.>fail(1))); - assertEquals(none(), sequence(Validation.>success(none()))); - assertEquals(some(success("string")), sequence(Validation.>success(some("string")))); - } + @Test + public void sequenceValidationTest() { + assertEquals(some(fail(1)), sequence(Validation.>fail(1))); + assertEquals(none(), sequence(Validation.>success(none()))); + assertEquals(some(success("string")), sequence(Validation.>success(some("string")))); + } + + @Test + public void testSequenceEitherLeft() { + assertEquals(left(none()), sequenceEitherLeft(none())); + assertEquals(left(some("0")), sequenceEitherLeft(some(left("0")))); + assertEquals(right("0"), sequenceEitherLeft(some(right("0")))); + } + + @Test + public void testSequenceEitherRight() { + assertEquals(right(none()), sequenceEitherRight(none())); + assertEquals(right(some("0")), sequenceEitherRight(some(right("0")))); + assertEquals(left("0"), sequenceEitherRight(some(left("0")))); + } + + @Test + public void testSequenceF() { + assertEquals(constant(none()).f(1), sequenceF(none()).f(1)); + assertEquals(constant(some("0")).f(1), sequenceF(some(constant("0"))).f(1)); + } + + @Test + public void testSequenceIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(none())).run(), sequenceIO(none()).run()); + assertEquals(IOFunctions.lazy(constant(some("0"))).run(), sequenceIO(some(IOFunctions.lazy(constant("0")))).run()); + } + + @Test + public void testSequenceList() { + assertEquals(List.arrayList(none()), sequenceList(none())); + assertEquals(List.nil(), sequenceList(some(List.nil()))); + assertEquals(List.arrayList(some("0")), sequenceList(some(List.single("0")))); + assertEquals(List.arrayList(some("0"), some("1")), sequenceList(some(List.arrayList("0", "1")))); + } + + @Test + public void testSequenceOption() { + assertEquals(some(none()), sequenceOption(none())); + assertEquals(none(), sequenceOption(some(none()))); + assertEquals(some(some("0")), sequenceOption(some(some("0")))); + } + + @Test + public void testSequenceP1() { + assertEquals(p(none()), sequenceP1(none())); + assertEquals(p(some("0")), sequenceP1(some(p("0")))); + } + + @Test + public void testSequenceSeq() { + assertEquals(Seq.arraySeq(none()), sequenceSeq(none())); + assertEquals(Seq.empty(), sequenceSeq(some(Seq.empty()))); + assertEquals(Seq.arraySeq(some("0")), sequenceSeq(some(Seq.single("0")))); + assertEquals(Seq.arraySeq(some("0"), some("1")), sequenceSeq(some(Seq.arraySeq("0", "1")))); + } + + @Test + public void testSequenceSet() { + assertEquals(Set.arraySet(optionOrd(stringOrd), none()), sequenceSet(stringOrd, none())); + assertEquals(Set.empty(optionOrd(stringOrd)), sequenceSet(stringOrd, some(Set.empty(stringOrd)))); + assertEquals(Set.arraySet(optionOrd(stringOrd), some("0")), sequenceSet(stringOrd, some(Set.single(stringOrd, "0")))); + assertEquals(Set.arraySet(optionOrd(stringOrd), some("0"), some("1")), sequenceSet(stringOrd, some(Set.arraySet(stringOrd, "0", "1")))); + } + + @Test + public void testSequenceStream() { + assertEquals(Stream.arrayStream(none()), sequenceStream(none())); + assertEquals(Stream.nil(), sequenceStream(some(Stream.nil()))); + assertEquals(Stream.arrayStream(some("0")), sequenceStream(some(Stream.single("0")))); + assertEquals(Stream.arrayStream(some("0"), some("1")), sequenceStream(some(Stream.arrayStream("0", "1")))); + } + + @Test + public void testSequenceTrampoline() { + assertEquals(Trampoline.pure(none()).run(), sequenceTrampoline(none()).run()); + assertEquals(Trampoline.pure(some(0)).run(), sequenceTrampoline(some(Trampoline.pure(0))).run()); + } + + @Test + public void testSequenceValidation() { + assertEquals(Validation.success(none()), sequenceValidation(none())); + assertEquals(Validation.fail(0), sequenceValidation(some(Validation.fail(0)))); + assertEquals(Validation.success(some(0)), sequenceValidation(some(Validation.success(0)))); + } + + @Test + public void testTraverseEitherLeft() { + assertEquals(left(none()), none().traverseEitherLeft(constant(left(0)))); + assertEquals(left(some(0)), some("0").traverseEitherLeft(constant(left(0)))); + assertEquals(left(none()), none().traverseEitherLeft(constant(right(0)))); + assertEquals(right(0), some("0").traverseEitherLeft(constant(right(0)))); + } + + @Test + public void testTraverseEitherRight() { + assertEquals(right(none()), none().traverseEitherRight(constant(right(0)))); + assertEquals(right(some(0)), some("0").traverseEitherRight(constant(right(0)))); + assertEquals(right(none()), none().traverseEitherRight(constant(left(0)))); + assertEquals(left(0), some("0").traverseEitherRight(constant(left(0)))); + } + + @Test + public void testTraverseF() { + assertEquals(constant(none()).f(1), none().traverseF(constant(constant(0))).f(1)); + assertEquals(constant(some(0)).f(1), some("0").traverseF(constant(constant(0))).f(1)); + } + + @Test + public void testTraverseIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(none())).run(), none().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(IOFunctions.lazy(constant(some(0))).run(), some("0").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseList() { + assertEquals(List.arrayList(none()), none().traverseList(constant(List.nil()))); + assertEquals(List.nil(), some("0").traverseList(constant(List.nil()))); + assertEquals(List.arrayList(none()), none().traverseList(constant(List.single(0)))); + assertEquals(List.arrayList(some(0)), some("0").traverseList(constant(List.single(0)))); + assertEquals(List.arrayList(none()), none().traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.arrayList(some(0), some(1)), some("0").traverseList(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseOption() { + assertEquals(some(none()), none().traverseOption(constant(none()))); + assertEquals(none(), some("0").traverseOption(constant(none()))); + assertEquals(some(none()), none().traverseOption(constant(some(0)))); + assertEquals(some(some(0)), some("0").traverseOption(constant(some(0)))); + } + + @Test + public void testTraverseP1() { + assertEquals(p(none()), none().traverseP1(constant(p(0)))); + assertEquals(p(some(0)), some("0").traverseP1(constant(p(0)))); + } + + @Test + public void testTraverseSeq() { + assertEquals(Seq.arraySeq(none()), none().traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.empty(), some("0").traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.arraySeq(none()), none().traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.arraySeq(some(0)), some("0").traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.arraySeq(none()), none().traverseSeq(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.arraySeq(some(0), some(1)), some("0").traverseSeq(constant(Seq.arraySeq(0, 1)))); + } + + @Test + public void testTraverseSet() { + assertEquals(Set.arraySet(optionOrd(intOrd), none()), none().traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.empty(optionOrd(intOrd)), some("0").traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.arraySet(optionOrd(intOrd), none()), none().traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.arraySet(optionOrd(intOrd), some(0)), some("0").traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.arraySet(optionOrd(intOrd), none()), none().traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + assertEquals(Set.arraySet(optionOrd(intOrd), some(0), some(1)), some("0").traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.arrayStream(none()), none().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.nil(), some("0").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.arrayStream(none()), none().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.arrayStream(some(0)), some("0").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.arrayStream(none()), none().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.arrayStream(some(0), some(1)), some("0").traverseStream(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testTraverseTrampoline() { + assertEquals(Trampoline.pure(none()).run(), none().traverseTrampoline(constant(Trampoline.pure(0))).run()); + assertEquals(Trampoline.pure(some(0)).run(), some("0").traverseTrampoline(constant(Trampoline.pure(0))).run()); + } + + @Test + public void testTraverseValidation() { + assertEquals(success(none()), none().traverseValidation(constant(Validation.fail(0)))); + assertEquals(fail(0), some("0").traverseValidation(constant(Validation.fail(0)))); + assertEquals(success(none()), none().traverseValidation(constant(Validation.success(0)))); + assertEquals(success(some(0)), some("0").traverseValidation(constant(Validation.success(0)))); + } } From 225622c0e9ac4544868d341455ea5e6894311a10 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Thu, 23 Jul 2020 13:38:44 -0400 Subject: [PATCH 744/811] Fixes #403. Add fj.data.Option.sequence*, fj.data.Option.traverse*; correct comment, distinguish between 0 and 0. --- core/src/main/java/fj/data/Option.java | 4 +- core/src/test/java/fj/data/OptionTest.java | 106 +++++++++++---------- 2 files changed, 56 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 6b62d2cf..655463b7 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -393,7 +393,7 @@ public final Option sequence(final Option o) { } /** - * Sequence the given option and collect the output on the right side of an either. + * Sequence the given option and collect the output on the left side of an either. * * @param option the given option * @param the type of the right value @@ -405,7 +405,7 @@ public static final Either, R> sequenceEitherLeft(final Option< } /** - * Sequence the given option and collect the output on the left side of an either. + * Sequence the given option and collect the output on the right side of an either. * * @param option the given option * @param the type of the right value diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index 403cbbd1..db37f1ed 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -11,6 +11,8 @@ import static fj.data.Either.*; import static fj.data.List.*; import static fj.data.Option.sequence; +import static fj.data.Option.sequenceEitherLeft; +import static fj.data.Option.sequenceEitherRight; import static fj.data.Option.sequenceF; import static fj.data.Option.sequenceIO; import static fj.data.Option.sequenceList; @@ -67,72 +69,72 @@ public void sequenceValidationTest() { @Test public void testSequenceEitherLeft() { assertEquals(left(none()), sequenceEitherLeft(none())); - assertEquals(left(some("0")), sequenceEitherLeft(some(left("0")))); - assertEquals(right("0"), sequenceEitherLeft(some(right("0")))); + assertEquals(left(some("zero")), sequenceEitherLeft(some(left("zero")))); + assertEquals(right("zero"), sequenceEitherLeft(some(right("zero")))); } @Test public void testSequenceEitherRight() { assertEquals(right(none()), sequenceEitherRight(none())); - assertEquals(right(some("0")), sequenceEitherRight(some(right("0")))); - assertEquals(left("0"), sequenceEitherRight(some(left("0")))); + assertEquals(right(some("zero")), sequenceEitherRight(some(right("zero")))); + assertEquals(left("zero"), sequenceEitherRight(some(left("zero")))); } @Test public void testSequenceF() { assertEquals(constant(none()).f(1), sequenceF(none()).f(1)); - assertEquals(constant(some("0")).f(1), sequenceF(some(constant("0"))).f(1)); + assertEquals(constant(some("zero")).f(1), sequenceF(some(constant("zero"))).f(1)); } @Test public void testSequenceIO() throws IOException { assertEquals(IOFunctions.lazy(constant(none())).run(), sequenceIO(none()).run()); - assertEquals(IOFunctions.lazy(constant(some("0"))).run(), sequenceIO(some(IOFunctions.lazy(constant("0")))).run()); + assertEquals(IOFunctions.lazy(constant(some("zero"))).run(), sequenceIO(some(IOFunctions.lazy(constant("zero")))).run()); } @Test public void testSequenceList() { - assertEquals(List.arrayList(none()), sequenceList(none())); + assertEquals(List.single(none()), sequenceList(none())); assertEquals(List.nil(), sequenceList(some(List.nil()))); - assertEquals(List.arrayList(some("0")), sequenceList(some(List.single("0")))); - assertEquals(List.arrayList(some("0"), some("1")), sequenceList(some(List.arrayList("0", "1")))); + assertEquals(List.single(some("zero")), sequenceList(some(List.single("zero")))); + assertEquals(List.arrayList(some("zero"), some("one")), sequenceList(some(List.arrayList("zero", "one")))); } @Test public void testSequenceOption() { assertEquals(some(none()), sequenceOption(none())); assertEquals(none(), sequenceOption(some(none()))); - assertEquals(some(some("0")), sequenceOption(some(some("0")))); + assertEquals(some(some("zero")), sequenceOption(some(some("zero")))); } @Test public void testSequenceP1() { assertEquals(p(none()), sequenceP1(none())); - assertEquals(p(some("0")), sequenceP1(some(p("0")))); + assertEquals(p(some("zero")), sequenceP1(some(p("zero")))); } @Test public void testSequenceSeq() { - assertEquals(Seq.arraySeq(none()), sequenceSeq(none())); + assertEquals(Seq.single(none()), sequenceSeq(none())); assertEquals(Seq.empty(), sequenceSeq(some(Seq.empty()))); - assertEquals(Seq.arraySeq(some("0")), sequenceSeq(some(Seq.single("0")))); - assertEquals(Seq.arraySeq(some("0"), some("1")), sequenceSeq(some(Seq.arraySeq("0", "1")))); + assertEquals(Seq.single(some("zero")), sequenceSeq(some(Seq.single("zero")))); + assertEquals(Seq.arraySeq(some("zero"), some("one")), sequenceSeq(some(Seq.arraySeq("zero", "one")))); } @Test public void testSequenceSet() { assertEquals(Set.arraySet(optionOrd(stringOrd), none()), sequenceSet(stringOrd, none())); assertEquals(Set.empty(optionOrd(stringOrd)), sequenceSet(stringOrd, some(Set.empty(stringOrd)))); - assertEquals(Set.arraySet(optionOrd(stringOrd), some("0")), sequenceSet(stringOrd, some(Set.single(stringOrd, "0")))); - assertEquals(Set.arraySet(optionOrd(stringOrd), some("0"), some("1")), sequenceSet(stringOrd, some(Set.arraySet(stringOrd, "0", "1")))); + assertEquals(Set.arraySet(optionOrd(stringOrd), some("zero")), sequenceSet(stringOrd, some(Set.single(stringOrd, "zero")))); + assertEquals(Set.arraySet(optionOrd(stringOrd), some("zero"), some("one")), sequenceSet(stringOrd, some(Set.arraySet(stringOrd, "zero", "one")))); } @Test public void testSequenceStream() { - assertEquals(Stream.arrayStream(none()), sequenceStream(none())); + assertEquals(Stream.single(none()), sequenceStream(none())); assertEquals(Stream.nil(), sequenceStream(some(Stream.nil()))); - assertEquals(Stream.arrayStream(some("0")), sequenceStream(some(Stream.single("0")))); - assertEquals(Stream.arrayStream(some("0"), some("1")), sequenceStream(some(Stream.arrayStream("0", "1")))); + assertEquals(Stream.single(some("zero")), sequenceStream(some(Stream.single("zero")))); + assertEquals(Stream.arrayStream(some("zero"), some("one")), sequenceStream(some(Stream.arrayStream("zero", "one")))); } @Test @@ -151,96 +153,96 @@ public void testSequenceValidation() { @Test public void testTraverseEitherLeft() { assertEquals(left(none()), none().traverseEitherLeft(constant(left(0)))); - assertEquals(left(some(0)), some("0").traverseEitherLeft(constant(left(0)))); + assertEquals(left(some(0)), some("zero").traverseEitherLeft(constant(left(0)))); assertEquals(left(none()), none().traverseEitherLeft(constant(right(0)))); - assertEquals(right(0), some("0").traverseEitherLeft(constant(right(0)))); + assertEquals(right(0), some("zero").traverseEitherLeft(constant(right(0)))); } @Test public void testTraverseEitherRight() { assertEquals(right(none()), none().traverseEitherRight(constant(right(0)))); - assertEquals(right(some(0)), some("0").traverseEitherRight(constant(right(0)))); + assertEquals(right(some(0)), some("zero").traverseEitherRight(constant(right(0)))); assertEquals(right(none()), none().traverseEitherRight(constant(left(0)))); - assertEquals(left(0), some("0").traverseEitherRight(constant(left(0)))); + assertEquals(left(0), some("zero").traverseEitherRight(constant(left(0)))); } @Test public void testTraverseF() { assertEquals(constant(none()).f(1), none().traverseF(constant(constant(0))).f(1)); - assertEquals(constant(some(0)).f(1), some("0").traverseF(constant(constant(0))).f(1)); + assertEquals(constant(some(0)).f(1), some("zero").traverseF(constant(constant(0))).f(1)); } @Test public void testTraverseIO() throws IOException { assertEquals(IOFunctions.lazy(constant(none())).run(), none().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); - assertEquals(IOFunctions.lazy(constant(some(0))).run(), some("0").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(IOFunctions.lazy(constant(some(0))).run(), some("zero").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); } @Test public void testTraverseList() { - assertEquals(List.arrayList(none()), none().traverseList(constant(List.nil()))); - assertEquals(List.nil(), some("0").traverseList(constant(List.nil()))); - assertEquals(List.arrayList(none()), none().traverseList(constant(List.single(0)))); - assertEquals(List.arrayList(some(0)), some("0").traverseList(constant(List.single(0)))); - assertEquals(List.arrayList(none()), none().traverseList(constant(List.arrayList(0, 1)))); - assertEquals(List.arrayList(some(0), some(1)), some("0").traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.single(none()), none().traverseList(constant(List.nil()))); + assertEquals(List.nil(), some("zero").traverseList(constant(List.nil()))); + assertEquals(List.single(none()), none().traverseList(constant(List.single(0)))); + assertEquals(List.single(some(0)), some("zero").traverseList(constant(List.single(0)))); + assertEquals(List.single(none()), none().traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.arrayList(some(0), some(1)), some("zero").traverseList(constant(List.arrayList(0, 1)))); } @Test public void testTraverseOption() { assertEquals(some(none()), none().traverseOption(constant(none()))); - assertEquals(none(), some("0").traverseOption(constant(none()))); + assertEquals(none(), some("zero").traverseOption(constant(none()))); assertEquals(some(none()), none().traverseOption(constant(some(0)))); - assertEquals(some(some(0)), some("0").traverseOption(constant(some(0)))); + assertEquals(some(some(0)), some("zero").traverseOption(constant(some(0)))); } @Test public void testTraverseP1() { assertEquals(p(none()), none().traverseP1(constant(p(0)))); - assertEquals(p(some(0)), some("0").traverseP1(constant(p(0)))); + assertEquals(p(some(0)), some("zero").traverseP1(constant(p(0)))); } @Test public void testTraverseSeq() { - assertEquals(Seq.arraySeq(none()), none().traverseSeq(constant(Seq.empty()))); - assertEquals(Seq.empty(), some("0").traverseSeq(constant(Seq.empty()))); - assertEquals(Seq.arraySeq(none()), none().traverseSeq(constant(Seq.single(0)))); - assertEquals(Seq.arraySeq(some(0)), some("0").traverseSeq(constant(Seq.single(0)))); - assertEquals(Seq.arraySeq(none()), none().traverseSeq(constant(Seq.arraySeq(0, 1)))); - assertEquals(Seq.arraySeq(some(0), some(1)), some("0").traverseSeq(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.single(none()), none().traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.empty(), some("zero").traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.single(none()), none().traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(some(0)), some("zero").traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(none()), none().traverseSeq(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.arraySeq(some(0), some(1)), some("zero").traverseSeq(constant(Seq.arraySeq(0, 1)))); } @Test public void testTraverseSet() { assertEquals(Set.arraySet(optionOrd(intOrd), none()), none().traverseSet(intOrd, constant(Set.empty(intOrd)))); - assertEquals(Set.empty(optionOrd(intOrd)), some("0").traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.empty(optionOrd(intOrd)), some("zero").traverseSet(intOrd, constant(Set.empty(intOrd)))); assertEquals(Set.arraySet(optionOrd(intOrd), none()), none().traverseSet(intOrd, constant(Set.single(intOrd, 0)))); - assertEquals(Set.arraySet(optionOrd(intOrd), some(0)), some("0").traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.arraySet(optionOrd(intOrd), some(0)), some("zero").traverseSet(intOrd, constant(Set.single(intOrd, 0)))); assertEquals(Set.arraySet(optionOrd(intOrd), none()), none().traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); - assertEquals(Set.arraySet(optionOrd(intOrd), some(0), some(1)), some("0").traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + assertEquals(Set.arraySet(optionOrd(intOrd), some(0), some(1)), some("zero").traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); } @Test public void testTraverseStream() { - assertEquals(Stream.arrayStream(none()), none().traverseStream(constant(Stream.nil()))); - assertEquals(Stream.nil(), some("0").traverseStream(constant(Stream.nil()))); - assertEquals(Stream.arrayStream(none()), none().traverseStream(constant(Stream.single(0)))); - assertEquals(Stream.arrayStream(some(0)), some("0").traverseStream(constant(Stream.single(0)))); - assertEquals(Stream.arrayStream(none()), none().traverseStream(constant(Stream.arrayStream(0, 1)))); - assertEquals(Stream.arrayStream(some(0), some(1)), some("0").traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.single(none()), none().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.nil(), some("zero").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(none()), none().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(some(0)), some("zero").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(none()), none().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.arrayStream(some(0), some(1)), some("zero").traverseStream(constant(Stream.arrayStream(0, 1)))); } @Test public void testTraverseTrampoline() { assertEquals(Trampoline.pure(none()).run(), none().traverseTrampoline(constant(Trampoline.pure(0))).run()); - assertEquals(Trampoline.pure(some(0)).run(), some("0").traverseTrampoline(constant(Trampoline.pure(0))).run()); + assertEquals(Trampoline.pure(some(0)).run(), some("zero").traverseTrampoline(constant(Trampoline.pure(0))).run()); } @Test public void testTraverseValidation() { assertEquals(success(none()), none().traverseValidation(constant(Validation.fail(0)))); - assertEquals(fail(0), some("0").traverseValidation(constant(Validation.fail(0)))); + assertEquals(fail(0), some("zero").traverseValidation(constant(Validation.fail(0)))); assertEquals(success(none()), none().traverseValidation(constant(Validation.success(0)))); - assertEquals(success(some(0)), some("0").traverseValidation(constant(Validation.success(0)))); + assertEquals(success(some(0)), some("zero").traverseValidation(constant(Validation.success(0)))); } } From f9ec6ee20804e1db8b6a4c0c238a5a51adbbe888 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Thu, 23 Jul 2020 17:56:43 -0400 Subject: [PATCH 745/811] Fixes #403. Add fj.data.Option.sequence*, fj.data.Option.traverse*; add bind tests. --- core/src/test/java/fj/data/OptionTest.java | 187 +++++++++++++++++++-- 1 file changed, 174 insertions(+), 13 deletions(-) diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index db37f1ed..d028d4f6 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -1,5 +1,6 @@ package fj.data; +import fj.P; import fj.control.Trampoline; import org.junit.Test; @@ -7,22 +8,11 @@ import static fj.Function.constant; import static fj.Ord.*; -import static fj.P.p; +import static fj.P.*; import static fj.data.Either.*; import static fj.data.List.*; +import static fj.data.Option.iif; import static fj.data.Option.sequence; -import static fj.data.Option.sequenceEitherLeft; -import static fj.data.Option.sequenceEitherRight; -import static fj.data.Option.sequenceF; -import static fj.data.Option.sequenceIO; -import static fj.data.Option.sequenceList; -import static fj.data.Option.sequenceOption; -import static fj.data.Option.sequenceP1; -import static fj.data.Option.sequenceSeq; -import static fj.data.Option.sequenceSet; -import static fj.data.Option.sequenceStream; -import static fj.data.Option.sequenceTrampoline; -import static fj.data.Option.sequenceValidation; import static fj.data.Option.*; import static fj.data.Validation.fail; import static fj.data.Validation.*; @@ -66,6 +56,177 @@ public void sequenceValidationTest() { assertEquals(some(success("string")), sequence(Validation.>success(some("string")))); } + @Test + public void testBind1() { + range(0, 1).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), 0), list.index(0).bind(Option::some)); + }); + + } + + @Test + public void testBind2() { + range(0, 2).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1)), list.index(0).bind(list.index(1), p2())); + }); + } + + @Test + public void testBind3() { + range(0, 3).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2)), list.index(0).bind(list.index(1), list.index(2), p3())); + }); + + } + + @Test + public void testBind4() { + range(0, 4).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3)), list.index(0).bind(list.index(1), list.index(2), list.index(3), p4())); + }); + + } + + @Test + public void testBind5() { + range(0, 5).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), p5())); + }); + } + + @Test + public void testBind6() { + range(0, 6).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), p6())); + }); + } + + @Test + public void testBind7() { + range(0, 7).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), p7())); + }); + } + + @Test + public void testBind8() { + range(0, 8).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), P.p8())); + }); + } + + @Test + public void testBindProduct2() { + range(0, 2).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1)), list.index(0).bindProduct(list.index(1))); + }); + } + + @Test + public void testBindProduct3() { + range(0, 3).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2)), list.index(0).bindProduct(list.index(1), list.index(2))); + }); + + } + + @Test + public void testBindProduct4() { + range(0, 4).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3))); + }); + + } + + @Test + public void testBindProduct5() { + range(0, 5).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4))); + }); + } + + @Test + public void testBindProduct6() { + range(0, 6).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5))); + }); + } + + @Test + public void testBindProduct7() { + range(0, 7).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6))); + }); + } + + @Test + public void testBindProduct8() { + range(0, 8).map(i -> arrayList(Option.none(), some(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) + .forEach(list -> { + assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7))); + }); + } + + @Test public void testSequenceEitherLeft() { assertEquals(left(none()), sequenceEitherLeft(none())); From fc85ee1ede0d15b64d12f4d0ec12d5ecc79ed0f8 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Fri, 24 Jul 2020 16:27:38 -0400 Subject: [PATCH 746/811] Fixes #403. Add fj.data.Option.sequence*, fj.data.Option.traverse.*; add sequenceEither, traverseEither as aliases for sequenceEitherRight, sequenceEitherLeft. --- core/src/main/java/fj/data/Option.java | 24 +++++++++++++++++++ core/src/test/java/fj/data/OptionTest.java | 27 ++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index 655463b7..b6876c63 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -392,6 +392,18 @@ public final Option sequence(final Option o) { return bind(c); } + /** + * Sequence the given option and collect the output on the right side of an either. + * + * @param option the given option + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either> sequenceEither(final Option> option) { + return option.traverseEitherRight(identity()); + } + /** * Sequence the given option and collect the output on the left side of an either. * @@ -529,6 +541,18 @@ public static final Validation> sequenceValidation(final Opt return option.traverseValidation(identity()); } + /** + * Traverse this option with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public final Either> traverseEither(final F> f) { + return traverseEitherRight(f); + } + /** * Traverse this option with the given function and collect the output on the left side of an either. * diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index d028d4f6..da5ef065 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -13,6 +13,19 @@ import static fj.data.List.*; import static fj.data.Option.iif; import static fj.data.Option.sequence; +import static fj.data.Option.sequenceEither; +import static fj.data.Option.sequenceEitherLeft; +import static fj.data.Option.sequenceEitherRight; +import static fj.data.Option.sequenceF; +import static fj.data.Option.sequenceIO; +import static fj.data.Option.sequenceList; +import static fj.data.Option.sequenceOption; +import static fj.data.Option.sequenceP1; +import static fj.data.Option.sequenceSeq; +import static fj.data.Option.sequenceSet; +import static fj.data.Option.sequenceStream; +import static fj.data.Option.sequenceTrampoline; +import static fj.data.Option.sequenceValidation; import static fj.data.Option.*; import static fj.data.Validation.fail; import static fj.data.Validation.*; @@ -226,6 +239,12 @@ public void testBindProduct8() { }); } + @Test + public void testSequenceEither() { + assertEquals(right(none()), sequenceEither(none())); + assertEquals(right(some("zero")), sequenceEither(some(right("zero")))); + assertEquals(left("zero"), sequenceEither(some(left("zero")))); + } @Test public void testSequenceEitherLeft() { @@ -311,6 +330,14 @@ public void testSequenceValidation() { assertEquals(Validation.success(some(0)), sequenceValidation(some(Validation.success(0)))); } + @Test + public void testTraverseEither() { + assertEquals(right(none()), none().traverseEither(constant(right(0)))); + assertEquals(right(some(0)), some("zero").traverseEither(constant(right(0)))); + assertEquals(right(none()), none().traverseEither(constant(left(0)))); + assertEquals(left(0), some("zero").traverseEither(constant(left(0)))); + } + @Test public void testTraverseEitherLeft() { assertEquals(left(none()), none().traverseEitherLeft(constant(left(0)))); From bf3fed02f7ae94107155ed93e271e9f621b0be2a Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Fri, 24 Jul 2020 12:26:28 -0400 Subject: [PATCH 747/811] Fixes #406. Several fj.data.Validation.accumulate functions construct unexpected or incorrect failures; add to ValidationTest. --- core/src/main/java/fj/data/Validation.java | 26 +- .../src/test/java/fj/data/ValidationTest.java | 245 +++++++++++++++++- 2 files changed, 242 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 2afb91f3..e99d64a1 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -738,20 +738,14 @@ public final Validation, B> accumulate(F f) { } - public final Validation, C> accumulate(Validation v2, F2 f) { - List list = List.nil(); - if (isFail()) { - list = list.cons(fail()); - } - if (v2.isFail()) { - list = list.cons(v2.fail()); - } - if (!list.isEmpty()) { - return fail(list); - } else { - return success(f.f(success(), v2.success())); - } + public final Validation, C> accumulate(Validation v2, F2 f) { + List list = fails(list(this, v2)); + if (!list.isEmpty()) { + return fail(list); + } else { + return success(f.f(success(), v2.success())); } + } @@ -784,7 +778,7 @@ public final Validation, D> accumulate(Validation v2, Va public final Validation, G> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, F6 f) { - List list = fails(list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5, v6)); if (!list.isEmpty()) { return fail(list); } else { @@ -793,7 +787,7 @@ public final Validation, D> accumulate(Validation v2, Va } public final Validation, H> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, F7 f) { - List list = fails(list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5, v6, v7)); if (!list.isEmpty()) { return fail(list); } else { @@ -802,7 +796,7 @@ public final Validation, D> accumulate(Validation v2, Va } public final Validation, I> accumulate(Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8, F8 f) { - List list = fails(list(this, v2, v3, v4, v5)); + List list = fails(list(this, v2, v3, v4, v5, v6, v7, v8)); if (!list.isEmpty()) { return fail(list); } else { diff --git a/core/src/test/java/fj/data/ValidationTest.java b/core/src/test/java/fj/data/ValidationTest.java index 0f1f3216..0df2deb9 100644 --- a/core/src/test/java/fj/data/ValidationTest.java +++ b/core/src/test/java/fj/data/ValidationTest.java @@ -1,14 +1,16 @@ package fj.data; +import fj.*; import fj.control.Trampoline; import org.junit.Test; import java.io.IOException; -import static fj.Function.constant; +import static fj.Function.*; import static fj.Ord.*; -import static fj.P.p; +import static fj.P.*; import static fj.data.Either.*; +import static fj.data.List.*; import static fj.data.Option.*; import static fj.data.Validation.sequenceEitherLeft; import static fj.data.Validation.sequenceEitherRight; @@ -27,6 +29,223 @@ public class ValidationTest { + @Test + public void testAccumulateSemigroup2() { + range(0, 2).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(), list.index(1))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1)), list.index(0).accumulate(Semigroup.listSemigroup(), list.index(1), p2())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1)), list.index(0).accumulate(Semigroup.listSemigroup(), list.index(1), uncurryF2(p2()))); + }); + } + + @Test + public void testAccumulateSemigroup3() { + range(0, 3).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> + accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), p3())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), uncurryF3(p3()))); + }); + + } + + @Test + public void testAccumulateSemigroup4() { + range(0, 4).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> + accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), p4())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), uncurryF4(p4()))); + }); + + } + + @Test + public void testAccumulateSemigroup5() { + range(0, 5).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> + accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), p5())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), uncurryF5(p5()))); + }); + } + + @Test + public void testAccumulateSemigroup6() { + range(0, 6).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> + accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), p6())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), uncurryF6(p6()))); + }); + } + + @Test + public void testAccumulateSemigroup7() { + range(0, 7).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> + accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), p7())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), uncurryF7(p7()))); + }); + } + + @Test + public void testAccumulateSemigroup8() { + range(0, 8).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> + accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7))); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), P.p8())); + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), uncurryF8(P.p8()))); + }); + } + + @Test + public void testAccumulate0() { + range(0, 1).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), 0), list.index(0).accumulate()); + }); + } + + @Test + public void testAccumulate1() { + range(0, 1).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), 0), list.index(0).accumulate(identity())); + }); + + } + + @Test + public void testAccumulate2() { + range(0, 2).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1)), list.index(0).accumulate(list.index(1), P::p)); + }); + } + + @Test + public void testAccumulate3() { + range(0, 3).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2)), list.index(0).accumulate(list.index(1), list.index(2), P::p)); + }); + + } + + @Test + public void testAccumulate4() { + range(0, 4).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), P::p)); + }); + + } + + @Test + public void testAccumulate5() { + range(0, 5).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), P::p)); + }); + } + + @Test + public void testAccumulate6() { + range(0, 6).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), P::p)); + }); + } + + @Test + public void testAccumulate7() { + range(0, 7).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), P::p)); + }); + } + + @Test + public void testAccumulate8() { + range(0, 8).map(i -> List., Integer>>arrayList(fail(arrayList(String.valueOf(i))), success(i))) + .foldLeft(accumulator -> list -> accumulator.isEmpty() ? + list.map(List::single) : + accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) + .forEach(list -> { + assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), P::p)); + }); + } + + @Test + public void testMap() { + assertEquals(Validation.fail("zero"), Validation.fail("zero").map(constant(0))); + assertEquals(Validation.success(0), Validation.success("zero").map(constant(0))); + assertEquals(Validation.fail("zero"), Validation.fail("zero").map(constant(0))); + assertEquals(Validation.success(0), Validation.success("zero").map(constant(0))); + } + + @Test + public void testBind() { + assertEquals(Validation.fail("zero"), Validation.fail("zero").bind(constant(Validation.fail("zero")))); + assertEquals(Validation.fail("zero"), Validation.success("zero").bind(constant(Validation.fail("zero")))); + assertEquals(Validation.fail("zero"), Validation.fail("zero").bind(constant(Validation.success(0)))); + assertEquals(Validation.success(0), Validation.success("zero").bind(constant(Validation.success(0)))); + } + @Test public void testSequenceEitherLeft() { assertEquals(left(fail("zero")), sequenceEitherLeft(fail("zero"))); @@ -55,10 +274,10 @@ public void testSequenceIO() throws IOException { @Test public void testSequenceList() { - assertEquals(List.single(fail("zero")), sequenceList(fail("zero"))); - assertEquals(List.nil(), sequenceList(success(List.nil()))); - assertEquals(List.single(success("zero")), sequenceList(success(List.single("zero")))); - assertEquals(List.arrayList(success("zero"), success("one")), sequenceList(success(List.arrayList("zero", "one")))); + assertEquals(single(fail("zero")), sequenceList(fail("zero"))); + assertEquals(nil(), sequenceList(success(nil()))); + assertEquals(single(success("zero")), sequenceList(success(single("zero")))); + assertEquals(arrayList(success("zero"), success("one")), sequenceList(success(arrayList("zero", "one")))); } @Test @@ -87,7 +306,7 @@ public void testSequenceSet() { assertEquals(Set.single(validationOrd(stringOrd, intOrd), fail("zero")), sequenceSet(stringOrd, intOrd, fail("zero"))); assertEquals(Set.empty(validationOrd(stringOrd, intOrd)), sequenceSet(stringOrd, intOrd, success(Set.empty(intOrd)))); assertEquals(Set.single(validationOrd(intOrd, stringOrd), success("zero")), sequenceSet(intOrd, stringOrd, success(Set.single(stringOrd, "zero")))); - assertEquals(Set.arraySet(validationOrd(intOrd, stringOrd), success("zero"), success("one")), sequenceSet(intOrd, stringOrd, Validation.success(Set.arraySet(stringOrd, "zero", "one")))); + assertEquals(Set.arraySet(validationOrd(intOrd, stringOrd), success("zero"), success("one")), sequenceSet(intOrd, stringOrd, success(Set.arraySet(stringOrd, "zero", "one")))); } @Test @@ -141,12 +360,12 @@ public void testTraverseIO() throws IOException { @Test public void testTraverseList() { - assertEquals(List.single(fail("zero")), fail("zero").traverseList(constant(List.nil()))); - assertEquals(List.nil(), success("zero").traverseList(constant(List.nil()))); - assertEquals(List.single(fail("zero")), fail("zero").traverseList(constant(List.single(0)))); - assertEquals(List.single(success(0)), success("zero").traverseList(constant(List.single(0)))); - assertEquals(List.single(fail("zero")), fail("zero").traverseList(constant(List.arrayList(0, 1)))); - assertEquals(List.arrayList(success(0), success(1)), success("zero").traverseList(constant(List.arrayList(0, 1)))); + assertEquals(single(fail("zero")), fail("zero").traverseList(constant(nil()))); + assertEquals(nil(), success("zero").traverseList(constant(nil()))); + assertEquals(single(fail("zero")), fail("zero").traverseList(constant(single(0)))); + assertEquals(single(success(0)), success("zero").traverseList(constant(single(0)))); + assertEquals(single(fail("zero")), fail("zero").traverseList(constant(arrayList(0, 1)))); + assertEquals(arrayList(success(0), success(1)), success("zero").traverseList(constant(arrayList(0, 1)))); } @Test From 4377adb82a2013d1faee7eac4c0f25821936ed43 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Fri, 24 Jul 2020 16:37:05 -0400 Subject: [PATCH 748/811] Fixes #407. Add fj.data.Seq.bind(F> f). --- core/src/main/java/fj/data/Seq.java | 25 ++++++++++++++++--------- core/src/test/java/fj/data/SeqTest.java | 17 ++++++++++++++--- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index abd20162..1ded05eb 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -1,20 +1,15 @@ package fj.data; import fj.*; +import fj.data.List.Buffer; +import fj.data.fingertrees.*; + +import java.util.*; import static fj.Bottom.error; import static fj.Monoid.intAdditionMonoid; import static fj.data.fingertrees.FingerTree.measured; -import fj.data.List.Buffer; -import fj.data.fingertrees.FingerTree; -import fj.data.fingertrees.MakeTree; -import fj.data.fingertrees.Measured; - -import java.util.AbstractList; -import java.util.Iterator; -import java.util.NoSuchElementException; - /** * Provides an immutable finite sequence, implemented as a finger tree. This structure gives O(1) access to * the head and tail, as well as O(log n) random access and concatenation of sequences. @@ -396,4 +391,16 @@ public Seq map(F f) { return new Seq<>(ftree.map(f, Seq.elemMeasured())); } + /** + * Bind the given function across this seq. + * + * @param f the given function + * @param the type of the seq value + * @return the seq + */ + public Seq bind(final F> f) { + return foldRight( + (element, accumulator) -> f.f(element).append(accumulator), + empty()); + } } diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java index a7c85175..b19cb7d4 100644 --- a/core/src/test/java/fj/data/SeqTest.java +++ b/core/src/test/java/fj/data/SeqTest.java @@ -3,11 +3,10 @@ import fj.P2; import org.junit.Test; +import static fj.Function.constant; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * Created by MarkPerry on 16/01/2015. @@ -46,4 +45,16 @@ public void test() { assertThat(p2._2(), is(Seq.empty())); } + @Test + public void testBind() { + assertEquals(Seq.empty(), Seq.empty().bind(constant(Seq.empty()))); + assertEquals(Seq.empty(), Seq.empty().bind(constant(Seq.single(0)))); + assertEquals(Seq.empty(), Seq.empty().bind(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.empty(), Seq.single("zero").bind(constant(Seq.empty()))); + assertEquals(Seq.single(0), Seq.single("zero").bind(constant(Seq.single(0)))); + assertEquals(Seq.arraySeq(0, 1), Seq.single("zero").bind(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.empty(), Seq.arraySeq("zero", "one").bind(constant(Seq.empty()))); + assertEquals(Seq.arraySeq(0, 0), Seq.arraySeq("zero", "one").bind(constant(Seq.single(0)))); + assertEquals(Seq.arraySeq(0, 1, 0, 1), Seq.arraySeq("zero", "one").bind(constant(Seq.arraySeq(0, 1)))); + } } From 671b9d25e8d5a1db25252a889de06467b0696468 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Fri, 24 Jul 2020 17:05:29 -0400 Subject: [PATCH 749/811] Fixes #408. Add fj.data.List.sequence* function, fj.data.List.traverse* functions. --- core/src/main/java/fj/data/List.java | 413 ++++++++++++++++++----- core/src/test/java/fj/data/ListTest.java | 218 +++++++++++- 2 files changed, 535 insertions(+), 96 deletions(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index e0e12877..422d246b 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -1,54 +1,30 @@ package fj.data; -import static fj.Bottom.error; +import fj.*; +import fj.control.Trampoline; +import fj.control.parallel.*; +import fj.data.optic.Optional; +import fj.data.optic.*; +import fj.data.vector.V2; +import fj.function.Effect1; -import fj.Equal; -import fj.F2Functions; -import fj.Hash; -import fj.Monoid; -import fj.Ord; -import fj.Ordering; -import fj.P; -import fj.P1; -import fj.Semigroup; -import fj.Show; -import fj.Unit; -import fj.P2; -import fj.F0; -import fj.F; -import fj.F2; -import fj.Function; +import java.lang.Class; +import java.util.*; +import static fj.Bottom.error; import static fj.Function.*; -import static fj.P.p; -import static fj.P.p2; +import static fj.Ord.intOrd; +import static fj.Ordering.GT; +import static fj.P.*; import static fj.Unit.unit; import static fj.data.Array.mkArray; +import static fj.data.Either.*; import static fj.data.List.Buffer.*; -import static fj.data.Option.none; -import static fj.data.Option.some; +import static fj.data.Option.*; import static fj.data.optic.Optional.optional; import static fj.data.optic.Prism.prism; import static fj.data.vector.V.v; import static fj.function.Booleans.not; -import static fj.Ordering.GT; -import static fj.Ord.intOrd; - - -import fj.control.Trampoline; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import fj.data.optic.Optional; -import fj.data.optic.PTraversal; -import fj.data.optic.Prism; -import fj.data.optic.Traversal; -import fj.data.vector.V2; -import fj.function.Effect1; - -import java.util.AbstractCollection; -import java.util.Collection; -import java.util.Iterator; -import java.util.NoSuchElementException; /** * Provides an in-memory, immutable, singly linked list. @@ -604,61 +580,315 @@ public final List sequence(final List bs) { return bind(c); } - /** - * Traverses through the List with the given function - * - * @param f The function that produces Option value - * @return none if applying f returns none to any element of the list or f mapped list in some . - */ - public final Option> traverseOption(final F> f) { - return foldRight( - (a, obs) -> f.f(a).bind(o -> obs.map(os -> os.cons(o))), - some(List.nil()) - ); - } + /** + * Sequence the given list and collect the output on the right side of an either. + * + * @param list the given list + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either> sequenceEither(final List> list) { + return list.traverseEither(identity()); + } - /** - * Traverse through the List with given function. - * - * @param f The function that produces Either value. - * @return error in left or f mapped list in right. - */ - public final Either> traverseEither(final F> f) { - return foldRight( - (a, acc) -> f.f(a).right().bind(e -> acc.right().map(es -> es.cons(e))), - Either.right(List.nil()) - ); - } + /** + * Sequence the given list and collect the output on the left side of an either. + * + * @param list the given list + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either, R> sequenceEitherLeft(final List> list) { + return list.traverseEitherLeft(identity()); + } - public final Stream> traverseStream(final F> f) { - return foldRight( - (a, acc) -> f.f(a).bind(s -> acc.map(ss -> ss.cons(s))), - Stream.nil() - ); - } + /** + * Sequence the given list and collect the output on the right side of an either. + * + * @param list the given list + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static final Either> sequenceEitherRight(final List> list) { + return list.traverseEitherRight(identity()); + } - public final P1> traverseP1(final F> f){ - return foldRight( - (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - p(List.nil()) - ); - } + /** + * Sequence the given list and collect the output as a function. + * + * @param list the given list + * @param the type of the input value + * @param the type of the output value + * @return the either + */ + public static final F> sequenceF(final List> list) { + return list.traverseF(identity()); + } - public final IO> traverseIO(F> f) { - return this.foldRight( - (a, acc) -> IOFunctions.bind(f.f(a), b -> IOFunctions.map(acc, bs -> bs.cons(b))), - IOFunctions.unit(List.nil()) - ); - } + /** + * Sequence the given list and collect the output as an IO. + * + * @param list the given list + * @param the type of the IO value + * @return the IO + */ + public static final IO> sequenceIO(final List> list) { + return list.traverseIO(identity()); + } + + /** + * Sequence the given list and collect the output as an list. + * + * @param list the given list + * @param the type of the list value + * @return the list + */ + public static final List> sequenceList(final List> list) { + return list.traverseList(identity()); + } + + /** + * Sequence the given list and collect the output as an list. + * + * @param list the given list + * @param the type of the list value + * @return the list + */ + public static final Option> sequenceOption(final List> list) { + return list.traverseOption(identity()); + } + + /** + * Sequence the given list and collect the output as a P1. + * + * @param list the given list + * @param the type of the P1 value + * @return the P1 + */ + public static final P1> sequenceP1(final List> list) { + return list.traverseP1(identity()); + } + + /** + * Sequence the given list and collect the output as a seq. + * + * @param list the given list + * @param the type of the seq value + * @return the seq + */ + public static final Seq> sequenceSeq(final List> list) { + return list.traverseSeq(identity()); + } + + /** + * Sequence the given list and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param list the given list + * @param the type of the set value + * @return the either + */ + public static final Set> sequenceSet(final Ord ord, final List> list) { + return list.traverseSet(ord, identity()); + } + + /** + * Sequence the given list and collect the output as a stream. + * + * @param list the given list + * @param the type of the stream value + * @return the stream + */ + public static final Stream> sequenceStream(final List> list) { + return list.traverseStream(identity()); + } + + /** + * Sequence the given list and collect the output as a trampoline. + * + * @param list the given trampoline + * @param the type of the stream value + * @return the stream + */ + public static final Trampoline> sequenceTrampoline(final List> list) { + return list.traverseTrampoline(identity()); + } + + /** + * Sequence the given list and collect the output as a validation; use the given semigroup to reduce the errors. + * + * @param semigroup the given semigroup + * @param list the given list + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static final Validation> sequenceValidation(final Semigroup semigroup, final List> list) { + return list.traverseValidation(semigroup, identity()); + } + + /** + * Traverse through the List with given function. + * + * @param f The function that produces Either value. + * @return error in left or f mapped list in right. + */ + public final Either> traverseEither(final F> f) { + return foldRight( + (a, acc) -> f.f(a).right().bind(e -> acc.right().map(es -> es.cons(e))), + Either.right(List.nil()) + ); + } + + /** + * Traverse this list with the given function and collect the output on the left side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public final Either, R> traverseEitherLeft(final F> f) { + return foldRight( + (element, either) -> f.f(element).left().bind(elementInner -> either.left().map(list -> list.cons(elementInner))), + left(nil())); + } + /** + * Traverse this list with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public final Either> traverseEitherRight(final F> f) { + return foldRight( + (element, either) -> f.f(element).right().bind(elementInner -> either.right().map(list -> list.cons(elementInner))), + right(nil())); + } + + /** + * Traverse this list with the given function and collect the output as a function. + * + * @param f the given function + * @param the type of the input value + * @param the type of the output value + * @return the function + */ public final F> traverseF(F> f) { return this.foldRight( (a, acc) -> Function.bind(acc, (bs) -> Function.compose(bs::cons, f.f(a))), constant(List.nil()) - ); + ); + } + + /** + * Traverse this list with the given function and collect the output as an IO. + * + * @param f the given function + * @param the type of the IO value + * @return the IO + */ + public final IO> traverseIO(F> f) { + return this.foldRight( + (a, acc) -> IOFunctions.bind(f.f(a), b -> IOFunctions.map(acc, bs -> bs.cons(b))), + IOFunctions.unit(List.nil()) + ); + } + + /** + * Traverse this list with the given function and collect the output as a list. + * + * @param f the given function + * @param the type of the list value + * @return the list + */ + public final List> traverseList(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), + single(List.nil())); } + /** + * Traverses through the List with the given function + * + * @param f The function that produces Option value + * @return none if applying f returns none to any element of the list or f mapped list in some . + */ + public final Option> traverseOption(final F> f) { + return foldRight( + (a, obs) -> f.f(a).bind(o -> obs.map(os -> os.cons(o))), + some(List.nil()) + ); + } + + /** + * Traverse this list with the given function and collect the output as a p1. + * + * @param f the given function + * @param the type of the p1 value + * @return the p1 + */ + public final P1> traverseP1(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), + p(List.nil()) + ); + } + + /** + * Traverse this list with the given function and collect the output as a seq. + * + * @param f the given function + * @param the type of the seq value + * @return the seq + */ + public final Seq> traverseSeq(final F> f) { + return foldRight( + (element, seq) -> f.f(element).bind(elementInner -> seq.map(list -> list.cons(elementInner))), + Seq.single(nil())); + } + + /** + * Traverse this list with the given function and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param f the given function + * @param the type of the set value + * @return the set + */ + public final Set> traverseSet(final Ord ord, final F> f) { + final Ord> listOption = Ord.listOrd(ord); + return foldRight( + (element, set) -> f.f(element).bind(listOption, elementInner -> set.map(listOption, list -> list.cons(elementInner))), + Set.single(listOption, nil())); + } + + /** + * Traverse this list with the given function and collect the output as a stream. + * + * @param f the given function + * @param the type of the stream value + * @return the stream + */ + public final Stream> traverseStream(final F> f) { + return foldRight( + (a, acc) -> f.f(a).bind(s -> acc.map(ss -> ss.cons(s))), + Stream.single(nil())); + } + + /** + * Traverse this list with the given function and collect the output as a trampoline. + * + * @param f the given function + * @param the type of the trampoline value + * @return the trampoline + */ public final Trampoline> traverseTrampoline(final F> f) { return foldRight( (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), @@ -671,12 +901,15 @@ public final Promise> traversePromise(final F> f) { Promise.promise(Strategy.idStrategy(), p(List.nil()))); } - public final List> traverseList(final F> f) { - return foldRight( - (a, acc) -> f.f(a).bind(b -> acc.map(bs -> bs.cons(b))), - single(List.nil())); - } - + /** + * Traverse this list with the given function and collect the output as a validation; use the given semigroup to reduce the errors. + * + * @param s the given semigroup + * @param f the given function + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ public final Validation> traverseValidation(Semigroup s, final F> f) { return Validation.sequence(s, map(f)); } @@ -1474,7 +1707,7 @@ public final A maximum(final Ord o) { public final Option maximumOption(final Ord o) { return NonEmptyList.fromList(this).map(nel -> nel.maximum(o)); } - + /** * Returns the minimum element in this list according to the given ordering. * @@ -1484,7 +1717,7 @@ public final Option maximumOption(final Ord o) { public final A minimum(final Ord o) { return foldLeft1(o::min); } - + /** * Returns the minimum element in this list according to the given ordering. * diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 3b720fe6..ca7d0f22 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -1,16 +1,36 @@ package fj.data; -import fj.Equal; -import fj.P2; +import fj.*; +import fj.control.Trampoline; import org.junit.Test; +import java.io.IOException; import java.util.Arrays; +import static fj.Function.constant; +import static fj.Ord.*; +import static fj.P.*; +import static fj.Semigroup.listSemigroup; +import static fj.data.Either.*; +import static fj.data.List.sequenceEither; +import static fj.data.List.sequenceEitherLeft; +import static fj.data.List.sequenceEitherRight; +import static fj.data.List.sequenceF; +import static fj.data.List.sequenceIO; +import static fj.data.List.sequenceList; +import static fj.data.List.sequenceOption; +import static fj.data.List.sequenceP1; +import static fj.data.List.sequenceSeq; +import static fj.data.List.sequenceSet; +import static fj.data.List.sequenceStream; +import static fj.data.List.sequenceTrampoline; +import static fj.data.List.sequenceValidation; +import static fj.data.List.*; +import static fj.data.Option.*; +import static fj.data.Validation.fail; +import static fj.data.Validation.*; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * Created by MarkPerry on 16/01/2015. @@ -91,4 +111,190 @@ public void array() { assertThat(List.range(1, max + 1).array(Integer[].class), equalTo(ints)); } + @Test + public void testSequenceEither() { + assertEquals(right(nil()), sequenceEither(nil())); + assertEquals(right(single("zero")), sequenceEither(single(right("zero")))); + assertEquals(left("zero"), sequenceEither(single(left("zero")))); + } + + @Test + public void testSequenceEitherLeft() { + assertEquals(left(nil()), sequenceEitherLeft(nil())); + assertEquals(left(single("zero")), sequenceEitherLeft(single(left("zero")))); + assertEquals(right("zero"), sequenceEitherLeft(single(right("zero")))); + } + + @Test + public void testSequenceEitherRight() { + assertEquals(right(nil()), sequenceEitherRight(nil())); + assertEquals(right(single("zero")), sequenceEitherRight(single(right("zero")))); + assertEquals(left("zero"), sequenceEitherRight(single(left("zero")))); + } + + @Test + public void testSequenceF() { + assertEquals(constant(nil()).f(1), sequenceF(nil()).f(1)); + assertEquals(constant(single("zero")).f(1), sequenceF(single(constant("zero"))).f(1)); + } + + @Test + public void testSequenceIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(nil())).run(), sequenceIO(nil()).run()); + assertEquals(IOFunctions.lazy(constant(single("zero"))).run(), sequenceIO(single(IOFunctions.lazy(constant("zero")))).run()); + } + + @Test + public void testSequenceList() { + assertEquals(single(nil()), sequenceList(nil())); + assertEquals(List.nil(), sequenceList(single(nil()))); + assertEquals(single(single("zero")), sequenceList(single(single("zero")))); + assertEquals(List.arrayList(single("zero"), single("one")), sequenceList(single(arrayList("zero", "one")))); + } + + @Test + public void testSequenceOption() { + assertEquals(some(nil()), sequenceOption(nil())); + assertEquals(none(), sequenceOption(single(none()))); + assertEquals(some(single("zero")), sequenceOption(single(some("zero")))); + } + + @Test + public void testSequenceP1() { + assertEquals(p(nil()), sequenceP1(nil())); + assertEquals(p(single("zero")), sequenceP1(single(p("zero")))); + } + + @Test + public void testSequenceSeq() { + assertEquals(Seq.single(nil()), sequenceSeq(nil())); + assertEquals(Seq.empty(), sequenceSeq(single(Seq.empty()))); + assertEquals(Seq.single(single("zero")), sequenceSeq(single(Seq.single("zero")))); + assertEquals(Seq.arraySeq(single("zero"), single("one")), sequenceSeq(single(Seq.arraySeq("zero", "one")))); + } + + @Test + public void testSequenceSet() { + assertEquals(Set.arraySet(listOrd(stringOrd), nil()), sequenceSet(stringOrd, nil())); + assertEquals(Set.empty(listOrd(stringOrd)), sequenceSet(stringOrd, single(Set.empty(stringOrd)))); + assertEquals(Set.arraySet(listOrd(stringOrd), single("zero")), sequenceSet(stringOrd, single(Set.single(stringOrd, "zero")))); + assertEquals(Set.arraySet(listOrd(stringOrd), single("zero"), single("one")), sequenceSet(stringOrd, single(Set.arraySet(stringOrd, "zero", "one")))); + } + + @Test + public void testSequenceStream() { + assertEquals(Stream.single(nil()), sequenceStream(nil())); + assertEquals(Stream.nil(), sequenceStream(single(Stream.nil()))); + assertEquals(Stream.single(single("zero")), sequenceStream(single(Stream.single("zero")))); + assertEquals(Stream.arrayStream(single("zero"), single("one")), sequenceStream(single(Stream.arrayStream("zero", "one")))); + } + + @Test + public void testSequenceTrampoline() { + assertEquals(Trampoline.pure(nil()).run(), sequenceTrampoline(nil()).run()); + assertEquals(Trampoline.pure(single(0)).run(), sequenceTrampoline(single(Trampoline.pure(0))).run()); + } + + @Test + public void testSequenceValidation() { + assertEquals(Validation.success(nil()), sequenceValidation(listSemigroup(), nil())); + assertEquals(Validation.fail(single(0)), sequenceValidation(listSemigroup(), single(Validation.fail(single(0))))); + assertEquals(Validation.success(single(0)), sequenceValidation(listSemigroup(), single(Validation.success(0)))); + } + + @Test + public void testTraverseEitherLeft() { + assertEquals(left(nil()), nil().traverseEitherLeft(constant(left(0)))); + assertEquals(left(single(0)), single("zero").traverseEitherLeft(constant(left(0)))); + assertEquals(left(nil()), nil().traverseEitherLeft(constant(right(0)))); + assertEquals(right(0), single("zero").traverseEitherLeft(constant(right(0)))); + } + + @Test + public void testTraverseEitherRight() { + assertEquals(right(nil()), nil().traverseEitherRight(constant(right(0)))); + assertEquals(right(single(0)), single("zero").traverseEitherRight(constant(right(0)))); + assertEquals(right(nil()), nil().traverseEitherRight(constant(left(0)))); + assertEquals(left(0), single("zero").traverseEitherRight(constant(left(0)))); + } + + @Test + public void testTraverseF() { + assertEquals(constant(nil()).f(1), nil().traverseF(constant(constant(0))).f(1)); + assertEquals(constant(single(0)).f(1), single("zero").traverseF(constant(constant(0))).f(1)); + } + + @Test + public void testTraverseIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(nil())).run(), nil().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(IOFunctions.lazy(constant(single(0))).run(), single("zero").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseList() { + assertEquals(single(nil()), nil().traverseList(constant(List.nil()))); + assertEquals(List.nil(), single("zero").traverseList(constant(List.nil()))); + assertEquals(single(nil()), nil().traverseList(constant(single(0)))); + assertEquals(single(single(0)), single("zero").traverseList(constant(single(0)))); + assertEquals(single(nil()), nil().traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.arrayList(single(0), single(1)), single("zero").traverseList(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseOption() { + assertEquals(some(nil()), nil().traverseOption(constant(none()))); + assertEquals(none(), single("zero").traverseOption(constant(none()))); + assertEquals(some(nil()), nil().traverseOption(constant(some(0)))); + assertEquals(some(single(0)), single("zero").traverseOption(constant(some(0)))); + } + + @Test + public void testTraverseP1() { + assertEquals(p(nil()), nil().traverseP1(constant(p(0)))); + assertEquals(p(single(0)), single("zero").traverseP1(constant(p(0)))); + } + + @Test + public void testTraverseSeq() { + assertEquals(Seq.single(nil()), nil().traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.empty(), single("zero").traverseSeq(constant(Seq.empty()))); + assertEquals(Seq.single(nil()), nil().traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(single(0)), single("zero").traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(nil()), nil().traverseSeq(constant(Seq.arraySeq(0, 1)))); + assertEquals(Seq.arraySeq(single(0), single(1)), single("zero").traverseSeq(constant(Seq.arraySeq(0, 1)))); + } + + @Test + public void testTraverseSet() { + assertEquals(Set.arraySet(listOrd(intOrd), nil()), nil().traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.empty(listOrd(intOrd)), single("zero").traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.single(listOrd(intOrd), nil()), nil().traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(listOrd(intOrd), single(0)), single("zero").traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(listOrd(intOrd), nil()), nil().traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + assertEquals(Set.arraySet(listOrd(intOrd), single(0), single(1)), single("zero").traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.single(nil()), nil().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.nil(), single("zero").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(nil()), nil().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(single(0)), single("zero").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(nil()), nil().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.arrayStream(single(0), single(1)), single("zero").traverseStream(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testTraverseTrampoline() { + assertEquals(Trampoline.pure(nil()).run(), nil().traverseTrampoline(constant(Trampoline.pure(0))).run()); + assertEquals(Trampoline.pure(single(0)).run(), single("zero").traverseTrampoline(constant(Trampoline.pure(0))).run()); + } + + @Test + public void testTraverseValidation() { + assertEquals(success(nil()), nil().traverseValidation(listSemigroup(), constant(Validation.fail(single(0))))); + assertEquals(fail(single(0)), single("zero").traverseValidation(listSemigroup(), constant(Validation.fail(single(0))))); + assertEquals(success(nil()), nil().traverseValidation(listSemigroup(), constant(Validation.success(0)))); + assertEquals(success(single(0)), single("zero").traverseValidation(listSemigroup(), constant(Validation.success(0)))); + } } From 24779066804769cd93a7e4cc4236b44836e43074 Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Fri, 24 Jul 2020 23:39:07 -0400 Subject: [PATCH 750/811] Fixes #412. Add fj.data.Seq.sequence*, fj.data.Seq.traverse* functions. --- core/src/main/java/fj/Ord.java | 51 ++-- core/src/main/java/fj/data/Seq.java | 361 ++++++++++++++++++++++++ core/src/test/java/fj/data/SeqTest.java | 251 +++++++++++++++- 3 files changed, 638 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index 0a778f4d..eef729c4 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -1,23 +1,11 @@ package fj; -import fj.data.Array; -import fj.data.Either; -import fj.data.List; -import fj.data.Natural; -import fj.data.NonEmptyList; -import fj.data.Option; -import fj.data.Set; -import fj.data.Stream; -import fj.data.Validation; - -import java.math.BigDecimal; -import java.math.BigInteger; +import fj.data.*; + +import java.math.*; import java.util.Comparator; -import static fj.Function.apply; -import static fj.Function.compose; -import static fj.Function.curry; -import static fj.Semigroup.semigroup; +import static fj.Function.*; import static fj.Semigroup.semigroupDef; /** @@ -541,6 +529,37 @@ public static Ord> listOrd(final Ord oa) { }); } + /** + * Return a seq ord using the given value ord. + * + * @param ord the given value ord + * @param the type of the seq value + * @return the seq ord + */ + public static Ord> seqOrd(final Ord ord) { + return ordDef((l1, l2) -> { + Seq x1 = l1; + Seq x2 = l2; + + while (x1.isNotEmpty() && x2.isNotEmpty()) { + final Ordering o = ord.compare(x1.head(), x2.head()); + if (o == Ordering.LT || o == Ordering.GT) { + return o; + } + x1 = x1.tail(); + x2 = x2.tail(); + } + + if (x1.isEmpty() && x2.isEmpty()) { + return Ordering.EQ; + } else if (x1.isEmpty()) { + return Ordering.LT; + } else { + return Ordering.GT; + } + }); + } + /** * An order instance for the {@link NonEmptyList} type. * diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 1ded05eb..3bcb7033 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -1,13 +1,19 @@ package fj.data; import fj.*; +import fj.control.Trampoline; import fj.data.List.Buffer; import fj.data.fingertrees.*; import java.util.*; import static fj.Bottom.error; +import static fj.Function.*; import static fj.Monoid.intAdditionMonoid; +import static fj.P.p; +import static fj.data.Either.*; +import static fj.data.Option.some; +import static fj.data.Validation.success; import static fj.data.fingertrees.FingerTree.measured; /** @@ -403,4 +409,359 @@ public Seq bind(final F> f) { (element, accumulator) -> f.f(element).append(accumulator), empty()); } + + /** + * Sequence the given seq and collect the output on the right side of an either. + * + * @param seq the given seq + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static Either> sequenceEither(final Seq> seq) { + return seq.traverseEither(identity()); + } + + /** + * Sequence the given seq and collect the output on the left side of an either. + * + * @param seq the given seq + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static Either, R> sequenceEitherLeft(final Seq> seq) { + return seq.traverseEitherLeft(identity()); + } + + /** + * Sequence the given seq and collect the output on the right side of an either. + * + * @param seq the given seq + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static Either> sequenceEitherRight(final Seq> seq) { + return seq.traverseEitherRight(identity()); + } + + /** + * Sequence the given seq and collect the output as a function. + * + * @param seq the given seq + * @param the type of the input value + * @param the type of the output value + * @return the either + */ + public static F> sequenceF(final Seq> seq) { + return seq.traverseF(identity()); + } + + /** + * Sequence the given seq and collect the output as an IO. + * + * @param seq the given seq + * @param the type of the IO value + * @return the IO + */ + public static IO> sequenceIO(final Seq> seq) { + return seq.traverseIO(identity()); + } + + /** + * Sequence the given seq and collect the output as a list. + * + * @param seq the given seq + * @param the type of the seq value + * @return the list + */ + public static List> sequenceList(final Seq> seq) { + return seq.traverseList(identity()); + } + + /** + * Sequence the given seq and collect the output as an seq. + * + * @param seq the given seq + * @param the type of the seq value + * @return the seq + */ + public static Option> sequenceOption(final Seq> seq) { + return seq.traverseOption(identity()); + } + + /** + * Sequence the given seq and collect the output as a P1. + * + * @param seq the given seq + * @param the type of the P1 value + * @return the P1 + */ + public static P1> sequenceP1(final Seq> seq) { + return seq.traverseP1(identity()); + } + + /** + * Sequence the given seq and collect the output as a seq. + * + * @param seq the given seq + * @param the type of the seq value + * @return the seq + */ + public static Seq> sequenceSeq(final Seq> seq) { + return seq.traverseSeq(identity()); + } + + /** + * Sequence the given seq and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param seq the given seq + * @param the type of the set value + * @return the either + */ + public static Set> sequenceSet(final Ord ord, final Seq> seq) { + return seq.traverseSet(ord, identity()); + } + + /** + * Sequence the given seq and collect the output as a stream. + * + * @param seq the given seq + * @param the type of the stream value + * @return the stream + */ + public static Stream> sequenceStream(final Seq> seq) { + return seq.traverseStream(identity()); + } + + /** + * Sequence the given seq and collect the output as a trampoline. + * + * @param seq the given trampoline + * @param the type of the stream value + * @return the stream + */ + public static Trampoline> sequenceTrampoline(final Seq> seq) { + return seq.traverseTrampoline(identity()); + } + + /** + * Sequence the given seq and collect the output as a validation. + * + * @param seq the given seq + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static Validation> sequenceValidation(final Seq> seq) { + return seq.traverseValidation(identity()); + } + + /** + * Sequence the given seq and collect the output as a validation; use the given semigroup to reduce the errors. + * + * @param semigroup the given semigroup + * @param seq the given seq + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static Validation> sequenceValidation(final Semigroup semigroup, final Seq> seq) { + return seq.traverseValidation(semigroup, identity()); + } + + /** + * Traverse this seq with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public Either> traverseEither(final F> f) { + return traverseEitherRight(f); + } + + /** + * Traverse this seq with the given function and collect the output on the left side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public Either, R> traverseEitherLeft(final F> f) { + return foldRight( + (element, either) -> f.f(element).left().bind(elementInner -> either.left().map(seq -> seq.cons(elementInner))), + left(empty())); + } + + /** + * Traverse this seq with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public Either> traverseEitherRight(final F> f) { + return foldRight( + (element, either) -> f.f(element).right().bind(elementInner -> either.right().map(seq -> seq.cons(elementInner))), + right(empty())); + } + + /** + * Traverse this seq with the given function and collect the output as a function. + * + * @param f the given function + * @param the type of the input value + * @param the type of the output value + * @return the function + */ + public F> traverseF(final F> f) { + return foldRight( + (element, fInner) -> Function.bind(f.f(element), elementInner -> andThen(fInner, seq -> seq.cons(elementInner))), + constant(empty())); + } + + /** + * Traverse this seq with the given function and collect the output as an IO. + * + * @param f the given function + * @param the type of the IO value + * @return the IO + */ + public IO> traverseIO(final F> f) { + return foldRight( + (element, io) -> IOFunctions.bind(f.f(element), elementInner -> IOFunctions.map(io, seq -> seq.cons(elementInner))), + IOFunctions.unit(empty()) + ); + } + + /** + * Traverse this seq with the given function and collect the output as a list. + * + * @param f the given function + * @param the type of the list value + * @return the list + */ + public List> traverseList(final F> f) { + return foldRight( + (element, list) -> f.f(element).bind(elementInner -> list.map(seq -> seq.cons(elementInner))), + List.single(empty())); + } + + /** + * Traverses through the Seq with the given function + * + * @param f The function that produces Option value + * @return none if applying f returns none to any element of the seq or f mapped seq in some . + */ + public Option> traverseOption(final F> f) { + return foldRight( + (element, option) -> f.f(element).bind(elementInner -> option.map(seq -> seq.cons(elementInner))), + some(empty()) + ); + } + + /** + * Traverse this seq with the given function and collect the output as a p1. + * + * @param f the given function + * @param the type of the p1 value + * @return the p1 + */ + public P1> traverseP1(final F> f) { + return foldRight( + (element, p1) -> f.f(element).bind(elementInner -> p1.map(seq -> seq.cons(elementInner))), + p(empty()) + ); + } + + /** + * Traverse this seq with the given function and collect the output as a seq. + * + * @param f the given function + * @param the type of the seq value + * @return the seq + */ + public Seq> traverseSeq(final F> f) { + return foldRight( + (element, seq) -> f.f(element).bind(elementInner -> seq.map(seqInner -> seqInner.cons(elementInner))), + single(empty())); + } + + /** + * Traverse this seq with the given function and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param f the given function + * @param the type of the set value + * @return the set + */ + public Set> traverseSet(final Ord ord, final F> f) { + final Ord> seqOrd = Ord.seqOrd(ord); + return foldRight( + (element, set) -> f.f(element).bind(seqOrd, elementInner -> set.map(seqOrd, seq -> seq.cons(elementInner))), + Set.single(seqOrd, empty())); + } + + /** + * Traverse this seq with the given function and collect the output as a stream. + * + * @param f the given function + * @param the type of the stream value + * @return the stream + */ + public Stream> traverseStream(final F> f) { + return foldRight( + (element, stream) -> f.f(element).bind(elementInner -> stream.map(seq -> seq.cons(elementInner))), + Stream.single(empty())); + } + + /** + * Traverse this seq with the given function and collect the output as a trampoline. + * + * @param f the given function + * @param the type of the trampoline value + * @return the trampoline + */ + public Trampoline> traverseTrampoline(final F> f) { + return foldRight( + (element, trampoline) -> f.f(element).bind(elementInner -> trampoline.map(seq -> seq.cons(elementInner))), + Trampoline.pure(empty())); + } + + /** + * Traverse this seq with the given function and collect the output as a validation. + * + * @param f the given function + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public Validation> traverseValidation(final F> f) { + return foldRight( + (element, validation) -> f.f(element).bind(elementInner -> validation.map(seq -> seq.cons(elementInner))), + success(empty()) + ); + } + + /** + * Traverse this seq with the given function and collect the output as a validation; use the given semigroup to reduce the errors. + * + * @param semigroup the given semigroup + * @param f the given function + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public Validation> traverseValidation(final Semigroup semigroup, final F> f) { + return foldRight( + (element, validation) -> f.f(element).map(Seq::single).accumulate(semigroup, validation, Seq::append), + success(empty()) + ); + } } diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java index b19cb7d4..0b62db00 100644 --- a/core/src/test/java/fj/data/SeqTest.java +++ b/core/src/test/java/fj/data/SeqTest.java @@ -1,9 +1,34 @@ package fj.data; import fj.P2; +import fj.control.Trampoline; import org.junit.Test; +import java.io.IOException; + import static fj.Function.constant; +import static fj.Ord.*; +import static fj.P.p; +import static fj.Semigroup.listSemigroup; +import static fj.data.Either.*; +import static fj.data.List.arrayList; +import static fj.data.Option.*; +import static fj.data.Seq.sequenceEither; +import static fj.data.Seq.sequenceEitherLeft; +import static fj.data.Seq.sequenceEitherRight; +import static fj.data.Seq.sequenceF; +import static fj.data.Seq.sequenceIO; +import static fj.data.Seq.sequenceList; +import static fj.data.Seq.sequenceOption; +import static fj.data.Seq.sequenceP1; +import static fj.data.Seq.sequenceSeq; +import static fj.data.Seq.sequenceSet; +import static fj.data.Seq.sequenceStream; +import static fj.data.Seq.sequenceTrampoline; +import static fj.data.Seq.sequenceValidation; +import static fj.data.Seq.*; +import static fj.data.Validation.fail; +import static fj.data.Validation.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; @@ -47,14 +72,222 @@ public void test() { @Test public void testBind() { - assertEquals(Seq.empty(), Seq.empty().bind(constant(Seq.empty()))); - assertEquals(Seq.empty(), Seq.empty().bind(constant(Seq.single(0)))); - assertEquals(Seq.empty(), Seq.empty().bind(constant(Seq.arraySeq(0, 1)))); - assertEquals(Seq.empty(), Seq.single("zero").bind(constant(Seq.empty()))); - assertEquals(Seq.single(0), Seq.single("zero").bind(constant(Seq.single(0)))); - assertEquals(Seq.arraySeq(0, 1), Seq.single("zero").bind(constant(Seq.arraySeq(0, 1)))); - assertEquals(Seq.empty(), Seq.arraySeq("zero", "one").bind(constant(Seq.empty()))); - assertEquals(Seq.arraySeq(0, 0), Seq.arraySeq("zero", "one").bind(constant(Seq.single(0)))); - assertEquals(Seq.arraySeq(0, 1, 0, 1), Seq.arraySeq("zero", "one").bind(constant(Seq.arraySeq(0, 1)))); + assertEquals(empty(), empty().bind(constant(empty()))); + assertEquals(empty(), empty().bind(constant(single(0)))); + assertEquals(empty(), empty().bind(constant(arraySeq(0, 1)))); + assertEquals(empty(), single("zero").bind(constant(empty()))); + assertEquals(single(0), single("zero").bind(constant(single(0)))); + assertEquals(arraySeq(0, 1), single("zero").bind(constant(arraySeq(0, 1)))); + assertEquals(empty(), arraySeq("zero", "one").bind(constant(empty()))); + assertEquals(arraySeq(0, 0), arraySeq("zero", "one").bind(constant(single(0)))); + assertEquals(arraySeq(0, 1, 0, 1), arraySeq("zero", "one").bind(constant(arraySeq(0, 1)))); + } + + @Test + public void testSequenceEither() { + assertEquals(right(empty()), sequenceEither(empty())); + assertEquals(right(single("zero")), sequenceEither(single(right("zero")))); + assertEquals(left("zero"), sequenceEither(single(left("zero")))); + } + + @Test + public void testSequenceEitherLeft() { + assertEquals(left(empty()), sequenceEitherLeft(empty())); + assertEquals(left(single("zero")), sequenceEitherLeft(single(left("zero")))); + assertEquals(right("zero"), sequenceEitherLeft(single(right("zero")))); + } + + @Test + public void testSequenceEitherRight() { + assertEquals(right(empty()), sequenceEitherRight(empty())); + assertEquals(right(single("zero")), sequenceEitherRight(single(right("zero")))); + assertEquals(left("zero"), sequenceEitherRight(single(left("zero")))); + } + + @Test + public void testSequenceF() { + assertEquals(constant(empty()).f(1), sequenceF(empty()).f(1)); + assertEquals(constant(single("zero")).f(1), sequenceF(single(constant("zero"))).f(1)); + } + + @Test + public void testSequenceIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(empty())).run(), sequenceIO(empty()).run()); + assertEquals(IOFunctions.lazy(constant(single("zero"))).run(), sequenceIO(single(IOFunctions.lazy(constant("zero")))).run()); + } + + @Test + public void testSequenceList() { + assertEquals(List.single(empty()), sequenceList(empty())); + assertEquals(List.nil(), sequenceList(single(List.nil()))); + assertEquals(List.single(single("zero")), sequenceList(single(List.single("zero")))); + assertEquals(arrayList(single("zero"), single("one")), sequenceList(single(arrayList("zero", "one")))); + } + + @Test + public void testSequenceOption() { + assertEquals(some(empty()), sequenceOption(empty())); + assertEquals(none(), sequenceOption(single(none()))); + assertEquals(some(single("zero")), sequenceOption(single(some("zero")))); + } + + @Test + public void testSequenceP1() { + assertEquals(p(empty()), sequenceP1(empty())); + assertEquals(p(single("zero")), sequenceP1(single(p("zero")))); + } + + @Test + public void testSequenceSeq() { + assertEquals(single(empty()), sequenceSeq(empty())); + assertEquals(empty(), sequenceSeq(single(empty()))); + assertEquals(single(single("zero")), sequenceSeq(single(single("zero")))); + assertEquals(arraySeq(single("zero"), single("one")), sequenceSeq(single(arraySeq("zero", "one")))); + } + + @Test + public void testSequenceSet() { + assertEquals(Set.arraySet(seqOrd(stringOrd), empty()), sequenceSet(stringOrd, empty())); + assertEquals(Set.empty(seqOrd(stringOrd)), sequenceSet(stringOrd, single(Set.empty(stringOrd)))); + assertEquals(Set.arraySet(seqOrd(stringOrd), single("zero")), sequenceSet(stringOrd, single(Set.single(stringOrd, "zero")))); + assertEquals(Set.arraySet(seqOrd(stringOrd), single("zero"), single("one")), sequenceSet(stringOrd, single(Set.arraySet(stringOrd, "zero", "one")))); + } + + @Test + public void testSequenceStream() { + assertEquals(Stream.single(empty()), sequenceStream(empty())); + assertEquals(Stream.nil(), sequenceStream(single(Stream.nil()))); + assertEquals(Stream.single(single("zero")), sequenceStream(single(Stream.single("zero")))); + assertEquals(Stream.arrayStream(single("zero"), single("one")), sequenceStream(single(Stream.arrayStream("zero", "one")))); + } + + @Test + public void testSequenceTrampoline() { + assertEquals(Trampoline.pure(empty()).run(), sequenceTrampoline(empty()).run()); + assertEquals(Trampoline.pure(single(0)).run(), sequenceTrampoline(single(Trampoline.pure(0))).run()); + } + + @Test + public void testSequenceValidation() { + assertEquals(success(empty()), sequenceValidation(empty())); + assertEquals(fail(single(0)), sequenceValidation(single(fail(single(0))))); + assertEquals(success(single(0)), sequenceValidation(single(success(0)))); + } + + @Test + public void testSequenceValidationSemigroup() { + assertEquals(success(empty()), sequenceValidation(listSemigroup(), empty())); + assertEquals(fail(List.single(0)), sequenceValidation(listSemigroup(), single(fail(List.single(0))))); + assertEquals(success(single(0)), sequenceValidation(listSemigroup(), single(success(0)))); + } + + @Test + public void testTraverseEitherLeft() { + assertEquals(left(empty()), empty().traverseEitherLeft(constant(left(0)))); + assertEquals(left(single(0)), single("zero").traverseEitherLeft(constant(left(0)))); + assertEquals(left(empty()), empty().traverseEitherLeft(constant(right(0)))); + assertEquals(right(0), single("zero").traverseEitherLeft(constant(right(0)))); + } + + @Test + public void testTraverseEitherRight() { + assertEquals(right(empty()), empty().traverseEitherRight(constant(right(0)))); + assertEquals(right(single(0)), single("zero").traverseEitherRight(constant(right(0)))); + assertEquals(right(empty()), empty().traverseEitherRight(constant(left(0)))); + assertEquals(left(0), single("zero").traverseEitherRight(constant(left(0)))); + } + + @Test + public void testTraverseF() { + assertEquals(constant(empty()).f(1), empty().traverseF(constant(constant(0))).f(1)); + assertEquals(constant(single(0)).f(1), single("zero").traverseF(constant(constant(0))).f(1)); + } + + @Test + public void testTraverseIO() throws IOException { + assertEquals(IOFunctions.lazy(constant(empty())).run(), empty().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(IOFunctions.lazy(constant(single(0))).run(), single("zero").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseList() { + assertEquals(List.single(empty()), empty().traverseList(constant(List.nil()))); + assertEquals(List.nil(), single("zero").traverseList(constant(List.nil()))); + assertEquals(List.single(empty()), empty().traverseList(constant(List.single(0)))); + assertEquals(List.single(single(0)), single("zero").traverseList(constant(List.single(0)))); + assertEquals(List.single(empty()), empty().traverseList(constant(arrayList(0, 1)))); + assertEquals(arrayList(single(0), single(1)), single("zero").traverseList(constant(arrayList(0, 1)))); + } + + @Test + public void testTraverseOption() { + assertEquals(some(empty()), empty().traverseOption(constant(none()))); + assertEquals(none(), single("zero").traverseOption(constant(none()))); + assertEquals(some(empty()), empty().traverseOption(constant(some(0)))); + assertEquals(some(single(0)), single("zero").traverseOption(constant(some(0)))); + } + + @Test + public void testTraverseP1() { + assertEquals(p(empty()), empty().traverseP1(constant(p(0)))); + assertEquals(p(single(0)), single("zero").traverseP1(constant(p(0)))); + } + + @Test + public void testTraverseSeq() { + assertEquals(single(empty()), empty().traverseSeq(constant(empty()))); + assertEquals(empty(), single("zero").traverseSeq(constant(empty()))); + assertEquals(single(empty()), empty().traverseSeq(constant(single(0)))); + assertEquals(single(single(0)), single("zero").traverseSeq(constant(single(0)))); + assertEquals(single(empty()), empty().traverseSeq(constant(arraySeq(0, 1)))); + assertEquals(arraySeq(single(0), single(1)), single("zero").traverseSeq(constant(arraySeq(0, 1)))); + } + + @Test + public void testTraverseSet() { + assertEquals(Set.arraySet(seqOrd(intOrd), empty()), empty().traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.empty(seqOrd(intOrd)), single("zero").traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.single(seqOrd(intOrd), empty()), empty().traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(seqOrd(intOrd), single(0)), single("zero").traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(seqOrd(intOrd), empty()), empty().traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + assertEquals(Set.arraySet(seqOrd(intOrd), single(0), single(1)), single("zero").traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.single(empty()), empty().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.nil(), single("zero").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(empty()), empty().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(single(0)), single("zero").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(empty()), empty().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.arrayStream(single(0), single(1)), single("zero").traverseStream(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testTraverseTrampoline() { + assertEquals(Trampoline.pure(empty()).run(), empty().traverseTrampoline(constant(Trampoline.pure(0))).run()); + assertEquals(Trampoline.pure(single(0)).run(), single("zero").traverseTrampoline(constant(Trampoline.pure(0))).run()); + } + + @Test + public void testTraverseValidation() { + assertEquals(success(empty()), empty().traverseValidation(constant(fail(single(0))))); + assertEquals(fail(single(0)), single("zero").traverseValidation(constant(fail(single(0))))); + assertEquals(success(empty()), empty().traverseValidation(constant(success(0)))); + assertEquals(success(single(0)), single("zero").traverseValidation(constant(success(0)))); + + assertEquals(success(arraySeq(0, 2, 4, 6, 8)), arraySeq(0, 2, 4, 6, 8).traverseValidation(i -> condition(i% 2 == 0, List.single(i), i))); + assertEquals(fail(List.single(1)), arraySeq(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).traverseValidation(i -> condition(i% 2 == 0, List.single(i), i))); + } + + @Test + public void testTraverseValidationSemigroup() { + assertEquals(success(empty()), empty().traverseValidation(listSemigroup(), constant(fail(List.single(0))))); + assertEquals(fail(List.single(0)), single("zero").traverseValidation(listSemigroup(), constant(fail(List.single(0))))); + assertEquals(success(empty()), empty().traverseValidation(listSemigroup(), constant(success(0)))); + assertEquals(success(single(0)), single("zero").traverseValidation(listSemigroup(), constant(success(0)))); + + assertEquals(success(arraySeq(0, 2, 4, 6, 8)), arraySeq(0, 2, 4, 6, 8).traverseValidation(listSemigroup(),i -> condition(i% 2 == 0, List.single(i), i))); + assertEquals(fail(arrayList(1, 3, 5, 7, 9)), arraySeq(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).traverseValidation(listSemigroup(),i -> condition(i% 2 == 0, List.single(i), i))); } } From 3bce5e0b885b87d94396d7f1cd6fb889958c0e8c Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Wed, 29 Jul 2020 14:17:37 -0400 Subject: [PATCH 751/811] Fixes #414. Add fj.data.Either.leftMap, rightMap. Also adds LeftProjection.traverseP1, RightProjection.valueE(String), RightProjection.orValue. --- core/src/main/java/fj/data/Either.java | 101 +++- core/src/test/java/fj/data/EitherTest.java | 653 +++++++++++++++++++++ 2 files changed, 739 insertions(+), 15 deletions(-) create mode 100644 core/src/test/java/fj/data/EitherTest.java diff --git a/core/src/main/java/fj/data/Either.java b/core/src/main/java/fj/data/Either.java index a9a746a9..c132ec49 100644 --- a/core/src/main/java/fj/data/Either.java +++ b/core/src/main/java/fj/data/Either.java @@ -1,27 +1,16 @@ package fj.data; -import fj.Equal; -import fj.F; -import fj.F0; -import fj.Function; -import fj.Hash; -import fj.P1; -import fj.Show; -import fj.Unit; +import fj.*; import fj.function.Effect1; -import java.util.Collection; -import java.util.Iterator; +import java.util.*; import static fj.Bottom.error; -import static fj.Function.compose; -import static fj.Function.identity; +import static fj.Function.*; import static fj.P.p; import static fj.Unit.unit; import static fj.data.Array.mkArray; -import static fj.data.List.cons_; -import static fj.data.List.list; -import static fj.data.List.single; +import static fj.data.List.*; import static fj.data.Option.some; /** @@ -321,6 +310,19 @@ public IO> traverseIO(final F> f) { IOFunctions.unit(Either.right(e.right().value())); } + /** + * Traverse this left with the given function and collect the output as a p1. + * + * @param f the given function + * @param the type of the p1 value + * @return the p1 + */ + public P1> traverseP1(final F> f) { + return e.isLeft() ? + f.f(value()).map(left_()) : + p(right(e.right().value())); + } + /** * Returns None if this projection has no value or if the given predicate * p does not hold for the value, otherwise, returns a right in Some. @@ -464,6 +466,16 @@ public Either either() { return e; } + /** + * Returns the value of this projection or fails with the given error message. + * + * @param err The error message to fail with. + * @return The value of this projection + */ + public B valueE(final String err) { + return valueE(p(err)); + } + /** * Returns the value of this projection or fails with the given error message. * @@ -487,6 +499,16 @@ public B value() { return valueE(p("right.value on Left")); } + /** + * The value of this projection or the given argument. + * + * @param a The value to return if this projection has no value. + * @return The value of this projection or the given argument. + */ + public B orValue(final B a) { + return e.isRight() ? value() : a; + } + /** * The value of this projection or the given argument. * @@ -586,12 +608,26 @@ public IO> traverseIO(final F> f) { IOFunctions.lazy(() -> left(e.left().value())); } + /** + * Traverse this right with the given function and collect the output as a p1. + * + * @param f the given function + * @param the type of the p1 value + * @return the p1 + */ public P1> traverseP1(final F> f) { return e.isRight() ? f.f(value()).map(right_()) : p(left(e.left().value())); } + /** + * Traverse this right with the given function and collect the output as an option. + * + * @param f the given function + * @param the type of the option value + * @return the option + */ public Option> traverseOption(final F> f) { return e.isRight() ? f.f(value()).map(right_()) : @@ -758,6 +794,22 @@ public static F, X> either_(final F left, final F the type of the function output + * @return the either + */ + public final Either leftMap(final F f) { + return left().map(f); + } + + /** + * Return a function that maps a given function across this either's left projection. + * + * @param the type of the right value + * @param the type of the left value + * @param the type of the function output * @return A function that maps another function across an either's left projection. */ public static F, F, Either>> leftMap_() { @@ -765,6 +817,22 @@ public static F, F, Either>> leftMap_() { } /** + * Map the given function across this either's right. + * + * @param f the given function + * @param the type of the function output + * @return the either + */ + public final Either rightMap(final F f) { + return right().map(f); + } + + /** + * Return a function that maps a given function across this either's right projection. + * + * @param the type of the right value + * @param the type of the left value + * @param the type of the function output * @return A function that maps another function across an either's right projection. */ public static F, F, Either>> rightMap_() { @@ -796,6 +864,7 @@ public static Either joinRight(final Either> e) { * * @param a The list of values to sequence with the either monad. * @return A sequenced value. + * @see fj.data.List#sequenceEitherLeft */ public static Either, X> sequenceLeft(final List> a) { return a.isEmpty() ? @@ -808,6 +877,8 @@ public static Either, X> sequenceLeft(final List> a) * * @param a The list of values to sequence with the either monad. * @return A sequenced value. + * @see fj.data.List#sequenceEither + * @see fj.data.List#sequenceEitherRight */ public static Either> sequenceRight(final List> a) { return a.isEmpty() ? diff --git a/core/src/test/java/fj/data/EitherTest.java b/core/src/test/java/fj/data/EitherTest.java new file mode 100644 index 00000000..31a83347 --- /dev/null +++ b/core/src/test/java/fj/data/EitherTest.java @@ -0,0 +1,653 @@ +package fj.data; + +import org.junit.Test; + +import java.io.IOException; + +import static fj.Function.constant; +import static fj.P.p; +import static fj.Unit.unit; +import static fj.data.Either.*; +import static org.junit.Assert.*; + +public final class EitherTest { + + public static final class LeftProjectionTest { + @Test + public void testIterator() { + assertEquals(0L, (long) left(0L).left().iterator().next()); + assertFalse(right(0).left().iterator().hasNext()); + } + + @Test + public void testEither() { + assertEquals(left(0), left(0).left().either()); + assertEquals(right(0), right(0).left().either()); + } + + @Test + public void testValueEString() { + assertEquals(0L, (long) left(0L).left().valueE("zero")); + + try { + right(0L).left().valueE("zero"); + fail(); + } catch (final Error error) { + assertEquals("zero", error.getMessage()); + } + } + + @Test + public void testValueEF0() { + assertEquals(0L, (long) left(0L).left().valueE(() -> "zero")); + + try { + right(0L).left().valueE(() -> "zero"); + fail(); + } catch (final Error error) { + assertEquals("zero", error.getMessage()); + } + } + + @Test + public void testValue() { + assertEquals(0L, (long) left(0L).left().value()); + + try { + right(0L).left().value(); + fail(); + } catch (final Error error) { + // pass + } + } + + @Test + public void testOrValue() { + assertEquals(0L, (long) left(0L).left().orValue(1L)); + assertEquals(1L, (long) right(0L).left().orValue(1L)); + } + + @Test + public void testOrValueF0() { + assertEquals(0L, (long) left(0L).left().orValue(() -> 1L)); + assertEquals(1L, (long) right(0L).left().orValue(() -> 1L)); + } + + @Test + public void testOn() { + assertEquals(0L, (long) Either.left(0L).left().on(constant(1L))); + assertEquals(1L, (long) Either.right(0L).left().on(constant(1L))); + } + + @Test + public void testForeach() { + left(0).left().foreach(constant(unit())); + right(0).left().foreach(ignore -> { + fail(); + return unit(); + }); + } + + @Test + public void testForeachDoEffect() { + left(0).left().foreachDoEffect(ignore -> { + }); + right(0).left().foreachDoEffect(ignore -> fail()); + } + + @Test + public void testMap() { + assertEquals(left(0), left("zero").left().map(constant(0))); + assertEquals(right("zero"), right("zero").left().map(constant(0))); + } + + @Test + public void testBind() { + assertEquals(left(0), left("zero").left().bind(constant(left(0)))); + assertEquals(right("zero"), right("zero").left().bind(constant(left(0)))); + } + + @Test + public void testSequence() { + assertEquals(left(0), left("zero").left().sequence(left(0))); + assertEquals(right(0), left("zero").left().sequence(right(0))); + assertEquals(right("zero"), right("zero").left().sequence(left(0))); + assertEquals(right("zero"), right("zero").left().sequence(right("one"))); + } + + @Test + public void testTraverseList() { + assertEquals(List.nil(), left("zero").left().traverseList(constant(List.nil()))); + assertEquals(List.single(left(0)), left("zero").left().traverseList(constant(List.single(0)))); + assertEquals(List.arrayList(left(0), left(1)), left("zero").left().traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.single(right("zero")), right("zero").left().traverseList(constant(List.nil()))); + assertEquals(List.single(right("zero")), right("zero").left().traverseList(constant(List.single(0)))); + assertEquals(List.single(right("zero")), right("zero").left().traverseList(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseIO() throws IOException { + assertEquals(left(0), left("zero").left().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(right("zero"), right("zero").left().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseP1() { + assertEquals(p(left(0)), left("zero").left().traverseP1(constant(p(0)))); + assertEquals(p(right("zero")), right("zero").left().traverseP1(constant(p(0)))); + } + + @Test + public void testFilter() { + assertEquals(Option.none(), left(0).left().filter(constant(false))); + assertEquals(Option.none(), right(0).left().filter(constant(false))); + assertEquals(Option.some(left(0)), left(0).left().filter(constant(true))); + assertEquals(Option.none(), right(0).left().filter(constant(true))); + } + + @Test + public void testApply() { + assertEquals(left(1), left("zero").left().apply(left(constant(1)))); + assertEquals(right("zero"), right("zero").left().apply(left(constant(1)))); + } + + @Test + public void testForAll() { + assertFalse(left(0).left().forall(constant(false))); + assertTrue(right(0).left().forall(constant(false))); + assertTrue(left(0).left().forall(constant(true))); + assertTrue(right(0).left().forall(constant(true))); + } + + @Test + public void testExists() { + assertFalse(left(0).left().exists(constant(false))); + assertFalse(right(0).left().exists(constant(false))); + assertTrue(left(0).left().exists(constant(true))); + assertFalse(right(0).left().exists(constant(true))); + } + + @Test + public void testToList() { + assertEquals(List.single(0), left(0).left().toList()); + assertEquals(List.nil(), right(0).left().toList()); + } + + @Test + public void testToOption() { + assertEquals(Option.some(0), left(0).left().toOption()); + assertEquals(Option.none(), right(0).left().toOption()); + } + + @Test + public void testToArray() { + assertEquals(Array.single(0), left(0).left().toArray()); + assertEquals(Array.empty(), right(0).left().toArray()); + } + + @Test + public void testToStream() { + assertEquals(Stream.single(0), left(0).left().toStream()); + assertEquals(Stream.nil(), right(0).left().toStream()); + } + + @Test + public void testToCollection() { + assertEquals(1L, left(0L).left().toCollection().size()); + assertEquals(0L, (long) left(0L).left().toCollection().iterator().next()); + assertTrue(right(0).left().toCollection().isEmpty()); + } + + @Test + public void testTraverseOption() { + assertEquals(Option.none(), left("zero").left().traverseOption(constant(Option.none()))); + assertEquals(Option.some(left(0)), left("zero").left().traverseOption(constant(Option.some(0)))); + assertEquals(Option.some(right("zero")), right("zero").left().traverseOption(constant(Option.none()))); + assertEquals(Option.some(right("zero")), right("zero").left().traverseOption(constant(Option.some(0)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.nil(), left("zero").left().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(left(0)), left("zero").left().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.arrayStream(left(0), left(1)), left("zero").left().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.single(right("zero")), right("zero").left().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(right("zero")), right("zero").left().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(right("zero")), right("zero").left().traverseStream(constant(Stream.arrayStream(0, 1)))); + } + } + + public static final class RightProjectionTest { + @Test + public void testIterator() { + assertEquals(0L, (long) right(0L).right().iterator().next()); + assertFalse(left(0).right().iterator().hasNext()); + } + + @Test + public void testEither() { + assertEquals(right(0), right(0).right().either()); + assertEquals(left(0), left(0).right().either()); + } + + @Test + public void testValueEString() { + assertEquals(0L, (long) right(0L).right().valueE("zero")); + + try { + left(0L).right().valueE("zero"); + fail(); + } catch (final Error error) { + assertEquals("zero", error.getMessage()); + } + } + + @Test + public void testValueEF0() { + assertEquals(0L, (long) right(0L).right().valueE(() -> "zero")); + + try { + left(0L).right().valueE(() -> "zero"); + fail(); + } catch (final Error error) { + assertEquals("zero", error.getMessage()); + } + } + + @Test + public void testValue() { + assertEquals(0L, (long) right(0L).right().value()); + + try { + left(0L).right().value(); + fail(); + } catch (final Error error) { + // pass + } + } + + @Test + public void testOrValue() { + assertEquals(0L, (long) right(0L).right().orValue(1L)); + assertEquals(1L, (long) left(0L).right().orValue(1L)); + } + + @Test + public void testOrValueF0() { + assertEquals(0L, (long) right(0L).right().orValue(() -> 1L)); + assertEquals(1L, (long) left(0L).right().orValue(() -> 1L)); + } + + @Test + public void testOn() { + assertEquals(0L, (long) Either.right(0L).right().on(constant(1L))); + assertEquals(1L, (long) Either.left(0L).right().on(constant(1L))); + } + + @Test + public void testForeach() { + right(0).right().foreach(constant(unit())); + left(0).right().foreach(ignore -> { + fail(); + return unit(); + }); + } + + @Test + public void testForeachDoEffect() { + right(0).right().foreachDoEffect(ignore -> { + }); + left(0).right().foreachDoEffect(ignore -> fail()); + } + + @Test + public void testMap() { + assertEquals(right(0), right("zero").right().map(constant(0))); + assertEquals(left("zero"), left("zero").right().map(constant(0))); + } + + @Test + public void testBind() { + assertEquals(right(0), right("zero").right().bind(constant(right(0)))); + assertEquals(left("zero"), left("zero").right().bind(constant(right(0)))); + } + + @Test + public void testSequence() { + assertEquals(right(0), right("zero").right().sequence(right(0))); + assertEquals(left(0), right("zero").right().sequence(left(0))); + assertEquals(left("zero"), left("zero").right().sequence(right(0))); + assertEquals(left("zero"), left("zero").right().sequence(left("one"))); + } + + @Test + public void testTraverseList() { + assertEquals(List.nil(), right("zero").right().traverseList(constant(List.nil()))); + assertEquals(List.single(right(0)), right("zero").right().traverseList(constant(List.single(0)))); + assertEquals(List.arrayList(right(0), right(1)), right("zero").right().traverseList(constant(List.arrayList(0, 1)))); + assertEquals(List.single(left("zero")), left("zero").right().traverseList(constant(List.nil()))); + assertEquals(List.single(left("zero")), left("zero").right().traverseList(constant(List.single(0)))); + assertEquals(List.single(left("zero")), left("zero").right().traverseList(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseIO() throws IOException { + assertEquals(right(0), right("zero").right().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(left("zero"), left("zero").right().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseP1() { + assertEquals(p(right(0)), right("zero").right().traverseP1(constant(p(0)))); + assertEquals(p(left("zero")), left("zero").right().traverseP1(constant(p(0)))); + } + + @Test + public void testFilter() { + assertEquals(Option.none(), right(0).right().filter(constant(false))); + assertEquals(Option.none(), left(0).right().filter(constant(false))); + assertEquals(Option.some(right(0)), right(0).right().filter(constant(true))); + assertEquals(Option.none(), left(0).right().filter(constant(true))); + } + + @Test + public void testApply() { + assertEquals(right(1), right("zero").right().apply(right(constant(1)))); + assertEquals(left("zero"), left("zero").right().apply(right(constant(1)))); + } + + @Test + public void testForAll() { + assertFalse(right(0).right().forall(constant(false))); + assertTrue(left(0).right().forall(constant(false))); + assertTrue(right(0).right().forall(constant(true))); + assertTrue(left(0).right().forall(constant(true))); + } + + @Test + public void testExists() { + assertFalse(right(0).right().exists(constant(false))); + assertFalse(left(0).right().exists(constant(false))); + assertTrue(right(0).right().exists(constant(true))); + assertFalse(left(0).right().exists(constant(true))); + } + + @Test + public void testToList() { + assertEquals(List.single(0), right(0).right().toList()); + assertEquals(List.nil(), left(0).right().toList()); + } + + @Test + public void testToOption() { + assertEquals(Option.some(0), right(0).right().toOption()); + assertEquals(Option.none(), left(0).right().toOption()); + } + + @Test + public void testToArray() { + assertEquals(Array.single(0), right(0).right().toArray()); + assertEquals(Array.empty(), left(0).right().toArray()); + } + + @Test + public void testToStream() { + assertEquals(Stream.single(0), right(0).right().toStream()); + assertEquals(Stream.nil(), left(0).right().toStream()); + } + + @Test + public void testToCollection() { + assertEquals(1L, right(0L).right().toCollection().size()); + assertEquals(0L, (long) right(0L).right().toCollection().iterator().next()); + assertTrue(left(0).right().toCollection().isEmpty()); + } + + @Test + public void testTraverseOption() { + assertEquals(Option.none(), right("zero").right().traverseOption(constant(Option.none()))); + assertEquals(Option.some(right(0)), right("zero").right().traverseOption(constant(Option.some(0)))); + assertEquals(Option.some(left("zero")), left("zero").right().traverseOption(constant(Option.none()))); + assertEquals(Option.some(left("zero")), left("zero").right().traverseOption(constant(Option.some(0)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.nil(), right("zero").right().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(right(0)), right("zero").right().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.arrayStream(right(0), right(1)), right("zero").right().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.single(left("zero")), left("zero").right().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(left("zero")), left("zero").right().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(left("zero")), left("zero").right().traverseStream(constant(Stream.arrayStream(0, 1)))); + } + } + + @Test + public void testIsLeft() { + assertTrue(left(0).isLeft()); + assertFalse(right(0).isLeft()); + } + + @Test + public void testIsRight() { + assertFalse(left(0).isRight()); + assertTrue(right(0).isRight()); + } + + @Test + public void testEither() { + assertEquals(-1L, (long) left("zero").either(constant(-1L), constant(1L))); + assertEquals(1L, (long) right("zero").either(constant(-1L), constant(1L))); + } + + @Test + public void testBimap() { + assertEquals(left(-1), left("zero").bimap(constant(-1), constant(1))); + assertEquals(right(1), right("zero").bimap(constant(-1), constant(1))); + } + + @Test + public void testTestEquals() { + assertNotEquals(null, left(0)); + assertNotEquals(new Object(), left(0)); + assertNotEquals(left(0), right(0)); + assertEquals(left(0), left(0)); + + assertNotEquals(null, right(0)); + assertNotEquals(new Object(), right(0)); + assertEquals(right(0), right(0)); + assertNotEquals(right(0), left(0)); + } + + @Test + public void testTestHashCode() { + assertEquals(left(0).hashCode(), left(0).hashCode()); + assertEquals(left(0).hashCode(), right(0).hashCode()); + assertEquals(right(0).hashCode(), left(0).hashCode()); + assertEquals(right(0).hashCode(), left(0).hashCode()); + } + + @Test + public void testSwap() { + assertEquals(right(0), left(0).swap()); + assertEquals(left(0), right(0).swap()); + } + + @Test + public void testLeft_() { + assertEquals(left(0), left_().f(0)); + } + + @Test + public void testRight_() { + assertEquals(right(0), right_().f(0)); + } + + @Test + public void testEither_() { + assertEquals(-1L, (long) either_(constant(-1L), constant(1L)).f(left("zero"))); + assertEquals(1L, (long) either_(constant(-1L), constant(1L)).f(right("zero"))); + } + + @Test + public void testLeftMap() { + assertEquals(left(0), left("zero").leftMap(constant(0))); + assertEquals(right("zero"), right("zero").leftMap(constant(0))); + } + + @Test + public void testLeftMap_() { + assertEquals(left(0), leftMap_().f(constant(0)).f(left("zero"))); + assertEquals(right("zero"), leftMap_().f(constant(0)).f(right("zero"))); + } + + @Test + public void testRightMap() { + assertEquals(left("zero"), left("zero").rightMap(constant(0))); + assertEquals(right(0), right("zero").rightMap(constant(0))); + } + + @Test + public void testRightMap_() { + assertEquals(left("zero"), rightMap_().f(constant(0)).f(left("zero"))); + assertEquals(right(0), rightMap_().f(constant(0)).f(right("zero"))); + } + + @Test + public void testJoinLeft() { + assertEquals(left(0), joinLeft(left(left(0)))); + assertEquals(right(0), joinLeft(left(right(0)))); + assertEquals(right(left(0)), joinLeft(right(left(0)))); + assertEquals(right(right(0)), joinLeft(right(right(0)))); + } + + @Test + public void testJoinRight() { + assertEquals(left(left(0)), joinRight(left(left(0)))); + assertEquals(left(right(0)), joinRight(left(right(0)))); + assertEquals(left(0), joinRight(right(left(0)))); + assertEquals(right(0), joinRight(right(right(0)))); + } + + @Test + public void testSequenceLeft() { + assertEquals(left(List.nil()), sequenceLeft(List.nil())); + assertEquals(left(List.single("zero")), sequenceLeft(List.single(left("zero")))); + assertEquals(right("zero"), sequenceLeft(List.single(right("zero")))); + } + + @Test + public void testSequenceRight() { + assertEquals(right(List.nil()), sequenceRight(List.nil())); + assertEquals(right(List.single("zero")), sequenceRight(List.single(right("zero")))); + assertEquals(left("zero"), sequenceRight(List.single(left("zero")))); + } + + @Test + public void testTraverseListRight() { + assertEquals(List.single(left("zero")), left("zero").traverseListRight(constant(List.nil()))); + assertEquals(List.single(left("zero")), left("zero").traverseListRight(constant(List.single(0)))); + assertEquals(List.single(left("zero")), left("zero").traverseListRight(constant(List.arrayList(0, 1)))); + assertEquals(List.nil(), right("zero").traverseListRight(constant(List.nil()))); + assertEquals(List.single(right(0)), right("zero").traverseListRight(constant(List.single(0)))); + assertEquals(List.arrayList(right(0), right(1)), right("zero").traverseListRight(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseListLeft() { + assertEquals(List.nil(), left("zero").traverseListLeft(constant(List.nil()))); + assertEquals(List.single(left(0)), left("zero").traverseListLeft(constant(List.single(0)))); + assertEquals(List.arrayList(left(0), left(1)), left("zero").traverseListLeft(constant(List.arrayList(0, 1)))); + assertEquals(List.single(right("zero")), right("zero").traverseListLeft(constant(List.nil()))); + assertEquals(List.single(right("zero")), right("zero").traverseListLeft(constant(List.single(0)))); + assertEquals(List.single(right("zero")), right("zero").traverseListLeft(constant(List.arrayList(0, 1)))); + } + + @Test + public void testTraverseIORight() throws IOException { + assertEquals(left("zero"), left("zero").traverseIORight(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(right(0), right("zero").traverseIORight(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseIOLeft() throws IOException { + assertEquals(left(0), left("zero").traverseIOLeft(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(right("zero"), right("zero").traverseIOLeft(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseOptionRight() { + assertEquals(Option.some(left("zero")), left("zero").traverseOptionRight(constant(Option.none()))); + assertEquals(Option.some(left("zero")), left("zero").traverseOptionRight(constant(Option.some(0)))); + assertEquals(Option.none(), right("zero").traverseOptionRight(constant(Option.none()))); + assertEquals(Option.some(right(0)), right("zero").traverseOptionRight(constant(Option.some(0)))); + } + + @Test + public void testTraverseOptionLeft() { + assertEquals(Option.none(), left("zero").traverseOptionLeft(constant(Option.none()))); + assertEquals(Option.some(left(0)), left("zero").traverseOptionLeft(constant(Option.some(0)))); + assertEquals(Option.some(right("zero")), right("zero").traverseOptionLeft(constant(Option.none()))); + assertEquals(Option.some(right("zero")), right("zero").traverseOptionLeft(constant(Option.some(0)))); + } + + @Test + public void testTraverseStreamRight() { + assertEquals(Stream.single(left("zero")), left("zero").traverseStreamRight(constant(Stream.nil()))); + assertEquals(Stream.single(left("zero")), left("zero").traverseStreamRight(constant(Stream.single(0)))); + assertEquals(Stream.single(left("zero")), left("zero").traverseStreamRight(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.nil(), right("zero").traverseStreamRight(constant(Stream.nil()))); + assertEquals(Stream.single(right(0)), right("zero").traverseStreamRight(constant(Stream.single(0)))); + assertEquals(Stream.arrayStream(right(0), right(1)), right("zero").traverseStreamRight(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testTraverseStreamLeft() { + assertEquals(Stream.nil(), left("zero").traverseStreamLeft(constant(Stream.nil()))); + assertEquals(Stream.single(left(0)), left("zero").traverseStreamLeft(constant(Stream.single(0)))); + assertEquals(Stream.arrayStream(left(0), left(1)), left("zero").traverseStreamLeft(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.single(right("zero")), right("zero").traverseStreamLeft(constant(Stream.nil()))); + assertEquals(Stream.single(right("zero")), right("zero").traverseStreamLeft(constant(Stream.single(0)))); + assertEquals(Stream.single(right("zero")), right("zero").traverseStreamLeft(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testReduce() { + assertEquals(0L, (long) reduce(left(0L))); + assertEquals(0L, (long) reduce(right(0L))); + } + + @Test + public void testIif() { + assertEquals(right(-1), iif(true, () -> -1, () -> 1)); + assertEquals(left(1), iif(false, () -> -1, () -> 1)); + } + + @Test + public void testLefts() { + assertEquals(List.nil(), lefts(List.nil())); + assertEquals(List.single(0), lefts(List.single(left(0)))); + assertEquals(List.nil(), lefts(List.single(right(0)))); + assertEquals(List.arrayList(0, 1), lefts(List.arrayList(left(0), left(1)))); + assertEquals(List.single(0), lefts(List.arrayList(left(0), right(1)))); + assertEquals(List.single(1), lefts(List.arrayList(right(0), left(1)))); + assertEquals(List.nil(), lefts(List.arrayList(right(0), right(1)))); + } + + @Test + public void testRights() { + assertEquals(List.nil(), rights(List.nil())); + assertEquals(List.single(0), rights(List.single(right(0)))); + assertEquals(List.single(0), lefts(List.single(left(0)))); + assertEquals(List.arrayList(0, 1), rights(List.arrayList(right(0), right(1)))); + assertEquals(List.single(0), rights(List.arrayList(right(0), left(1)))); + assertEquals(List.single(1), rights(List.arrayList(left(0), right(1)))); + assertEquals(List.nil(), rights(List.arrayList(left(0), left(1)))); + } + + @Test + public void testTestToString() { + assertNotNull(left(0).toString()); + assertNotNull(right(0).toString()); + } +} \ No newline at end of file From 849dc39c6d5e937f9cd650da8e5de5cbf2bf062d Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Thu, 6 Aug 2020 10:35:26 -0400 Subject: [PATCH 752/811] Fixes #417. Add fj.data.State.bind(F>). --- core/src/main/java/fj/data/State.java | 18 +++++++++++ core/src/test/java/fj/data/StateTest.java | 39 +++++++++++++++++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index f29d55d7..f0156b36 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -111,6 +111,24 @@ public State withs(F f) { return suspended(s -> runF.f(f.f(s))); } + /** + * Bind the given function across this state. + * + * @param f the given function + * @param the type of the output value + * @return the state + */ + public State bind(F> f) { + return flatMap(f); + } + + /** + * Bind the given function across this state. + * + * @param f the given function + * @param the type of the output value + * @return the state + */ public State flatMap(F> f) { return suspended(s -> runF.f(s).bind(result -> Trampoline.pure(f.f(result._2()).run(result._1())))); } diff --git a/core/src/test/java/fj/data/StateTest.java b/core/src/test/java/fj/data/StateTest.java index 9fc8a9fb..37b21030 100644 --- a/core/src/test/java/fj/data/StateTest.java +++ b/core/src/test/java/fj/data/StateTest.java @@ -2,14 +2,47 @@ import org.junit.Test; +import static fj.P.p; +import static org.junit.Assert.assertEquals; + /** * Created by MarkPerry on 18/12/2014. */ public class StateTest { - @Test - public void map() { + @Test + public void testBind() { + assertEquals(p(2, "one"), state().run(1)); + assertEquals(p(3, "two"), state().run(2)); + assertEquals(p(4, "three"), state().run(3)); + assertEquals(p(2, "?"), state().bind(state -> State.constant("?")).run(1)); + assertEquals(p(3, "?"), state().bind(state -> State.constant("?")).run(2)); + assertEquals(p(4, "?"), state().bind(state -> State.constant("?")).run(3)); + } + + @Test + public void testFlatMap() { + assertEquals(p(2, "one"), state().run(1)); + assertEquals(p(3, "two"), state().run(2)); + assertEquals(p(4, "three"), state().run(3)); + assertEquals(p(2, "?"), state().flatMap(state -> State.constant("?")).run(1)); + assertEquals(p(3, "?"), state().flatMap(state -> State.constant("?")).run(2)); + assertEquals(p(4, "?"), state().flatMap(state -> State.constant("?")).run(3)); + } - } + private static final State state() { + return State.unit(i -> p(i + 1, toLapine(i))); + } + private static String toLapine( + final int i) { + return i == 1 ? + "one" : + i == 2 ? + "two" : + i == 3 ? + "three" : + i == 4 ? + "four" : "hrair"; + } } From c427a086d6a06a14074719d2f3c9a011ce7ad14d Mon Sep 17 00:00:00 2001 From: Drew Taylor Date: Thu, 22 Oct 2020 07:07:30 -0400 Subject: [PATCH 753/811] Fixes #424. Add fj.data.Stream.sequence*, fj.data.Stream.traverse* functions. --- core/src/main/java/fj/data/Stream.java | 432 +++++++++++++++++- .../test/java/fj/data/IOFunctionsTest.java | 2 +- core/src/test/java/fj/data/StreamTest.java | 237 ++++++++++ 3 files changed, 649 insertions(+), 22 deletions(-) diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index a523515b..e05e26bf 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -4,6 +4,7 @@ import fj.F0; import fj.F3; import fj.Hash; +import fj.Semigroup; import fj.Show; import fj.F; import fj.F2; @@ -14,6 +15,7 @@ import fj.P1; import fj.P2; import fj.Unit; +import fj.control.Trampoline; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; import fj.Ordering; @@ -1094,27 +1096,6 @@ public final Stream takeWhile(final F f) { Stream.nil(); } - /** - * Traversable instance of Stream for IO. - * - * @return traversed value - */ - public final IO> traverseIO(F> f) { - return this.foldRight1((a, acc) -> - IOFunctions.bind(acc, (Stream bs) -> - IOFunctions.map(f.f(a), bs::cons)), IOFunctions.unit(Stream.nil())); - - } - - /** - * Traversable instance of Stream for Option. - * - * @return traversed value - */ - public final Option> traverseOption(F> f) { - return this.foldRight1((a, acc) -> acc.bind(bs -> f.f(a).map(bs::cons)), some(Stream.nil())); - } - /** * Removes elements from the head of this stream that do not match the given predicate function * until an element is found that does match or the stream is exhausted. @@ -1669,4 +1650,413 @@ public static F>, F, Stream>> bind_() { public static F, B>>, F, B>>> foldRight() { return curry((f, b, as) -> as.foldRight(f, b)); } + + /** + * Sequence the given stream and collect the output on the right side of an either. + * + * @param stream the given stream + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static Either> sequenceEither( + final Stream> stream) { + return stream.traverseEither(identity()); + } + + /** + * Sequence the given stream and collect the output on the left side of an either. + * + * @param stream the given stream + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static Either, R> sequenceEitherLeft( + final Stream> stream) { + return stream.traverseEitherLeft(identity()); + } + + /** + * Sequence the given stream and collect the output on the right side of an either. + * + * @param stream the given stream + * @param the type of the right value + * @param the type of the left value + * @return the either + */ + public static Either> sequenceEitherRight( + final Stream> stream) { + return stream.traverseEitherRight(identity()); + } + + /** + * Sequence the given stream and collect the output as a function. + * + * @param stream the given stream + * @param the type of the input value + * @param the type of the output value + * @return the either + */ + public static F> sequenceF( + final Stream> stream) { + return stream.traverseF(identity()); + } + + /** + * Sequence the given stream and collect the output as an IO. + * + * @param stream the given stream + * @param the type of the IO value + * @return the IO + */ + public static IO> sequenceIO( + final Stream> stream) { + return stream.traverseIO(identity()); + } + + /** + * Sequence the given stream and collect the output as a list. + * + * @param stream the given stream + * @param the type of the list value + * @return the list + */ + public static List> sequenceList( + final Stream> stream) { + return stream.traverseList(identity()); + } + + /** + * Sequence the given stream and collect the output as an stream. + * + * @param stream the given stream + * @param the type of the option value + * @return the stream + */ + public static Option> sequenceOption( + final Stream> stream) { + return stream.traverseOption(identity()); + } + + /** + * Sequence the given stream and collect the output as a P1. + * + * @param stream the given stream + * @param the type of the P1 value + * @return the P1 + */ + public static P1> sequenceP1( + final Stream> stream) { + return stream.traverseP1(identity()); + } + + /** + * Sequence the given stream and collect the output as a seq. + * + * @param stream the given stream + * @param the type of the stream value + * @return the seq + */ + public static Seq> sequenceSeq( + final Stream> stream) { + return stream.traverseSeq(identity()); + } + + /** + * Sequence the given stream and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param stream the given stream + * @param the type of the set value + * @return the either + */ + public static Set> sequenceSet( + final Ord ord, + final Stream> stream) { + return stream.traverseSet(ord, identity()); + } + + /** + * Sequence the given stream and collect the output as a stream. + * + * @param stream the given stream + * @param the type of the stream value + * @return the stream + */ + public static Stream> sequenceStream( + final Stream> stream) { + return stream.traverseStream(identity()); + } + + /** + * Sequence the given stream and collect the output as a trampoline. + * + * @param stream the given trampoline + * @param the type of the stream value + * @return the stream + */ + public static Trampoline> sequenceTrampoline( + final Stream> stream) { + return stream.traverseTrampoline(identity()); + } + + /** + * Sequence the given stream and collect the output as a validation. + * + * @param stream the given stream + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static Validation> sequenceValidation( + final Stream> stream) { + return stream.traverseValidation(identity()); + } + + /** + * Sequence the given stream and collect the output as a validation; use the given semigroup to reduce the errors. + * + * @param semigroup the given semigroup + * @param stream the given stream + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public static Validation> sequenceValidation( + final Semigroup semigroup, + final Stream> stream) { + return stream.traverseValidation(semigroup, identity()); + } + + /** + * Traverse this stream with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public Either> traverseEither( + final F> f) { + return traverseEitherRight(f); + } + + /** + * Traverse this stream with the given function and collect the output on the left side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public Either, R> traverseEitherLeft( + final F> f) { + return foldRight1( + ( + element, + either) -> f.f(element).left().bind(elementInner -> either.left().map(stream -> stream.cons(elementInner))), + Either.left(nil())); + } + + /** + * Traverse this stream with the given function and collect the output on the right side of an either. + * + * @param f the given function + * @param the type of the left value + * @param the type of the right value + * @return the either + */ + public Either> traverseEitherRight( + final F> f) { + return foldRight1( + ( + element, + either) -> f.f(element).right().bind(elementInner -> either.right().map(stream -> stream.cons(elementInner))), + Either.right(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a function. + * + * @param f the given function + * @param the type of the input value + * @param the type of the output value + * @return the function + */ + public F> traverseF( + final F> f) { + return foldRight1( + ( + element, + fInner) -> Function.bind(f.f(element), elementInner -> andThen(fInner, stream -> stream.cons(elementInner))), + Function.constant(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as an IO. + * + * @param f the given function + * @param the type of the IO value + * @return the IO + */ + public IO> traverseIO( + final F> f) { + return foldRight1( + ( + element, + io) -> IOFunctions.bind(f.f(element), elementInner -> IOFunctions.map(io, stream -> stream.cons(elementInner))), + IOFunctions.unit(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a list. + * + * @param f the given function + * @param the type of the list value + * @return the list + */ + public List> traverseList( + final F> f) { + return foldRight1( + ( + element, + list) -> f.f(element).bind(elementInner -> list.map(stream -> stream.cons(elementInner))), + List.single(nil())); + } + + /** + * Traverses through the Seq with the given function + * + * @param f The function that produces Option value + * @return none if applying f returns none to any element of the seq or f mapped seq in some . + */ + public Option> traverseOption( + final F> f) { + return foldRight1( + ( + element, + option) -> f.f(element).bind(elementInner -> option.map(stream -> stream.cons(elementInner))), + Option.some(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a p1. + * + * @param f the given function + * @param the type of the p1 value + * @return the p1 + */ + public P1> traverseP1( + final F> f) { + return foldRight1( + ( + element, + p1) -> f.f(element).bind(elementInner -> p1.map(stream -> stream.cons(elementInner))), + P.p(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a seq. + * + * @param f the given function + * @param the type of the seq value + * @return the seq + */ + public Seq> traverseSeq( + final F> f) { + return foldRight1( + ( + element, + seq) -> f.f(element).bind(elementInner -> seq.map(stream -> stream.cons(elementInner))), + Seq.single(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a set; use the given ord to order the set. + * + * @param ord the given ord + * @param f the given function + * @param the type of the set value + * @return the set + */ + public Set> traverseSet( + final Ord ord, + final F> f) { + final Ord> seqOrd = Ord.streamOrd(ord); + return foldRight1( + ( + element, + set) -> f.f(element).bind(seqOrd, elementInner -> set.map(seqOrd, seq -> seq.cons(elementInner))), + Set.single(seqOrd, nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a stream. + * + * @param f the given function + * @param the type of the stream value + * @return the stream + */ + public Stream> traverseStream( + final F> f) { + return foldRight1( + ( + element, + stream) -> f.f(element).bind(elementInner -> stream.map(seq -> seq.cons(elementInner))), + Stream.single(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a trampoline. + * + * @param f the given function + * @param the type of the trampoline value + * @return the trampoline + */ + public Trampoline> traverseTrampoline( + final F> f) { + return foldRight1( + ( + element, + trampoline) -> f.f(element).bind(elementInner -> trampoline.map(seq -> seq.cons(elementInner))), + Trampoline.pure(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a validation. + * + * @param f the given function + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public final Validation> traverseValidation( + final F> f) { + return foldRight1( + ( + element, + validation) -> f.f(element).bind(elementInner -> validation.map(stream -> stream.cons(elementInner))), + Validation.success(nil())); + } + + /** + * Traverse this stream with the given function and collect the output as a validation; use the given semigroup to + * reduce the errors. + * + * @param semigroup the given semigroup + * @param f the given function + * @param the type of the failure value + * @param the type of the success value + * @return the validation + */ + public final Validation> traverseValidation( + final Semigroup semigroup, + final F> f) { + return foldRight1( + ( + element, + validation) -> f.f(element).map(Stream::single).accumulate(semigroup, validation, (stream1, stream2) -> stream1.append(stream2)), + Validation.success(nil())); + } } diff --git a/core/src/test/java/fj/data/IOFunctionsTest.java b/core/src/test/java/fj/data/IOFunctionsTest.java index b943db36..5213878c 100644 --- a/core/src/test/java/fj/data/IOFunctionsTest.java +++ b/core/src/test/java/fj/data/IOFunctionsTest.java @@ -73,7 +73,7 @@ public void testTraverseIO() throws IOException { System.setOut(new PrintStream(outContent)); stream.traverseIO(IOFunctions::stdoutPrint).run(); System.setOut(originalOut); - assertThat(outContent.toString(), is("foobar3bar2foo1")); + assertThat(outContent.toString(), is("foo1bar2foobar3")); } @Test diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index 999a3a3e..313678aa 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -2,13 +2,40 @@ import fj.Equal; import fj.P2; +import fj.control.Trampoline; import org.junit.Test; +import java.io.IOException; import java.util.ConcurrentModificationException; +import static fj.Function.constant; +import static fj.Ord.*; +import static fj.P.p; +import static fj.Semigroup.listSemigroup; +import static fj.data.Either.left; +import static fj.data.Either.right; +import static fj.data.List.arrayList; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.Seq.arraySeq; +import static fj.data.Seq.empty; +import static fj.data.Stream.sequenceEitherLeft; +import static fj.data.Stream.sequenceEitherRight; +import static fj.data.Stream.sequenceF; +import static fj.data.Stream.sequenceIO; +import static fj.data.Stream.sequenceList; +import static fj.data.Stream.sequenceOption; +import static fj.data.Stream.sequenceP1; +import static fj.data.Stream.sequenceSeq; +import static fj.data.Stream.sequenceSet; +import static fj.data.Stream.sequenceStream; +import static fj.data.Stream.sequenceTrampoline; +import static fj.data.Stream.sequenceValidation; import static fj.data.Stream.*; +import static fj.data.Validation.*; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; /** @@ -103,4 +130,214 @@ public void testMinus() { assertThat(s1.minus(Equal.charEqual, s2), is(stream(new Character[]{'a', 'c', 'd'}))); } + + @Test + public void testSequenceEither() { + assertEquals(right(nil()), sequenceEither(nil())); + assertEquals(right(single("zero")), sequenceEither(single(right("zero")))); + assertEquals(left("zero"), sequenceEither(single(left("zero")))); + } + + @Test + public void testSequenceEitherLeft() { + assertEquals(left(nil()), sequenceEitherLeft(nil())); + assertEquals(left(single("zero")), sequenceEitherLeft(single(left("zero")))); + assertEquals(right("zero"), sequenceEitherLeft(single(right("zero")))); + } + + @Test + public void testSequenceEitherRight() { + assertEquals(right(nil()), sequenceEitherRight(nil())); + assertEquals(right(single("zero")), sequenceEitherRight(single(right("zero")))); + assertEquals(left("zero"), sequenceEitherRight(single(left("zero")))); + } + + @Test + public void testSequenceF() { + assertEquals(constant(nil()).f(1), sequenceF(nil()).f(1)); + assertEquals(constant(single("zero")).f(1), sequenceF(single(constant("zero"))).f(1)); + } + + @Test + public void testSequenceIO() + throws IOException { + assertEquals(IOFunctions.lazy(constant(nil())).run(), sequenceIO(nil()).run()); + assertEquals(IOFunctions.lazy(constant(single("zero"))).run(), sequenceIO(single(IOFunctions.lazy(constant("zero")))).run()); + } + + @Test + public void testSequenceList() { + assertEquals(List.single(nil()), sequenceList(nil())); + assertEquals(List.nil(), sequenceList(single(List.nil()))); + assertEquals(List.single(single("zero")), sequenceList(single(List.single("zero")))); + assertEquals(arrayList(single("zero"), single("one")), sequenceList(single(arrayList("zero", "one")))); + } + + @Test + public void testSequenceOption() { + assertEquals(some(nil()), sequenceOption(nil())); + assertEquals(none(), sequenceOption(single(none()))); + assertEquals(some(single("zero")), sequenceOption(single(some("zero")))); + } + + @Test + public void testSequenceP1() { + assertEquals(p(nil()), sequenceP1(nil())); + assertEquals(p(single("zero")), sequenceP1(single(p("zero")))); + } + + @Test + public void testSequenceSeq() { + assertEquals(Seq.single(nil()), sequenceSeq(nil())); + assertEquals(Seq.empty(), sequenceSeq(single(Seq.empty()))); + assertEquals(Seq.single(single("zero")), sequenceSeq(single(Seq.single("zero")))); + assertEquals(arraySeq(single("zero"), single("one")), sequenceSeq(single(arraySeq("zero", "one")))); + } + + @Test + public void testSequenceSet() { + assertEquals(Set.arraySet(streamOrd(stringOrd), nil()), sequenceSet(stringOrd, nil())); + assertEquals(Set.empty(streamOrd(stringOrd)), sequenceSet(stringOrd, single(Set.empty(stringOrd)))); + assertEquals(Set.arraySet(streamOrd(stringOrd), single("zero")), sequenceSet(stringOrd, single(Set.single(stringOrd, "zero")))); + assertEquals(Set.arraySet(streamOrd(stringOrd), single("zero"), single("one")), sequenceSet(stringOrd, single(Set.arraySet(stringOrd, "zero", "one")))); + } + + @Test + public void testSequenceStream() { + assertEquals(single(nil()), sequenceStream(nil())); + assertEquals(nil(), sequenceStream(single(nil()))); + assertEquals(single(single("zero")), sequenceStream(single(single("zero")))); + assertEquals(arrayStream(single("zero"), single("one")), sequenceStream(single(arrayStream("zero", "one")))); + } + + @Test + public void testSequenceTrampoline() { + assertEquals(Trampoline.pure(nil()).run(), sequenceTrampoline(nil()).run()); + assertEquals(Trampoline.pure(single(0)).run(), sequenceTrampoline(single(Trampoline.pure(0))).run()); + } + + @Test + public void testSequenceValidation() { + assertEquals(success(nil()), sequenceValidation(nil())); + assertEquals(fail(single(0)), sequenceValidation(single(fail(single(0))))); + assertEquals(success(single(0)), sequenceValidation(single(success(0)))); + } + + @Test + public void testSequenceValidationSemigroup() { + assertEquals(success(nil()), sequenceValidation(listSemigroup(), nil())); + assertEquals(fail(List.single(0)), sequenceValidation(listSemigroup(), single(fail(List.single(0))))); + assertEquals(success(single(0)), sequenceValidation(listSemigroup(), single(success(0)))); + } + + @Test + public void testTraverseEitherLeft() { + assertEquals(left(nil()), nil().traverseEitherLeft(constant(left(0)))); + assertEquals(left(single(0)), single("zero").traverseEitherLeft(constant(left(0)))); + assertEquals(left(nil()), nil().traverseEitherLeft(constant(right(0)))); + assertEquals(right(0), single("zero").traverseEitherLeft(constant(right(0)))); + } + + @Test + public void testTraverseEitherRight() { + assertEquals(right(nil()), nil().traverseEitherRight(constant(right(0)))); + assertEquals(right(single(0)), single("zero").traverseEitherRight(constant(right(0)))); + assertEquals(right(nil()), nil().traverseEitherRight(constant(left(0)))); + assertEquals(left(0), single("zero").traverseEitherRight(constant(left(0)))); + } + + @Test + public void testTraverseF() { + assertEquals(constant(nil()).f(1), nil().traverseF(constant(constant(0))).f(1)); + assertEquals(constant(single(0)).f(1), single("zero").traverseF(constant(constant(0))).f(1)); + } + + @Test + public void testTraverseIO() + throws IOException { + assertEquals(IOFunctions.lazy(constant(nil())).run(), nil().traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + assertEquals(IOFunctions.lazy(constant(single(0))).run(), single("zero").traverseIO(constant(IOFunctions.lazy(constant(0)))).run()); + } + + @Test + public void testTraverseList() { + assertEquals(List.single(nil()), nil().traverseList(constant(List.nil()))); + assertEquals(List.nil(), single("zero").traverseList(constant(List.nil()))); + assertEquals(List.single(nil()), nil().traverseList(constant(List.single(0)))); + assertEquals(List.single(single(0)), single("zero").traverseList(constant(List.single(0)))); + assertEquals(List.single(nil()), nil().traverseList(constant(arrayList(0, 1)))); + assertEquals(arrayList(single(0), single(1)), single("zero").traverseList(constant(arrayList(0, 1)))); + } + + @Test + public void testTraverseOption() { + assertEquals(some(nil()), nil().traverseOption(constant(none()))); + assertEquals(none(), single("zero").traverseOption(constant(none()))); + assertEquals(some(nil()), nil().traverseOption(constant(some(0)))); + assertEquals(some(single(0)), single("zero").traverseOption(constant(some(0)))); + } + + @Test + public void testTraverseP1() { + assertEquals(p(nil()), nil().traverseP1(constant(p(0)))); + assertEquals(p(single(0)), single("zero").traverseP1(constant(p(0)))); + } + + @Test + public void testTraverseSeq() { + assertEquals(Seq.single(nil()), nil().traverseSeq(constant(empty()))); + assertEquals(Seq.empty(), single("zero").traverseSeq(constant(empty()))); + assertEquals(Seq.single(nil()), nil().traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(single(0)), single("zero").traverseSeq(constant(Seq.single(0)))); + assertEquals(Seq.single(nil()), nil().traverseSeq(constant(arraySeq(0, 1)))); + assertEquals(arraySeq(single(0), single(1)), single("zero").traverseSeq(constant(arraySeq(0, 1)))); + } + + @Test + public void testTraverseSet() { + assertEquals(Set.arraySet(streamOrd(intOrd), nil()), nil().traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.empty(streamOrd(intOrd)), single("zero").traverseSet(intOrd, constant(Set.empty(intOrd)))); + assertEquals(Set.single(streamOrd(intOrd), nil()), nil().traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(streamOrd(intOrd), single(0)), single("zero").traverseSet(intOrd, constant(Set.single(intOrd, 0)))); + assertEquals(Set.single(streamOrd(intOrd), nil()), nil().traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + assertEquals(Set.arraySet(streamOrd(intOrd), single(0), single(1)), single("zero").traverseSet(intOrd, constant(Set.arraySet(intOrd, 0, 1)))); + } + + @Test + public void testTraverseStream() { + assertEquals(Stream.single(nil()), nil().traverseStream(constant(Stream.nil()))); + assertEquals(Stream.nil(), single("zero").traverseStream(constant(Stream.nil()))); + assertEquals(Stream.single(nil()), nil().traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(single(0)), single("zero").traverseStream(constant(Stream.single(0)))); + assertEquals(Stream.single(nil()), nil().traverseStream(constant(Stream.arrayStream(0, 1)))); + assertEquals(Stream.arrayStream(single(0), single(1)), single("zero").traverseStream(constant(Stream.arrayStream(0, 1)))); + } + + @Test + public void testTraverseTrampoline() { + assertEquals(Trampoline.pure(nil()).run(), nil().traverseTrampoline(constant(Trampoline.pure(0))).run()); + assertEquals(Trampoline.pure(single(0)).run(), single("zero").traverseTrampoline(constant(Trampoline.pure(0))).run()); + } + + @Test + public void testTraverseValidation() { + assertEquals(success(nil()), nil().traverseValidation(constant(fail(single(0))))); + assertEquals(fail(single(0)), single("zero").traverseValidation(constant(fail(single(0))))); + assertEquals(success(nil()), nil().traverseValidation(constant(success(0)))); + assertEquals(success(single(0)), single("zero").traverseValidation(constant(success(0)))); + + assertEquals(success(arraySeq(0, 2, 4, 6, 8)), arraySeq(0, 2, 4, 6, 8).traverseValidation(i -> condition(i % 2 == 0, List.single(i), i))); + assertEquals(fail(List.single(1)), arraySeq(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).traverseValidation(i -> condition(i % 2 == 0, List.single(i), i))); + } + + @Test + public void testTraverseValidationSemigroup() { + assertEquals(success(nil()), nil().traverseValidation(listSemigroup(), constant(fail(List.single(0))))); + assertEquals(fail(List.single(0)), single("zero").traverseValidation(listSemigroup(), constant(fail(List.single(0))))); + assertEquals(success(nil()), nil().traverseValidation(listSemigroup(), constant(success(0)))); + assertEquals(success(single(0)), single("zero").traverseValidation(listSemigroup(), constant(success(0)))); + + assertEquals(success(arraySeq(0, 2, 4, 6, 8)), arraySeq(0, 2, 4, 6, 8).traverseValidation(listSemigroup(), i -> condition(i % 2 == 0, List.single(i), i))); + assertEquals(fail(arrayList(1, 3, 5, 7, 9)), arraySeq(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).traverseValidation(listSemigroup(), i -> condition(i % 2 == 0, List.single(i), i))); + } } From 254e3f55d964ef27278dbfb51ef0981f7e07c96f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Feb 2021 14:24:27 +1000 Subject: [PATCH 754/811] Fixed code to not use Java 8 features --- .../fj/control/parallel/StrategyTest.java | 9 +++++- core/src/test/java/fj/data/OptionTest.java | 30 ++++++++--------- .../src/test/java/fj/data/ValidationTest.java | 32 +++++++++---------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/core/src/test/java/fj/control/parallel/StrategyTest.java b/core/src/test/java/fj/control/parallel/StrategyTest.java index 8475b35a..0c605829 100644 --- a/core/src/test/java/fj/control/parallel/StrategyTest.java +++ b/core/src/test/java/fj/control/parallel/StrategyTest.java @@ -5,6 +5,7 @@ import fj.P1; import fj.Unit; import fj.data.Enumerator; +import fj.data.Java; import fj.data.List; import fj.data.Stream; import org.junit.Test; @@ -49,10 +50,16 @@ public void testStrategyCompletion() { @Test public void testStrategyMergeAll() { final List l = List.range(0, 100); - final List> p1s = mergeAll(l.map(x -> CompletableFuture.supplyAsync(() -> x))); + final List> p1s = mergeAll(l.map(x -> future(x))); assertThat(P1.sequence(p1s)._1(), is(l)); } + public static Future future(A a) { + FutureTask ft = new FutureTask<>(() -> a); + new Thread(ft).start(); + return ft; + } + @Test public void testStrategyCallables() throws Exception { final Strategy> s = strategy(c -> c); diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index da5ef065..5a7bbdbf 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -75,7 +75,7 @@ public void testBind1() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), 0), list.index(0).bind(Option::some)); }); @@ -87,7 +87,7 @@ public void testBind2() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1)), list.index(0).bind(list.index(1), p2())); }); } @@ -98,7 +98,7 @@ public void testBind3() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2)), list.index(0).bind(list.index(1), list.index(2), p3())); }); @@ -110,7 +110,7 @@ public void testBind4() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3)), list.index(0).bind(list.index(1), list.index(2), list.index(3), p4())); }); @@ -122,7 +122,7 @@ public void testBind5() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), p5())); }); } @@ -133,7 +133,7 @@ public void testBind6() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), p6())); }); } @@ -144,7 +144,7 @@ public void testBind7() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), p7())); }); } @@ -155,7 +155,7 @@ public void testBind8() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).bind(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), P.p8())); }); } @@ -166,7 +166,7 @@ public void testBindProduct2() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1)), list.index(0).bindProduct(list.index(1))); }); } @@ -177,7 +177,7 @@ public void testBindProduct3() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2)), list.index(0).bindProduct(list.index(1), list.index(2))); }); @@ -189,7 +189,7 @@ public void testBindProduct4() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3))); }); @@ -201,7 +201,7 @@ public void testBindProduct5() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4))); }); } @@ -212,7 +212,7 @@ public void testBindProduct6() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5))); }); } @@ -223,7 +223,7 @@ public void testBindProduct7() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6))); }); } @@ -234,7 +234,7 @@ public void testBindProduct8() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List.>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.forall(Option::isSome), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).bindProduct(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7))); }); } diff --git a/core/src/test/java/fj/data/ValidationTest.java b/core/src/test/java/fj/data/ValidationTest.java index 0df2deb9..bf2c34e9 100644 --- a/core/src/test/java/fj/data/ValidationTest.java +++ b/core/src/test/java/fj/data/ValidationTest.java @@ -35,7 +35,7 @@ public void testAccumulateSemigroup2() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(), list.index(1))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1)), list.index(0).accumulate(Semigroup.listSemigroup(), list.index(1), p2())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1)), list.index(0).accumulate(Semigroup.listSemigroup(), list.index(1), uncurryF2(p2()))); @@ -49,7 +49,7 @@ public void testAccumulateSemigroup3() { accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), p3())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), uncurryF3(p3()))); @@ -64,7 +64,7 @@ public void testAccumulateSemigroup4() { accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), p4())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), uncurryF4(p4()))); @@ -79,7 +79,7 @@ public void testAccumulateSemigroup5() { accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), p5())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), uncurryF5(p5()))); @@ -93,7 +93,7 @@ public void testAccumulateSemigroup6() { accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), p6())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), uncurryF6(p6()))); @@ -107,7 +107,7 @@ public void testAccumulateSemigroup7() { accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), p7())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), uncurryF7(p7()))); @@ -121,7 +121,7 @@ public void testAccumulateSemigroup8() { accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(iif(list.exists(Validation::isFail), list.filter(Validation::isFail).bind(validation -> validation.fail())), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7))); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), P.p8())); assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).bind(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).accumulate(Semigroup.listSemigroup(),list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), uncurryF8(P.p8()))); @@ -134,7 +134,7 @@ public void testAccumulate0() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), 0), list.index(0).accumulate()); }); } @@ -145,7 +145,7 @@ public void testAccumulate1() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), 0), list.index(0).accumulate(identity())); }); @@ -157,7 +157,7 @@ public void testAccumulate2() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1)), list.index(0).accumulate(list.index(1), P::p)); }); } @@ -168,7 +168,7 @@ public void testAccumulate3() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2)), list.index(0).accumulate(list.index(1), list.index(2), P::p)); }); @@ -180,7 +180,7 @@ public void testAccumulate4() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), P::p)); }); @@ -192,7 +192,7 @@ public void testAccumulate5() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), P::p)); }); } @@ -203,7 +203,7 @@ public void testAccumulate6() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), P::p)); }); } @@ -214,7 +214,7 @@ public void testAccumulate7() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), P::p)); }); } @@ -225,7 +225,7 @@ public void testAccumulate8() { .foldLeft(accumulator -> list -> accumulator.isEmpty() ? list.map(List::single) : accumulator.bind(accumulatorElement -> list.map(accumulatorElement::snoc)), List., Integer>>>nil()) - .forEach(list -> { + .foreachDoEffect(list -> { assertEquals(condition(list.forall(Validation::isSuccess), list.filter(Validation::isFail).map(validation -> validation.fail()), p(0, 1, 2, 3, 4, 5, 6, 7)), list.index(0).accumulate(list.index(1), list.index(2), list.index(3), list.index(4), list.index(5), list.index(6), list.index(7), P::p)); }); } From 8bf7192dec8054aa77b4db157e1237fc4670f7dd Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Mar 2021 01:12:16 +1000 Subject: [PATCH 755/811] Update release notes for 4.8, 4.8.1 and release notes --- etc/release-notes/release-notes-4.8.1.adoc | 34 ++++++++++++++++++ etc/release-notes/release-notes-4.8.adoc | 41 +++++++++++++++++----- etc/release-process.txt | 35 ++++++++++++++++++ 3 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 etc/release-notes/release-notes-4.8.1.adoc diff --git a/etc/release-notes/release-notes-4.8.1.adoc b/etc/release-notes/release-notes-4.8.1.adoc new file mode 100644 index 00000000..45deb658 --- /dev/null +++ b/etc/release-notes/release-notes-4.8.1.adoc @@ -0,0 +1,34 @@ + += Release 4.8.1 + +Released: 8 Oct 2018 + +== Enhancements + +- Add Trampoline.suspend(final F0> a). See #367 https://github.com/functionaljava/functionaljava/pull/367. + +== Fixes + +- Fix regression in lifted semigroup sum. Fix #365, see #366 https://github.com/functionaljava/functionaljava/pull/366. + +== Internal + +- Fix compile under jdk11. Enable jdk11 travis build, see #361 https://github.com/functionaljava/functionaljava/pull/361. +- Fix warnings, see #369 https://github.com/functionaljava/functionaljava/pull/369. +- Add P tests, see #360 https://github.com/functionaljava/functionaljava/pull/360. +- Exclude consume/ from coverage, see #357 https://github.com/functionaljava/functionaljava/pull/357. +- Add DList tests, see #356 https://github.com/functionaljava/functionaljava/pull/356 +- Add Visitor tests, see #354 https://github.com/functionaljava/functionaljava/pull/354. + +== Breaking Changes + +* None. + +== Documentation + +* None. + +== Contributors + +* Jean Baptiste Giraudeau +* Gabor Liptak diff --git a/etc/release-notes/release-notes-4.8.adoc b/etc/release-notes/release-notes-4.8.adoc index 22dbc552..7e8aed61 100644 --- a/etc/release-notes/release-notes-4.8.adoc +++ b/etc/release-notes/release-notes-4.8.adoc @@ -1,28 +1,53 @@ -= Release += Release 4.8 -Proposed release: +Released: 18 Aug 2018 == Enhancements -* TODO. +- Enable upload of snapshot artifacts, see https://github.com/functionaljava/functionaljava/commit/e834e8b. +- Add append methods to all Px classes. Fix #326, see https://github.com/functionaljava/functionaljava/commit/065ed43. +- Introduce the Eval monad, see https://github.com/functionaljava/functionaljava/commit/98294fc. +- Fluent Equal/Ord construction, see #333 https://github.com/functionaljava/functionaljava/pull/333 +- Implement Zipper Eq and Hash and add tests, see #343 https://github.com/functionaljava/functionaljava/pull/343. +- Implement Vector equals, see #350 https://github.com/functionaljava/functionaljava/pull/350. == Fixes -* TODO. +- Fixed a bug in the NonEmptyList Semigroup implementation that resulted in the same NonEmptyList appended to itself. Regression in 4.7, see https://github.com/functionaljava/functionaljava/commit/07f94fa. +- Fixes #334: exception in Either.LeftProjection.traverseIO, see #335 https://github.com/functionaljava/functionaljava/pull/335 == Internal -* TODO. +- Added Scalacheck Arbitrary implementations for Natural and NonEmptyList, see https://github.com/functionaljava/functionaljava/commit/405c3ec +- Added unit test coverage for Semigroup implementations. The StringBuffer and StringBuilder tests fail because both of those types are mutable. The IO test fails because the ArbitraryIO implementation does not implement equals. See https://github.com/functionaljava/functionaljava/commit/ef81130. +- Fixed the ArbitraryIO implementation and created a Properties object for testing the IO semigroup. See https://github.com/functionaljava/functionaljava/commit/a8e979f. +- Equal: remove reference to static field of LazyString. Fix #321, see https://github.com/functionaljava/functionaljava/commit/6c6dabd. +- Add IOFunctions tests, see #340 https://github.com/functionaljava/functionaljava/pull/340. +- Add Stream tests, see #341 https://github.com/functionaljava/functionaljava/pull/341. +- Add tests for Try, F, FW, Digit. See #346 https://github.com/functionaljava/functionaljava/pull/346 +- Add Vector tests, see #347 https://github.com/functionaljava/functionaljava/pull/347 +- Add Optic tests, see #348 https://github.com/functionaljava/functionaljava/pull/348 +- Add Parser tests, see #349 https://github.com/functionaljava/functionaljava/pull/349 +- Add FingerTree tests, see #351 https://github.com/functionaljava/functionaljava/pull/351 +- Add TreeZipper tests, see #352 https://github.com/functionaljava/functionaljava/pull/352 +- Add Reader/Writer tests, see #353 https://github.com/functionaljava/functionaljava/pull/353 == Breaking Changes -* TODO. +None. == Documentation -* TODO. +None. == Contributors -* TODO. +* Jean Baptiste Giraudeau +* Ryan Johnson +* l1cache (cache@bk.ru) +* Gabor Liptak +* janbols +* Iaroslav Zeigerman +* Signey Quitorio + diff --git a/etc/release-process.txt b/etc/release-process.txt index e9bdbb15..2a87eef2 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -41,3 +41,38 @@ Update the website and Github README.adoc. This includes adding any features to Send a message to the group and social media about the release, TODO. +Setup Artifact Signing +====================== +The below text is a summary from https://gist.github.com/phit/bd3c6d156a2fa5f3b1bc15fa94b3256c. + +As of 2021-02-12, for Windows download Gpg4win 3.1.15 at https://gpg4win.org/index.html. You need to provide 3 things: +- the public key id +- the path to the secret key ring file for your private key +- the passphrase for your private key + +Open a command prompt and run "gpg --gen-key" and follow the prompts. +Get your key id by running: "gpg --list-key" + +Example output: + +gpg: checking the trustdb +gpg: marginals needed: 3 completes needed: 1 trust model: pgp +gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u +gpg: next trustdb check due at 2019-06-17 +C:/Users/phit/AppData/Roaming/gnupg/pubring.kbx +----------------------------------------------- +pub rsa2048 2017-06-17 [SC] [expires: 2019-06-17] + 77273D57FA5140E5A91905087A1B92B81840D019 +uid [ultimate] phit@hush.com +sub rsa2048 2017-06-17 [E] [expires: 2019-06-17] + +In this case we only have one key, 77273D57FA5140E5A91905087A1B92B81840D019 or short* 1840D019 which is basically just the last 8 characters of the long ID. + +Export the key using "gpg --export-secret-key > %UserProfile%\secring.gpg" + +In %UserProfile%\.gradle\gradle.properties, set the values below: + +signing.keyId=XXXXXXXX +signing.password=mypassword +signing.secretKeyRingFile=path/to/secring.gpg + From e9aa23acf3d2b53b9b114dd2e75f163028e52c42 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Mar 2021 01:15:54 +1000 Subject: [PATCH 756/811] Removed obsolete change log file and directed from the readme to the release notes dir --- ChangeLog.md | 52 ---------------------------------------------------- README.adoc | 4 ++++ 2 files changed, 4 insertions(+), 52 deletions(-) delete mode 100644 ChangeLog.md diff --git a/ChangeLog.md b/ChangeLog.md deleted file mode 100644 index acdbedea..00000000 --- a/ChangeLog.md +++ /dev/null @@ -1,52 +0,0 @@ -4.8.1 ------ - -### Enhancements - -- Add Trampoline.suspend(final F0> a). (see [#367](https://github.com/functionaljava/functionaljava/pull/367)); - -### Fixes - -- Fix regression in lifted semigroup sum. Fix #365 (see [#366](https://github.com/functionaljava/functionaljava/pull/366)); - -### Internal - -- Fix compile under jdk11. Enable jdk11 travis build. (see [#361](https://github.com/functionaljava/functionaljava/pull/361)); -- Fix warnings (see [#369](https://github.com/functionaljava/functionaljava/pull/369)); -- Add P tests (see [#360](https://github.com/functionaljava/functionaljava/pull/360)); -- Exclude consume/ from coverage (see [#357](https://github.com/functionaljava/functionaljava/pull/357)); -- Add DList tests (see [#356](https://github.com/functionaljava/functionaljava/pull/356)); -- Add Visitor tests (see [#354](https://github.com/functionaljava/functionaljava/pull/354)); - -4.8 ---- - -### Enhancements - -- Enable upload of snapshot artifacts. (see [`e834e8b`](https://github.com/functionaljava/functionaljava/commit/e834e8b)); -- Add append methods to all Px classes. Fix #326 (see [`065ed43`](https://github.com/functionaljava/functionaljava/commit/065ed43)); -- Introduce the Eval monad (see [`98294fc`](https://github.com/functionaljava/functionaljava/commit/98294fc)); -- Fluent Equal/Ord construction (see [#333](https://github.com/functionaljava/functionaljava/pull/333)); -- Implement Zipper Eq and Hash and add tests (see [#343](https://github.com/functionaljava/functionaljava/pull/343)); -- Implement Vector equals (see [#350](https://github.com/functionaljava/functionaljava/pull/350)); - -### Fixes - -- Fixed a bug in the NonEmptyList Semigroup implementation that resulted in the same NonEmptyList appended to itself. (Regression in 4.7, see [`07f94fa`](https://github.com/functionaljava/functionaljava/commit/07f94fa)); -- Fixes #334: exception in Either.LeftProjection.traverseIO (see [#335](https://github.com/functionaljava/functionaljava/pull/335)); - -### Internal - -- Added Scalacheck Arbitrary implementations for Natural and NonEmptyList. (see [`405c3ec`](https://github.com/functionaljava/functionaljava/commit/405c3ec)); -- Added unit test coverage for Semigroup implementations. The StringBuffer and StringBuilder tests fail because both of those types are mutable. The IO test fails because the ArbitraryIO implementation does not implement equals. (see [`ef81130`](https://github.com/functionaljava/functionaljava/commit/ef81130)); -- Fixed the ArbitraryIO implementation and created a Properties object for testing the IO semigroup. (see [`a8e979f`](https://github.com/functionaljava/functionaljava/commit/a8e979f)); -- Equal: remove reference to static field of LazyString. Fix #321 (see [`6c6dabd`](https://github.com/functionaljava/functionaljava/commit/6c6dabd)); -- Add IOFunctions tests (see [#340](https://github.com/functionaljava/functionaljava/pull/340)); -- Add Stream tests (see [#341](https://github.com/functionaljava/functionaljava/pull/341)); -- Add tests for Try, F, FW, Digit (see [#346](https://github.com/functionaljava/functionaljava/pull/346)); -- Add Vector tests (see [#347](https://github.com/functionaljava/functionaljava/pull/347)); -- Add Optic tests (see [#348](https://github.com/functionaljava/functionaljava/pull/348)); -- Add Parser tests (see [#349](https://github.com/functionaljava/functionaljava/pull/349)); -- Add FingerTree tests (see [#351](https://github.com/functionaljava/functionaljava/pull/351)); -- Add TreeZipper tests (see [#352](https://github.com/functionaljava/functionaljava/pull/352)); -- Add Reader/Writer tests (see [#353](https://github.com/functionaljava/functionaljava/pull/353)); diff --git a/README.adoc b/README.adoc index 8a3ad347..cb53d003 100644 --- a/README.adoc +++ b/README.adoc @@ -122,3 +122,7 @@ A more complete description of the features mentioned above are: == License link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause license) available at https://en.wikipedia.org/wiki/BSD_licenses[]. + +== Release Notes + +For release notes for each version, see the directory etc/release-notes. \ No newline at end of file From 9da757d0777a6bd19b37c52e44ceefec1bcb26d5 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Mar 2021 01:20:56 +1000 Subject: [PATCH 757/811] Prepare for 4.9 release --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c9d8be40..c264be1c 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true + isSnapshot = false fjBaseVersion = "4.9" snapshotAppendix = "-SNAPSHOT" @@ -55,7 +55,7 @@ allprojects { fjConsumeVersion = "4.8.1" signModule = false - useRetroLambda = false + useRetroLambda = true projectTitle = "Functional Java" projectName = "functionaljava" From c18ab08039573891c54ddd88cc41a77844587272 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Mar 2021 01:43:16 +1000 Subject: [PATCH 758/811] Created 4.9 release notes --- etc/release-notes/release-notes-4.9.adoc | 42 ++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 etc/release-notes/release-notes-4.9.adoc diff --git a/etc/release-notes/release-notes-4.9.adoc b/etc/release-notes/release-notes-4.9.adoc new file mode 100644 index 00000000..62db8e99 --- /dev/null +++ b/etc/release-notes/release-notes-4.9.adoc @@ -0,0 +1,42 @@ + += Release 4.9 + +Released: 14 March 2021 + +== Enhancements + +* Added Gen.streamOf(Gen) +* Added Option.sequence(Validation>) +* Added Gen.sequence(Validation>) +* Added Validation sequence and traverse functions to support various types. Added success and fails functions. +* Added Option sequence and traverse functions for various types. +* Added Seq.bind. +* Added List sequence and traverse functions for various types. +* Added Ord.seqOrd +* Added Seq sequence and traverse functions for various types. +* Added functions to Either. +* Added State bind synonym for flatMap. +* Added Steam sequence and traverse functions for various types. + +== Fixes + +* Fixed Validation.accumulate functions. + +== Internal + +* Support JPMS modules through 'Automatic-Module-Name'. + +== Breaking Changes + +* None. + +== Documentation + +* None. + +== Contributors + +* Jean Baptiste Giraudeau +* Gregoire Neuville +* Drew Taylor +* Mark Perry From c7dbd3fda84fec43b3104e0b60dc2a316a98fff4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 13 Mar 2021 17:30:24 +1000 Subject: [PATCH 759/811] Prep for 4.9 release --- etc/release-process.txt | 17 +++++++++++++++++ gradle.properties | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/etc/release-process.txt b/etc/release-process.txt index 2a87eef2..b22ec4e4 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -76,3 +76,20 @@ signing.keyId=XXXXXXXX signing.password=mypassword signing.secretKeyRingFile=path/to/secring.gpg +Upload your key + +C:\repos\functionaljava>gpg --list-key +C:/Users/maper/AppData/Roaming/gnupg/pubring.kbx +------------------------------------------------ +pub rsa3072 2021-02-12 [SC] [expires: 2023-02-12] + E86A4EC34F25A9CF6118582A7985AAE03F41B2F9 +uid [ultimate] Mark Perry +sub rsa3072 2021-02-12 [E] [expires: 2023-02-12] + + +C:\repos\functionaljava>gpg --keyserver hkp://keyserver.ubuntu.com --send-keys E86A4EC34F25A9CF6118582A7985AAE03F41B2F9 +gpg: sending key 7985AAE03F41B2F9 to hkp://keyserver.ubuntu.com + +gradle upload (takes about 3 mins) + + diff --git a/gradle.properties b/gradle.properties index d4552a30..07c2b60c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false +signingEnabled = true From bcb4d199d2a82eafa7adf1b6b91246db29e45818 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 1 Apr 2021 17:45:39 +1000 Subject: [PATCH 760/811] Upgrade from Gradle 5.6.2 to 6.8.3 --- build.gradle | 26 +++++++++++------------- gradle/wrapper/gradle-wrapper.properties | 2 +- props-core-scalacheck/build.gradle | 4 ++++ 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/build.gradle b/build.gradle index d1b829d3..bcd01f5e 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ buildscript { dependencies { classpath "com.github.ben-manes:gradle-versions-plugin:0.27.0" + classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:5.3.0" } wrapper { @@ -20,6 +21,7 @@ buildscript { } } + if (JavaVersion.current().isJava8Compatible()) { allprojects { tasks.withType(Javadoc) { @@ -117,8 +119,8 @@ task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec") // We only care about coverage of: def projectForFoverage = ["core", "quickcheck", "java-core"] - classDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.output) - sourceDirectories = files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs) + getClassDirectories().from(files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.output)) + getSourceDirectories().from(files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs)) reports { html.enabled = true @@ -130,8 +132,7 @@ configure(subprojects.findAll { it.name != "props-core" }) { apply plugin: "maven" apply plugin: "signing" - apply plugin: "osgi" - + apply plugin: "biz.aQute.bnd.builder" sourceCompatibility = "1.8" javadoc { @@ -156,16 +157,13 @@ configure(subprojects.findAll { it.name != "props-core" }) { jar { version project.fjVersion - manifest { - name = 'Functional Java' - instruction 'Signature-Version', project.fjVersion - instruction 'Bundle-ActivationPolicy', 'lazy' - instruction 'Bundle-Vendor', 'functionaljava.org' - if(project.name != "core") { - instruction 'Require-Bundle', 'org.functionaljava;bundle-version="'+project.fjBaseVersion+'"' - } - instruction 'Automatic-Module-Name', "functionaljava${project.name == 'core' ? '' : ".$project.name"}" - } + bnd ( + 'Bundle-Name': 'Functional Java', + 'Signature-Version': project.fjVersion, + 'Bundle-ActivationPolicy': 'lazy', + 'Bundle-Vendor': 'functionaljava.org', + 'Automatic-Module-Name': "functionaljava${project.name == 'core' ? '' : ".$project.name"}", + ) } eclipse { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ca9d6281..8cf6eb5a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index 5207bf50..f26b5425 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -19,5 +19,9 @@ dependencies { testRuntime junitRuntime } +tasks.withType(ScalaCompile) { + scalaCompileOptions.additionalParameters = ["-feature", "-language:implicitConversions", "-language:postfixOps"] +} + performSigning(signingEnabled, signModule) configureUpload(signingEnabled, signModule) From 3ddcfe6e15ec840d27719c47c67be493061552d0 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 1 Apr 2021 17:46:08 +1000 Subject: [PATCH 761/811] Target Java 8 JVM --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bcd01f5e..62f48dde 100644 --- a/build.gradle +++ b/build.gradle @@ -106,7 +106,7 @@ subprojects { } tasks.withType(JavaCompile) { - options.compilerArgs.addAll(['--release', '10']) + options.compilerArgs.addAll(['--release', '8']) if (displayCompilerWarnings) { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" } From 851245c47700063529f55ac416dea09cb55c7bc2 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 1 Apr 2021 17:52:35 +1000 Subject: [PATCH 762/811] Don't sign modules by default --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From fe4607210b0fdff9d1824b2e166a084bcd3ec32b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 1 Apr 2021 17:52:54 +1000 Subject: [PATCH 763/811] Updated gradle version to 6.8.3 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 62f48dde..57c36c18 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { } wrapper { - gradleVersion = "5.6.2" + gradleVersion = "6.8.3" distributionType = Wrapper.DistributionType.ALL } } From 50aee0c7e35e128b5bdce7b8278ee98d27b16c4a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 2 Apr 2021 00:15:18 +1000 Subject: [PATCH 764/811] Removed F1Functions, F1W, F2Functions and F2W --- core/src/main/java/fj/F.java | 681 ++++++++- core/src/main/java/fj/F1Functions.java | 687 --------- core/src/main/java/fj/F1W.java | 687 --------- core/src/main/java/fj/F2.java | 274 +++- core/src/main/java/fj/F2Functions.java | 273 ---- core/src/main/java/fj/F2W.java | 254 --- core/src/main/java/fj/Monoid.java | 4 +- core/src/main/java/fj/P1.java | 2 +- core/src/main/java/fj/P2.java | 4 +- core/src/main/java/fj/P3.java | 6 +- core/src/main/java/fj/P4.java | 8 +- core/src/main/java/fj/P5.java | 10 +- core/src/main/java/fj/P6.java | 12 +- core/src/main/java/fj/P7.java | 14 +- core/src/main/java/fj/P8.java | 16 +- core/src/main/java/fj/Semigroup.java | 5 +- core/src/main/java/fj/control/Trampoline.java | 9 +- .../java/fj/control/parallel/ParModule.java | 4 +- core/src/main/java/fj/data/IOFunctions.java | 5 +- core/src/main/java/fj/data/Iteratee.java | 3 +- core/src/main/java/fj/data/List.java | 2 +- core/src/main/java/fj/data/NonEmptyList.java | 3 +- core/src/main/java/fj/data/Reader.java | 3 +- core/src/main/java/fj/data/Tree.java | 4 +- core/src/main/java/fj/data/TreeMap.java | 7 +- core/src/main/java/fj/data/TreeZipper.java | 1356 ++++++++--------- core/src/main/java/fj/data/Zipper.java | 1170 +++++++------- .../java/fj/data/fingertrees/FingerTree.java | 536 +++---- core/src/test/java/fj/FFunctionsTest.java | 90 +- core/src/test/java/fj/FWFunctionsTest.java | 23 - .../test/java/fj/data/IOFunctionsTest.java | 3 +- .../test/java/fj/function/StringsTest.java | 3 +- .../main/java/fj/demo/Comonad_example.java | 3 +- demo/src/main/java/fj/demo/IODemo.java | 5 +- demo/src/main/java/fj/demo/IOWalkthrough.java | 7 +- demo/src/main/java/fj/demo/Primes2.java | 4 +- .../main/java/fj/demo/WriterDemo_Halver.java | 3 +- .../java/fj/demo/concurrent/MapReduce.java | 15 +- .../src/main/java/fj/demo/euler/Problem2.java | 6 +- .../src/test/scala/fj/data/CheckHashMap.scala | 236 +-- .../test/scala/fj/data/CheckIteratee.scala | 3 +- .../src/test/java/fj/data/ReaderTest.java | 6 +- 42 files changed, 2730 insertions(+), 3716 deletions(-) delete mode 100644 core/src/main/java/fj/F1Functions.java delete mode 100644 core/src/main/java/fj/F1W.java delete mode 100644 core/src/main/java/fj/F2Functions.java delete mode 100644 core/src/main/java/fj/F2W.java delete mode 100644 core/src/test/java/fj/FWFunctionsTest.java diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java index e2db316e..d2208236 100644 --- a/core/src/main/java/fj/F.java +++ b/core/src/main/java/fj/F.java @@ -1,12 +1,27 @@ package fj; +import fj.control.parallel.Actor; +import fj.control.parallel.Promise; +import fj.control.parallel.Strategy; +import fj.data.*; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.TreeSet; +import java.util.concurrent.*; +import java.util.function.Function; + +import static fj.data.Option.some; +import static fj.data.Stream.iterableStream; +import static fj.data.Zipper.fromStream; + /** * A transformation or function from A to B. This type can be represented * using the Java 7 closure syntax. * * @version %build.number% */ -public interface F { +public interface F extends Function { /** * Transform A to B. * @@ -15,4 +30,668 @@ public interface F { */ B f(A a); + default B apply(A a) { + return f(a); + } + + /** + * Function composition + * + * @param g A function to compose with this one. + * @return The composed function such that this function is applied last. + */ + default F o(final F g) { + return c -> f(g.f(c)); + } + + /** + * First-class function composition + * + * @return A function that composes this function with another. + */ + default F, F> o() { + return g -> o(g); + } + + /** + * Function composition flipped. + * + * @param g A function with which to compose this one. + * @return The composed function such that this function is applied first. + */ + @SuppressWarnings("unchecked") + default F andThen(final F g) { + return g.o(this); + } + + /** + * First-class composition flipped. + * + * @return A function that invokes this function and then a given function on the result. + */ + default F, F> andThen() { + return g -> andThen(g); + } + + /** + * Binds a given function across this function (Reader Monad). + * + * @param g A function that takes the return value of this function as an argument, yielding a new function. + * @return A function that invokes this function on its argument and then the given function on the result. + */ + default F bind(final F> g) { + return a -> g.f(f(a)).f(a); + } + + /** + * First-class function binding. + * + * @return A function that binds another function across this function. + */ + default F>, F> bind() { + return g -> bind(g); + } + + /** + * Function application in an environment (Applicative Functor). + * + * @param g A function with the same argument type as this function, yielding a function that takes the return + * value of this function. + * @return A new function that invokes the given function on its argument, yielding a new function that is then + * applied to the result of applying this function to the argument. + */ + default F apply(final F> g) { + return a -> g.f(a).f(f(a)); + } + + /** + * First-class function application in an environment. + * + * @return A function that applies a given function within the environment of this function. + */ + default F>, F> apply() { + return g -> apply(g); + } + + /** + * Applies this function over the arguments of another function. + * + * @param g The function over whose arguments to apply this function. + * @return A new function that invokes this function on its arguments before invoking the given function. + */ + default F> on(final F> g) { + return a1 -> a2 -> g.f(f(a1)).f(f(a2)); + } + + + + /** + * Applies this function over the arguments of another function. + * + * @return A function that applies this function over the arguments of another function. + */ + default F>, F>> on() { + return g -> on(g); + } + + /** + * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1. + * + * @return This function promoted to return its result in a product-1. + */ + default F> lazy() { + return a -> P.lazy(() -> f(a)); + } + + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument to return a lazy value. + */ + default P1 partial(final A a) { + return P.lazy(() -> f(a)); + } + + /** + * Promotes this function to map over a product-1. + * + * @return This function promoted to map over a product-1. + */ + default F, P1> mapP1() { + return p -> p.map(this); + } + + /** + * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option. + * + * @return This function promoted to return its result in an Option. + */ + default F> optionK() { + return a -> some(f(a)); + } + + /** + * Promotes this function to map over an optional value. + * + * @return This function promoted to map over an optional value. + */ + default F, Option> mapOption() { + return o -> o.map(this); + } + + /** + * Promotes this function so that it returns its result in a List. Kleisli arrow for List. + * + * @return This function promoted to return its result in a List. + */ + default F> listK() { + return a -> List.single(f(a)); + } + + /** + * Promotes this function to map over a List. + * + * @return This function promoted to map over a List. + */ + default F, List> mapList() { + return x -> x.map(this); + } + + /** + * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream. + * + * @return This function promoted to return its result in a Stream. + */ + default F> streamK() { + return a -> Stream.single(f(a)); + } + + /** + * Promotes this function to map over a Stream. + * + * @return This function promoted to map over a Stream. + */ + default F, Stream> mapStream() { + return x -> x.map(this); + } + + /** + * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array. + * + * @return This function promoted to return its result in a Array. + */ + default F> arrayK() { + return a -> Array.single(f(a)); + + } + + /** + * Promotes this function to map over a Array. + * + * @return This function promoted to map over a Array. + */ + default F, Array> mapArray() { + return x -> x.map(this); + } + + /** + * Returns a function that contramaps over a given actor. + * + * @return A function that contramaps over a given actor. + */ + default F, Actor> contramapActor() { + return a -> a.contramap(this); + } + + /** + * Promotes this function to a concurrent function that returns a Promise of a value. + * + * @param s A parallel strategy for concurrent execution. + * @return A concurrent function that returns a Promise of a value. + */ + default F> promiseK(final Strategy s) { + return Promise.promise(s, this); + } + + /** + * Promotes this function to map over a Promise. + * + * @return This function promoted to map over Promises. + */ + default F, Promise> mapPromise() { + return p -> p.fmap(this); + } + + /** + * Promotes this function so that it returns its result on the left side of an Either. + * Kleisli arrow for the Either left projection. + * + * @return This function promoted to return its result on the left side of an Either. + */ + @SuppressWarnings("unchecked") + default F> eitherLeftK() { + return Either.left_().o(this); + } + + /** + * Promotes this function so that it returns its result on the right side of an Either. + * Kleisli arrow for the Either right projection. + * + * @return This function promoted to return its result on the right side of an Either. + */ + @SuppressWarnings("unchecked") + default F> eitherRightK() { + return Either.right_().o(this); + } + + /** + * Promotes this function to map over the left side of an Either. + * + * @return This function promoted to map over the left side of an Either. + */ + @SuppressWarnings("unchecked") + default F, Either> mapLeft() { + return Either.leftMap_().f(this); + } + + /** + * Promotes this function to map over the right side of an Either. + * + * @return This function promoted to map over the right side of an Either. + */ + @SuppressWarnings("unchecked") + default F, Either> mapRight() { + return Either.rightMap_().f(this); + } + + /** + * Returns a function that returns the left side of a given Either, or this function applied to the right side. + * + * @return a function that returns the left side of a given Either, or this function applied to the right side. + */ + default F, B> onLeft() { + return e -> e.left().on(this); + } + + /** + * Returns a function that returns the right side of a given Either, or this function applied to the left side. + * + * @return a function that returns the right side of a given Either, or this function applied to the left side. + */ + default F, B> onRight() { + return e -> e.right().on(this); + } + + /** + * Promotes this function to return its value in an Iterable. + * + * @return This function promoted to return its value in an Iterable. + */ + @SuppressWarnings("unchecked") + default F> iterableK() { + return IterableW.arrow().f(this); + } + + /** + * Promotes this function to map over Iterables. + * + * @return This function promoted to map over Iterables. + */ + @SuppressWarnings("unchecked") + default F, IterableW> mapIterable() { + return IterableW.map().f(this).o(IterableW.wrap()); + } + + /** + * Promotes this function to return its value in a NonEmptyList. + * + * @return This function promoted to return its value in a NonEmptyList. + */ + @SuppressWarnings("unchecked") + default F> nelK() { + return NonEmptyList.nel().o(this); + } + + /** + * Promotes this function to map over a NonEmptyList. + * + * @return This function promoted to map over a NonEmptyList. + */ + default F, NonEmptyList> mapNel() { + return list -> list.map(this); + } + + /** + * Promotes this function to return its value in a Set. + * + * @param o An order for the set. + * @return This function promoted to return its value in a Set. + */ + default F> setK(final Ord o) { + return a -> Set.single(o, f(a)); + } + + /** + * Promotes this function to map over a Set. + * + * @param o An order for the resulting set. + * @return This function promoted to map over a Set. + */ + default F, Set> mapSet(final Ord o) { + return s -> s.map(o, this); + } + + /** + * Promotes this function to return its value in a Tree. + * + * @return This function promoted to return its value in a Tree. + */ + default F> treeK() { + return a -> Tree.leaf(f(a)); + } + + /** + * Promotes this function to map over a Tree. + * + * @return This function promoted to map over a Tree. + */ + @SuppressWarnings("unchecked") + default F, Tree> mapTree() { + return Tree.fmap_().f(this); + } + + /** + * Returns a function that maps this function over a tree and folds it with the given monoid. + * + * @param m The monoid with which to fold the mapped tree. + * @return a function that maps this function over a tree and folds it with the given monoid. + */ + default F, B> foldMapTree(final Monoid m) { + return Tree.foldMap_(this, m); + } + + /** + * Promotes this function to return its value in a TreeZipper. + * + * @return This function promoted to return its value in a TreeZipper. + */ + default F> treeZipperK() { + return treeK().andThen(TreeZipper.fromTree()); + } + + /** + * Promotes this function to map over a TreeZipper. + * + * @return This function promoted to map over a TreeZipper. + */ + default F, TreeZipper> mapTreeZipper() { + return z -> z.map(this); + } + + /** + * Promotes this function so that it returns its result on the failure side of a Validation. + * Kleisli arrow for the Validation failure projection. + * + * @return This function promoted to return its result on the failure side of a Validation. + */ + default F> failK() { + return a -> Validation.fail(f(a)); + + } + + /** + * Promotes this function so that it returns its result on the success side of an Validation. + * Kleisli arrow for the Validation success projection. + * + * @return This function promoted to return its result on the success side of an Validation. + */ + default F> successK() { + return a -> Validation.success(f(a)); + } + + /** + * Promotes this function to map over the failure side of a Validation. + * + * @return This function promoted to map over the failure side of a Validation. + */ + default F, Validation> mapFail() { + return v -> v.f().map(this); + } + + /** + * Promotes this function to map over the success side of a Validation. + * + * @return This function promoted to map over the success side of a Validation. + */ + default F, Validation> mapSuccess() { + return v -> v.map(this); + } + + /** + * Returns a function that returns the failure side of a given Validation, + * or this function applied to the success side. + * + * @return a function that returns the failure side of a given Validation, + * or this function applied to the success side. + */ + default F, B> onFail() { + return v -> v.f().on(this); + } + + /** + * Returns a function that returns the success side of a given Validation, + * or this function applied to the failure side. + * + * @return a function that returns the success side of a given Validation, + * or this function applied to the failure side. + */ + default F, B> onSuccess() { + return v -> v.on(this); + } + + /** + * Promotes this function to return its value in a Zipper. + * + * @return This function promoted to return its value in a Zipper. + */ + default F> zipperK() { + return streamK().andThen(s -> fromStream(s).some()); + } + + /** + * Promotes this function to map over a Zipper. + * + * @return This function promoted to map over a Zipper. + */ + default F, Zipper> mapZipper() { + return z -> z.map(this); + } + + /** + * Promotes this function to map over an Equal as a contravariant functor. + * + * @return This function promoted to map over an Equal as a contravariant functor. + */ + default F, Equal> contramapEqual() { + return e -> e.contramap(this); + } + + /** + * Promotes this function to map over a Hash as a contravariant functor. + * + * @return This function promoted to map over a Hash as a contravariant functor. + */ + default F, Hash> contramapHash() { + return h -> h.contramap(this); + } + + /** + * Promotes this function to map over a Show as a contravariant functor. + * + * @return This function promoted to map over a Show as a contravariant functor. + */ + default F, Show> contramapShow() { + return s -> s.contramap(this); + } + + /** + * Promotes this function to map over the first element of a pair. + * + * @return This function promoted to map over the first element of a pair. + */ + default F, P2> mapFst() { + return P2.map1_(this); + } + + /** + * Promotes this function to map over the second element of a pair. + * + * @return This function promoted to map over the second element of a pair. + */ + default F, P2> mapSnd() { + return P2.map2_(this); + } + + /** + * Promotes this function to map over both elements of a pair. + * + * @return This function promoted to map over both elements of a pair. + */ + default F, P2> mapBoth() { + return p2 -> P2.map(this, p2); + } + + /** + * Maps this function over a SynchronousQueue. + * + * @param as A SynchronousQueue to map this function over. + * @return A new SynchronousQueue with this function applied to each element. + */ + default SynchronousQueue mapJ(final SynchronousQueue as) { + final SynchronousQueue bs = new SynchronousQueue<>(); + bs.addAll(iterableStream(as).map(this).toCollection()); + return bs; + } + + + /** + * Maps this function over a PriorityBlockingQueue. + * + * @param as A PriorityBlockingQueue to map this function over. + * @return A new PriorityBlockingQueue with this function applied to each element. + */ + default PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { + return new PriorityBlockingQueue<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over a LinkedBlockingQueue. + * + * @param as A LinkedBlockingQueue to map this function over. + * @return A new LinkedBlockingQueue with this function applied to each element. + */ + default LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { + return new LinkedBlockingQueue<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over a CopyOnWriteArraySet. + * + * @param as A CopyOnWriteArraySet to map this function over. + * @return A new CopyOnWriteArraySet with this function applied to each element. + */ + default CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { + return new CopyOnWriteArraySet<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over a CopyOnWriteArrayList. + * + * @param as A CopyOnWriteArrayList to map this function over. + * @return A new CopyOnWriteArrayList with this function applied to each element. + */ + default CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { + return new CopyOnWriteArrayList<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over a ConcurrentLinkedQueue. + * + * @param as A ConcurrentLinkedQueue to map this function over. + * @return A new ConcurrentLinkedQueue with this function applied to each element. + */ + default ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { + return new ConcurrentLinkedQueue<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over an ArrayBlockingQueue. + * + * @param as An ArrayBlockingQueue to map this function over. + * @return A new ArrayBlockingQueue with this function applied to each element. + */ + default ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { + final ArrayBlockingQueue bs = new ArrayBlockingQueue<>(as.size()); + bs.addAll(iterableStream(as).map(this).toCollection()); + return bs; + } + + + /** + * Maps this function over a TreeSet. + * + * @param as A TreeSet to map this function over. + * @return A new TreeSet with this function applied to each element. + */ + default TreeSet mapJ(final TreeSet as) { + return new TreeSet<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over a PriorityQueue. + * + * @param as A PriorityQueue to map this function over. + * @return A new PriorityQueue with this function applied to each element. + */ + default java.util.PriorityQueue mapJ(final java.util.PriorityQueue as) { + return new java.util.PriorityQueue<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over a LinkedList. + * + * @param as A LinkedList to map this function over. + * @return A new LinkedList with this function applied to each element. + */ + default LinkedList mapJ(final LinkedList as) { + return new LinkedList<>(iterableStream(as).map(this).toCollection()); + } + + /** + * Maps this function over an ArrayList. + * + * @param as An ArrayList to map this function over. + * @return A new ArrayList with this function applied to each element. + */ + default ArrayList mapJ(final ArrayList as) { + return new ArrayList<>(iterableStream(as).map(this).toCollection()); + } + + default F map(F f) { + return f.o(this); + } + + default F contramap(F f) { + return o(f); + } + + /** + * Both map (with g) and contramap (with f) the target function. (Profunctor pattern) + */ + default F dimap(F f, F g) { + return c -> g.f(f(f.f(c))); + } + + } diff --git a/core/src/main/java/fj/F1Functions.java b/core/src/main/java/fj/F1Functions.java deleted file mode 100644 index 00bdf515..00000000 --- a/core/src/main/java/fj/F1Functions.java +++ /dev/null @@ -1,687 +0,0 @@ -package fj; - -import fj.control.parallel.Actor; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import fj.data.*; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.PriorityQueue; -import java.util.TreeSet; -import java.util.concurrent.*; - -import static fj.data.Option.some; -import static fj.data.Stream.iterableStream; -import static fj.data.Zipper.fromStream; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F1Functions { - - - private F1Functions() { - } - - /** - * Function composition - * - * @param g A function to compose with this one. - * @return The composed function such that this function is applied last. - */ - public static F o(final F f, final F g) { - return c -> f.f(g.f(c)); - } - - /** - * First-class function composition - * - * @return A function that composes this function with another. - */ - public static F, F> o(final F f) { - return g -> o(f, g); - } - - /** - * Function composition flipped. - * - * @param g A function with which to compose this one. - * @return The composed function such that this function is applied first. - */ - @SuppressWarnings("unchecked") - public static F andThen(final F f, final F g) { - return o(g, f); - } - - /** - * First-class composition flipped. - * - * @return A function that invokes this function and then a given function on the result. - */ - public static F, F> andThen(final F f) { - return g -> andThen(f, g); - } - - /** - * Binds a given function across this function (Reader Monad). - * - * @param g A function that takes the return value of this function as an argument, yielding a new function. - * @return A function that invokes this function on its argument and then the given function on the result. - */ - public static F bind(final F f, final F> g) { - return a -> g.f(f.f(a)).f(a); - } - - /** - * First-class function binding. - * - * @return A function that binds another function across this function. - */ - public static F>, F> bind(final F f) { - return g -> bind(f, g); - } - - /** - * Function application in an environment (Applicative Functor). - * - * @param g A function with the same argument type as this function, yielding a function that takes the return - * value of this function. - * @return A new function that invokes the given function on its argument, yielding a new function that is then - * applied to the result of applying this function to the argument. - */ - public static F apply(final F f, final F> g) { - return a -> g.f(a).f(f.f(a)); - } - - /** - * First-class function application in an environment. - * - * @return A function that applies a given function within the environment of this function. - */ - public static F>, F> apply(final F f) { - return g -> apply(f, g); - } - - /** - * Applies this function over the arguments of another function. - * - * @param g The function over whose arguments to apply this function. - * @return A new function that invokes this function on its arguments before invoking the given function. - */ - public static F> on(final F f, final F> g) { - return a1 -> a2 -> g.f(f.f(a1)).f(f.f(a2)); - } - - - - /** - * Applies this function over the arguments of another function. - * - * @return A function that applies this function over the arguments of another function. - */ - public static F>, F>> on(final F f) { - return g -> on(f, g); - } - - /** - * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1. - * - * @return This function promoted to return its result in a product-1. - */ - public static F> lazy(final F f) { - return a -> P.lazy(() -> f.f(a)); - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument to return a lazy value. - */ - public static P1 f(final F f, final A a) { - return P.lazy(() -> f.f(a)); - } - - /** - * Promotes this function to map over a product-1. - * - * @return This function promoted to map over a product-1. - */ - public static F, P1> mapP1(final F f) { - return p -> p.map(f); - } - - /** - * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option. - * - * @return This function promoted to return its result in an Option. - */ - public static F> optionK(final F f) { - return a -> some(f.f(a)); - } - - /** - * Promotes this function to map over an optional value. - * - * @return This function promoted to map over an optional value. - */ - public static F, Option> mapOption(final F f) { - return o -> o.map(f); - } - - /** - * Promotes this function so that it returns its result in a List. Kleisli arrow for List. - * - * @return This function promoted to return its result in a List. - */ - public static F> listK(final F f) { - return a -> List.single(f.f(a)); - } - - /** - * Promotes this function to map over a List. - * - * @return This function promoted to map over a List. - */ - public static F, List> mapList(final F f) { - return x -> x.map(f); - } - - /** - * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream. - * - * @return This function promoted to return its result in a Stream. - */ - public static F> streamK(final F f) { - return a -> Stream.single(f.f(a)); - } - - /** - * Promotes this function to map over a Stream. - * - * @return This function promoted to map over a Stream. - */ - public static F, Stream> mapStream(final F f) { - return x -> x.map(f); - } - - /** - * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array. - * - * @return This function promoted to return its result in a Array. - */ - public static F> arrayK(final F f) { - return a -> Array.single(f.f(a)); - - } - - /** - * Promotes this function to map over a Array. - * - * @return This function promoted to map over a Array. - */ - public static F, Array> mapArray(final F f) { - return x -> x.map(f); - } - - /** - * Returns a function that contramaps over a given actor. - * - * @return A function that contramaps over a given actor. - */ - public static F, Actor> contramapActor(final F f) { - return a -> a.contramap(f); - } - - /** - * Promotes this function to a concurrent function that returns a Promise of a value. - * - * @param s A parallel strategy for concurrent execution. - * @return A concurrent function that returns a Promise of a value. - */ - public static F> promiseK(final F f, final Strategy s) { - return Promise.promise(s, f); - } - - /** - * Promotes this function to map over a Promise. - * - * @return This function promoted to map over Promises. - */ - public static F, Promise> mapPromise(final F f) { - return p -> p.fmap(f); - } - - /** - * Promotes this function so that it returns its result on the left side of an Either. - * Kleisli arrow for the Either left projection. - * - * @return This function promoted to return its result on the left side of an Either. - */ - @SuppressWarnings("unchecked") - public static F> eitherLeftK(final F f) { - return o(Either.left_(), f); - } - - /** - * Promotes this function so that it returns its result on the right side of an Either. - * Kleisli arrow for the Either right projection. - * - * @return This function promoted to return its result on the right side of an Either. - */ - @SuppressWarnings("unchecked") - public static F> eitherRightK(final F f) { - return o(Either.right_(), f); - } - - /** - * Promotes this function to map over the left side of an Either. - * - * @return This function promoted to map over the left side of an Either. - */ - @SuppressWarnings("unchecked") - public static F, Either> mapLeft(final F f) { - return Either.leftMap_().f(f); - } - - /** - * Promotes this function to map over the right side of an Either. - * - * @return This function promoted to map over the right side of an Either. - */ - @SuppressWarnings("unchecked") - public static F, Either> mapRight(final F f) { - return Either.rightMap_().f(f); - } - - /** - * Returns a function that returns the left side of a given Either, or this function applied to the right side. - * - * @return a function that returns the left side of a given Either, or this function applied to the right side. - */ - public static F, B> onLeft(final F f) { - return e -> e.left().on(f); - } - - /** - * Returns a function that returns the right side of a given Either, or this function applied to the left side. - * - * @return a function that returns the right side of a given Either, or this function applied to the left side. - */ - public static F, B> onRight(final F f) { - return e -> e.right().on(f); - } - - /** - * Promotes this function to return its value in an Iterable. - * - * @return This function promoted to return its value in an Iterable. - */ - @SuppressWarnings("unchecked") - public static F> iterableK(final F f) { - return IterableW.arrow().f(f); - } - - /** - * Promotes this function to map over Iterables. - * - * @return This function promoted to map over Iterables. - */ - @SuppressWarnings("unchecked") - public static F, IterableW> mapIterable(final F f) { - return o(IterableW.map().f(f), IterableW.wrap()); - } - - /** - * Promotes this function to return its value in a NonEmptyList. - * - * @return This function promoted to return its value in a NonEmptyList. - */ - @SuppressWarnings("unchecked") - public static F> nelK(final F f) { - return o(NonEmptyList.nel(), f); - } - - /** - * Promotes this function to map over a NonEmptyList. - * - * @return This function promoted to map over a NonEmptyList. - */ - public static F, NonEmptyList> mapNel(final F f) { - return list -> list.map(f); - } - - /** - * Promotes this function to return its value in a Set. - * - * @param o An order for the set. - * @return This function promoted to return its value in a Set. - */ - public static F> setK(final F f, final Ord o - ) { - return a -> Set.single(o, f.f(a)); - } - - /** - * Promotes this function to map over a Set. - * - * @param o An order for the resulting set. - * @return This function promoted to map over a Set. - */ - public static F, Set> mapSet(final F f, final Ord o) { - return s -> s.map(o, f); - } - - /** - * Promotes this function to return its value in a Tree. - * - * @return This function promoted to return its value in a Tree. - */ - public static F> treeK(final F f) { - return a -> Tree.leaf(f.f(a)); - } - - /** - * Promotes this function to map over a Tree. - * - * @return This function promoted to map over a Tree. - */ - @SuppressWarnings("unchecked") - public static F, Tree> mapTree(final F f) { - return Tree.fmap_().f(f); - } - - /** - * Returns a function that maps this function over a tree and folds it with the given monoid. - * - * @param m The monoid with which to fold the mapped tree. - * @return a function that maps this function over a tree and folds it with the given monoid. - */ - public static F, B> foldMapTree(final F f, final Monoid m) { - return Tree.foldMap_(f, m); - } - - /** - * Promotes this function to return its value in a TreeZipper. - * - * @return This function promoted to return its value in a TreeZipper. - */ - public static F> treeZipperK(final F f) { - return andThen(treeK(f), TreeZipper.fromTree()); - } - - /** - * Promotes this function to map over a TreeZipper. - * - * @return This function promoted to map over a TreeZipper. - */ - public static F, TreeZipper> mapTreeZipper(final F f) { - return (z) -> z.map(f); - } - - /** - * Promotes this function so that it returns its result on the failure side of a Validation. - * Kleisli arrow for the Validation failure projection. - * - * @return This function promoted to return its result on the failure side of a Validation. - */ - public static F> failK(final F f) { - return a -> Validation.fail(f.f(a)); - - } - - /** - * Promotes this function so that it returns its result on the success side of an Validation. - * Kleisli arrow for the Validation success projection. - * - * @return This function promoted to return its result on the success side of an Validation. - */ - public static F> successK(final F f) { - return a -> Validation.success(f.f(a)); - } - - /** - * Promotes this function to map over the failure side of a Validation. - * - * @return This function promoted to map over the failure side of a Validation. - */ - public static F, Validation> mapFail(final F f) { - return v -> v.f().map(f); - } - - /** - * Promotes this function to map over the success side of a Validation. - * - * @return This function promoted to map over the success side of a Validation. - */ - public static F, Validation> mapSuccess(final F f) { - return v -> v.map(f); - } - - /** - * Returns a function that returns the failure side of a given Validation, - * or this function applied to the success side. - * - * @return a function that returns the failure side of a given Validation, - * or this function applied to the success side. - */ - public static F, B> onFail(final F f) { - return v -> v.f().on(f); - } - - /** - * Returns a function that returns the success side of a given Validation, - * or this function applied to the failure side. - * - * @return a function that returns the success side of a given Validation, - * or this function applied to the failure side. - */ - public static F, B> onSuccess(final F f) { - return v -> v.on(f); - } - - /** - * Promotes this function to return its value in a Zipper. - * - * @return This function promoted to return its value in a Zipper. - */ - public static F> zipperK(final F f) { - return andThen(streamK(f), s -> fromStream(s).some()); - } - - /** - * Promotes this function to map over a Zipper. - * - * @return This function promoted to map over a Zipper. - */ - public static F, Zipper> mapZipper(final F f) { - return z -> z.map(f); - } - - /** - * Promotes this function to map over an Equal as a contravariant functor. - * - * @return This function promoted to map over an Equal as a contravariant functor. - */ - public static F, Equal> contramapEqual(final F f) { - return e -> e.contramap(f); - } - - /** - * Promotes this function to map over a Hash as a contravariant functor. - * - * @return This function promoted to map over a Hash as a contravariant functor. - */ - public static F, Hash> contramapHash(final F f) { - return h -> h.contramap(f); - } - - /** - * Promotes this function to map over a Show as a contravariant functor. - * - * @return This function promoted to map over a Show as a contravariant functor. - */ - public static F, Show> contramapShow(final F f) { - return s -> s.contramap(f); - } - - /** - * Promotes this function to map over the first element of a pair. - * - * @return This function promoted to map over the first element of a pair. - */ - public static F, P2> mapFst(final F f) { - return P2.map1_(f); - } - - /** - * Promotes this function to map over the second element of a pair. - * - * @return This function promoted to map over the second element of a pair. - */ - public static F, P2> mapSnd(final F f) { - return P2.map2_(f); - } - - /** - * Promotes this function to map over both elements of a pair. - * - * @return This function promoted to map over both elements of a pair. - */ - public static F, P2> mapBoth(final F f) { - return p2 -> P2.map(f, p2); - } - - /** - * Maps this function over a SynchronousQueue. - * - * @param as A SynchronousQueue to map this function over. - * @return A new SynchronousQueue with this function applied to each element. - */ - public static SynchronousQueue mapJ(final F f, final SynchronousQueue as) { - final SynchronousQueue bs = new SynchronousQueue<>(); - bs.addAll(iterableStream(as).map(f).toCollection()); - return bs; - } - - - /** - * Maps this function over a PriorityBlockingQueue. - * - * @param as A PriorityBlockingQueue to map this function over. - * @return A new PriorityBlockingQueue with this function applied to each element. - */ - public static PriorityBlockingQueue mapJ(final F f, final PriorityBlockingQueue as) { - return new PriorityBlockingQueue<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over a LinkedBlockingQueue. - * - * @param as A LinkedBlockingQueue to map this function over. - * @return A new LinkedBlockingQueue with this function applied to each element. - */ - public static LinkedBlockingQueue mapJ(final F f, final LinkedBlockingQueue as) { - return new LinkedBlockingQueue<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over a CopyOnWriteArraySet. - * - * @param as A CopyOnWriteArraySet to map this function over. - * @return A new CopyOnWriteArraySet with this function applied to each element. - */ - public static CopyOnWriteArraySet mapJ(final F f, final CopyOnWriteArraySet as) { - return new CopyOnWriteArraySet<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over a CopyOnWriteArrayList. - * - * @param as A CopyOnWriteArrayList to map this function over. - * @return A new CopyOnWriteArrayList with this function applied to each element. - */ - public static CopyOnWriteArrayList mapJ(final F f, final CopyOnWriteArrayList as) { - return new CopyOnWriteArrayList<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over a ConcurrentLinkedQueue. - * - * @param as A ConcurrentLinkedQueue to map this function over. - * @return A new ConcurrentLinkedQueue with this function applied to each element. - */ - public static ConcurrentLinkedQueue mapJ(final F f, final ConcurrentLinkedQueue as) { - return new ConcurrentLinkedQueue<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over an ArrayBlockingQueue. - * - * @param as An ArrayBlockingQueue to map this function over. - * @return A new ArrayBlockingQueue with this function applied to each element. - */ - public static ArrayBlockingQueue mapJ(final F f, final ArrayBlockingQueue as) { - final ArrayBlockingQueue bs = new ArrayBlockingQueue<>(as.size()); - bs.addAll(iterableStream(as).map(f).toCollection()); - return bs; - } - - - /** - * Maps this function over a TreeSet. - * - * @param as A TreeSet to map this function over. - * @return A new TreeSet with this function applied to each element. - */ - public static TreeSet mapJ(final F f, final TreeSet as) { - return new TreeSet<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over a PriorityQueue. - * - * @param as A PriorityQueue to map this function over. - * @return A new PriorityQueue with this function applied to each element. - */ - public static PriorityQueue mapJ(final F f, final PriorityQueue as) { - return new PriorityQueue<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over a LinkedList. - * - * @param as A LinkedList to map this function over. - * @return A new LinkedList with this function applied to each element. - */ - public static LinkedList mapJ(final F f, final LinkedList as) { - return new LinkedList<>(iterableStream(as).map(f).toCollection()); - } - - /** - * Maps this function over an ArrayList. - * - * @param as An ArrayList to map this function over. - * @return A new ArrayList with this function applied to each element. - */ - public static ArrayList mapJ(final F f, final ArrayList as) { - return new ArrayList<>(iterableStream(as).map(f).toCollection()); - } - - public static F map(F target, F f) { - return o(f, target); - } - - public static F contramap(F target, F f) { - return o(target, f); - } - - /** - * Both map (with g) and contramap (with f) the target function. (Profunctor pattern) - */ - public static F dimap(F target, F f, F g) { - return c -> g.f(target.f(f.f(c))); - } - -} diff --git a/core/src/main/java/fj/F1W.java b/core/src/main/java/fj/F1W.java deleted file mode 100644 index 611c9e01..00000000 --- a/core/src/main/java/fj/F1W.java +++ /dev/null @@ -1,687 +0,0 @@ -package fj; - -import fj.control.parallel.Actor; -import fj.control.parallel.Promise; -import fj.control.parallel.Strategy; -import fj.data.*; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.PriorityQueue; -import java.util.TreeSet; -import java.util.concurrent.*; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F1W implements F { - - /** - * Function composition - * - * @param g A function to compose with this one. - * @return The composed function such that this function is applied last. - */ - public final F1W o(final F g) { - return lift(F1Functions.o(this, g)); - } - - /** - * First-class function composition - * - * @return A function that composes this function with another. - */ - public final F1W, F> o() { - return lift(F1Functions.o(this)); - } - - /** - * Function composition flipped. - * - * @param g A function with which to compose this one. - * @return The composed function such that this function is applied first. - */ - @SuppressWarnings("unchecked") - public final F1W andThen(final F g) { - return lift(F1Functions.andThen(this, g)); - } - - /** - * First-class composition flipped. - * - * @return A function that invokes this function and then a given function on the result. - */ - public final F1W, F> andThen() { - return lift( F1Functions.andThen(this)); - } - - /** - * Binds a given function across this function (Reader Monad). - * - * @param g A function that takes the return value of this function as an argument, yielding a new function. - * @return A function that invokes this function on its argument and then the given function on the result. - */ - public final F1W bind(final F> g) { - return lift(F1Functions.bind(this, g)); - } - - - /** - * First-class function binding. - * - * @return A function that binds another function across this function. - */ - public final F1W>, F> bind() { - return lift(F1Functions.bind(this)); - } - - /** - * Function application in an environment (Applicative Functor). - * - * @param g A function with the same argument type as this function, yielding a function that takes the return - * value of this function. - * @return A new function that invokes the given function on its argument, yielding a new function that is then - * applied to the result of applying this function to the argument. - */ - public final F1W apply(final F> g) { - return lift(F1Functions.apply(this, g)); - } - - - /** - * First-class function application in an environment. - * - * @return A function that applies a given function within the environment of this function. - */ - public final F1W>, F> apply() { - return lift(F1Functions.apply(this)); - } - - /** - * Applies this function over the arguments of another function. - * - * @param g The function over whose arguments to apply this function. - * @return A new function that invokes this function on its arguments before invoking the given function. - */ - public final F1W> on(final F> g) { - return lift(F1Functions.on(this, g)); - } - - - /** - * Applies this function over the arguments of another function. - * - * @return A function that applies this function over the arguments of another function. - */ - public final F1W>, F>> on() { - return lift(F1Functions.on(this)); - } - - /** - * Promotes this function so that it returns its result in a product-1. Kleisli arrow for P1. - * - * @return This function promoted to return its result in a product-1. - */ - public final F1W> lazy() { - return lift(F1Functions.lazy(this)); - } - - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument to return a lazy value. - */ - public final P1 lazy(final A a) { - return F1Functions.f(this, a); - } - - /** - * Promotes this function to map over a product-1. - * - * @return This function promoted to map over a product-1. - */ - public final F1W, P1> mapP1() { - return lift(F1Functions.mapP1(this)); - } - - /** - * Promotes this function so that it returns its result in an Option. Kleisli arrow for Option. - * - * @return This function promoted to return its result in an Option. - */ - public final F1W> optionK() { - return lift(F1Functions.optionK(this)); - } - - - /** - * Promotes this function to map over an optional value. - * - * @return This function promoted to map over an optional value. - */ - public final F1W, Option> mapOption() { - return lift(F1Functions.mapOption(this)); - } - - /** - * Promotes this function so that it returns its result in a List. Kleisli arrow for List. - * - * @return This function promoted to return its result in a List. - */ - public final F1W> listK() { - return lift( F1Functions.listK(this)); - } - - /** - * Promotes this function to map over a List. - * - * @return This function promoted to map over a List. - */ - public final F1W, List> mapList() { - return lift(F1Functions.mapList(this)); - } - - /** - * Promotes this function so that it returns its result in a Stream. Kleisli arrow for Stream. - * - * @return This function promoted to return its result in a Stream. - */ - public final F1W> streamK() { - return lift(F1Functions.streamK(this)); - } - - /** - * Promotes this function to map over a Stream. - * - * @return This function promoted to map over a Stream. - */ - public final F1W, Stream> mapStream() { - return lift(F1Functions.mapStream(this)); - } - - /** - * Promotes this function so that it returns its result in a Array. Kleisli arrow for Array. - * - * @return This function promoted to return its result in a Array. - */ - public final F1W> arrayK() { - return lift(F1Functions.arrayK(this)); - - } - - /** - * Promotes this function to map over a Array. - * - * @return This function promoted to map over a Array. - */ - public final F1W, Array> mapArray() { - return lift(F1Functions.mapArray(this)); - } - - /** - * Returns a function that contramaps over a given actor. - * - * @return A function that contramaps over a given actor. - */ - public final F1W, Actor> contramapActor() { - return lift(F1Functions.contramapActor(this)); - } - - /** - * Promotes this function to a concurrent function that returns a Promise of a value. - * - * @param s A parallel strategy for concurrent execution. - * @return A concurrent function that returns a Promise of a value. - */ - public final F1W> promiseK(final Strategy s) { - return lift(F1Functions.promiseK(this, s)); - } - - /** - * Promotes this function to map over a Promise. - * - * @return This function promoted to map over Promises. - */ - public final F1W, Promise> mapPromise() { - return lift(F1Functions.mapPromise(this)); - } - - /** - * Promotes this function so that it returns its result on the left side of an Either. - * Kleisli arrow for the Either left projection. - * - * @return This function promoted to return its result on the left side of an Either. - */ - @SuppressWarnings("unchecked") - public final F1W> eitherLeftK() { - return lift(F1Functions.eitherLeftK(this)); - } - - /** - * Promotes this function so that it returns its result on the right side of an Either. - * Kleisli arrow for the Either right projection. - * - * @return This function promoted to return its result on the right side of an Either. - */ - @SuppressWarnings("unchecked") - public final F1W> eitherRightK() { - return lift(F1Functions.eitherRightK(this)); - } - - /** - * Promotes this function to map over the left side of an Either. - * - * @return This function promoted to map over the left side of an Either. - */ - @SuppressWarnings("unchecked") - public final F1W, Either> mapLeft() { - return lift(F1Functions.mapLeft(this)); - } - - /** - * Promotes this function to map over the right side of an Either. - * - * @return This function promoted to map over the right side of an Either. - */ - @SuppressWarnings("unchecked") - public final F1W, Either> mapRight() { - return lift(F1Functions.mapRight(this)); - } - - /** - * Returns a function that returns the left side of a given Either, or this function applied to the right side. - * - * @return a function that returns the left side of a given Either, or this function applied to the right side. - */ - public final F1W, B> onLeft() { - return lift(F1Functions.onLeft(this)); - } - - /** - * Returns a function that returns the right side of a given Either, or this function applied to the left side. - * - * @return a function that returns the right side of a given Either, or this function applied to the left side. - */ - public final F1W, B> onRight() { - return lift(F1Functions.onRight(this)); - } - - /** - * Promotes this function to return its value in an Iterable. - * - * @return This function promoted to return its value in an Iterable. - */ - @SuppressWarnings("unchecked") - public final F1W> iterableK() { - return lift( F1Functions.iterableK(this)); - } - - /** - * Promotes this function to map over Iterables. - * - * @return This function promoted to map over Iterables. - */ - @SuppressWarnings("unchecked") - public final F1W, IterableW> mapIterable() { - return lift( F1Functions.mapIterable(this)); - } - - /** - * Promotes this function to return its value in a NonEmptyList. - * - * @return This function promoted to return its value in a NonEmptyList. - */ - @SuppressWarnings("unchecked") - public final F1W> nelK() { - return lift(F1Functions.nelK(this)); - } - - /** - * Promotes this function to map over a NonEmptyList. - * - * @return This function promoted to map over a NonEmptyList. - */ - public final F1W, NonEmptyList> mapNel() { - return lift(F1Functions.mapNel(this)); - } - - /** - * Promotes this function to return its value in a Set. - * - * @param o An order for the set. - * @return This function promoted to return its value in a Set. - */ - public final F1W> setK(final Ord o) { - return lift(F1Functions.setK(this, o)); - } - - /** - * Promotes this function to map over a Set. - * - * @param o An order for the resulting set. - * @return This function promoted to map over a Set. - */ - public final F1W, Set> mapSet(final Ord o) { - return lift(F1Functions.mapSet(this, o)); - } - - /** - * Promotes this function to return its value in a Tree. - * - * @return This function promoted to return its value in a Tree. - */ - public final F1W> treeK() { - return lift(F1Functions.treeK(this)); - } - - /** - * Promotes this function to map over a Tree. - * - * @return This function promoted to map over a Tree. - */ - @SuppressWarnings("unchecked") - public final F1W, Tree> mapTree() { - return lift(F1Functions.mapTree(this)); - } - - /** - * Returns a function that maps this function over a tree and folds it with the given monoid. - * - * @param m The monoid with which to fold the mapped tree. - * @return a function that maps this function over a tree and folds it with the given monoid. - */ - public final F1W, B> foldMapTree(final Monoid m) { - return lift(F1Functions.foldMapTree(this, m)); - } - - /** - * Promotes this function to return its value in a TreeZipper. - * - * @return This function promoted to return its value in a TreeZipper. - */ - public final F1W> treeZipperK() { - return lift(F1Functions.treeZipperK(this)); - } - - /** - * Promotes this function to map over a TreeZipper. - * - * @return This function promoted to map over a TreeZipper. - */ - public final F1W, TreeZipper> mapTreeZipper() { - return lift(F1Functions.mapTreeZipper(this)); - } - - /** - * Promotes this function so that it returns its result on the failure side of a Validation. - * Kleisli arrow for the Validation failure projection. - * - * @return This function promoted to return its result on the failure side of a Validation. - */ - public final F1W> failK() { - return lift(F1Functions.failK(this)); - } - - /** - * Promotes this function so that it returns its result on the success side of an Validation. - * Kleisli arrow for the Validation success projection. - * - * @return This function promoted to return its result on the success side of an Validation. - */ - public final F1W> successK() { - return lift( F1Functions.successK(this)); - } - - /** - * Promotes this function to map over the failure side of a Validation. - * - * @return This function promoted to map over the failure side of a Validation. - */ - public final F1W, Validation> mapFail() { - return lift(F1Functions.mapFail(this)); - } - - /** - * Promotes this function to map over the success side of a Validation. - * - * @return This function promoted to map over the success side of a Validation. - */ - public final F1W, Validation> mapSuccess() { - return lift(F1Functions.mapSuccess(this)); - } - - /** - * Returns a function that returns the failure side of a given Validation, - * or this function applied to the success side. - * - * @return a function that returns the failure side of a given Validation, - * or this function applied to the success side. - */ - public final F1W, B> onFail() { - return lift(F1Functions.onFail(this)); - } - - /** - * Returns a function that returns the success side of a given Validation, - * or this function applied to the failure side. - * - * @return a function that returns the success side of a given Validation, - * or this function applied to the failure side. - */ - public final F1W, B> onSuccess() { - return lift(F1Functions.onSuccess(this)); - } - - /** - * Promotes this function to return its value in a Zipper. - * - * @return This function promoted to return its value in a Zipper. - */ - public final F1W> zipperK() { - return lift(F1Functions.zipperK(this)); - } - - /** - * Promotes this function to map over a Zipper. - * - * @return This function promoted to map over a Zipper. - */ - public final F1W, Zipper> mapZipper() { - return lift(F1Functions.mapZipper(this)); - } - - /** - * Promotes this function to map over an Equal as a contravariant functor. - * - * @return This function promoted to map over an Equal as a contravariant functor. - */ - public final F1W, Equal> contramapEqual() { - return lift(F1Functions.contramapEqual(this)); - } - - /** - * Promotes this function to map over a Hash as a contravariant functor. - * - * @return This function promoted to map over a Hash as a contravariant functor. - */ - public final F1W, Hash> contramapHash() { - return lift(F1Functions.contramapHash(this)); - } - - /** - * Promotes this function to map over a Show as a contravariant functor. - * - * @return This function promoted to map over a Show as a contravariant functor. - */ - public final F1W, Show> contramapShow() { - return lift(F1Functions.contramapShow(this)); - } - - /** - * Promotes this function to map over the first element of a pair. - * - * @return This function promoted to map over the first element of a pair. - */ - public final F1W, P2> mapFst() { - return lift(F1Functions.mapFst(this)); - } - - /** - * Promotes this function to map over the second element of a pair. - * - * @return This function promoted to map over the second element of a pair. - */ - public final F1W, P2> mapSnd() { - return lift(F1Functions.mapSnd(this)); - } - - /** - * Promotes this function to map over both elements of a pair. - * - * @return This function promoted to map over both elements of a pair. - */ - public final F1W, P2> mapBoth() { - return lift(F1Functions.mapBoth(this)); - } - - /** - * Maps this function over a SynchronousQueue. - * - * @param as A SynchronousQueue to map this function over. - * @return A new SynchronousQueue with this function applied to each element. - */ - public final SynchronousQueue mapJ(final SynchronousQueue as) { - return F1Functions.mapJ(this, as); - } - - - /** - * Maps this function over a PriorityBlockingQueue. - * - * @param as A PriorityBlockingQueue to map this function over. - * @return A new PriorityBlockingQueue with this function applied to each element. - */ - public final PriorityBlockingQueue mapJ(final PriorityBlockingQueue as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over a LinkedBlockingQueue. - * - * @param as A LinkedBlockingQueue to map this function over. - * @return A new LinkedBlockingQueue with this function applied to each element. - */ - public final LinkedBlockingQueue mapJ(final LinkedBlockingQueue as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over a CopyOnWriteArraySet. - * - * @param as A CopyOnWriteArraySet to map this function over. - * @return A new CopyOnWriteArraySet with this function applied to each element. - */ - public final CopyOnWriteArraySet mapJ(final CopyOnWriteArraySet as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over a CopyOnWriteArrayList. - * - * @param as A CopyOnWriteArrayList to map this function over. - * @return A new CopyOnWriteArrayList with this function applied to each element. - */ - public final CopyOnWriteArrayList mapJ(final CopyOnWriteArrayList as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over a ConcurrentLinkedQueue. - * - * @param as A ConcurrentLinkedQueue to map this function over. - * @return A new ConcurrentLinkedQueue with this function applied to each element. - */ - public final ConcurrentLinkedQueue mapJ(final ConcurrentLinkedQueue as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over an ArrayBlockingQueue. - * - * @param as An ArrayBlockingQueue to map this function over. - * @return A new ArrayBlockingQueue with this function applied to each element. - */ - public final ArrayBlockingQueue mapJ(final ArrayBlockingQueue as) { - return F1Functions.mapJ(this, as); - } - - - /** - * Maps this function over a TreeSet. - * - * @param as A TreeSet to map this function over. - * @return A new TreeSet with this function applied to each element. - */ - public final TreeSet mapJ(final TreeSet as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over a PriorityQueue. - * - * @param as A PriorityQueue to map this function over. - * @return A new PriorityQueue with this function applied to each element. - */ - public final PriorityQueue mapJ(final PriorityQueue as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over a LinkedList. - * - * @param as A LinkedList to map this function over. - * @return A new LinkedList with this function applied to each element. - */ - public final LinkedList mapJ(final LinkedList as) { - return F1Functions.mapJ(this, as); - } - - /** - * Maps this function over an ArrayList. - * - * @param as An ArrayList to map this function over. - * @return A new ArrayList with this function applied to each element. - */ - public final ArrayList mapJ(final ArrayList as) { - return F1Functions.mapJ(this, as); - } - - public final F1W map(F f) { - return lift(F1Functions.map(this, f)); - } - - public final F1W contramap(F f) { - return lift(F1Functions.contramap(this, f)); - } - - public static class F1WFunc extends F1W { - final F func; - public F1WFunc(F f) { - func = f; - } - - @Override - public final B f(A a) { - return func.f(a); - } - } - - /** - * Lifts the function into the fully featured function wrapper - */ - public static F1W lift(final F f) { - return new F1WFunc<>(f); - } -} diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index 63555fd5..ba0e6f2f 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -1,12 +1,24 @@ package fj; +import fj.control.parallel.Promise; +import fj.data.*; + +import java.util.function.BiFunction; + +import static fj.P.p; +import static fj.data.IterableW.wrap; +import static fj.data.Set.iterableSet; +import static fj.data.Tree.node; +import static fj.data.TreeZipper.treeZipper; +import static fj.data.Zipper.zipper; + /** * A transformation function of arity-2 from A and B to C. * This type can be represented using the Java 7 closure syntax. * * @version %build.number% */ -public interface F2 { +public interface F2 extends BiFunction { /** * Transform A and B to C. * @@ -16,4 +28,264 @@ public interface F2 { */ C f(A a, B b); + default C apply(A a, B b) { + return f(a, b); + } + + /** + * Partial application. + * + * @param a The A to which to apply this function. + * @return The function partially applied to the given argument. + */ + default F f(final A a) { + return b -> f(a, b); + } + + /** + * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function. + * + * @return a wrapped function of arity-1 that returns another wrapped function. + */ + default F> curry() { + return a -> b -> f(a, b); + } + + /** + * Flips the arguments of this function. + * + * @return A new function with the arguments of this function flipped. + */ + default F2 flip() { + return (b, a) -> f(a, b); + } + + /** + * Uncurries this function to a function on tuples. + * + * @return A new function that calls this function with the elements of a given tuple. + */ + default F, C> tuple() { + return p -> f(p._1(), p._2()); + } + + /** + * Promotes this function to a function on Arrays. + * + * @return This function promoted to transform Arrays. + */ + default F2, Array, Array> arrayM() { + return (a, b) -> a.bind(b, curry()); + } + + /** + * Promotes this function to a function on Promises. + * + * @return This function promoted to transform Promises. + */ + default F2, Promise, Promise> promiseM() { + return (a, b) -> a.bind(b, curry()); + } + + /** + * Promotes this function to a function on Iterables. + * + * @return This function promoted to transform Iterables. + */ + default F2, Iterable, IterableW> iterableM() { + return (a, b) -> IterableW.liftM2(curry()).f(a).f(b); + } + + /** + * Promotes this function to a function on Lists. + * + * @return This function promoted to transform Lists. + */ + default F2, List, List> listM() { + return (a, b) -> List.liftM2(curry()).f(a).f(b); + } + + /** + * Promotes this function to a function on non-empty lists. + * + * @return This function promoted to transform non-empty lists. + */ + default F2, NonEmptyList, NonEmptyList> nelM() { + return (as, bs) -> NonEmptyList.fromList(as.toList().bind(bs.toList(), this)).some(); + } + + /** + * Promotes this function to a function on Options. + * + * @return This function promoted to transform Options. + */ + default F2, Option, Option> optionM() { + return (a, b) -> Option.liftM2(curry()).f(a).f(b); + } + + /** + * Promotes this function to a function on Sets. + * + * @param o An ordering for the result of the promoted function. + * @return This function promoted to transform Sets. + */ + default F2, Set, Set> setM(final Ord o) { + return (as, bs) -> { + Set cs = Set.empty(o); + for (final A a : as) + for (final B b : bs) + cs = cs.insert(f(a, b)); + return cs; + }; + } + + /** + * Promotes this function to a function on Streams. + * + * @return This function promoted to transform Streams. + */ + default F2, Stream, Stream> streamM() { + return (as, bs) -> as.bind(bs, this); + } + + /** + * Promotes this function to a function on Trees. + * + * @return This function promoted to transform Trees. + */ + default F2, Tree, Tree> treeM() { + F2 outer = this; + return new F2, Tree, Tree>() { + public Tree f(final Tree as, final Tree bs) { + final F2, Tree, Tree> self = this; + return node(outer.f(as.root(), bs.root()), P.lazy(() -> self.streamM().f(as.subForest()._1(), bs.subForest()._1()))); + } + }; + } + + /** + * Promotes this function to zip two arrays, applying the function lock-step over both Arrays. + * + * @return A function that zips two arrays with this function. + */ + default F2, Array, Array> zipArrayM() { + return (as, bs) -> as.zipWith(bs, this); + } + + /** + * Promotes this function to zip two iterables, applying the function lock-step over both iterables. + * + * @return A function that zips two iterables with this function. + */ + default F2, Iterable, Iterable> zipIterableM() { + return (as, bs) -> wrap(as).zipWith(bs, this); + } + + /** + * Promotes this function to zip two lists, applying the function lock-step over both lists. + * + * @return A function that zips two lists with this function. + */ + default F2, List, List> zipListM() { + return (as, bs) -> as.zipWith(bs, this); + } + + + /** + * Promotes this function to zip two streams, applying the function lock-step over both streams. + * + * @return A function that zips two streams with this function. + */ + default F2, Stream, Stream> zipStreamM() { + return (as, bs) -> as.zipWith(bs, this); + } + + /** + * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists. + * + * @return A function that zips two non-empty lists with this function. + */ + default F2, NonEmptyList, NonEmptyList> zipNelM() { + return (as, bs) -> NonEmptyList.fromList(as.toList().zipWith(bs.toList(), this)).some(); + } + + /** + * Promotes this function to zip two sets, applying the function lock-step over both sets. + * + * @param o An ordering for the resulting set. + * @return A function that zips two sets with this function. + */ + default F2, Set, Set> zipSetM(final Ord o) { + return (as, bs) -> iterableSet(o, as.toStream().zipWith(bs.toStream(), this)); + } + + /** + * Promotes this function to zip two trees, applying the function lock-step over both trees. + * The structure of the resulting tree is the structural intersection of the two trees. + * + * @return A function that zips two trees with this function. + */ + default F2, Tree, Tree> zipTreeM() { + F2 outer = this; + return new F2, Tree, Tree>() { + public Tree f(final Tree ta, final Tree tb) { + final F2, Tree, Tree> self = this; + return node(outer.f(ta.root(), tb.root()), P.lazy(() -> self.zipStreamM().f(ta.subForest()._1(), tb.subForest()._1()))); + } + }; + } + + /** + * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions. + * The structure of the resulting zipper is the structural intersection of the two zippers. + * + * @return A function that zips two zippers with this function. + */ + default F2, Zipper, Zipper> zipZipperM() { + return (ta, tb) -> { + final F2, Stream, Stream> sf = this.zipStreamM(); + return zipper(sf.f(ta.lefts(), tb.lefts()), f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); + }; + } + + /** + * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions. + * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. + * + * @return A function that zips two TreeZippers with this function. + */ + default F2, TreeZipper, TreeZipper> zipTreeZipperM() { + F2 outer = this; + return (ta, tb) -> { + final F2>, Stream>, Stream>> sf = outer.treeM().zipStreamM(); + F2>, A, Stream>>, P3>, B, Stream>>, P3>, C, Stream>>> g = + (pa, pb) -> p(outer.treeM().zipStreamM().f(pa._1(), pb._1()), outer.f(pa._2(), pb._2()), + outer.treeM().zipStreamM().f(pa._3(), pb._3())); + final + F2>, A, Stream>>>, + Stream>, B, Stream>>>, + Stream>, C, Stream>>>> + pf = g.zipStreamM(); + return treeZipper(outer.treeM().f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()), + sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4())); + }; + } + + default F2 contramapFirst(F f) { + return (z, b) -> f(f.f(z), b); + } + + default F2 contramapSecond(F f) { + return (a, z) -> f(a, f.f(z)); + } + + default F2 contramap(F f, F g) { + return contramapFirst(f).contramapSecond(g); + } + + default F2 map(F f) { + return (a, b) -> f.f(f(a, b)); + } + + } diff --git a/core/src/main/java/fj/F2Functions.java b/core/src/main/java/fj/F2Functions.java deleted file mode 100644 index f69e02ed..00000000 --- a/core/src/main/java/fj/F2Functions.java +++ /dev/null @@ -1,273 +0,0 @@ -package fj; - -import fj.control.parallel.Promise; -import fj.data.*; - -import static fj.P.p; -import static fj.data.IterableW.wrap; -import static fj.data.Set.iterableSet; -import static fj.data.Tree.node; -import static fj.data.TreeZipper.treeZipper; -import static fj.data.Zipper.zipper; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F2Functions { - - - private F2Functions() { - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public static F f(final F2 f, final A a) { - return b -> f.f(a, b); - } - - /** - * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function. - * - * @return a wrapped function of arity-1 that returns another wrapped function. - */ - public static F> curry(final F2 f) { - return a -> b -> f.f(a, b); - } - - /** - * Flips the arguments of this function. - * - * @return A new function with the arguments of this function flipped. - */ - public static F2 flip(final F2 f) { - return (b, a) -> f.f(a, b); - } - - /** - * Uncurries this function to a function on tuples. - * - * @return A new function that calls this function with the elements of a given tuple. - */ - public static F, C> tuple(final F2 f) { - return p -> f.f(p._1(), p._2()); - } - - /** - * Promotes this function to a function on Arrays. - * - * @return This function promoted to transform Arrays. - */ - public static F2, Array, Array> arrayM(final F2 f) { - return (a, b) -> a.bind(b, curry(f)); - } - - /** - * Promotes this function to a function on Promises. - * - * @return This function promoted to transform Promises. - */ - public static F2, Promise, Promise> promiseM(final F2 f) { - return (a, b) -> a.bind(b, curry(f)); - } - - /** - * Promotes this function to a function on Iterables. - * - * @return This function promoted to transform Iterables. - */ - public static F2, Iterable, IterableW> iterableM(final F2 f) { - return (a, b) -> IterableW.liftM2(curry(f)).f(a).f(b); - } - - /** - * Promotes this function to a function on Lists. - * - * @return This function promoted to transform Lists. - */ - public static F2, List, List> listM(final F2 f) { - return (a, b) -> List.liftM2(curry(f)).f(a).f(b); - } - - /** - * Promotes this function to a function on non-empty lists. - * - * @return This function promoted to transform non-empty lists. - */ - public static F2, NonEmptyList, NonEmptyList> nelM(final F2 f) { - return (as, bs) -> NonEmptyList.fromList(as.toList().bind(bs.toList(), f)).some(); - } - - /** - * Promotes this function to a function on Options. - * - * @return This function promoted to transform Options. - */ - public static F2, Option, Option> optionM(final F2 f) { - return (a, b) -> Option.liftM2(curry(f)).f(a).f(b); - } - - /** - * Promotes this function to a function on Sets. - * - * @param o An ordering for the result of the promoted function. - * @return This function promoted to transform Sets. - */ - public static F2, Set, Set> setM(final F2 f, final Ord o) { - return (as, bs) -> { - Set cs = Set.empty(o); - for (final A a : as) - for (final B b : bs) - cs = cs.insert(f.f(a, b)); - return cs; - }; - } - - /** - * Promotes this function to a function on Streams. - * - * @return This function promoted to transform Streams. - */ - public static F2, Stream, Stream> streamM(final F2 f) { - return (as, bs) -> as.bind(bs, f); - } - - /** - * Promotes this function to a function on Trees. - * - * @return This function promoted to transform Trees. - */ - public static F2, Tree, Tree> treeM(final F2 f) { - return new F2, Tree, Tree>() { - public Tree f(final Tree as, final Tree bs) { - final F2, Tree, Tree> self = this; - return node(f.f(as.root(), bs.root()), P.lazy(() -> streamM(self).f(as.subForest()._1(), bs.subForest()._1()))); - } - }; - } - - /** - * Promotes this function to zip two arrays, applying the function lock-step over both Arrays. - * - * @return A function that zips two arrays with this function. - */ - public static F2, Array, Array> zipArrayM(final F2 f) { - return (as, bs) -> as.zipWith(bs, f); - } - - /** - * Promotes this function to zip two iterables, applying the function lock-step over both iterables. - * - * @return A function that zips two iterables with this function. - */ - public static F2, Iterable, Iterable> zipIterableM(final F2 f) { - return (as, bs) -> wrap(as).zipWith(bs, f); - } - - /** - * Promotes this function to zip two lists, applying the function lock-step over both lists. - * - * @return A function that zips two lists with this function. - */ - public static F2, List, List> zipListM(final F2 f) { - return (as, bs) -> as.zipWith(bs, f); - } - - - /** - * Promotes this function to zip two streams, applying the function lock-step over both streams. - * - * @return A function that zips two streams with this function. - */ - public static F2, Stream, Stream> zipStreamM(final F2 f) { - return (as, bs) -> as.zipWith(bs, f); - } - - /** - * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists. - * - * @return A function that zips two non-empty lists with this function. - */ - public static F2, NonEmptyList, NonEmptyList> zipNelM(final F2 f) { - return (as, bs) -> NonEmptyList.fromList(as.toList().zipWith(bs.toList(), f)).some(); - } - - /** - * Promotes this function to zip two sets, applying the function lock-step over both sets. - * - * @param o An ordering for the resulting set. - * @return A function that zips two sets with this function. - */ - public static F2, Set, Set> zipSetM(final F2 f, final Ord o) { - return (as, bs) -> iterableSet(o, as.toStream().zipWith(bs.toStream(), f)); - } - - /** - * Promotes this function to zip two trees, applying the function lock-step over both trees. - * The structure of the resulting tree is the structural intersection of the two trees. - * - * @return A function that zips two trees with this function. - */ - public static F2, Tree, Tree> zipTreeM(final F2 f) { - return new F2, Tree, Tree>() { - public Tree f(final Tree ta, final Tree tb) { - final F2, Tree, Tree> self = this; - return node(f.f(ta.root(), tb.root()), P.lazy(() -> zipStreamM(self).f(ta.subForest()._1(), tb.subForest()._1()))); - } - }; - } - - /** - * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions. - * The structure of the resulting zipper is the structural intersection of the two zippers. - * - * @return A function that zips two zippers with this function. - */ - public static F2, Zipper, Zipper> zipZipperM(final F2 f) { - return (ta, tb) -> { - final F2, Stream, Stream> sf = zipStreamM(f); - return zipper(sf.f(ta.lefts(), tb.lefts()), f.f(ta.focus(), tb.focus()), sf.f(ta.rights(), tb.rights())); - }; - } - - /** - * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions. - * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. - * - * @return A function that zips two TreeZippers with this function. - */ - public static F2, TreeZipper, TreeZipper> zipTreeZipperM(final F2 f) { - return (ta, tb) -> { - final F2>, Stream>, Stream>> sf = zipStreamM(treeM(f)); - final - F2>, A, Stream>>>, - Stream>, B, Stream>>>, - Stream>, C, Stream>>>> - pf = - zipStreamM((pa, pb) -> p(zipStreamM(treeM(f)).f(pa._1(), pb._1()), f.f(pa._2(), pb._2()), - zipStreamM(treeM(f)).f(pa._3(), pb._3()))); - return treeZipper(treeM(f).f(ta.p()._1(), tb.p()._1()), sf.f(ta.lefts(), tb.lefts()), - sf.f(ta.rights(), tb.rights()), pf.f(ta.p()._4(), tb.p()._4())); - }; - } - - public static F2 contramapFirst(F2 target, F f) { - return (z, b) -> target.f(f.f(z), b); - } - - public static F2 contramapSecond(F2 target, F f) { - return (a, z) -> target.f(a, f.f(z)); - } - - public static F2 contramap(F2 target, F f, F g) { - return contramapSecond(contramapFirst(target, f), g); - } - - public static F2 map(F2 target, F f) { - return (a, b) -> f.f(target.f(a, b)); - } - -} diff --git a/core/src/main/java/fj/F2W.java b/core/src/main/java/fj/F2W.java deleted file mode 100644 index 1f35855a..00000000 --- a/core/src/main/java/fj/F2W.java +++ /dev/null @@ -1,254 +0,0 @@ -package fj; - -import fj.control.parallel.Promise; -import fj.data.*; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F2W implements F2 { - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public final F1W f(final A a) { - return F1W.lift(F2Functions.f(this, a)); - } - - /** - * Curries this wrapped function to a wrapped function of arity-1 that returns another wrapped function. - * - * @return a wrapped function of arity-1 that returns another wrapped function. - */ - public final F1W> curry() { - return F1W.lift(F2Functions.curry(this)); - } - - /** - * Flips the arguments of this function. - * - * @return A new function with the arguments of this function flipped. - */ - public final F2W flip() { - return lift(F2Functions.flip(this)); - } - - /** - * Uncurries this function to a function on tuples. - * - * @return A new function that calls this function with the elements of a given tuple. - */ - public final F1W, C> tuple() { - return F1W.lift(F2Functions.tuple(this)); - } - - /** - * Promotes this function to a function on Arrays. - * - * @return This function promoted to transform Arrays. - */ - public final F2W, Array, Array> arrayM() { - return lift(F2Functions.arrayM(this)); - } - - /** - * Promotes this function to a function on Promises. - * - * @return This function promoted to transform Promises. - */ - public final F2W, Promise, Promise> promiseM() { - return lift(F2Functions.promiseM(this)); - } - - /** - * Promotes this function to a function on Iterables. - * - * @return This function promoted to transform Iterables. - */ - public final F2W, Iterable, IterableW> iterableM() { - return lift(F2Functions.iterableM(this)); - } - - /** - * Promotes this function to a function on Lists. - * - * @return This function promoted to transform Lists. - */ - public final F2W, List, List> listM() { - return lift(F2Functions.listM(this)); - } - - /** - * Promotes this function to a function on non-empty lists. - * - * @return This function promoted to transform non-empty lists. - */ - public final F2W, NonEmptyList, NonEmptyList> nelM() { - return lift(F2Functions.nelM(this)); - } - - /** - * Promotes this function to a function on Options. - * - * @return This function promoted to transform Options. - */ - public final F2W, Option, Option> optionM() { - return lift(F2Functions.optionM(this)); - } - - /** - * Promotes this function to a function on Sets. - * - * @param o An ordering for the result of the promoted function. - * @return This function promoted to transform Sets. - */ - public final F2W, Set, Set> setM(final Ord o) { - return lift(F2Functions.setM(this, o)); - } - - /** - * Promotes this function to a function on Streams. - * - * @return This function promoted to transform Streams. - */ - public final F2W, Stream, Stream> streamM() { - return lift(F2Functions.streamM(this)); - } - - /** - * Promotes this function to a function on Trees. - * - * @return This function promoted to transform Trees. - */ - public final F2W, Tree, Tree> treeM() { - return lift(F2Functions.treeM(this)); - } - - /** - * Promotes this function to zip two arrays, applying the function lock-step over both Arrays. - * - * @return A function that zips two arrays with this function. - */ - public final F2W, Array, Array> zipArrayM() { - return lift(F2Functions.zipArrayM(this)); - } - - /** - * Promotes this function to zip two iterables, applying the function lock-step over both iterables. - * - * @return A function that zips two iterables with this function. - */ - public final F2W, Iterable, Iterable> zipIterableM() { - return lift(F2Functions.zipIterableM(this)); - } - - /** - * Promotes this function to zip two lists, applying the function lock-step over both lists. - * - * @return A function that zips two lists with this function. - */ - public final F2W, List, List> zipListM() { - return lift(F2Functions.zipListM(this)); - } - - - /** - * Promotes this function to zip two streams, applying the function lock-step over both streams. - * - * @return A function that zips two streams with this function. - */ - public final F2W, Stream, Stream> zipStreamM() { - return lift(F2Functions.zipStreamM(this)); - } - - /** - * Promotes this function to zip two non-empty lists, applying the function lock-step over both lists. - * - * @return A function that zips two non-empty lists with this function. - */ - public final F2W, NonEmptyList, NonEmptyList> zipNelM() { - return lift(F2Functions.zipNelM(this)); - } - - /** - * Promotes this function to zip two sets, applying the function lock-step over both sets. - * - * @param o An ordering for the resulting set. - * @return A function that zips two sets with this function. - */ - public final F2W, Set, Set> zipSetM(final Ord o) { - return lift(F2Functions.zipSetM(this, o)); - } - - /** - * Promotes this function to zip two trees, applying the function lock-step over both trees. - * The structure of the resulting tree is the structural intersection of the two trees. - * - * @return A function that zips two trees with this function. - */ - public final F2W, Tree, Tree> zipTreeM() { - return lift(F2Functions.zipTreeM(this)); - } - - /** - * Promotes this function to zip two zippers, applying the function lock-step over both zippers in both directions. - * The structure of the resulting zipper is the structural intersection of the two zippers. - * - * @return A function that zips two zippers with this function. - */ - public final F2W, Zipper, Zipper> zipZipperM() { - return lift(F2Functions.zipZipperM(this)); - } - - /** - * Promotes this function to zip two TreeZippers, applying the function lock-step over both zippers in all directions. - * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. - * - * @return A function that zips two TreeZippers with this function. - */ - public final F2W, TreeZipper, TreeZipper> zipTreeZipperM() { - return lift(F2Functions.zipTreeZipperM(this)); - } - - public final F2W contramapFirst(F f) { - return lift(F2Functions.contramapFirst(this, f)); - } - - public final F2W contramapSecond(F f) { - return lift(F2Functions.contramapSecond(this, f)); - } - - public final F2W contramap(F f, F g) { - return lift(F2Functions.contramap(this, f, g)); - } - - public final F2W map(F f) { - return lift(F2Functions.map(this, f)); - } - - - public static class F2WFunc extends F2W { - final F2 func; - public F2WFunc(F2 f) { - func = f; - } - - @Override - public final C f(A a, B b) { - return func.f(a, b); - } - } - - /** - * Lifts the function into the fully featured function wrapper - */ - public static F2W lift(final F2 f) { - return new F2WFunc<>(f); - } - - - -} diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 490dc9d6..96d24b82 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -1,7 +1,5 @@ package fj; -import static fj.F1Functions.dimap; - import fj.data.*; import static fj.Function.*; @@ -146,7 +144,7 @@ public B append(B a1, B a2) { @Override public F prepend(B b) { - return dimap(def.prepend(g.f(b)), g, f); + return def.prepend(g.f(b)).dimap(g, f); } @Override diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 5e627403..420b820b 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -108,7 +108,7 @@ public final P1 bind(final P1 cb, final F> f) { * Binds the given function to the values in the given P1s with a final join. */ public final P1 bind(final P1 cb, final F2 f) { - return bind(cb, F2W.lift(f).curry()); + return bind(cb, f.curry()); } /** diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index b434a0da..841b356e 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -166,7 +166,7 @@ public final Stream sequenceW(final Stream, C>> fs) { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P2.__1()).f(this); + return P2.__1().lazy().f(this); } /** @@ -175,7 +175,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P2.__2()).f(this); + return P2.__2().lazy().f(this); } /** diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index fe980059..6e08a0ba 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -101,7 +101,7 @@ public X _3() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P3.__1()).f(this); + return P3.__1().lazy().f(this); } /** @@ -110,7 +110,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P3.__2()).f(this); + return P3.__2().lazy().f(this); } /** @@ -119,7 +119,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return F1Functions.lazy(P3.__3()).f(this); + return P3.__3().lazy().f(this); } diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index a7bf8167..4fa2ef8c 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -146,7 +146,7 @@ public X _4() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P4.__1()).f(this); + return P4.__1().lazy().f(this); } /** @@ -155,7 +155,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P4.__2()).f(this); + return P4.__2().lazy().f(this); } /** @@ -164,7 +164,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return F1Functions.lazy(P4.__3()).f(this); + return P4.__3().lazy().f(this); } /** @@ -173,7 +173,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return F1Functions.lazy(P4.__4()).f(this); + return P4.__4().lazy().f(this); } diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index 69262327..fabc4227 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -199,7 +199,7 @@ public X _5() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P5.__1()).f(this); + return P5.__1().lazy().f(this); } /** @@ -208,7 +208,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P5.__2()).f(this); + return P5.__2().lazy().f(this); } /** @@ -217,7 +217,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return F1Functions.lazy(P5.__3()).f(this); + return P5.__3().lazy().f(this); } /** @@ -226,7 +226,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return F1Functions.lazy(P5.__4()).f(this); + return P5.__4().lazy().f(this); } /** @@ -235,7 +235,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return F1Functions.lazy(P5.__5()).f(this); + return P5.__5().lazy().f(this); } /** diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index fbf91948..670622c7 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -261,7 +261,7 @@ public X _6() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P6.__1()).f(this); + return P6.__1().lazy().f(this); } /** @@ -270,7 +270,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P6.__2()).f(this); + return P6.__2().lazy().f(this); } /** @@ -279,7 +279,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return F1Functions.lazy(P6.__3()).f(this); + return P6.__3().lazy().f(this); } /** @@ -288,7 +288,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return F1Functions.lazy(P6.__4()).f(this); + return P6.__4().lazy().f(this); } /** @@ -297,7 +297,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return F1Functions.lazy(P6.__5()).f(this); + return P6.__5().lazy().f(this); } /** @@ -306,7 +306,7 @@ public final P1 _5_() { * @return the 1-product projection over the sixth element. */ public final P1 _6_() { - return F1Functions.lazy(P6.__6()).f(this); + return P6.__6().lazy().f(this); } /** diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index b1c67b30..6c9ac804 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -330,7 +330,7 @@ public X _7() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P7.__1()).f(this); + return P7.__1().lazy().f(this); } /** @@ -339,7 +339,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P7.__2()).f(this); + return P7.__2().lazy().f(this); } /** @@ -348,7 +348,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return F1Functions.lazy(P7.__3()).f(this); + return P7.__3().lazy().f(this); } /** @@ -357,7 +357,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return F1Functions.lazy(P7.__4()).f(this); + return P7.__4().lazy().f(this); } /** @@ -366,7 +366,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return F1Functions.lazy(P7.__5()).f(this); + return P7.__5().lazy().f(this); } /** @@ -375,7 +375,7 @@ public final P1 _5_() { * @return the 1-product projection over the sixth element. */ public final P1 _6_() { - return F1Functions.lazy(P7.__6()).f(this); + return P7.__6().lazy().f(this); } /** @@ -384,7 +384,7 @@ public final P1 _6_() { * @return the 1-product projection over the seventh element. */ public final P1 _7_() { - return F1Functions.lazy(P7.__7()).f(this); + return P7.__7().lazy().f(this); } /** diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index f15d63a1..f3902c5e 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -408,7 +408,7 @@ public X _8() { * @return the 1-product projection over the first element. */ public final P1 _1_() { - return F1Functions.lazy(P8.__1()).f(this); + return P8.__1().lazy().f(this); } /** @@ -417,7 +417,7 @@ public final P1 _1_() { * @return the 1-product projection over the second element. */ public final P1 _2_() { - return F1Functions.lazy(P8.__2()).f(this); + return P8.__2().lazy().f(this); } /** @@ -426,7 +426,7 @@ public final P1 _2_() { * @return the 1-product projection over the third element. */ public final P1 _3_() { - return F1Functions.lazy(P8.__3()).f(this); + return P8.__3().lazy().f(this); } /** @@ -435,7 +435,7 @@ public final P1 _3_() { * @return the 1-product projection over the fourth element. */ public final P1 _4_() { - return F1Functions.lazy(P8.__4()).f(this); + return P8.__4().lazy().f(this); } /** @@ -444,7 +444,7 @@ public final P1 _4_() { * @return the 1-product projection over the fifth element. */ public final P1 _5_() { - return F1Functions.lazy(P8.__5()).f(this); + return P8.__5().lazy().f(this); } /** @@ -453,7 +453,7 @@ public final P1 _5_() { * @return the 1-product projection over the sixth element. */ public final P1 _6_() { - return F1Functions.lazy(P8.__6()).f(this); + return P8.__6().lazy().f(this); } /** @@ -462,7 +462,7 @@ public final P1 _6_() { * @return the 1-product projection over the seventh element. */ public final P1 _7_() { - return F1Functions.lazy(P8.__7()).f(this); + return P8.__7().lazy().f(this); } /** @@ -471,7 +471,7 @@ public final P1 _7_() { * @return the 1-product projection over the eighth element. */ public final P1 _8_() { - return F1Functions.lazy(P8.__8()).f(this); + return P8.__8().lazy().f(this); } /** diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index ef8029b3..6fbc5fc6 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -13,13 +13,10 @@ import java.math.BigDecimal; import java.math.BigInteger; -import static fj.F1Functions.dimap; import static fj.Function.constant; import static fj.Function.identity; import static fj.Monoid.*; import static fj.data.DList.listDList; -import static fj.data.Option.none; -import static fj.data.Option.some; /** * Implementations must satisfy the law of associativity: @@ -193,7 +190,7 @@ public B append(B a1, B a2) { @Override public F prepend(B b) { - return dimap(def.prepend(g.f(b)), g, f); + return def.prepend(g.f(b)).dimap(g, f); } @Override diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index 47fd282b..e3b58e1c 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -171,7 +171,7 @@ public static F>, Trampoline> suspend_() { * @return A new trampoline that runs this trampoline, then applies the given function to the result. */ public final Trampoline map(final F f) { - return bind(F1Functions.o(Trampoline.pure(), f)); + return bind(Trampoline.pure().o(f)); } /** @@ -266,10 +266,11 @@ public final Trampoline zipWith(final Trampoline b, final F2>, B> eb = b.resume(); for (final P1> x : ea.left()) { for (final P1> y : eb.left()) { - return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(() -> ta.zipWith(tb, f))))); + F, F, Trampoline>> z = ta -> tb -> suspend(() -> ta.zipWith(tb, f)); + return suspend(x.bind(y, z)); } for (final B y : eb.right()) { - return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y)))); + return suspend(x.map(ta -> ta.map(f.flip().f(y)))); } } for (final A x : ea.right()) { @@ -277,7 +278,7 @@ public final Trampoline zipWith(final Trampoline b, final F2 pure(f.f(x, y))); } for (final P1> y : eb.left()) { - return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x)))); + return suspend(y.map(liftM2(f.curry()).f(pure(x)))); } } throw Bottom.error("Match error: Trampoline is neither done nor suspended."); diff --git a/core/src/main/java/fj/control/parallel/ParModule.java b/core/src/main/java/fj/control/parallel/ParModule.java index 514988aa..b9eeacbf 100644 --- a/core/src/main/java/fj/control/parallel/ParModule.java +++ b/core/src/main/java/fj/control/parallel/ParModule.java @@ -67,7 +67,7 @@ public F, Promise> promise() { * that can be claimed in the future. */ public F> promise(final F f) { - return F1Functions.promiseK(f, strategy); + return f.promiseK(strategy); } /** @@ -88,7 +88,7 @@ public F, F>> promisePure() { * that can be claimed in the future. */ public F2> promise(final F2 f) { - return P2.untuple(F1Functions.promiseK(F2Functions.tuple(f), strategy)); + return P2.untuple(f.tuple().promiseK(strategy)); } diff --git a/core/src/main/java/fj/data/IOFunctions.java b/core/src/main/java/fj/data/IOFunctions.java index 2ea15dfb..9573deea 100644 --- a/core/src/main/java/fj/data/IOFunctions.java +++ b/core/src/main/java/fj/data/IOFunctions.java @@ -2,7 +2,6 @@ import fj.F; import fj.F0; -import fj.F1Functions; import fj.F2; import fj.Function; import fj.P; @@ -204,7 +203,7 @@ public IO> f(IterV it) { return i; } final Input input = Input.el(s); - final F, IterV>, P1>> cont = F1Functions.lazy(Function.apply(input)); + final F, IterV>, P1>> cont = Function., IterV>apply(input).lazy(); i = i.fold(done, cont)._1(); } return i; @@ -248,7 +247,7 @@ public IO> f(IterV it) { } final Input input = Input.el(buffer); final F, IterV>, P1>> cont = - F1Functions.lazy(Function.apply(input)); + Function., IterV>apply(input).lazy(); i = i.fold(done, cont)._1(); } return i; diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index bcb03cc0..be68ed02 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -2,7 +2,6 @@ import fj.F; import fj.F0; -import fj.F1Functions; import fj.Function; import fj.P; import fj.P2; @@ -82,7 +81,7 @@ public Z fold(final F>, Z> done, final F, IterV, Option> runCont = new F, Option>() { - final F>, Option> done = F1Functions.andThen(P2.__1(), Option.some_()); + final F>, Option> done = P2.>__1().andThen(Option.some_()); final F, IterV>, Option> cont = Function.constant(Option.none()); @Override diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 422d246b..5b5fff67 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -969,7 +969,7 @@ public final B foldRight(final F2 f, final B b) { * @return A Trampoline containing the final result after the right-fold reduction. */ public final Trampoline foldRightC(final F2 f, final B b) { - return Trampoline.suspend(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head()))); + return Trampoline.suspend(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(f.f(head()))); } /** diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 4073476d..34c8b957 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -169,9 +169,10 @@ public NonEmptyList bind(final F> f) { * @return a NonEmptyList of the sublists of this list. */ public NonEmptyList> sublists() { + F, Option>> f = s -> NonEmptyList.fromList(Conversions.Stream_List().f(s)); return fromList( somes(toList().toStream().substreams() - .map(F1Functions.o(NonEmptyList::fromList, Conversions.Stream_List())).toList())).some(); + .map(f).toList())).some(); } /** diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index af66c87e..9374e300 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -1,7 +1,6 @@ package fj.data; import fj.F; -import fj.F1Functions; /** * The Reader monad (also called the function monad, so equivalent to the idea of F). @@ -32,7 +31,7 @@ public final B f(A a) { } public final Reader map(F f) { - return unit(F1Functions.andThen(function, f)); + return unit(function.andThen(f)); } public final Reader andThen(F f) { diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index 9eebb932..f430d6d2 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -127,7 +127,7 @@ public static F, P1>>> subForest_() { public Stream flatten() { final F2, P1>, Stream> squish = new F2, P1>, Stream>() { public Stream f(final Tree t, final P1> xs) { - return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(F2Functions.curry(this)).f(xs._1()))); + return cons(t.root(), t.subForest().map(Stream., Stream>foldRight().f(this.curry()).f(xs._1()))); } }; return squish.f(this, P.p(Stream.nil())); @@ -305,7 +305,7 @@ public static Show> show2D(final Show s) { * @return A new tree of the results of applying the given function over this tree and the given tree, position-wise. */ public Tree zipWith(final Tree bs, final F2 f) { - return F2Functions.zipTreeM(f).f(this, bs); + return f.zipTreeM().f(this, bs); } /** diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index cd111d06..38607dbc 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -2,7 +2,6 @@ import fj.Equal; import fj.F; -import fj.F1Functions; import fj.Hash; import fj.Ord; import fj.P; @@ -308,9 +307,9 @@ public TreeMap update(final K k, final F f, final V v) { * and the optional value is the value associated with the given key if present, otherwise None. */ public P3, Option, Set> split(Ord ord, final K k) { - final F>>, Set> getSome = F1Functions.mapSet(F1Functions.o(Option.fromSome(), P2.__2()), ord); + final F>>, Set> getSome = Option.fromSome().o(P2.>__2()).mapSet(ord); return tree.split(p(k, Option.none())).map1(getSome).map3(getSome) - .map2(F1Functions.o(Option.join(), F1Functions.mapOption(P2.__2()))); + .map2(Option.join().o(P2.>__2().mapOption())); } /** @@ -359,7 +358,7 @@ public P3, Option, TreeMap> splitLookup(final K k) { */ @SuppressWarnings("unchecked") public TreeMap map(final F f) { - final F>, P2>> g = compose(p2 -> p(p2._1(), p2._2()), P2.map2_(F1Functions.mapOption(f))); + final F>, P2>> g = compose(p2 -> p(p2._1(), p2._2()), P2.map2_(f.mapOption())); final F>> coord = flip(P.>p2()).f(Option.none()); final Ord o = tree.ord().contramap(coord); return new TreeMap<>(tree.map(TreeMap.ord(o), g)); diff --git a/core/src/main/java/fj/data/TreeZipper.java b/core/src/main/java/fj/data/TreeZipper.java index 9ffad4f4..545238f3 100644 --- a/core/src/main/java/fj/data/TreeZipper.java +++ b/core/src/main/java/fj/data/TreeZipper.java @@ -1,678 +1,678 @@ -package fj.data; - -import fj.*; -import fj.function.Booleans; - -import java.util.Iterator; - -import static fj.Equal.p3Equal; -import static fj.Equal.p4Equal; -import static fj.Equal.streamEqual; -import static fj.Equal.treeEqual; -import static fj.Function.compose; -import static fj.Function.curry; -import static fj.Function.flip; -import static fj.Function.uncurryF2; -import static fj.Show.p3Show; -import static fj.Show.p4Show; -import static fj.Show.streamShow; -import static fj.Show.treeShow; -import static fj.data.Option.none; -import static fj.data.Option.some; -import static fj.data.Stream.nil; -import static fj.data.Stream.unfold; -import static fj.data.Tree.node; -import static fj.data.Tree.unfoldTree; - -/** - * Provides a zipper structure for rose trees, which is a Tree supplied with a location within that tree. - * Provides navigation, insertion, deletion, and memorization of visited locations within a tree. - */ -public final class TreeZipper implements Iterable> { - - /** - * Returns an iterator of all the positions of this TreeZipper. Exists for use with the foreach syntax. - * - * @return An iterator of all the positions of this TreeZipper. - */ - public Iterator> iterator() { - return positions().toTree().iterator(); - } - - private final Tree tree; - private final Stream> lefts; - private final Stream> rights; - private final Stream>, A, Stream>>> parents; - - private TreeZipper(final Tree tree, - final Stream> lefts, - final Stream> rights, - final Stream>, A, Stream>>> parents) { - this.tree = tree; - this.lefts = lefts; - this.rights = rights; - this.parents = parents; - } - - @Override - public final boolean equals(Object other) { - return Equal.equals0(TreeZipper.class, this, other, () -> Equal.treeZipperEqual(Equal.anyEqual())); - } - - @Override - public final int hashCode() { - return Hash.treeZipperHash(Hash.anyHash()).hash(this); - } - - /** - * Creates a new tree zipper given a currently selected tree, a forest on the left, a forest on the right, - * and a stream of parent contexts. - * - * @param tree The currently selected tree. - * @param lefts The selected tree's left siblings, closest first. - * @param rights The selected tree's right siblings, closest first. - * @param parents The parent of the selected tree, and the parent's siblings. - * @return A new zipper with the given tree selected, and the given forests on the left and right. - */ - public static TreeZipper treeZipper(final Tree tree, - final Stream> lefts, - final Stream> rights, - final Stream>, A, Stream>>> parents) { - return new TreeZipper<>(tree, lefts, rights, parents); - } - - /** - * First-class constructor for tree zippers. - * - * @return A function that returns a new tree zipper, given a selected tree, left and right siblings, - * and a parent context. - */ - public static - F, F>, F>, F>, A, Stream>>>, TreeZipper>>>> - treeZipper() { - return curry( - TreeZipper::treeZipper); - } - - /** - * Returns the product-4 representation of this zipper. - * - * @return the product-4 representation of this zipper. - */ - public P4, Stream>, Stream>, Stream>, A, Stream>>>> p() { - return P.p(tree, lefts, rights, parents); - } - - /** - * A first-class function that returns the product-4 representation of a given zipper. - * - * @return a function that converts a given zipper to its product-4 representation. - */ - public static - F, P4, Stream>, Stream>, Stream>, A, Stream>>>>> p_() { - return TreeZipper::p; - } - - /** - * An Equal instance for tree zippers. - * - * @param e An Equal instance for tree elements. - * @return An Equal instance for tree zippers. - */ - public static Equal> eq(final Equal e) { - return p4Equal( - treeEqual(e), - streamEqual(treeEqual(e)), - streamEqual(treeEqual(e)), - streamEqual(p3Equal(streamEqual(treeEqual(e)), e, streamEqual(treeEqual(e))))).contramap(TreeZipper.p_()); - } - - /** - * A Show instance for tree zippers. - * - * @param s A Show instance for tree elements. - * @return A Show instance for tree zippers. - */ - public static Show> show(final Show s) { - return p4Show( - treeShow(s), - streamShow(treeShow(s)), - streamShow(treeShow(s)), - streamShow(p3Show(streamShow(treeShow(s)), s, streamShow(treeShow(s))))).contramap(TreeZipper.p_()); - } - - private static Stream> combChildren(final Stream> ls, - final Tree t, - final Stream> rs) { - return ls.foldLeft(compose(flip(Stream.cons()), P.p1()), Stream.cons(t, P.p(rs))); - } - - /** - * Navigates to the parent of the current location. - * - * @return A new tree zipper focused on the parent node of the current node, - * or none if the current node is the root node. - */ - public Option> parent() { - if (parents.isEmpty()) - return none(); - else { - final P3>, A, Stream>> p = parents.head(); - return some(treeZipper(node(p._2(), combChildren(lefts, tree, rights)), p._1(), p._3(), parents.tail()._1())); - } - } - - /** - * Navigates to the top-most parent of the current location. - * - * @return A new tree zipper focused on the top-most parent of the current node. - */ - public TreeZipper root() { - return parent().option(this, TreeZipper.root_()); - } - - /** - * A first-class version of the root function. - * - * @return A function that returns a new tree-zipper focused on the root of the given tree zipper's tree. - */ - public static F, TreeZipper> root_() { - return TreeZipper::root; - } - - /** - * Navigates to the left sibling of the current location. - * - * @return A new tree zipper focused on the left sibling of the current node, - * or none if there are no siblings on the left. - */ - public Option> left() { - return lefts.isEmpty() ? Option.none() - : some(treeZipper(lefts.head(), lefts.tail()._1(), rights.cons(tree), parents)); - } - - /** - * Navigates to the right sibling of the current location. - * - * @return A new tree zipper focused on the right sibling of the current node, - * or none if there are no siblings on the right. - */ - public Option> right() { - return rights.isEmpty() ? Option.none() - : some(treeZipper(rights.head(), lefts.cons(tree), rights.tail()._1(), parents)); - } - - /** - * Navigtes to the first child of the current location. - * - * @return A new tree zipper focused on the first child of the current node, or none if the node has no children. - */ - public Option> firstChild() { - final Stream> ts = tree.subForest()._1(); - return ts.isEmpty() ? Option.none() - : some(treeZipper(ts.head(), Stream.nil(), ts.tail()._1(), downParents())); - } - - /** - * Navigtes to the last child of the current location. - * - * @return A new tree zipper focused on the last child of the current node, or none if the node has no children. - */ - public Option> lastChild() { - final Stream> ts = tree.subForest()._1().reverse(); - return ts.isEmpty() ? Option.none() - : some(treeZipper(ts.head(), ts.tail()._1(), Stream.nil(), downParents())); - } - - /** - * Navigates to the given child of the current location, starting at index 0. - * - * @param n The index of the child to which to navigate. - * @return An optional tree zipper focused on the child node at the given index, or none if there is no such child. - */ - public Option> getChild(final int n) { - Option> r = none(); - for (final P2>, Stream>> lr - : splitChildren(Stream.nil(), tree.subForest()._1(), n)) { - r = some(treeZipper(lr._1().head(), lr._1().tail()._1(), lr._2(), downParents())); - } - return r; - } - - /** - * Navigates to the first child of the current location, that satisfies the given predicate. - * - * @param p A predicate to be satisfied by the child node. - * @return An optional tree zipper focused on the first child node that satisfies the given predicate, - * or none if there is no such child. - */ - public Option> findChild(final F, Boolean> p) { - Option> r = none(); - - final F2>, Stream>, Option>, Tree, Stream>>>> split = - new F2>, Stream>, Option>, Tree, Stream>>>>() { - public Option>, Tree, Stream>>> f(final Stream> acc, - final Stream> xs) { - return xs.isNotEmpty() - ? p.f(xs.head()) ? some(P.p(acc, xs.head(), xs.tail()._1())) - : f(acc.cons(xs.head()), xs.tail()._1()) - : Option.none(); - } - }; - - Stream> subforest = tree.subForest()._1(); - if (subforest.isNotEmpty()) { - for (final P3>, Tree, Stream>> ltr - : split.f(Stream.nil(), subforest)) { - r = some(treeZipper(ltr._2(), ltr._1(), ltr._3(), downParents())); - } - } - return r; - } - - private Stream>, A, Stream>>> downParents() { - return parents.cons(P.p(lefts, tree.root(), rights)); - } - - private static Option, Stream>> splitChildren(final Stream acc, - final Stream xs, - final int n) { - return n == 0 ? some(P.p(acc, xs)) - : xs.isNotEmpty() ? splitChildren(acc.cons(xs.head()), xs.tail()._1(), n - 1) - : Option.none(); - } - - private static Stream>, A, Stream>>> lp3nil() { - return nil(); - } - - /** - * Creates a new tree zipper focused on the root of the given tree. - * - * @param t A tree over which to create a new zipper. - * @return a new tree zipper focused on the root of the given tree. - */ - public static TreeZipper fromTree(final Tree t) { - return treeZipper(t, Stream.nil(), Stream.nil(), TreeZipper.lp3nil()); - } - - /** - * Creates a new tree zipper focused on the first element of the given forest. - * - * @param ts A forest over which to create a new zipper. - * @return a new tree zipper focused on the first element of the given forest. - */ - public static Option> fromForest(final Stream> ts) { - return ts.isNotEmpty() - ? some(treeZipper(ts.head(), Stream.nil(), ts.tail()._1(), TreeZipper.lp3nil())) - : Option.none(); - } - - /** - * Returns the tree containing this location. - * - * @return the tree containing this location. - */ - public Tree toTree() { - return root().tree; - } - - /** - * Returns the forest containing this location. - * - * @return the forest containing this location. - */ - public Stream> toForest() { - final TreeZipper r = root(); - return combChildren(r.lefts, r.tree, r.rights); - } - - /** - * Returns the tree at the currently focused node. - * - * @return the tree at the currently focused node. - */ - public Tree focus() { - return tree; - } - - /** - * Returns the left siblings of the currently focused node. - * - * @return the left siblings of the currently focused node. - */ - public Stream> lefts() { - return lefts; - } - - /** - * Returns the right siblings of the currently focused node. - * - * @return the right siblings of the currently focused node. - */ - public Stream> rights() { - return rights; - } - - /** - * Returns the parents of the currently focused node. - * - * @return the parents of the currently focused node. - */ - public Stream>, A, Stream>>> parents() { - return parents; - } - - /** - * Indicates whether the current node is at the top of the tree. - * - * @return true if the current node is the root of the tree, otherwise false. - */ - public boolean isRoot() { - return parents.isEmpty(); - } - - /** - * Indicates whether the current node is the leftmost tree in the current forest. - * - * @return true if the current node has no left siblings, otherwise false. - */ - public boolean isFirst() { - return lefts.isEmpty(); - } - - /** - * Indicates whether the current node is the rightmost tree in the current forest. - * - * @return true if the current node has no siblings on its right, otherwise false. - */ - public boolean isLast() { - return rights.isEmpty(); - } - - /** - * Indicates whether the current node is at the bottom of the tree. - * - * @return true if the current node has no child nodes, otherwise false. - */ - public boolean isLeaf() { - return tree.subForest()._1().isEmpty(); - } - - /** - * Indicates whether the current node is a child node of another node. - * - * @return true if the current node has a parent node, otherwise false. - */ - public boolean isChild() { - return !isRoot(); - } - - /** - * Indicates whether the current node has any child nodes. - * - * @return true if the current node has child nodes, otherwise false. - */ - public boolean hasChildren() { - return !isLeaf(); - } - - /** - * Replaces the current node with the given tree. - * - * @param t A tree with which to replace the current node. - * @return A new tree zipper in which the focused node is replaced with the given tree. - */ - public TreeZipper setTree(final Tree t) { - return treeZipper(t, lefts, rights, parents); - } - - /** - * Modifies the current node with the given function. - * - * @param f A function with which to modify the current tree. - * @return A new tree zipper in which the focused node has been transformed by the given function. - */ - public TreeZipper modifyTree(final F, Tree> f) { - return setTree(f.f(tree)); - } - - /** - * Modifies the label at the current node with the given function. - * - * @param f A function with which to transform the current node's label. - * @return A new tree zipper with the focused node's label transformed by the given function. - */ - public TreeZipper modifyLabel(final F f) { - return setLabel(f.f(getLabel())); - } - - /** - * Replaces the label of the current node with the given value. - * - * @param v The new value for the node's label. - * @return A new tree zipper with the focused node's label replaced by the given value. - */ - public TreeZipper setLabel(final A v) { - return modifyTree(t -> Tree.node(v, t.subForest())); - } - - /** - * Returns the label at the current node. - * - * @return the label at the current node. - */ - public A getLabel() { - return tree.root(); - } - - /** - * Inserts a tree to the left of the current position. The inserted tree becomes the current tree. - * - * @param t A tree to insert to the left of the current position. - * @return A new tree zipper with the given tree in focus and the current tree on the right. - */ - public TreeZipper insertLeft(final Tree t) { - return treeZipper(t, lefts, rights.cons(tree), parents); - } - - /** - * Inserts a tree to the right of the current position. The inserted tree becomes the current tree. - * - * @param t A tree to insert to the right of the current position. - * @return A new tree zipper with the given tree in focus and the current tree on the left. - */ - public TreeZipper insertRight(final Tree t) { - return treeZipper(t, lefts.cons(tree), rights, parents); - } - - /** - * Inserts a tree as the first child of the current node. The inserted tree becomes the current tree. - * - * @param t A tree to insert. - * @return A new tree zipper with the given tree in focus, as the first child of the current node. - */ - public TreeZipper insertDownFirst(final Tree t) { - return treeZipper(t, Stream.nil(), tree.subForest()._1(), downParents()); - } - - /** - * Inserts a tree as the last child of the current node. The inserted tree becomes the current tree. - * - * @param t A tree to insert. - * @return A new tree zipper with the given tree in focus, as the last child of the current node. - */ - public TreeZipper insertDownLast(final Tree t) { - return treeZipper(t, tree.subForest()._1().reverse(), Stream.nil(), downParents()); - } - - /** - * Inserts a tree at the specified location in the current node's stream of children. The inserted tree - * becomes the current node. - * - * @param n The index at which to insert the given tree, starting at 0. - * @param t A tree to insert. - * @return A new tree zipper with the given tree in focus, at the specified index in the current node's stream - * of children, or None if the current node has fewer than n children. - */ - public Option> insertDownAt(final int n, final Tree t) { - Option> r = none(); - for (final P2>, Stream>> lr - : splitChildren(Stream.nil(), tree.subForest()._1(), n)) { - r = some(treeZipper(t, lr._1(), lr._2(), downParents())); - } - return r; - } - - /** - * Removes the current node from the tree. The new position becomes the right sibling, or the left sibling - * if the current node has no right siblings, or the parent node if the current node has no siblings. - * - * @return A new tree zipper with the current node removed. - */ - public Option> delete() { - Option> r = none(); - if (rights.isNotEmpty()) - r = some(treeZipper(rights.head(), lefts, rights.tail()._1(), parents)); - else if (lefts.isNotEmpty()) - r = some(treeZipper(lefts.head(), lefts.tail()._1(), rights, parents)); - else for (final TreeZipper loc : parent()) - r = some(loc.modifyTree(t -> node(t.root(), Stream.nil()))); - return r; - } - - /** - * Zips the nodes in this zipper with a boolean that indicates whether that node has focus. - * All of the booleans will be false, except for the focused node. - * - * @return A new zipper of pairs, with each node of this zipper paired with a boolean that is true if that - * node has focus, and false otherwise. - */ - public TreeZipper> zipWithFocus() { - final F> f = flip(P.p2()).f(false); - return map(f).modifyLabel(P2.map2_(Booleans.not)); - } - - /** - * Maps the given function across this zipper (covariant functor pattern). - * - * @param f A function to map across this zipper. - * @return A new zipper with the given function applied to the label of every node. - */ - public TreeZipper map(final F f) { - final F, Tree> g = Tree.fmap_().f(f); - final F>, Stream>> h = Stream., Tree>map_().f(g); - return treeZipper(tree.fmap(f), lefts.map(g), rights.map(g), parents.map( - p -> p.map1(h).map2(f).map3(h))); - } - - /** - * First-class conversion of a Tree to the corresponding tree zipper. - * - * @return A function that takes a tree to its tree zipper representation. - */ - public static F, TreeZipper> fromTree() { - return TreeZipper::fromTree; - } - - /** - * A first-class version of the left() function. - * - * @return A function that focuses the given tree zipper on its left sibling. - */ - public static F, Option>> left_() { - return TreeZipper::left; - } - - /** - * A first-class version of the right() function. - * - * @return A function that focuses the given tree zipper on its right sibling. - */ - public static F, Option>> right_() { - return TreeZipper::right; - } - - /** - * Returns a zipper over the tree of all possible permutations of this tree zipper (comonad pattern). - * This tree zipper becomes the focused node of the new zipper. - * - * @return A tree zipper over the tree of all possible permutations of this tree zipper. - */ - public TreeZipper> positions() { - final Tree> t = unfoldTree(TreeZipper.dwn()).f(this); - final Stream>> l = uf(TreeZipper.left_()); - final Stream>> r = uf(TreeZipper.right_()); - final Stream>>, TreeZipper, Stream>>>> p = unfold( - o -> { - Option>>, TreeZipper, Stream>>>, - Option>>> r1 = none(); - for (final TreeZipper z : o) { - r1 = some(P.p(P.p(z.uf(TreeZipper.left_()), z, z.uf(TreeZipper.right_())), z.parent())); - } - return r1; - }, parent()); - return treeZipper(t, l, r, p); - } - - private Stream>> uf(final F, Option>> f) { - return unfold( - o -> { - Option>, Option>>> r = none(); - for (final TreeZipper c : o) { - r = some(P.p(unfoldTree(TreeZipper.dwn()).f(c), f.f(c))); - } - return r; - }, f.f(this)); - } - - private static F, P2, P1>>>> dwn() { - F>, Option, Option>>>> fwd = o -> o.map(c -> P.p(c, c.right())); - return tz -> P.p(tz, P.lazy(() -> unfold(fwd, tz.firstChild()))); - } - - /** - * Maps the given function over the tree of all positions for this zipper (comonad pattern). Returns a zipper - * over the tree of results of the function application. - * - * @param f A function to map over the tree of all positions for this zipper. - * @return A zipper over the tree of results of the function application. - */ - public TreeZipper cobind(final F, B> f) { - return positions().map(f); - } - - /** - * A first-class version of the findChild function. - * - * @return a function that finds the first child, of a given tree zipper, that matches a given predicate. - */ - public static F2, Boolean>, TreeZipper, Option>> findChild() { - return (f, az) -> az.findChild(f); - } - - /** - * Zips this TreeZipper with another, applying the given function lock-step over both zippers in all directions. - * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. - * - * @param bs A TreeZipper to zip this one with. - * @param f A function with which to zip together the two TreeZippers. - * @return The result of applying the given function over this TreeZipper and the given TreeZipper, location-wise. - */ - public TreeZipper zipWith(final TreeZipper bs, final F2 f) { - return F2Functions.zipTreeZipperM(f).f(this, bs); - } - - /** - * Zips this TreeZipper with another, applying the given function lock-step over both zippers in all directions. - * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. - * - * @param bs A TreeZipper to zip this one with. - * @param f A function with which to zip together the two TreeZippers. - * @return The result of applying the given function over this TreeZipper and the given TreeZipper, location-wise. - */ - public TreeZipper zipWith(final TreeZipper bs, final F> f) { - return zipWith(bs, uncurryF2(f)); - } -} +package fj.data; + +import fj.*; +import fj.function.Booleans; + +import java.util.Iterator; + +import static fj.Equal.p3Equal; +import static fj.Equal.p4Equal; +import static fj.Equal.streamEqual; +import static fj.Equal.treeEqual; +import static fj.Function.compose; +import static fj.Function.curry; +import static fj.Function.flip; +import static fj.Function.uncurryF2; +import static fj.Show.p3Show; +import static fj.Show.p4Show; +import static fj.Show.streamShow; +import static fj.Show.treeShow; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.Stream.nil; +import static fj.data.Stream.unfold; +import static fj.data.Tree.node; +import static fj.data.Tree.unfoldTree; + +/** + * Provides a zipper structure for rose trees, which is a Tree supplied with a location within that tree. + * Provides navigation, insertion, deletion, and memorization of visited locations within a tree. + */ +public final class TreeZipper implements Iterable> { + + /** + * Returns an iterator of all the positions of this TreeZipper. Exists for use with the foreach syntax. + * + * @return An iterator of all the positions of this TreeZipper. + */ + public Iterator> iterator() { + return positions().toTree().iterator(); + } + + private final Tree tree; + private final Stream> lefts; + private final Stream> rights; + private final Stream>, A, Stream>>> parents; + + private TreeZipper(final Tree tree, + final Stream> lefts, + final Stream> rights, + final Stream>, A, Stream>>> parents) { + this.tree = tree; + this.lefts = lefts; + this.rights = rights; + this.parents = parents; + } + + @Override + public final boolean equals(Object other) { + return Equal.equals0(TreeZipper.class, this, other, () -> Equal.treeZipperEqual(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.treeZipperHash(Hash.anyHash()).hash(this); + } + + /** + * Creates a new tree zipper given a currently selected tree, a forest on the left, a forest on the right, + * and a stream of parent contexts. + * + * @param tree The currently selected tree. + * @param lefts The selected tree's left siblings, closest first. + * @param rights The selected tree's right siblings, closest first. + * @param parents The parent of the selected tree, and the parent's siblings. + * @return A new zipper with the given tree selected, and the given forests on the left and right. + */ + public static TreeZipper treeZipper(final Tree tree, + final Stream> lefts, + final Stream> rights, + final Stream>, A, Stream>>> parents) { + return new TreeZipper<>(tree, lefts, rights, parents); + } + + /** + * First-class constructor for tree zippers. + * + * @return A function that returns a new tree zipper, given a selected tree, left and right siblings, + * and a parent context. + */ + public static + F, F>, F>, F>, A, Stream>>>, TreeZipper>>>> + treeZipper() { + return curry( + TreeZipper::treeZipper); + } + + /** + * Returns the product-4 representation of this zipper. + * + * @return the product-4 representation of this zipper. + */ + public P4, Stream>, Stream>, Stream>, A, Stream>>>> p() { + return P.p(tree, lefts, rights, parents); + } + + /** + * A first-class function that returns the product-4 representation of a given zipper. + * + * @return a function that converts a given zipper to its product-4 representation. + */ + public static + F, P4, Stream>, Stream>, Stream>, A, Stream>>>>> p_() { + return TreeZipper::p; + } + + /** + * An Equal instance for tree zippers. + * + * @param e An Equal instance for tree elements. + * @return An Equal instance for tree zippers. + */ + public static Equal> eq(final Equal e) { + return p4Equal( + treeEqual(e), + streamEqual(treeEqual(e)), + streamEqual(treeEqual(e)), + streamEqual(p3Equal(streamEqual(treeEqual(e)), e, streamEqual(treeEqual(e))))).contramap(TreeZipper.p_()); + } + + /** + * A Show instance for tree zippers. + * + * @param s A Show instance for tree elements. + * @return A Show instance for tree zippers. + */ + public static Show> show(final Show s) { + return p4Show( + treeShow(s), + streamShow(treeShow(s)), + streamShow(treeShow(s)), + streamShow(p3Show(streamShow(treeShow(s)), s, streamShow(treeShow(s))))).contramap(TreeZipper.p_()); + } + + private static Stream> combChildren(final Stream> ls, + final Tree t, + final Stream> rs) { + return ls.foldLeft(compose(flip(Stream.cons()), P.p1()), Stream.cons(t, P.p(rs))); + } + + /** + * Navigates to the parent of the current location. + * + * @return A new tree zipper focused on the parent node of the current node, + * or none if the current node is the root node. + */ + public Option> parent() { + if (parents.isEmpty()) + return none(); + else { + final P3>, A, Stream>> p = parents.head(); + return some(treeZipper(node(p._2(), combChildren(lefts, tree, rights)), p._1(), p._3(), parents.tail()._1())); + } + } + + /** + * Navigates to the top-most parent of the current location. + * + * @return A new tree zipper focused on the top-most parent of the current node. + */ + public TreeZipper root() { + return parent().option(this, TreeZipper.root_()); + } + + /** + * A first-class version of the root function. + * + * @return A function that returns a new tree-zipper focused on the root of the given tree zipper's tree. + */ + public static F, TreeZipper> root_() { + return TreeZipper::root; + } + + /** + * Navigates to the left sibling of the current location. + * + * @return A new tree zipper focused on the left sibling of the current node, + * or none if there are no siblings on the left. + */ + public Option> left() { + return lefts.isEmpty() ? Option.none() + : some(treeZipper(lefts.head(), lefts.tail()._1(), rights.cons(tree), parents)); + } + + /** + * Navigates to the right sibling of the current location. + * + * @return A new tree zipper focused on the right sibling of the current node, + * or none if there are no siblings on the right. + */ + public Option> right() { + return rights.isEmpty() ? Option.none() + : some(treeZipper(rights.head(), lefts.cons(tree), rights.tail()._1(), parents)); + } + + /** + * Navigtes to the first child of the current location. + * + * @return A new tree zipper focused on the first child of the current node, or none if the node has no children. + */ + public Option> firstChild() { + final Stream> ts = tree.subForest()._1(); + return ts.isEmpty() ? Option.none() + : some(treeZipper(ts.head(), Stream.nil(), ts.tail()._1(), downParents())); + } + + /** + * Navigtes to the last child of the current location. + * + * @return A new tree zipper focused on the last child of the current node, or none if the node has no children. + */ + public Option> lastChild() { + final Stream> ts = tree.subForest()._1().reverse(); + return ts.isEmpty() ? Option.none() + : some(treeZipper(ts.head(), ts.tail()._1(), Stream.nil(), downParents())); + } + + /** + * Navigates to the given child of the current location, starting at index 0. + * + * @param n The index of the child to which to navigate. + * @return An optional tree zipper focused on the child node at the given index, or none if there is no such child. + */ + public Option> getChild(final int n) { + Option> r = none(); + for (final P2>, Stream>> lr + : splitChildren(Stream.nil(), tree.subForest()._1(), n)) { + r = some(treeZipper(lr._1().head(), lr._1().tail()._1(), lr._2(), downParents())); + } + return r; + } + + /** + * Navigates to the first child of the current location, that satisfies the given predicate. + * + * @param p A predicate to be satisfied by the child node. + * @return An optional tree zipper focused on the first child node that satisfies the given predicate, + * or none if there is no such child. + */ + public Option> findChild(final F, Boolean> p) { + Option> r = none(); + + final F2>, Stream>, Option>, Tree, Stream>>>> split = + new F2>, Stream>, Option>, Tree, Stream>>>>() { + public Option>, Tree, Stream>>> f(final Stream> acc, + final Stream> xs) { + return xs.isNotEmpty() + ? p.f(xs.head()) ? some(P.p(acc, xs.head(), xs.tail()._1())) + : f(acc.cons(xs.head()), xs.tail()._1()) + : Option.none(); + } + }; + + Stream> subforest = tree.subForest()._1(); + if (subforest.isNotEmpty()) { + for (final P3>, Tree, Stream>> ltr + : split.f(Stream.nil(), subforest)) { + r = some(treeZipper(ltr._2(), ltr._1(), ltr._3(), downParents())); + } + } + return r; + } + + private Stream>, A, Stream>>> downParents() { + return parents.cons(P.p(lefts, tree.root(), rights)); + } + + private static Option, Stream>> splitChildren(final Stream acc, + final Stream xs, + final int n) { + return n == 0 ? some(P.p(acc, xs)) + : xs.isNotEmpty() ? splitChildren(acc.cons(xs.head()), xs.tail()._1(), n - 1) + : Option.none(); + } + + private static Stream>, A, Stream>>> lp3nil() { + return nil(); + } + + /** + * Creates a new tree zipper focused on the root of the given tree. + * + * @param t A tree over which to create a new zipper. + * @return a new tree zipper focused on the root of the given tree. + */ + public static TreeZipper fromTree(final Tree t) { + return treeZipper(t, Stream.nil(), Stream.nil(), TreeZipper.lp3nil()); + } + + /** + * Creates a new tree zipper focused on the first element of the given forest. + * + * @param ts A forest over which to create a new zipper. + * @return a new tree zipper focused on the first element of the given forest. + */ + public static Option> fromForest(final Stream> ts) { + return ts.isNotEmpty() + ? some(treeZipper(ts.head(), Stream.nil(), ts.tail()._1(), TreeZipper.lp3nil())) + : Option.none(); + } + + /** + * Returns the tree containing this location. + * + * @return the tree containing this location. + */ + public Tree toTree() { + return root().tree; + } + + /** + * Returns the forest containing this location. + * + * @return the forest containing this location. + */ + public Stream> toForest() { + final TreeZipper r = root(); + return combChildren(r.lefts, r.tree, r.rights); + } + + /** + * Returns the tree at the currently focused node. + * + * @return the tree at the currently focused node. + */ + public Tree focus() { + return tree; + } + + /** + * Returns the left siblings of the currently focused node. + * + * @return the left siblings of the currently focused node. + */ + public Stream> lefts() { + return lefts; + } + + /** + * Returns the right siblings of the currently focused node. + * + * @return the right siblings of the currently focused node. + */ + public Stream> rights() { + return rights; + } + + /** + * Returns the parents of the currently focused node. + * + * @return the parents of the currently focused node. + */ + public Stream>, A, Stream>>> parents() { + return parents; + } + + /** + * Indicates whether the current node is at the top of the tree. + * + * @return true if the current node is the root of the tree, otherwise false. + */ + public boolean isRoot() { + return parents.isEmpty(); + } + + /** + * Indicates whether the current node is the leftmost tree in the current forest. + * + * @return true if the current node has no left siblings, otherwise false. + */ + public boolean isFirst() { + return lefts.isEmpty(); + } + + /** + * Indicates whether the current node is the rightmost tree in the current forest. + * + * @return true if the current node has no siblings on its right, otherwise false. + */ + public boolean isLast() { + return rights.isEmpty(); + } + + /** + * Indicates whether the current node is at the bottom of the tree. + * + * @return true if the current node has no child nodes, otherwise false. + */ + public boolean isLeaf() { + return tree.subForest()._1().isEmpty(); + } + + /** + * Indicates whether the current node is a child node of another node. + * + * @return true if the current node has a parent node, otherwise false. + */ + public boolean isChild() { + return !isRoot(); + } + + /** + * Indicates whether the current node has any child nodes. + * + * @return true if the current node has child nodes, otherwise false. + */ + public boolean hasChildren() { + return !isLeaf(); + } + + /** + * Replaces the current node with the given tree. + * + * @param t A tree with which to replace the current node. + * @return A new tree zipper in which the focused node is replaced with the given tree. + */ + public TreeZipper setTree(final Tree t) { + return treeZipper(t, lefts, rights, parents); + } + + /** + * Modifies the current node with the given function. + * + * @param f A function with which to modify the current tree. + * @return A new tree zipper in which the focused node has been transformed by the given function. + */ + public TreeZipper modifyTree(final F, Tree> f) { + return setTree(f.f(tree)); + } + + /** + * Modifies the label at the current node with the given function. + * + * @param f A function with which to transform the current node's label. + * @return A new tree zipper with the focused node's label transformed by the given function. + */ + public TreeZipper modifyLabel(final F f) { + return setLabel(f.f(getLabel())); + } + + /** + * Replaces the label of the current node with the given value. + * + * @param v The new value for the node's label. + * @return A new tree zipper with the focused node's label replaced by the given value. + */ + public TreeZipper setLabel(final A v) { + return modifyTree(t -> Tree.node(v, t.subForest())); + } + + /** + * Returns the label at the current node. + * + * @return the label at the current node. + */ + public A getLabel() { + return tree.root(); + } + + /** + * Inserts a tree to the left of the current position. The inserted tree becomes the current tree. + * + * @param t A tree to insert to the left of the current position. + * @return A new tree zipper with the given tree in focus and the current tree on the right. + */ + public TreeZipper insertLeft(final Tree t) { + return treeZipper(t, lefts, rights.cons(tree), parents); + } + + /** + * Inserts a tree to the right of the current position. The inserted tree becomes the current tree. + * + * @param t A tree to insert to the right of the current position. + * @return A new tree zipper with the given tree in focus and the current tree on the left. + */ + public TreeZipper insertRight(final Tree t) { + return treeZipper(t, lefts.cons(tree), rights, parents); + } + + /** + * Inserts a tree as the first child of the current node. The inserted tree becomes the current tree. + * + * @param t A tree to insert. + * @return A new tree zipper with the given tree in focus, as the first child of the current node. + */ + public TreeZipper insertDownFirst(final Tree t) { + return treeZipper(t, Stream.nil(), tree.subForest()._1(), downParents()); + } + + /** + * Inserts a tree as the last child of the current node. The inserted tree becomes the current tree. + * + * @param t A tree to insert. + * @return A new tree zipper with the given tree in focus, as the last child of the current node. + */ + public TreeZipper insertDownLast(final Tree t) { + return treeZipper(t, tree.subForest()._1().reverse(), Stream.nil(), downParents()); + } + + /** + * Inserts a tree at the specified location in the current node's stream of children. The inserted tree + * becomes the current node. + * + * @param n The index at which to insert the given tree, starting at 0. + * @param t A tree to insert. + * @return A new tree zipper with the given tree in focus, at the specified index in the current node's stream + * of children, or None if the current node has fewer than n children. + */ + public Option> insertDownAt(final int n, final Tree t) { + Option> r = none(); + for (final P2>, Stream>> lr + : splitChildren(Stream.nil(), tree.subForest()._1(), n)) { + r = some(treeZipper(t, lr._1(), lr._2(), downParents())); + } + return r; + } + + /** + * Removes the current node from the tree. The new position becomes the right sibling, or the left sibling + * if the current node has no right siblings, or the parent node if the current node has no siblings. + * + * @return A new tree zipper with the current node removed. + */ + public Option> delete() { + Option> r = none(); + if (rights.isNotEmpty()) + r = some(treeZipper(rights.head(), lefts, rights.tail()._1(), parents)); + else if (lefts.isNotEmpty()) + r = some(treeZipper(lefts.head(), lefts.tail()._1(), rights, parents)); + else for (final TreeZipper loc : parent()) + r = some(loc.modifyTree(t -> node(t.root(), Stream.nil()))); + return r; + } + + /** + * Zips the nodes in this zipper with a boolean that indicates whether that node has focus. + * All of the booleans will be false, except for the focused node. + * + * @return A new zipper of pairs, with each node of this zipper paired with a boolean that is true if that + * node has focus, and false otherwise. + */ + public TreeZipper> zipWithFocus() { + final F> f = flip(P.p2()).f(false); + return map(f).modifyLabel(P2.map2_(Booleans.not)); + } + + /** + * Maps the given function across this zipper (covariant functor pattern). + * + * @param f A function to map across this zipper. + * @return A new zipper with the given function applied to the label of every node. + */ + public TreeZipper map(final F f) { + final F, Tree> g = Tree.fmap_().f(f); + final F>, Stream>> h = Stream., Tree>map_().f(g); + return treeZipper(tree.fmap(f), lefts.map(g), rights.map(g), parents.map( + p -> p.map1(h).map2(f).map3(h))); + } + + /** + * First-class conversion of a Tree to the corresponding tree zipper. + * + * @return A function that takes a tree to its tree zipper representation. + */ + public static F, TreeZipper> fromTree() { + return TreeZipper::fromTree; + } + + /** + * A first-class version of the left() function. + * + * @return A function that focuses the given tree zipper on its left sibling. + */ + public static F, Option>> left_() { + return TreeZipper::left; + } + + /** + * A first-class version of the right() function. + * + * @return A function that focuses the given tree zipper on its right sibling. + */ + public static F, Option>> right_() { + return TreeZipper::right; + } + + /** + * Returns a zipper over the tree of all possible permutations of this tree zipper (comonad pattern). + * This tree zipper becomes the focused node of the new zipper. + * + * @return A tree zipper over the tree of all possible permutations of this tree zipper. + */ + public TreeZipper> positions() { + final Tree> t = unfoldTree(TreeZipper.dwn()).f(this); + final Stream>> l = uf(TreeZipper.left_()); + final Stream>> r = uf(TreeZipper.right_()); + final Stream>>, TreeZipper, Stream>>>> p = unfold( + o -> { + Option>>, TreeZipper, Stream>>>, + Option>>> r1 = none(); + for (final TreeZipper z : o) { + r1 = some(P.p(P.p(z.uf(TreeZipper.left_()), z, z.uf(TreeZipper.right_())), z.parent())); + } + return r1; + }, parent()); + return treeZipper(t, l, r, p); + } + + private Stream>> uf(final F, Option>> f) { + return unfold( + o -> { + Option>, Option>>> r = none(); + for (final TreeZipper c : o) { + r = some(P.p(unfoldTree(TreeZipper.dwn()).f(c), f.f(c))); + } + return r; + }, f.f(this)); + } + + private static F, P2, P1>>>> dwn() { + F>, Option, Option>>>> fwd = o -> o.map(c -> P.p(c, c.right())); + return tz -> P.p(tz, P.lazy(() -> unfold(fwd, tz.firstChild()))); + } + + /** + * Maps the given function over the tree of all positions for this zipper (comonad pattern). Returns a zipper + * over the tree of results of the function application. + * + * @param f A function to map over the tree of all positions for this zipper. + * @return A zipper over the tree of results of the function application. + */ + public TreeZipper cobind(final F, B> f) { + return positions().map(f); + } + + /** + * A first-class version of the findChild function. + * + * @return a function that finds the first child, of a given tree zipper, that matches a given predicate. + */ + public static F2, Boolean>, TreeZipper, Option>> findChild() { + return (f, az) -> az.findChild(f); + } + + /** + * Zips this TreeZipper with another, applying the given function lock-step over both zippers in all directions. + * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. + * + * @param bs A TreeZipper to zip this one with. + * @param f A function with which to zip together the two TreeZippers. + * @return The result of applying the given function over this TreeZipper and the given TreeZipper, location-wise. + */ + public TreeZipper zipWith(final TreeZipper bs, final F2 f) { + return f.zipTreeZipperM().f(this, bs); + } + + /** + * Zips this TreeZipper with another, applying the given function lock-step over both zippers in all directions. + * The structure of the resulting TreeZipper is the structural intersection of the two TreeZippers. + * + * @param bs A TreeZipper to zip this one with. + * @param f A function with which to zip together the two TreeZippers. + * @return The result of applying the given function over this TreeZipper and the given TreeZipper, location-wise. + */ + public TreeZipper zipWith(final TreeZipper bs, final F> f) { + return zipWith(bs, uncurryF2(f)); + } +} diff --git a/core/src/main/java/fj/data/Zipper.java b/core/src/main/java/fj/data/Zipper.java index 2514d8e2..4b96377f 100644 --- a/core/src/main/java/fj/data/Zipper.java +++ b/core/src/main/java/fj/data/Zipper.java @@ -1,585 +1,585 @@ -package fj.data; - -import fj.*; -import fj.function.Integers; - -import java.util.Iterator; - -import static fj.Function.compose; -import static fj.Function.curry; -import static fj.Function.flip; -import static fj.Function.join; -import static fj.Function.uncurryF2; -import static fj.data.Option.none; -import static fj.data.Option.some; -import static fj.data.Stream.nil; -import static fj.data.Stream.repeat; - -/** - * Provides a pointed stream, which is a non-empty zipper-like stream structure that tracks an index (focus) - * position in a stream. Focus can be moved forward and backwards through the stream, elements can be inserted - * before or after the focused position, and the focused item can be deleted. - *

      - * Based on the pointedlist library by Jeff Wheeler. - */ -public final class Zipper implements Iterable> { - private final Stream left; - private final A focus; - private final Stream right; - - private Zipper(final Stream left, final A focus, final Stream right) { - this.left = left; - this.focus = focus; - this.right = right; - } - - - /** - * Creates a new Zipper with the given streams before and after the focus, and the given focused item. - * - * @param left The stream of elements before the focus. - * @param focus The element under focus. - * @param right The stream of elements after the focus. - * @return a new Zipper with the given streams before and after the focus, and the given focused item. - */ - public static Zipper zipper(final Stream left, final A focus, final Stream right) { - return new Zipper<>(left, focus, right); - } - - /** - * Creates a new Zipper from the given triple. - * - * @param p A triple of the elements before the focus, the focus element, and the elements after the focus, - * respectively. - * @return a new Zipper created from the given triple. - */ - public static Zipper zipper(final P3, A, Stream> p) { - return new Zipper<>(p._1(), p._2(), p._3()); - } - - /** - * First-class constructor of zippers. - * - * @return A function that yields a new zipper given streams on the left and right and a focus element. - */ - public static F3, A, Stream, Zipper> zipper() { - return Zipper::zipper; - } - - /** - * Returns the product-3 representation of this Zipper. - * - * @return the product-3 representation of this Zipper. - */ - public P3, A, Stream> p() { - return P.p(left, focus, right); - } - - /** - * A first-class function that yields the product-3 representation of a given Zipper. - * - * @return A first-class function that yields the product-3 representation of a given Zipper. - */ - public static F, P3, A, Stream>> p_() { - return Zipper::p; - } - - /** - * An Ord instance for Zippers. - * - * @param o An Ord instance for the element type. - * @return An Ord instance for Zippers. - */ - public static Ord> ord(final Ord o) { - final Ord> so = Ord.streamOrd(o); - return Ord.p3Ord(so, o, so).contramap(Zipper.p_()); - } - - @Override - public final boolean equals(Object other) { - return Equal.equals0(Zipper.class, this, other, () -> Equal.zipperEqual(Equal.anyEqual())); - } - - @Override - public final int hashCode() { - return Hash.zipperHash(Hash.anyHash()).hash(this); - } - - /** - * An Equal instance for Zippers. - * - * @param e An Equal instance for the element type. - * @return An Equal instance for Zippers. - */ - public static Equal> eq(final Equal e) { - final Equal> se = Equal.streamEqual(e); - return Equal.p3Equal(se, e, se).contramap(Zipper.p_()); - } - - /** - * A Show instance for Zippers. - * - * @param s A Show instance for the element type. - * @return A Show instance for Zippers. - */ - public static Show> show(final Show s) { - final Show> ss = Show.streamShow(s); - return Show.p3Show(ss, s, ss).contramap(Zipper.p_()); - } - - /** - * Maps the given function across the elements of this zipper (covariant functor pattern). - * - * @param f A function to map across this zipper. - * @return A new zipper with the given function applied to all elements. - */ - public Zipper map(final F f) { - return zipper(left.map(f), f.f(focus), right.map(f)); - } - - /** - * Performs a right-fold reduction across this zipper. - * - * @param f The function to apply on each element of this zipper. - * @param z The beginning value to start the application from. - * @return the final result after the right-fold reduction. - */ - public B foldRight(final F> f, final B z) { - return left.foldLeft(flip(f), - right.cons(focus).foldRight(compose( - Function., B, B>andThen().f(P1.__1()), f), z)); - } - - /** - * Creates a new zipper with a single element. - * - * @param a The focus element of the new zipper. - * @return a new zipper with a single element which is in focus. - */ - public static Zipper single(final A a) { - return zipper(Stream.nil(), a, Stream.nil()); - } - - /** - * Possibly create a zipper if the provided stream has at least one element, otherwise None. - * The provided stream's head will be the focus of the zipper, and the rest of the stream will follow - * on the right side. - * - * @param a The stream from which to create a zipper. - * @return a new zipper if the provided stream has at least one element, otherwise None. - */ - @SuppressWarnings("IfMayBeConditional") - public static Option> fromStream(final Stream a) { - if (a.isEmpty()) - return none(); - else - return some(zipper(Stream.nil(), a.head(), a.tail()._1())); - } - - /** - * Possibly create a zipper if the provided stream has at least one element, otherwise None. - * The provided stream's last element will be the focus of the zipper, following the rest of the stream in order, - * to the left. - * - * @param a The stream from which to create a zipper. - * @return a new zipper if the provided stream has at least one element, otherwise None. - */ - public static Option> fromStreamEnd(final Stream a) { - if (a.isEmpty()) - return none(); - else { - final Stream xs = a.reverse(); - return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); - } - } - - /** - * Returns the focus element of this zipper. - * - * @return the focus element of this zipper. - */ - public A focus() { - return focus; - } - - /** - * Possibly moves the focus to the next element in the list. - * - * @return An optional zipper with the focus moved one element to the right, if there are elements to the right of - * focus, otherwise None. - */ - public Option> next() { - return right.isEmpty() ? Option.none() : some(tryNext()); - } - - /** - * Attempts to move the focus to the next element, or throws an error if there are no more elements. - * - * @return A zipper with the focus moved one element to the right, if there are elements to the right of - * focus, otherwise throws an error. - */ - public Zipper tryNext() { - if (right.isEmpty()) - throw new Error("Tried next at the end of a zipper."); - else - return zipper(left.cons(focus), right.head(), right.tail()._1()); - } - - /** - * Possibly moves the focus to the previous element in the list. - * - * @return An optional zipper with the focus moved one element to the left, if there are elements to the left of - * focus, otherwise None. - */ - public Option> previous() { - return left.isEmpty() ? Option.none() : some(tryPrevious()); - } - - /** - * Attempts to move the focus to the previous element, or throws an error if there are no more elements. - * - * @return A zipper with the focus moved one element to the left, if there are elements to the left of - * focus, otherwise throws an error. - */ - public Zipper tryPrevious() { - if (left.isEmpty()) - throw new Error("Tried previous at the beginning of a zipper."); - else - return zipper(left.tail()._1(), left.head(), right.cons(focus)); - } - - /** - * First-class version of the next() function. - * - * @return A function that moves the given zipper's focus to the next element. - */ - public static F, Option>> next_() { - return Zipper::next; - } - - /** - * First-class version of the previous() function. - * - * @return A function that moves the given zipper's focus to the previous element. - */ - public static F, Option>> previous_() { - return Zipper::previous; - } - - /** - * Inserts an element to the left of the focus, then moves the focus to the new element. - * - * @param a A new element to insert into this zipper. - * @return A new zipper with the given element in focus, and the current focus element on its right. - */ - public Zipper insertLeft(final A a) { - return zipper(left, a, right.cons(focus)); - } - - /** - * Inserts an element to the right of the focus, then moves the focus to the new element. - * - * @param a A new element to insert into this zipper. - * @return A new zipper with the given element in focus, and the current focus element on its left. - */ - public Zipper insertRight(final A a) { - return zipper(left.cons(focus), a, right); - } - - /** - * Possibly deletes the element at the focus, then moves the element on the left into focus. - * If no element is on the left, focus on the element to the right. - * Returns None if the focus element is the only element in this zipper. - * - * @return A new zipper with this zipper's focus element removed, or None if deleting the focus element - * would cause the zipper to be empty. - */ - public Option> deleteLeft() { - return left.isEmpty() && right.isEmpty() - ? Option.none() - : some(zipper(left.isEmpty() ? left : left.tail()._1(), - left.isEmpty() ? right.head() : left.head(), - left.isEmpty() ? right.tail()._1() : right)); - } - - /** - * Possibly deletes the element at the focus, then moves the element on the right into focus. - * If no element is on the right, focus on the element to the left. - * Returns None if the focus element is the only element in this zipper. - * - * @return A new zipper with this zipper's focus element removed, or None if deleting the focus element - * would cause the zipper to be empty. - */ - public Option> deleteRight() { - return left.isEmpty() && right.isEmpty() - ? Option.none() - : some(zipper(right.isEmpty() ? left.tail()._1() : left, - right.isEmpty() ? left.head() : right.head(), - right.isEmpty() ? right : right.tail()._1())); - } - - /** - * Deletes all elements in the zipper except the focus. - * - * @return A new zipper with the focus element as the only element. - */ - public Zipper deleteOthers() { - final Stream nil = nil(); - return zipper(nil, focus, nil); - } - - /** - * Returns the length of this zipper. - * - * @return the length of this zipper. - */ - public int length() { - return foldRight(Function.constant(Integers.add.f(1)), 0); - } - - /** - * Returns whether the focus is on the first element. - * - * @return true if the focus is on the first element, otherwise false. - */ - public boolean atStart() { - return left.isEmpty(); - } - - /** - * Returns whether the focus is on the last element. - * - * @return true if the focus is on the last element, otherwise false. - */ - public boolean atEnd() { - return right.isEmpty(); - } - - /** - * Creates a zipper of variations of this zipper, in which each element is focused, - * with this zipper as the focus of the zipper of zippers (comonad pattern). - * - * @return a zipper of variations of the provided zipper, in which each element is focused, - * with this zipper as the focus of the zipper of zippers. - */ - public Zipper> positions() { - final Stream> left = Stream.unfold( - p -> p.previous().map(join(P.p2())), this); - final Stream> right = Stream.unfold( - p -> p.next().map(join(P.p2())), this); - - return zipper(left, this, right); - } - - /** - * Maps over variations of this zipper, such that the given function is applied to each variation (comonad pattern). - * - * @param f The comonadic function to apply for each variation of this zipper. - * @return A new zipper, with the given function applied for each variation of this zipper. - */ - public Zipper cobind(final F, B> f) { - return positions().map(f); - } - - /** - * Zips the elements of this zipper with a boolean that indicates whether that element has focus. - * All of the booleans will be false, except the focused element. - * - * @return A new zipper of pairs, with each element of this zipper paired with a boolean that is true if that - * element has focus, and false otherwise. - */ - public Zipper> zipWithFocus() { - return zipper(left.zip(repeat(false)), P.p(focus, true), right.zip(repeat(false))); - } - - /** - * Move the focus to the specified index. - * - * @param n The index to which to move the focus. - * @return A new zipper with the focus moved to the specified index, or none if there is no such index. - */ - public Option> move(final int n) { - final int ll = left.length(); - final int rl = right.length(); - Option> p = some(this); - if (n < 0 || n >= length()) - return none(); - else if (ll >= n) - for (int i = ll - n; i > 0; i--) - p = p.bind(Zipper.previous_()); - else if (rl >= n) - for (int i = rl - n; i > 0; i--) - p = p.bind(Zipper.next_()); - return p; - } - - /** - * A first-class version of the move function. - * - * @return A function that moves the focus of the given zipper to the given index. - */ - public static F, Option>>> move() { - return curry((i, a) -> a.move(i)); - } - - /** - * Moves the focus to the element matching the given predicate, if present. - * - * @param p A predicate to match. - * @return A new zipper with the nearest matching element focused if it is present in this zipper. - */ - public Option> find(final F p) { - if (p.f(focus())) - return some(this); - else { - final Zipper> ps = positions(); - return ps.lefts().interleave(ps.rights()).find(zipper -> p.f(zipper.focus())); - } - } - - /** - * Returns the index of the focus. - * - * @return the index of the focus. - */ - public int index() { - return left.length(); - } - - /** - * Move the focus to the next element. If the last element is focused, loop to the first element. - * - * @return A new zipper with the next element focused, unless the last element is currently focused, in which case - * the first element becomes focused. - */ - public Zipper cycleNext() { - if (left.isEmpty() && right.isEmpty()) - return this; - else if (right.isEmpty()) { - final Stream xs = left.reverse(); - return zipper(Stream.nil(), xs.head(), xs.tail()._1().snoc(P.p(focus))); - } else - return tryNext(); - } - - /** - * Move the focus to the previous element. If the first element is focused, loop to the last element. - * - * @return A new zipper with the previous element focused, unless the first element is currently focused, - * in which case the last element becomes focused. - */ - public Zipper cyclePrevious() { - if (left.isEmpty() && right.isEmpty()) - return this; - else if (left.isEmpty()) { - final Stream xs = right.reverse(); - return zipper(xs.tail()._1().snoc(P.p(focus)), xs.head(), Stream.nil()); - } else - return tryPrevious(); - } - - /** - * Possibly deletes the element at the focus, then move the element on the left into focus. If no element is on the - * left, focus on the last element. If the deletion will cause the list to be empty, return None. - * - * @return A new zipper with the focused element removed, and focus on the previous element to the left, or the last - * element if there is no element to the left. - */ - public Option> deleteLeftCycle() { - if (left.isEmpty() && right.isEmpty()) - return none(); - else if (left.isNotEmpty()) - return some(zipper(left.tail()._1(), left.head(), right)); - else { - final Stream xs = right.reverse(); - return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); - } - } - - /** - * Possibly deletes the element at the focus, then move the element on the right into focus. If no element is on the - * right, focus on the first element. If the deletion will cause the list to be empty, return None. - * - * @return A new zipper with the focused element removed, and focus on the next element to the right, or the first - * element if there is no element to the right. - */ - public Option> deleteRightCycle() { - if (left.isEmpty() && right.isEmpty()) - return none(); - else if (right.isNotEmpty()) - return some(zipper(left, right.head(), right.tail()._1())); - else { - final Stream xs = left.reverse(); - return some(zipper(Stream.nil(), xs.head(), xs.tail()._1())); - } - } - - /** - * Replaces the element in focus with the given element. - * - * @param a An element to replace the focused element with. - * @return A new zipper with the given element in focus. - */ - public Zipper replace(final A a) { - return zipper(left, a, right); - } - - /** - * Returns the Stream representation of this zipper. - * - * @return A stream that contains all the elements of this zipper. - */ - public Stream toStream() { - return left.reverse().snoc(P.p(focus)).append(right); - } - - /** - * Returns a Stream of the elements to the left of focus. - * - * @return a Stream of the elements to the left of focus. - */ - public Stream lefts() { - return left; - } - - /** - * Returns a Stream of the elements to the right of focus. - * - * @return a Stream of the elements to the right of focus. - */ - public Stream rights() { - return right; - } - - /** - * Zips this Zipper with another, applying the given function lock-step over both zippers in both directions. - * The structure of the resulting Zipper is the structural intersection of the two Zippers. - * - * @param bs A Zipper to zip this one with. - * @param f A function with which to zip together the two Zippers. - * @return The result of applying the given function over this Zipper and the given Zipper, location-wise. - */ - public Zipper zipWith(final Zipper bs, final F2 f) { - return F2Functions.zipZipperM(f).f(this, bs); - } - - - /** - * Zips this Zipper with another, applying the given function lock-step over both zippers in both directions. - * The structure of the resulting Zipper is the structural intersection of the two Zippers. - * - * @param bs A Zipper to zip this one with. - * @param f A function with which to zip together the two Zippers. - * @return The result of applying the given function over this Zipper and the given Zipper, location-wise. - */ - public Zipper zipWith(final Zipper bs, final F> f) { - return zipWith(bs, uncurryF2(f)); - } - - /** - * Returns an iterator of all the positions of this Zipper, starting from the leftmost position. - * - * @return An iterator of all the positions of this Zipper, starting from the leftmost position. - */ - public Iterator> iterator() { return positions().toStream().iterator(); } -} +package fj.data; + +import fj.*; +import fj.function.Integers; + +import java.util.Iterator; + +import static fj.Function.compose; +import static fj.Function.curry; +import static fj.Function.flip; +import static fj.Function.join; +import static fj.Function.uncurryF2; +import static fj.data.Option.none; +import static fj.data.Option.some; +import static fj.data.Stream.nil; +import static fj.data.Stream.repeat; + +/** + * Provides a pointed stream, which is a non-empty zipper-like stream structure that tracks an index (focus) + * position in a stream. Focus can be moved forward and backwards through the stream, elements can be inserted + * before or after the focused position, and the focused item can be deleted. + *

      + * Based on the pointedlist library by Jeff Wheeler. + */ +public final class Zipper implements Iterable> { + private final Stream left; + private final A focus; + private final Stream right; + + private Zipper(final Stream left, final A focus, final Stream right) { + this.left = left; + this.focus = focus; + this.right = right; + } + + + /** + * Creates a new Zipper with the given streams before and after the focus, and the given focused item. + * + * @param left The stream of elements before the focus. + * @param focus The element under focus. + * @param right The stream of elements after the focus. + * @return a new Zipper with the given streams before and after the focus, and the given focused item. + */ + public static Zipper zipper(final Stream left, final A focus, final Stream right) { + return new Zipper<>(left, focus, right); + } + + /** + * Creates a new Zipper from the given triple. + * + * @param p A triple of the elements before the focus, the focus element, and the elements after the focus, + * respectively. + * @return a new Zipper created from the given triple. + */ + public static Zipper zipper(final P3, A, Stream> p) { + return new Zipper<>(p._1(), p._2(), p._3()); + } + + /** + * First-class constructor of zippers. + * + * @return A function that yields a new zipper given streams on the left and right and a focus element. + */ + public static F3, A, Stream, Zipper> zipper() { + return Zipper::zipper; + } + + /** + * Returns the product-3 representation of this Zipper. + * + * @return the product-3 representation of this Zipper. + */ + public P3, A, Stream> p() { + return P.p(left, focus, right); + } + + /** + * A first-class function that yields the product-3 representation of a given Zipper. + * + * @return A first-class function that yields the product-3 representation of a given Zipper. + */ + public static F, P3, A, Stream>> p_() { + return Zipper::p; + } + + /** + * An Ord instance for Zippers. + * + * @param o An Ord instance for the element type. + * @return An Ord instance for Zippers. + */ + public static Ord> ord(final Ord o) { + final Ord> so = Ord.streamOrd(o); + return Ord.p3Ord(so, o, so).contramap(Zipper.p_()); + } + + @Override + public final boolean equals(Object other) { + return Equal.equals0(Zipper.class, this, other, () -> Equal.zipperEqual(Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.zipperHash(Hash.anyHash()).hash(this); + } + + /** + * An Equal instance for Zippers. + * + * @param e An Equal instance for the element type. + * @return An Equal instance for Zippers. + */ + public static Equal> eq(final Equal e) { + final Equal> se = Equal.streamEqual(e); + return Equal.p3Equal(se, e, se).contramap(Zipper.p_()); + } + + /** + * A Show instance for Zippers. + * + * @param s A Show instance for the element type. + * @return A Show instance for Zippers. + */ + public static Show> show(final Show s) { + final Show> ss = Show.streamShow(s); + return Show.p3Show(ss, s, ss).contramap(Zipper.p_()); + } + + /** + * Maps the given function across the elements of this zipper (covariant functor pattern). + * + * @param f A function to map across this zipper. + * @return A new zipper with the given function applied to all elements. + */ + public Zipper map(final F f) { + return zipper(left.map(f), f.f(focus), right.map(f)); + } + + /** + * Performs a right-fold reduction across this zipper. + * + * @param f The function to apply on each element of this zipper. + * @param z The beginning value to start the application from. + * @return the final result after the right-fold reduction. + */ + public B foldRight(final F> f, final B z) { + return left.foldLeft(flip(f), + right.cons(focus).foldRight(compose( + Function., B, B>andThen().f(P1.__1()), f), z)); + } + + /** + * Creates a new zipper with a single element. + * + * @param a The focus element of the new zipper. + * @return a new zipper with a single element which is in focus. + */ + public static Zipper single(final A a) { + return zipper(Stream.nil(), a, Stream.nil()); + } + + /** + * Possibly create a zipper if the provided stream has at least one element, otherwise None. + * The provided stream's head will be the focus of the zipper, and the rest of the stream will follow + * on the right side. + * + * @param a The stream from which to create a zipper. + * @return a new zipper if the provided stream has at least one element, otherwise None. + */ + @SuppressWarnings("IfMayBeConditional") + public static Option> fromStream(final Stream a) { + if (a.isEmpty()) + return none(); + else + return some(zipper(Stream.nil(), a.head(), a.tail()._1())); + } + + /** + * Possibly create a zipper if the provided stream has at least one element, otherwise None. + * The provided stream's last element will be the focus of the zipper, following the rest of the stream in order, + * to the left. + * + * @param a The stream from which to create a zipper. + * @return a new zipper if the provided stream has at least one element, otherwise None. + */ + public static Option> fromStreamEnd(final Stream a) { + if (a.isEmpty()) + return none(); + else { + final Stream xs = a.reverse(); + return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); + } + } + + /** + * Returns the focus element of this zipper. + * + * @return the focus element of this zipper. + */ + public A focus() { + return focus; + } + + /** + * Possibly moves the focus to the next element in the list. + * + * @return An optional zipper with the focus moved one element to the right, if there are elements to the right of + * focus, otherwise None. + */ + public Option> next() { + return right.isEmpty() ? Option.none() : some(tryNext()); + } + + /** + * Attempts to move the focus to the next element, or throws an error if there are no more elements. + * + * @return A zipper with the focus moved one element to the right, if there are elements to the right of + * focus, otherwise throws an error. + */ + public Zipper tryNext() { + if (right.isEmpty()) + throw new Error("Tried next at the end of a zipper."); + else + return zipper(left.cons(focus), right.head(), right.tail()._1()); + } + + /** + * Possibly moves the focus to the previous element in the list. + * + * @return An optional zipper with the focus moved one element to the left, if there are elements to the left of + * focus, otherwise None. + */ + public Option> previous() { + return left.isEmpty() ? Option.none() : some(tryPrevious()); + } + + /** + * Attempts to move the focus to the previous element, or throws an error if there are no more elements. + * + * @return A zipper with the focus moved one element to the left, if there are elements to the left of + * focus, otherwise throws an error. + */ + public Zipper tryPrevious() { + if (left.isEmpty()) + throw new Error("Tried previous at the beginning of a zipper."); + else + return zipper(left.tail()._1(), left.head(), right.cons(focus)); + } + + /** + * First-class version of the next() function. + * + * @return A function that moves the given zipper's focus to the next element. + */ + public static F, Option>> next_() { + return Zipper::next; + } + + /** + * First-class version of the previous() function. + * + * @return A function that moves the given zipper's focus to the previous element. + */ + public static F, Option>> previous_() { + return Zipper::previous; + } + + /** + * Inserts an element to the left of the focus, then moves the focus to the new element. + * + * @param a A new element to insert into this zipper. + * @return A new zipper with the given element in focus, and the current focus element on its right. + */ + public Zipper insertLeft(final A a) { + return zipper(left, a, right.cons(focus)); + } + + /** + * Inserts an element to the right of the focus, then moves the focus to the new element. + * + * @param a A new element to insert into this zipper. + * @return A new zipper with the given element in focus, and the current focus element on its left. + */ + public Zipper insertRight(final A a) { + return zipper(left.cons(focus), a, right); + } + + /** + * Possibly deletes the element at the focus, then moves the element on the left into focus. + * If no element is on the left, focus on the element to the right. + * Returns None if the focus element is the only element in this zipper. + * + * @return A new zipper with this zipper's focus element removed, or None if deleting the focus element + * would cause the zipper to be empty. + */ + public Option> deleteLeft() { + return left.isEmpty() && right.isEmpty() + ? Option.none() + : some(zipper(left.isEmpty() ? left : left.tail()._1(), + left.isEmpty() ? right.head() : left.head(), + left.isEmpty() ? right.tail()._1() : right)); + } + + /** + * Possibly deletes the element at the focus, then moves the element on the right into focus. + * If no element is on the right, focus on the element to the left. + * Returns None if the focus element is the only element in this zipper. + * + * @return A new zipper with this zipper's focus element removed, or None if deleting the focus element + * would cause the zipper to be empty. + */ + public Option> deleteRight() { + return left.isEmpty() && right.isEmpty() + ? Option.none() + : some(zipper(right.isEmpty() ? left.tail()._1() : left, + right.isEmpty() ? left.head() : right.head(), + right.isEmpty() ? right : right.tail()._1())); + } + + /** + * Deletes all elements in the zipper except the focus. + * + * @return A new zipper with the focus element as the only element. + */ + public Zipper deleteOthers() { + final Stream nil = nil(); + return zipper(nil, focus, nil); + } + + /** + * Returns the length of this zipper. + * + * @return the length of this zipper. + */ + public int length() { + return foldRight(Function.constant(Integers.add.f(1)), 0); + } + + /** + * Returns whether the focus is on the first element. + * + * @return true if the focus is on the first element, otherwise false. + */ + public boolean atStart() { + return left.isEmpty(); + } + + /** + * Returns whether the focus is on the last element. + * + * @return true if the focus is on the last element, otherwise false. + */ + public boolean atEnd() { + return right.isEmpty(); + } + + /** + * Creates a zipper of variations of this zipper, in which each element is focused, + * with this zipper as the focus of the zipper of zippers (comonad pattern). + * + * @return a zipper of variations of the provided zipper, in which each element is focused, + * with this zipper as the focus of the zipper of zippers. + */ + public Zipper> positions() { + final Stream> left = Stream.unfold( + p -> p.previous().map(join(P.p2())), this); + final Stream> right = Stream.unfold( + p -> p.next().map(join(P.p2())), this); + + return zipper(left, this, right); + } + + /** + * Maps over variations of this zipper, such that the given function is applied to each variation (comonad pattern). + * + * @param f The comonadic function to apply for each variation of this zipper. + * @return A new zipper, with the given function applied for each variation of this zipper. + */ + public Zipper cobind(final F, B> f) { + return positions().map(f); + } + + /** + * Zips the elements of this zipper with a boolean that indicates whether that element has focus. + * All of the booleans will be false, except the focused element. + * + * @return A new zipper of pairs, with each element of this zipper paired with a boolean that is true if that + * element has focus, and false otherwise. + */ + public Zipper> zipWithFocus() { + return zipper(left.zip(repeat(false)), P.p(focus, true), right.zip(repeat(false))); + } + + /** + * Move the focus to the specified index. + * + * @param n The index to which to move the focus. + * @return A new zipper with the focus moved to the specified index, or none if there is no such index. + */ + public Option> move(final int n) { + final int ll = left.length(); + final int rl = right.length(); + Option> p = some(this); + if (n < 0 || n >= length()) + return none(); + else if (ll >= n) + for (int i = ll - n; i > 0; i--) + p = p.bind(Zipper.previous_()); + else if (rl >= n) + for (int i = rl - n; i > 0; i--) + p = p.bind(Zipper.next_()); + return p; + } + + /** + * A first-class version of the move function. + * + * @return A function that moves the focus of the given zipper to the given index. + */ + public static F, Option>>> move() { + return curry((i, a) -> a.move(i)); + } + + /** + * Moves the focus to the element matching the given predicate, if present. + * + * @param p A predicate to match. + * @return A new zipper with the nearest matching element focused if it is present in this zipper. + */ + public Option> find(final F p) { + if (p.f(focus())) + return some(this); + else { + final Zipper> ps = positions(); + return ps.lefts().interleave(ps.rights()).find(zipper -> p.f(zipper.focus())); + } + } + + /** + * Returns the index of the focus. + * + * @return the index of the focus. + */ + public int index() { + return left.length(); + } + + /** + * Move the focus to the next element. If the last element is focused, loop to the first element. + * + * @return A new zipper with the next element focused, unless the last element is currently focused, in which case + * the first element becomes focused. + */ + public Zipper cycleNext() { + if (left.isEmpty() && right.isEmpty()) + return this; + else if (right.isEmpty()) { + final Stream xs = left.reverse(); + return zipper(Stream.nil(), xs.head(), xs.tail()._1().snoc(P.p(focus))); + } else + return tryNext(); + } + + /** + * Move the focus to the previous element. If the first element is focused, loop to the last element. + * + * @return A new zipper with the previous element focused, unless the first element is currently focused, + * in which case the last element becomes focused. + */ + public Zipper cyclePrevious() { + if (left.isEmpty() && right.isEmpty()) + return this; + else if (left.isEmpty()) { + final Stream xs = right.reverse(); + return zipper(xs.tail()._1().snoc(P.p(focus)), xs.head(), Stream.nil()); + } else + return tryPrevious(); + } + + /** + * Possibly deletes the element at the focus, then move the element on the left into focus. If no element is on the + * left, focus on the last element. If the deletion will cause the list to be empty, return None. + * + * @return A new zipper with the focused element removed, and focus on the previous element to the left, or the last + * element if there is no element to the left. + */ + public Option> deleteLeftCycle() { + if (left.isEmpty() && right.isEmpty()) + return none(); + else if (left.isNotEmpty()) + return some(zipper(left.tail()._1(), left.head(), right)); + else { + final Stream xs = right.reverse(); + return some(zipper(xs.tail()._1(), xs.head(), Stream.nil())); + } + } + + /** + * Possibly deletes the element at the focus, then move the element on the right into focus. If no element is on the + * right, focus on the first element. If the deletion will cause the list to be empty, return None. + * + * @return A new zipper with the focused element removed, and focus on the next element to the right, or the first + * element if there is no element to the right. + */ + public Option> deleteRightCycle() { + if (left.isEmpty() && right.isEmpty()) + return none(); + else if (right.isNotEmpty()) + return some(zipper(left, right.head(), right.tail()._1())); + else { + final Stream xs = left.reverse(); + return some(zipper(Stream.nil(), xs.head(), xs.tail()._1())); + } + } + + /** + * Replaces the element in focus with the given element. + * + * @param a An element to replace the focused element with. + * @return A new zipper with the given element in focus. + */ + public Zipper replace(final A a) { + return zipper(left, a, right); + } + + /** + * Returns the Stream representation of this zipper. + * + * @return A stream that contains all the elements of this zipper. + */ + public Stream toStream() { + return left.reverse().snoc(P.p(focus)).append(right); + } + + /** + * Returns a Stream of the elements to the left of focus. + * + * @return a Stream of the elements to the left of focus. + */ + public Stream lefts() { + return left; + } + + /** + * Returns a Stream of the elements to the right of focus. + * + * @return a Stream of the elements to the right of focus. + */ + public Stream rights() { + return right; + } + + /** + * Zips this Zipper with another, applying the given function lock-step over both zippers in both directions. + * The structure of the resulting Zipper is the structural intersection of the two Zippers. + * + * @param bs A Zipper to zip this one with. + * @param f A function with which to zip together the two Zippers. + * @return The result of applying the given function over this Zipper and the given Zipper, location-wise. + */ + public Zipper zipWith(final Zipper bs, final F2 f) { + return f.zipZipperM().f(this, bs); + } + + + /** + * Zips this Zipper with another, applying the given function lock-step over both zippers in both directions. + * The structure of the resulting Zipper is the structural intersection of the two Zippers. + * + * @param bs A Zipper to zip this one with. + * @param f A function with which to zip together the two Zippers. + * @return The result of applying the given function over this Zipper and the given Zipper, location-wise. + */ + public Zipper zipWith(final Zipper bs, final F> f) { + return zipWith(bs, uncurryF2(f)); + } + + /** + * Returns an iterator of all the positions of this Zipper, starting from the leftmost position. + * + * @return An iterator of all the positions of this Zipper, starting from the leftmost position. + */ + public Iterator> iterator() { return positions().toStream().iterator(); } +} diff --git a/core/src/main/java/fj/data/fingertrees/FingerTree.java b/core/src/main/java/fj/data/fingertrees/FingerTree.java index 160b5508..ab0effb0 100644 --- a/core/src/main/java/fj/data/fingertrees/FingerTree.java +++ b/core/src/main/java/fj/data/fingertrees/FingerTree.java @@ -1,268 +1,268 @@ -package fj.data.fingertrees; - -import fj.*; -import fj.data.Option; -import fj.data.Seq; -import fj.data.Stream; - -import static fj.Monoid.intAdditionMonoid; -import static fj.Monoid.intMaxMonoid; -import static fj.data.Stream.nil; - -/** - * Provides 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in - * amortized O(1) time. Concatenation and splitting time is O(log n) in the size of the smaller piece. - * A general purpose data structure that can serve as a sequence, priority queue, search tree, priority search queue - * and more. - *

      - * This class serves as a datastructure construction kit, rather than a datastructure in its own right. By supplying - * a monoid, a measurement function, insertion, deletion, and so forth, any purely functional datastructure can be - * emulated. See {@link Seq} for an example. - *

      - * Based on "Finger trees: a simple general-purpose data structure", by Ralf Hinze and Ross Paterson. - * - * @param The monoidal type with which to annotate nodes. - * @param The type of the tree's elements. - */ -public abstract class FingerTree { - private final Measured m; - - /** - * Folds the tree to the right with the given function and the given initial element. - * - * @param f A function with which to fold the tree. - * @param z An initial element to apply to the fold. - * @return A reduction of this tree by applying the given function, associating to the right. - */ - public abstract B foldRight(final F> f, final B z); - - public final B foldRight(final F2 f, final B z) { - return foldRight(F2Functions.curry(f), z); - } - - /** - * Folds the tree to the right with the given function. - * - * @param f A function with which to fold the tree. - * @return A reduction of this tree by applying the given function, associating to the right. - */ - public abstract A reduceRight(final F> f); - - /** - * Folds the tree to the left with the given function and the given initial element. - * - * @param f A function with which to fold the tree. - * @param z An initial element to apply to the fold. - * @return A reduction of this tree by applying the given function, associating to the left. - */ - public abstract B foldLeft(final F> f, final B z); - - public final B foldLeft(final F2 f, final B z) { - return foldLeft(F2Functions.curry(f), z); - } - - /** - * Folds the tree to the left with the given function. - * - * @param f A function with which to fold the tree. - * @return A reduction of this tree by applying the given function, associating to the right. - */ - public abstract A reduceLeft(final F> f); - - /** - * Maps the given function across this tree, measuring with the given Measured instance. - * - * @param f A function to map across the values of this tree. - * @param m A measuring with which to annotate the tree. - * @return A new tree with the same structure as this tree, with each element transformed by the given function, - * and nodes annotated according to the given measuring. - */ - public abstract FingerTree map(final F f, final Measured m); - - public final FingerTree filter(final F f) { - FingerTree tree = new Empty<>(m); - return foldLeft((acc, a) -> f.f(a) ? acc.snoc(a) : acc, tree); - } - - /** - * Returns the sum of this tree's annotations. - * - * @return the sum of this tree's annotations. - */ - public abstract V measure(); - - /** - * Indicates whether this tree is empty. - * - * @return true if this tree is the empty tree, otherwise false. - */ - public final boolean isEmpty() { - return this instanceof Empty; - } - - public final Measured measured() { - return m; - } - - /** - * Provides pattern matching on trees. This is the Church encoding of the FingerTree datatype. - * - * @param empty The function to apply to this empty tree. - * @param single A function to apply if this tree contains a single element. - * @param deep A function to apply if this tree contains more than one element. - * @return The result of the function that matches this tree structurally, applied to this tree. - */ - public abstract B match(final F, B> empty, final F, B> single, - final F, B> deep); - - FingerTree(final Measured m) { - this.m = m; - } - - /** - * Constructs a Measured instance for the element type, given a monoid and a measuring function. - * - * @param monoid A monoid for the measures. - * @param measure A function with which to measure element values. - * @return A Measured instance for the given element type, that uses the given monoid and measuring function. - */ - public static Measured measured(final Monoid monoid, final F measure) { - return Measured.measured(monoid, measure); - } - - /** - * Returns a builder of trees and tree components that annotates them using the given Measured instance. - * - * @param m A Measured instance with which to annotate trees, digits, and nodes. - * @return A builder of trees and tree components that annotates them using the given Measured instance. - */ - public static MakeTree mkTree(final Measured m) { - return new MakeTree<>(m); - } - - /** - * Adds the given element to this tree as the first element. - * - * @param a The element to add to the front of this tree. - * @return A new tree with the given element at the front. - */ - public abstract FingerTree cons(final A a); - - /** - * Adds the given element to this tree as the last element. - * - * @param a The element to add to the end of this tree. - * @return A new tree with the given element at the end. - */ - public abstract FingerTree snoc(final A a); - - /** - * The first element of this tree. This is an O(1) operation. - * - * @return The first element if this tree is nonempty, otherwise throws an error. - */ - public abstract A head(); - - public final Option headOption() { - return isEmpty() ? Option.none() : Option.some(head()); - } - - /** - * Performs a reduction on this finger tree using the given arguments. - * - * @param nil The value to return if this finger tree is empty. - * @param cons The function to apply to the head and tail of this finger tree if it is not empty. - * @return A reduction on this finger tree. - */ - public final B uncons(B nil, F2, B> cons) { - return isEmpty() ? nil : cons.f(head(), tail()); - } - - - /** - * The last element of this tree. This is an O(1) operation. - * - * @return The last element if this tree is nonempty, otherwise throws an error. - */ - public abstract A last(); - - /** - * The tree without the first element. This is an O(1) operation. - * - * @return The tree without the first element if this tree is nonempty, otherwise throws an error. - */ - public abstract FingerTree tail(); - - /** - * The tree without the last element. This is an O(1) operation. - * - * @return The tree without the last element if this tree is nonempty, otherwise throws an error. - */ - public abstract FingerTree init(); - - /** - * Appends one finger tree to another. - * - * @param t A finger tree to append to this one. - * @return A new finger tree which is a concatenation of this tree and the given tree. - */ - public abstract FingerTree append(final FingerTree t); - - /** - * Splits this tree into a pair of subtrees at the point where the given predicate, based on the measure, - * changes from false to true. This is a O(log(n)) operation. - * - * @return Pair: the subtree containing elements before the point where pred first holds and the subtree - * containing element at and after the point where pred first holds. Empty if pred never holds. - */ - public final P2, FingerTree> split(final F predicate) { - if (!isEmpty() && predicate.f(measure())) { - final P3, A, FingerTree> lxr = split1(predicate); - return P.p(lxr._1(), lxr._3().cons(lxr._2())); - } else { - return P.p(this, mkTree(m).empty()); - } - } - - /** - * Like split, but returns the element where pred first holds separately. - * - * Throws an error if the tree is empty. - */ - public final P3, A, FingerTree> split1(final F predicate) { - return split1(predicate, measured().zero()); - } - - abstract P3, A, FingerTree> split1(final F predicate, final V acc); - - public abstract P2 lookup(final F o, final int i); - - public abstract int length(); - - public static FingerTree emptyIntAddition() { - return empty(intAdditionMonoid, Function.constant(1)); - } - - /** - * Creates an empty finger tree with elements of type A and node annotations - * of type V. - * - * @param m A monoid to combine node annotations - * @param f Function to convert node element to annotation. - * @return An empty finger tree. - */ - public static FingerTree empty(Monoid m, F f) { - return FingerTree.mkTree(measured(m, f)).empty(); - } - - /** - * Returns a finger tree which combines the integer node annotations with the - * maximum function. A priority queue with integer priorities. - */ - public static FingerTree> emptyIntMax() { - return empty(intMaxMonoid, (P2 p) -> p._1()); - } - - public abstract Stream toStream(); - -} +package fj.data.fingertrees; + +import fj.*; +import fj.data.Option; +import fj.data.Seq; +import fj.data.Stream; + +import static fj.Monoid.intAdditionMonoid; +import static fj.Monoid.intMaxMonoid; +import static fj.data.Stream.nil; + +/** + * Provides 2-3 finger trees, a functional representation of persistent sequences supporting access to the ends in + * amortized O(1) time. Concatenation and splitting time is O(log n) in the size of the smaller piece. + * A general purpose data structure that can serve as a sequence, priority queue, search tree, priority search queue + * and more. + *

      + * This class serves as a datastructure construction kit, rather than a datastructure in its own right. By supplying + * a monoid, a measurement function, insertion, deletion, and so forth, any purely functional datastructure can be + * emulated. See {@link Seq} for an example. + *

      + * Based on "Finger trees: a simple general-purpose data structure", by Ralf Hinze and Ross Paterson. + * + * @param The monoidal type with which to annotate nodes. + * @param The type of the tree's elements. + */ +public abstract class FingerTree { + private final Measured m; + + /** + * Folds the tree to the right with the given function and the given initial element. + * + * @param f A function with which to fold the tree. + * @param z An initial element to apply to the fold. + * @return A reduction of this tree by applying the given function, associating to the right. + */ + public abstract B foldRight(final F> f, final B z); + + public final B foldRight(final F2 f, final B z) { + return foldRight(f.curry(), z); + } + + /** + * Folds the tree to the right with the given function. + * + * @param f A function with which to fold the tree. + * @return A reduction of this tree by applying the given function, associating to the right. + */ + public abstract A reduceRight(final F> f); + + /** + * Folds the tree to the left with the given function and the given initial element. + * + * @param f A function with which to fold the tree. + * @param z An initial element to apply to the fold. + * @return A reduction of this tree by applying the given function, associating to the left. + */ + public abstract B foldLeft(final F> f, final B z); + + public final B foldLeft(final F2 f, final B z) { + return foldLeft(f.curry(), z); + } + + /** + * Folds the tree to the left with the given function. + * + * @param f A function with which to fold the tree. + * @return A reduction of this tree by applying the given function, associating to the right. + */ + public abstract A reduceLeft(final F> f); + + /** + * Maps the given function across this tree, measuring with the given Measured instance. + * + * @param f A function to map across the values of this tree. + * @param m A measuring with which to annotate the tree. + * @return A new tree with the same structure as this tree, with each element transformed by the given function, + * and nodes annotated according to the given measuring. + */ + public abstract FingerTree map(final F f, final Measured m); + + public final FingerTree filter(final F f) { + FingerTree tree = new Empty<>(m); + return foldLeft((acc, a) -> f.f(a) ? acc.snoc(a) : acc, tree); + } + + /** + * Returns the sum of this tree's annotations. + * + * @return the sum of this tree's annotations. + */ + public abstract V measure(); + + /** + * Indicates whether this tree is empty. + * + * @return true if this tree is the empty tree, otherwise false. + */ + public final boolean isEmpty() { + return this instanceof Empty; + } + + public final Measured measured() { + return m; + } + + /** + * Provides pattern matching on trees. This is the Church encoding of the FingerTree datatype. + * + * @param empty The function to apply to this empty tree. + * @param single A function to apply if this tree contains a single element. + * @param deep A function to apply if this tree contains more than one element. + * @return The result of the function that matches this tree structurally, applied to this tree. + */ + public abstract B match(final F, B> empty, final F, B> single, + final F, B> deep); + + FingerTree(final Measured m) { + this.m = m; + } + + /** + * Constructs a Measured instance for the element type, given a monoid and a measuring function. + * + * @param monoid A monoid for the measures. + * @param measure A function with which to measure element values. + * @return A Measured instance for the given element type, that uses the given monoid and measuring function. + */ + public static Measured measured(final Monoid monoid, final F measure) { + return Measured.measured(monoid, measure); + } + + /** + * Returns a builder of trees and tree components that annotates them using the given Measured instance. + * + * @param m A Measured instance with which to annotate trees, digits, and nodes. + * @return A builder of trees and tree components that annotates them using the given Measured instance. + */ + public static MakeTree mkTree(final Measured m) { + return new MakeTree<>(m); + } + + /** + * Adds the given element to this tree as the first element. + * + * @param a The element to add to the front of this tree. + * @return A new tree with the given element at the front. + */ + public abstract FingerTree cons(final A a); + + /** + * Adds the given element to this tree as the last element. + * + * @param a The element to add to the end of this tree. + * @return A new tree with the given element at the end. + */ + public abstract FingerTree snoc(final A a); + + /** + * The first element of this tree. This is an O(1) operation. + * + * @return The first element if this tree is nonempty, otherwise throws an error. + */ + public abstract A head(); + + public final Option headOption() { + return isEmpty() ? Option.none() : Option.some(head()); + } + + /** + * Performs a reduction on this finger tree using the given arguments. + * + * @param nil The value to return if this finger tree is empty. + * @param cons The function to apply to the head and tail of this finger tree if it is not empty. + * @return A reduction on this finger tree. + */ + public final B uncons(B nil, F2, B> cons) { + return isEmpty() ? nil : cons.f(head(), tail()); + } + + + /** + * The last element of this tree. This is an O(1) operation. + * + * @return The last element if this tree is nonempty, otherwise throws an error. + */ + public abstract A last(); + + /** + * The tree without the first element. This is an O(1) operation. + * + * @return The tree without the first element if this tree is nonempty, otherwise throws an error. + */ + public abstract FingerTree tail(); + + /** + * The tree without the last element. This is an O(1) operation. + * + * @return The tree without the last element if this tree is nonempty, otherwise throws an error. + */ + public abstract FingerTree init(); + + /** + * Appends one finger tree to another. + * + * @param t A finger tree to append to this one. + * @return A new finger tree which is a concatenation of this tree and the given tree. + */ + public abstract FingerTree append(final FingerTree t); + + /** + * Splits this tree into a pair of subtrees at the point where the given predicate, based on the measure, + * changes from false to true. This is a O(log(n)) operation. + * + * @return Pair: the subtree containing elements before the point where pred first holds and the subtree + * containing element at and after the point where pred first holds. Empty if pred never holds. + */ + public final P2, FingerTree> split(final F predicate) { + if (!isEmpty() && predicate.f(measure())) { + final P3, A, FingerTree> lxr = split1(predicate); + return P.p(lxr._1(), lxr._3().cons(lxr._2())); + } else { + return P.p(this, mkTree(m).empty()); + } + } + + /** + * Like split, but returns the element where pred first holds separately. + * + * Throws an error if the tree is empty. + */ + public final P3, A, FingerTree> split1(final F predicate) { + return split1(predicate, measured().zero()); + } + + abstract P3, A, FingerTree> split1(final F predicate, final V acc); + + public abstract P2 lookup(final F o, final int i); + + public abstract int length(); + + public static FingerTree emptyIntAddition() { + return empty(intAdditionMonoid, Function.constant(1)); + } + + /** + * Creates an empty finger tree with elements of type A and node annotations + * of type V. + * + * @param m A monoid to combine node annotations + * @param f Function to convert node element to annotation. + * @return An empty finger tree. + */ + public static FingerTree empty(Monoid m, F f) { + return FingerTree.mkTree(measured(m, f)).empty(); + } + + /** + * Returns a finger tree which combines the integer node annotations with the + * maximum function. A priority queue with integer priorities. + */ + public static FingerTree> emptyIntMax() { + return empty(intMaxMonoid, (P2 p) -> p._1()); + } + + public abstract Stream toStream(); + +} diff --git a/core/src/test/java/fj/FFunctionsTest.java b/core/src/test/java/fj/FFunctionsTest.java index e13b1f2b..e0df9164 100644 --- a/core/src/test/java/fj/FFunctionsTest.java +++ b/core/src/test/java/fj/FFunctionsTest.java @@ -1,43 +1,47 @@ -package fj; - -import fj.data.Tree; -import fj.data.TreeZipper; -import org.junit.Test; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; - -public class FFunctionsTest { - @Test - public void testApply() { - F8 f8 = - (i1, i2, i3, i4, i5, i6, i7, i8) -> - i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8; - F7 f7 = F8Functions.f(f8, 8); - F6 f6 = - F7Functions.f(f7, 7); - F5 f5 = F6Functions.f(f6, 6); - F4 f4 = F5Functions.f(f5, 5); - F3 f3 = F4Functions.f(f4, 4); - F2 f2 = F3Functions.f(f3, 3); - F f1 = F2Functions.f(f2, 2); - assertThat(F1Functions.f(f1, 1).f(), is(36)); - } - - @Test - public void testTreeK() { - final Tree t1 = F1Functions.treeK(Function.identity()).f(1); - final Tree t2 = F1Functions.treeK(Function.identity()).f(2); - assertThat(F1Functions.mapTree(i -> i + 1).f(t1), - is(F1Functions.mapTree(i -> i * 1).f(t2))); - } - - @Test - public void testTreeZipperK() { - final TreeZipper tz1 = F1Functions.treeZipperK(Function.identity()).f(1); - final TreeZipper tz2 = F1Functions.treeZipperK(Function.identity()).f(2); - assertThat(F1Functions.mapTreeZipper(i -> i + 1).f(tz1), - is(F1Functions.mapTreeZipper(i -> i * 1).f(tz2))); - } -} +package fj; + +import fj.data.Tree; +import fj.data.TreeZipper; +import org.junit.Test; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.*; + +public class FFunctionsTest { + @Test + public void testApply() { + F8 f8 = + (i1, i2, i3, i4, i5, i6, i7, i8) -> + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8; + F7 f7 = F8Functions.f(f8, 8); + F6 f6 = + F7Functions.f(f7, 7); + F5 f5 = F6Functions.f(f6, 6); + F4 f4 = F5Functions.f(f5, 5); + F3 f3 = F4Functions.f(f4, 4); + F2 f2 = F3Functions.f(f3, 3); + F f1 = f2.f(2); + assertThat(f1.f(1), is(36)); + } + + @Test + public void testTreeK() { + final Tree t1 = Function.identity().treeK().f(1); + final Tree t2 = Function.identity().treeK().f(2); + F f = i -> i + 1; + F g = i -> i * 1; + assertThat(f.mapTree().f(t1), + is(g.mapTree().f(t2))); + } + + @Test + public void testTreeZipperK() { + final TreeZipper tz1 = Function.identity().treeZipperK().f(1); + final TreeZipper tz2 = Function.identity().treeZipperK().f(2); + F f = i -> i + 1; + F g = i -> i * 1; + assertThat(f.mapTreeZipper().f(tz1), + is(g.mapTreeZipper().f(tz2))); + } +} diff --git a/core/src/test/java/fj/FWFunctionsTest.java b/core/src/test/java/fj/FWFunctionsTest.java deleted file mode 100644 index 1c034ab9..00000000 --- a/core/src/test/java/fj/FWFunctionsTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package fj; - -import org.junit.Test; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -public class FWFunctionsTest { - @Test - public void testLift1() { - F f = i -> i + 1; - F1W f1w = F1W.lift(f); - assertThat(f1w.f(1), is(2)); - } - - @Test - public void testLift2() { - F2 f2 = (i, j) -> i + j; - F2W f2w = F2W.lift(f2); - assertThat(f2w.f(1, 2), is(3)); - } - -} diff --git a/core/src/test/java/fj/data/IOFunctionsTest.java b/core/src/test/java/fj/data/IOFunctionsTest.java index 5213878c..adad0d11 100644 --- a/core/src/test/java/fj/data/IOFunctionsTest.java +++ b/core/src/test/java/fj/data/IOFunctionsTest.java @@ -107,7 +107,8 @@ public void testReplicateM() throws IOException { @Test public void testLift() throws IOException { final IO readName = () -> new BufferedReader(new StringReader("foo")).readLine(); - final F> upperCaseAndPrint = F1Functions., String>o(this::println).f(String::toUpperCase); + F> f = this::println; + final F> upperCaseAndPrint = f.o().f(String::toUpperCase); final IO readAndPrintUpperCasedName = IOFunctions.bind(readName, upperCaseAndPrint); assertThat(readAndPrintUpperCasedName.run(), is("FOO")); } diff --git a/core/src/test/java/fj/function/StringsTest.java b/core/src/test/java/fj/function/StringsTest.java index 92cf44d3..c13e1b81 100644 --- a/core/src/test/java/fj/function/StringsTest.java +++ b/core/src/test/java/fj/function/StringsTest.java @@ -3,7 +3,6 @@ import fj.Function; import org.junit.Test; -import static fj.F1Functions.o; import static fj.Function.compose; import static fj.function.Strings.*; import static org.junit.Assert.*; @@ -17,7 +16,7 @@ public void testLines() { @Test public void testLinesEmpty() { - assertThat(o(unlines(), lines()).f(""), is("")); + assertThat(unlines().o(lines()).f(""), is("")); } @Test diff --git a/demo/src/main/java/fj/demo/Comonad_example.java b/demo/src/main/java/fj/demo/Comonad_example.java index 8d5bc683..3b5661f8 100644 --- a/demo/src/main/java/fj/demo/Comonad_example.java +++ b/demo/src/main/java/fj/demo/Comonad_example.java @@ -1,6 +1,5 @@ package fj.demo; -import fj.F1Functions; import fj.P; import static fj.data.List.asString; import static fj.data.List.fromString; @@ -26,7 +25,7 @@ public static Stream> perms(final Stream s) { for (final Zipper z : fromStream(s)) r = join(z.cobind(zp -> perms(zp.lefts().reverse().append(zp.rights())).map( - F1Functions.o(Stream.cons().f(zp.focus()), P.p1()) + Stream.cons().f(zp.focus()).o(P.p1()) ) ).toStream()); return r; diff --git a/demo/src/main/java/fj/demo/IODemo.java b/demo/src/main/java/fj/demo/IODemo.java index 6451a46b..ea313e77 100644 --- a/demo/src/main/java/fj/demo/IODemo.java +++ b/demo/src/main/java/fj/demo/IODemo.java @@ -4,7 +4,6 @@ import fj.data.IOFunctions; import fj.data.LazyString; -import static fj.F1W.lift; import static fj.data.IOFunctions.interact; import static fj.data.IOFunctions.runSafe; import static fj.data.LazyString.lines_; @@ -29,7 +28,7 @@ public static void main(String[] args) { * and prints that last line. */ public final void readFirstShortLine() { - F f = lift(lines_()).andThen(l -> l.filter(s -> s.length() < 3)).andThen(unlines_()); + F f = lines_().andThen(l -> l.filter(s -> s.length() < 3)).andThen(unlines_()); runSafe(interact(f)); } @@ -37,7 +36,7 @@ public final void readFirstShortLine() { * Read a stream of input lazily using interact, in effect reading the first line */ public final void readFirstLine() { - F f = lift(LazyString::lines).andThen(unlines_()); + F f = lines_().andThen(unlines_()); runSafe(interact(f)); } diff --git a/demo/src/main/java/fj/demo/IOWalkthrough.java b/demo/src/main/java/fj/demo/IOWalkthrough.java index 609d2502..5c1c4663 100644 --- a/demo/src/main/java/fj/demo/IOWalkthrough.java +++ b/demo/src/main/java/fj/demo/IOWalkthrough.java @@ -1,8 +1,6 @@ package fj.demo; import fj.F; -import fj.F1Functions; -import fj.F1W; import fj.Unit; import fj.data.IO; import fj.data.IOFunctions; @@ -49,7 +47,7 @@ public static void main(String[] args) { // now we create a function which takes a string, upper cases it and creates an IO value that would print the upper cased string if executed - final F> upperCaseAndPrint = F1Functions., String>o(IOFunctions::stdoutPrintln).f(String::toUpperCase); + final F> upperCaseAndPrint = s -> stdoutPrintln(s.toUpperCase()); // we now want to compose reading the name with printing it, for that we need to have access to the runtime value that is returned when the // IO value for read is executed, hence we use fj.data.IOFunctions.bind instead of fj.data.IOFunctions.append @@ -73,10 +71,11 @@ public static void main(String[] args) { // assigning the functions to variables like above, but you can use the fj.F1W syntax wrapper for composing single-argument functions and fj.data.IOW // for composing IO values instead, the entire program can be written like so: + F f = String::toUpperCase; IOW.lift(stdoutPrintln("What's your name again?")) .append(stdoutPrint("Name: ")) .append(stdinReadLine()) - .bind(F1W.lift((String s) -> s.toUpperCase()).andThen(IOFunctions::stdoutPrintln)) + .bind(f.andThen(IOFunctions::stdoutPrintln)) .safe().run().on((IOException e) -> { e.printStackTrace(); return Unit.unit(); }); } } diff --git a/demo/src/main/java/fj/demo/Primes2.java b/demo/src/main/java/fj/demo/Primes2.java index 96a852f3..37bfb249 100644 --- a/demo/src/main/java/fj/demo/Primes2.java +++ b/demo/src/main/java/fj/demo/Primes2.java @@ -1,7 +1,5 @@ package fj.demo; -import fj.F1Functions; - import static fj.data.Enumerator.naturalEnumerator; import fj.Show; @@ -21,7 +19,7 @@ public class Primes2 { // Finds primes in a given stream. public static Stream sieve(final Stream xs) { - return cons(xs.head(), () -> sieve(xs.tail()._1().removeAll(F1Functions.o(naturalOrd.equal().eq(ZERO), mod.f(xs.head()))))); + return cons(xs.head(), () -> sieve(xs.tail()._1().removeAll(naturalOrd.equal().eq(ZERO).o(mod.f(xs.head()))))); } // A stream of all primes less than n. diff --git a/demo/src/main/java/fj/demo/WriterDemo_Halver.java b/demo/src/main/java/fj/demo/WriterDemo_Halver.java index a2a270f6..8473e588 100644 --- a/demo/src/main/java/fj/demo/WriterDemo_Halver.java +++ b/demo/src/main/java/fj/demo/WriterDemo_Halver.java @@ -4,7 +4,6 @@ import fj.P2; import fj.data.Writer; -import static fj.F1Functions.map; import static fj.Monoid.stringMonoid; /** @@ -24,7 +23,7 @@ static void testWriter() { Integer init = 32; P2 p1 = half().f(init).flatMap(half()).flatMap(half()).run(); System.out.println(p1); - System.out.println(map(half(), w -> w.flatMap(half()).flatMap(half()).run()).f(init)); + System.out.println(half().map(w -> w.flatMap(half()).flatMap(half()).run()).f(init)); } } diff --git a/demo/src/main/java/fj/demo/concurrent/MapReduce.java b/demo/src/main/java/fj/demo/concurrent/MapReduce.java index 3cb2d761..38a62caa 100644 --- a/demo/src/main/java/fj/demo/concurrent/MapReduce.java +++ b/demo/src/main/java/fj/demo/concurrent/MapReduce.java @@ -35,14 +35,15 @@ public static Promise countWords(final List> documents, // Main program does the requisite IO gymnastics public static void main(final String[] args) { + F z = fileName -> { + try { + return new BufferedReader(new FileReader(new File(fileName))); + } catch (FileNotFoundException e) { + throw new Error(e); + } + }; final List> documents = list(args).map( - F1Functions.andThen(fileName -> { - try { - return new BufferedReader(new FileReader(new File(fileName))); - } catch (FileNotFoundException e) { - throw new Error(e); - } - }, new F>() { + z.andThen(new F>() { public Stream f(final BufferedReader reader) { final Option s; try { diff --git a/demo/src/main/java/fj/demo/euler/Problem2.java b/demo/src/main/java/fj/demo/euler/Problem2.java index eda4a72d..a5639ab9 100644 --- a/demo/src/main/java/fj/demo/euler/Problem2.java +++ b/demo/src/main/java/fj/demo/euler/Problem2.java @@ -1,8 +1,6 @@ package fj.demo.euler; -import fj.F1Functions; import fj.F2; -import fj.F2Functions; import fj.data.Stream; import static fj.data.Stream.cons; import static fj.function.Integers.even; @@ -23,13 +21,13 @@ public static void main(final String[] args) { static void java7() { final Stream fibs = new F2>() { public Stream f(final Integer a, final Integer b) { - return cons(a, F1Functions.lazy(F2Functions.curry(this).f(b)).f(a + b)); + return cons(a, this.curry().f(b).lazy().f(a + b)); } }.f(1, 2); out.println(sum(fibs.filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); } - static F2> fibsJava8 = (a, b) -> cons(a, F1Functions.lazy(F2Functions.curry(Problem2.fibsJava8).f(b)).f(a + b)); + static F2> fibsJava8 = (a, b) -> cons(a, Problem2.fibsJava8.curry().f(b).lazy().f(a + b)); static void java8() { out.println(sum(fibsJava8.f(1, 2).filter(even).takeWhile(intOrd.isLessThan(4000001)).toList())); diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala index dd95dabf..dfde81e3 100755 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala @@ -1,119 +1,119 @@ -package fj -package data - -import fj.function.Effect1 -import org.scalacheck.Prop._ -import ArbitraryHashMap._ -import Equal._ -import Hash._ -import Ord._ -import fj.data.Option._ -import scala.collection.JavaConversions._ -import org.scalacheck.{Arbitrary, Properties} -import data.ArbitraryList._ -import org.scalacheck.Arbitrary._ -import java.util.Map - -object CheckHashMap extends Properties("HashMap") { - implicit val equalInt: Equal[Int] = intEqual contramap ((x: Int) => (x: java.lang.Integer)) - implicit val hashInt: Hash[Int] = intHash contramap ((x: Int) => (x: java.lang.Integer)) - - implicit def arbitraryListOfIterableP2: Arbitrary[java.lang.Iterable[P2[Int, String]]] = - Arbitrary(listOf(arbitrary[(Int, String)]) - .map(_.map((tuple: (Int, String)) => P.p(tuple._1, tuple._2)) - .asInstanceOf[java.lang.Iterable[P2[Int, String]]])) - - property("eq") = forAll((m: HashMap[Int, String], x: Int, y: Int) => m.eq(x, y) == equalInt.eq(x, y)) - - property("hash") = forAll((m: HashMap[Int, String], x: Int) => m.hash(x) == hashInt.hash(x)) - - property("get") = forAll((m: HashMap[Int, String], k: Int) => optionEqual(stringEqual).eq(m.get(k), m.get.f(k))) - - property("set") = forAll((m: HashMap[Int, String], k: Int, v: String) => { - m.set(k, v) - m.get(k).some == v - }) - - property("clear") = forAll((m: HashMap[Int, String], k: Int) => { - m.clear - m.get(k).isNone - }) - - property("contains") = forAll((m: HashMap[Int, String], k: Int) => m.get(k).isSome == m.contains(k)) - - property("keys") = forAll((m: HashMap[Int, String]) => m.keys.forall((k: Int) => (m.get(k).isSome): java.lang.Boolean)) - - property("isEmpty") = forAll((m: HashMap[Int, String], k: Int) => m.get(k).isNone || !m.isEmpty) - - property("size") = forAll((m: HashMap[Int, String], k: Int) => m.get(k).isNone || m.size != 0) - - property("delete") = forAll((m: HashMap[Int, String], k: Int) => { - m.delete(k) - m.get(k).isNone - }) - - property("toList") = forAll((m: HashMap[Int, String]) => { - val list = m.toList - list.length() == m.keys().length() && list.forall((entry: P2[Int, String]) => - optionEqual(stringEqual).eq(m.get(entry._1()), some(entry._2())).asInstanceOf[java.lang.Boolean]) - }) - - property("getDelete") = forAll((m: HashMap[Int, String], k: Int) => { - val x = m.get(k) - val y = m.getDelete(k) - val z = m.get(k) - - z.isNone && optionEqual(stringEqual).eq(x, y) - }) - - property("from") = forAll((entries: java.lang.Iterable[P2[Int, String]]) => { - val map = HashMap.iterableHashMap[Int, String](equalInt, hashInt, entries) - entries.groupBy(_._1) - .forall((e: (Int, Iterable[P2[Int, String]])) => e._2 - .exists((elem: P2[Int, String]) => optionEqual(stringEqual).eq(map.get(e._1), Option.some(elem._2)))) - }) - - property("map") = forAll((m: HashMap[Int, String]) => { - val keyFunction: F[Int, String] = (i: Int) => i.toString - val valueFunction: (String) => String = (s: String) => s + "a" - val mapped = m.map(keyFunction, valueFunction, stringEqual, stringHash) - val keysAreEqual = m.keys().map(keyFunction).toSet == mapped.keys.toSet - val appliedFunctionsToKeysAndValues: Boolean = m.keys().forall((key: Int) => { - val mappedValue = mapped.get(keyFunction.f(key)) - val oldValueMapped = some(valueFunction.f(m.get(key).some())) - Equal.optionEqual(stringEqual).eq(mappedValue, oldValueMapped) - }) - - keysAreEqual && appliedFunctionsToKeysAndValues - }) - - property("toMap") = forAll((m: HashMap[Int, String]) => { - val toMap: Map[Int, String] = m.toMap - m.keys().forall((key: Int) => m.get(key).some() == toMap.get(key)) - }) - - property("fromMap") = forAll((m: HashMap[Int, String]) => { - val map = new java.util.HashMap[Int, String]() - m.keys().foreach((key: Int) => { - map.put(key, m.get(key).some()) - Unit.unit() - }) - val fromMap: HashMap[Int, String] = new HashMap[Int, String](map) - val keysAreEqual = m.keys.toSet == fromMap.keys.toSet - val valuesAreEqual = m.keys().forall((key: Int) => - optionEqual(stringEqual).eq(m.get(key), fromMap.get(key))) - keysAreEqual && valuesAreEqual - }) - - property("No null values") = forAll((m: List[Int]) => { - val map = HashMap.hashMap[Int, Int]() - m.foreachDoEffect(new Effect1[Int] { - def f(a: Int) { - map.set(a, null.asInstanceOf[Int]) - } - }) - m.forall(new F[Int, java.lang.Boolean]() { - def f(a: Int) = map.contains(a) == false - }) - }) +package fj +package data + +import fj.function.Effect1 +import org.scalacheck.Prop._ +import ArbitraryHashMap._ +import Equal._ +import Hash._ +import Ord._ +import fj.data.Option._ +import scala.collection.JavaConversions._ +import org.scalacheck.{Arbitrary, Properties} +import data.ArbitraryList._ +import org.scalacheck.Arbitrary._ +import java.util.Map + +object CheckHashMap extends Properties("HashMap") { + implicit val equalInt: Equal[Int] = intEqual contramap ((x: Int) => (x: java.lang.Integer)) + implicit val hashInt: Hash[Int] = intHash contramap ((x: Int) => (x: java.lang.Integer)) + + implicit def arbitraryListOfIterableP2: Arbitrary[java.lang.Iterable[P2[Int, String]]] = + Arbitrary(listOf(arbitrary[(Int, String)]) + .map(_.map((tuple: (Int, String)) => P.p(tuple._1, tuple._2)) + .asInstanceOf[java.lang.Iterable[P2[Int, String]]])) + + property("eq") = forAll((m: HashMap[Int, String], x: Int, y: Int) => m.eq(x, y) == equalInt.eq(x, y)) + + property("hash") = forAll((m: HashMap[Int, String], x: Int) => m.hash(x) == hashInt.hash(x)) + + property("get") = forAll((m: HashMap[Int, String], k: Int) => optionEqual(stringEqual).eq(m.get(k), m.get.f(k))) + + property("set") = forAll((m: HashMap[Int, String], k: Int, v: String) => { + m.set(k, v) + m.get(k).some == v + }) + + property("clear") = forAll((m: HashMap[Int, String], k: Int) => { + m.clear + m.get(k).isNone + }) + + property("contains") = forAll((m: HashMap[Int, String], k: Int) => m.get(k).isSome == m.contains(k)) + + property("keys") = forAll((m: HashMap[Int, String]) => m.keys.forall((k: Int) => (m.get(k).isSome): java.lang.Boolean)) + + property("isEmpty") = forAll((m: HashMap[Int, String], k: Int) => m.get(k).isNone || !m.isEmpty) + + property("size") = forAll((m: HashMap[Int, String], k: Int) => m.get(k).isNone || m.size != 0) + + property("delete") = forAll((m: HashMap[Int, String], k: Int) => { + m.delete(k) + m.get(k).isNone + }) + + property("toList") = forAll((m: HashMap[Int, String]) => { + val list = m.toList + list.length() == m.keys().length() && list.forall((entry: P2[Int, String]) => + optionEqual(stringEqual).eq(m.get(entry._1()), some(entry._2())).asInstanceOf[java.lang.Boolean]) + }) + + property("getDelete") = forAll((m: HashMap[Int, String], k: Int) => { + val x = m.get(k) + val y = m.getDelete(k) + val z = m.get(k) + + z.isNone && optionEqual(stringEqual).eq(x, y) + }) + + property("from") = forAll((entries: java.lang.Iterable[P2[Int, String]]) => { + val map = HashMap.iterableHashMap[Int, String](equalInt, hashInt, entries) + entries.groupBy(_._1) + .forall((e: (Int, Iterable[P2[Int, String]])) => e._2 + .exists((elem: P2[Int, String]) => optionEqual(stringEqual).eq(map.get(e._1), Option.some(elem._2)))) + }) + + property("map") = forAll((m: HashMap[Int, String]) => { + val keyFunction: F[Int, String] = (i: Int) => i.toString + val valueFunction: (String) => String = (s: String) => s + "a" + val mapped = m.map(keyFunction, valueFunction, stringEqual, stringHash) + val keysAreEqual = m.keys().map(keyFunction).toSet == mapped.keys.toSet + val appliedFunctionsToKeysAndValues: Boolean = m.keys().forall((key: Int) => { + val mappedValue = mapped.get(keyFunction.f(key)) + val oldValueMapped = some(valueFunction.f(m.get(key).some())) + Equal.optionEqual(stringEqual).eq(mappedValue, oldValueMapped) + }) + + keysAreEqual && appliedFunctionsToKeysAndValues + }) + + property("toMap") = forAll((m: HashMap[Int, String]) => { + val toMap: Map[Int, String] = m.toMap + m.keys().forall((key: Int) => m.get(key).some() == toMap.get(key)) + }) + + property("fromMap") = forAll((m: HashMap[Int, String]) => { + val map = new java.util.HashMap[Int, String]() + m.keys().foreach((key: Int) => { + map.put(key, m.get(key).some()) + Unit.unit() + }) + val fromMap: HashMap[Int, String] = new HashMap[Int, String](map) + val keysAreEqual = m.keys.toSet == fromMap.keys.toSet + val valuesAreEqual = m.keys().forall((key: Int) => + optionEqual(stringEqual).eq(m.get(key), fromMap.get(key))) + keysAreEqual && valuesAreEqual + }) + + property("No null values") = forAll((list: List[Int]) => { + val m = HashMap.hashMap[Int, Int]() + list.foreachDoEffect(new Effect1[Int] { + def f(a: Int) { + m.set(a, null.asInstanceOf[Int]) + } + }) + list.forall(new F[Int, java.lang.Boolean]() { + def f(a: Int) = m.contains(a) == false + }) + }) } \ No newline at end of file diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala index 86feeb7a..ff085f87 100644 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckIteratee.scala @@ -7,7 +7,6 @@ import Unit.unit import List.{list, nil} import Option.{some, none} import fj.Function._ -import fj.F1Functions import fj.data.Iteratee._ import org.scalacheck.Prop._ @@ -50,7 +49,7 @@ object CheckIteratee extends Properties("Iteratee") { var tail = l while(!isDone(i) && !tail.isEmpty) { val input = Input.el(tail.head) - val cont: F[F[Input[E], IterV[E, A]], P1[IterV[E, A]]] = F1Functions.`lazy`(Function.apply(input)) + val cont: F[F[Input[E], IterV[E, A]], P1[IterV[E, A]]] = Function.apply(input).`lazy`() i = i.fold(done, cont)._1 tail = tail.tail } diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index 87e2b52a..044595d0 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -5,8 +5,6 @@ import fj.test.*; import org.junit.Test; -import static fj.F1Functions.bind; -import static fj.F1Functions.map; import static fj.test.Arbitrary.*; import static fj.test.Cogen.cogenInteger; import static fj.test.Property.prop; @@ -44,7 +42,7 @@ public void testMapProp() { arbF(cogenInteger, arbInteger), arbInteger, (f, g, i) -> { - int expected = map(f, g).f(i); + int expected = f.map(g).f(i); // System.out.println(String.format("input: %d, result: %d", i, expected)); return prop(expected == Reader.unit(f).map(g).f(i)); }); @@ -59,7 +57,7 @@ public void testFlatMapProp() { a, arbInteger, (f, g, i) -> { - int expected = bind(f, j -> g.f(j).getFunction()).f(i); + int expected = f.bind(j -> g.f(j).getFunction()).f(i); // System.out.println(String.format("input: %d, result: %d", i, expected)); return prop(expected == Reader.unit(f).flatMap(g).f(i)); } From 2f005d9ff90641085e7678f9199a171177813af8 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 2 Apr 2021 00:27:14 +1000 Subject: [PATCH 765/811] Removed FxFunctions and FxW for arity 3-8 --- core/src/main/java/fj/F3Functions.java | 22 ---------------------- core/src/main/java/fj/F3W.java | 8 -------- core/src/main/java/fj/F4Functions.java | 21 --------------------- core/src/main/java/fj/F4W.java | 9 --------- core/src/main/java/fj/F5Functions.java | 21 --------------------- core/src/main/java/fj/F5W.java | 9 --------- core/src/main/java/fj/F6Functions.java | 22 ---------------------- core/src/main/java/fj/F6W.java | 9 --------- core/src/main/java/fj/F7Functions.java | 22 ---------------------- core/src/main/java/fj/F7W.java | 9 --------- core/src/main/java/fj/F8Functions.java | 20 -------------------- core/src/main/java/fj/F8W.java | 9 --------- core/src/test/java/fj/FFunctionsTest.java | 17 ----------------- 13 files changed, 198 deletions(-) delete mode 100644 core/src/main/java/fj/F3Functions.java delete mode 100644 core/src/main/java/fj/F3W.java delete mode 100644 core/src/main/java/fj/F4Functions.java delete mode 100644 core/src/main/java/fj/F4W.java delete mode 100644 core/src/main/java/fj/F5Functions.java delete mode 100644 core/src/main/java/fj/F5W.java delete mode 100644 core/src/main/java/fj/F6Functions.java delete mode 100644 core/src/main/java/fj/F6W.java delete mode 100644 core/src/main/java/fj/F7Functions.java delete mode 100644 core/src/main/java/fj/F7W.java delete mode 100644 core/src/main/java/fj/F8Functions.java delete mode 100644 core/src/main/java/fj/F8W.java diff --git a/core/src/main/java/fj/F3Functions.java b/core/src/main/java/fj/F3Functions.java deleted file mode 100644 index 18e811d9..00000000 --- a/core/src/main/java/fj/F3Functions.java +++ /dev/null @@ -1,22 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F3Functions { - - - private F3Functions() { - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public static F2 f(final F3 f, final A a) { - return (b, c) -> f.f(a, b, c); - } - -} diff --git a/core/src/main/java/fj/F3W.java b/core/src/main/java/fj/F3W.java deleted file mode 100644 index d6ffa80b..00000000 --- a/core/src/main/java/fj/F3W.java +++ /dev/null @@ -1,8 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F3W implements F3 { - -} diff --git a/core/src/main/java/fj/F4Functions.java b/core/src/main/java/fj/F4Functions.java deleted file mode 100644 index cb353764..00000000 --- a/core/src/main/java/fj/F4Functions.java +++ /dev/null @@ -1,21 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F4Functions { - - private F4Functions() { - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public static F3 f(final F4 f, final A a) { - return (b, c, d) -> f.f(a, b, c, d); - } - -} diff --git a/core/src/main/java/fj/F4W.java b/core/src/main/java/fj/F4W.java deleted file mode 100644 index 3cc92e55..00000000 --- a/core/src/main/java/fj/F4W.java +++ /dev/null @@ -1,9 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F4W implements F4 { - - -} diff --git a/core/src/main/java/fj/F5Functions.java b/core/src/main/java/fj/F5Functions.java deleted file mode 100644 index c39b228f..00000000 --- a/core/src/main/java/fj/F5Functions.java +++ /dev/null @@ -1,21 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F5Functions { - - private F5Functions() { - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public static F4 f(final F5 f, final A a) { - return (b, c, d, e) -> f.f(a, b, c, d, e); - } - -} diff --git a/core/src/main/java/fj/F5W.java b/core/src/main/java/fj/F5W.java deleted file mode 100644 index 5fa407cd..00000000 --- a/core/src/main/java/fj/F5W.java +++ /dev/null @@ -1,9 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F5W implements F5 { - - -} diff --git a/core/src/main/java/fj/F6Functions.java b/core/src/main/java/fj/F6Functions.java deleted file mode 100644 index 320b95f4..00000000 --- a/core/src/main/java/fj/F6Functions.java +++ /dev/null @@ -1,22 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F6Functions { - - private F6Functions() { - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public static F5 f(final F6 func, final A a) { - return (b, c, d, e, f) -> func.f(a, b, c, d, e, f); - } - - -} diff --git a/core/src/main/java/fj/F6W.java b/core/src/main/java/fj/F6W.java deleted file mode 100644 index adaf723f..00000000 --- a/core/src/main/java/fj/F6W.java +++ /dev/null @@ -1,9 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F6W implements F6 { - - -} diff --git a/core/src/main/java/fj/F7Functions.java b/core/src/main/java/fj/F7Functions.java deleted file mode 100644 index e583ba4b..00000000 --- a/core/src/main/java/fj/F7Functions.java +++ /dev/null @@ -1,22 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F7Functions { - - private F7Functions() { - } - - /** - * Partial application. - * - * @param a The A to which to apply this function. - * @return The function partially applied to the given argument. - */ - public static F6 f(final F7 func, final A a) { - return (b, c, d, e, f, g) -> func.f(a, b, c, d, e, f, g); - } - - -} diff --git a/core/src/main/java/fj/F7W.java b/core/src/main/java/fj/F7W.java deleted file mode 100644 index fdcec3d5..00000000 --- a/core/src/main/java/fj/F7W.java +++ /dev/null @@ -1,9 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F7W implements F7 { - - -} diff --git a/core/src/main/java/fj/F8Functions.java b/core/src/main/java/fj/F8Functions.java deleted file mode 100644 index 8b9883a3..00000000 --- a/core/src/main/java/fj/F8Functions.java +++ /dev/null @@ -1,20 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 6/04/2014. - */ -public final class F8Functions { - - private F8Functions() { - } - - /** - * Partial application. - * - * @return The function partially applied to the given argument. - */ - public static F7 f(final F8 func, final A a) { - return (b, c, d, e, f, g, h) -> func.f(a, b, c, d, e, f, g, h); - } - -} diff --git a/core/src/main/java/fj/F8W.java b/core/src/main/java/fj/F8W.java deleted file mode 100644 index d0a9f861..00000000 --- a/core/src/main/java/fj/F8W.java +++ /dev/null @@ -1,9 +0,0 @@ -package fj; - -/** - * Created by MarkPerry on 22/01/2015. - */ -public abstract class F8W implements F8 { - - -} diff --git a/core/src/test/java/fj/FFunctionsTest.java b/core/src/test/java/fj/FFunctionsTest.java index e0df9164..b235ff67 100644 --- a/core/src/test/java/fj/FFunctionsTest.java +++ b/core/src/test/java/fj/FFunctionsTest.java @@ -7,23 +7,6 @@ import static org.junit.Assert.*; public class FFunctionsTest { - @Test - public void testApply() { - F8 f8 = - (i1, i2, i3, i4, i5, i6, i7, i8) -> - i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8; - F7 f7 = F8Functions.f(f8, 8); - F6 f6 = - F7Functions.f(f7, 7); - F5 f5 = F6Functions.f(f6, 6); - F4 f4 = F5Functions.f(f5, 5); - F3 f3 = F4Functions.f(f4, 4); - F2 f2 = F3Functions.f(f3, 3); - F f1 = f2.f(2); - assertThat(f1.f(1), is(36)); - } @Test public void testTreeK() { From 202f88c5eb051fe74cfff9ff71952058f47d936a Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 2 Apr 2021 00:31:15 +1000 Subject: [PATCH 766/811] Added functional interface annotations to functions --- core/src/main/java/fj/F.java | 1 + core/src/main/java/fj/F0.java | 1 + core/src/main/java/fj/F2.java | 1 + core/src/main/java/fj/F3.java | 1 + core/src/main/java/fj/F4.java | 1 + core/src/main/java/fj/F5.java | 1 + core/src/main/java/fj/F6.java | 1 + core/src/main/java/fj/F7.java | 1 + core/src/main/java/fj/F8.java | 1 + 9 files changed, 9 insertions(+) diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java index d2208236..45cec4fe 100644 --- a/core/src/main/java/fj/F.java +++ b/core/src/main/java/fj/F.java @@ -21,6 +21,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F extends Function { /** * Transform A to B. diff --git a/core/src/main/java/fj/F0.java b/core/src/main/java/fj/F0.java index eab82a01..14c00ca2 100644 --- a/core/src/main/java/fj/F0.java +++ b/core/src/main/java/fj/F0.java @@ -3,6 +3,7 @@ /** * Created by MarkPerry on 21/01/2015. */ +@FunctionalInterface public interface F0 { A f(); diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index ba0e6f2f..4f7c306d 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -18,6 +18,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F2 extends BiFunction { /** * Transform A and B to C. diff --git a/core/src/main/java/fj/F3.java b/core/src/main/java/fj/F3.java index 540afdaa..b8c4dcf3 100644 --- a/core/src/main/java/fj/F3.java +++ b/core/src/main/java/fj/F3.java @@ -6,6 +6,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F3 { /** * Transform A, B and C to D. diff --git a/core/src/main/java/fj/F4.java b/core/src/main/java/fj/F4.java index 84dcfafa..d63f03a7 100644 --- a/core/src/main/java/fj/F4.java +++ b/core/src/main/java/fj/F4.java @@ -6,6 +6,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F4 { /** * Transform A, B, C and D to E. diff --git a/core/src/main/java/fj/F5.java b/core/src/main/java/fj/F5.java index 5fea676b..f63ae797 100644 --- a/core/src/main/java/fj/F5.java +++ b/core/src/main/java/fj/F5.java @@ -7,6 +7,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F5 { /** * Transform A, B, C, D and E to diff --git a/core/src/main/java/fj/F6.java b/core/src/main/java/fj/F6.java index 20101cf7..558c17fc 100644 --- a/core/src/main/java/fj/F6.java +++ b/core/src/main/java/fj/F6.java @@ -7,6 +7,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F6 { /** * Transform A, B, C, D, E and diff --git a/core/src/main/java/fj/F7.java b/core/src/main/java/fj/F7.java index 5a3ea1ef..05caefb4 100644 --- a/core/src/main/java/fj/F7.java +++ b/core/src/main/java/fj/F7.java @@ -7,6 +7,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F7 { /** * Transform A, B, C, D, E, diff --git a/core/src/main/java/fj/F8.java b/core/src/main/java/fj/F8.java index 8b986456..5aa103f2 100644 --- a/core/src/main/java/fj/F8.java +++ b/core/src/main/java/fj/F8.java @@ -7,6 +7,7 @@ * * @version %build.number% */ +@FunctionalInterface public interface F8 { /** * Transform A, B, C, D, E, From 2ee2950ab391a7213b01d9e0f6a81473e8b4c76e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 2 Apr 2021 01:37:55 +1000 Subject: [PATCH 767/811] Removed IOW --- core/src/main/java/fj/data/IO.java | 28 ++++++++++++ core/src/main/java/fj/data/IOW.java | 45 ------------------- core/src/main/java/fj/data/SafeIO.java | 1 + demo/src/main/java/fj/demo/IOWalkthrough.java | 3 +- 4 files changed, 30 insertions(+), 47 deletions(-) delete mode 100644 core/src/main/java/fj/data/IOW.java diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index ee27bdb7..992abaf2 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -4,6 +4,9 @@ * Created by MarkPerry on 19/06/2014. */ +import fj.F; +import fj.Unit; + import java.io.IOException; /** @@ -13,8 +16,33 @@ * * @param the type of the result produced by the IO */ +@FunctionalInterface public interface IO { A run() throws IOException; + default SafeIO> safe() { + return IOFunctions.toSafeValidation(this); + } + + default IO map(F f) { + return IOFunctions.map(this, f); + } + + default IO bind(F> f) { + return IOFunctions.bind(this, f); + } + + default IO append(IO iob) { + return IOFunctions.append(this, iob); + } + + public static IO getContents() { + return () -> IOFunctions.getContents().run(); + } + + public static IO interact(F f) { + return () -> IOFunctions.interact(f).run(); + } + } diff --git a/core/src/main/java/fj/data/IOW.java b/core/src/main/java/fj/data/IOW.java deleted file mode 100644 index 859c9cdb..00000000 --- a/core/src/main/java/fj/data/IOW.java +++ /dev/null @@ -1,45 +0,0 @@ -package fj.data; - -import fj.F; -import fj.Unit; - -import java.io.IOException; - -/** - * Created by MarkPerry on 9/06/2015. - */ -public final class IOW implements IO { - - private final IO io; - - private IOW(IO in) { - io = in; - } - - public static IOW lift(IO io) { - return new IOW<>(io); - } - - @Override - public A run() throws IOException { - return io.run(); - } - - public SafeIO> safe() { - return IOFunctions.toSafeValidation(io); - } - - public IOW map(F f) { return lift(IOFunctions.map(io, f)); } - - public IOW bind(F> f) { return lift(IOFunctions.bind(io, f)); } - - public IOW append(IO iob) { return lift(IOFunctions.append(io, iob)); } - - public static IOW getContents() { - return lift(() -> IOFunctions.getContents().run()); - } - - public static IOW interact(F f) { - return lift(() -> IOFunctions.interact(f).run()); - } -} diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index ef4c608c..11fdc31a 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -3,6 +3,7 @@ /** * Created by MarkPerry on 3/07/2014. */ +@FunctionalInterface public interface SafeIO extends IO { @Override diff --git a/demo/src/main/java/fj/demo/IOWalkthrough.java b/demo/src/main/java/fj/demo/IOWalkthrough.java index 5c1c4663..2f1cb9eb 100644 --- a/demo/src/main/java/fj/demo/IOWalkthrough.java +++ b/demo/src/main/java/fj/demo/IOWalkthrough.java @@ -4,7 +4,6 @@ import fj.Unit; import fj.data.IO; import fj.data.IOFunctions; -import fj.data.IOW; import java.io.BufferedReader; import java.io.IOException; @@ -72,7 +71,7 @@ public static void main(String[] args) { // for composing IO values instead, the entire program can be written like so: F f = String::toUpperCase; - IOW.lift(stdoutPrintln("What's your name again?")) + stdoutPrintln("What's your name again?") .append(stdoutPrint("Name: ")) .append(stdinReadLine()) .bind(f.andThen(IOFunctions::stdoutPrintln)) From ef68abe9ecdf083cdfecc2b0c6c367073d0a4867 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 5 Apr 2021 12:18:51 +1000 Subject: [PATCH 768/811] Removed deprecated monoid methods --- core/src/main/java/fj/Monoid.java | 51 +------------------------------ 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 96d24b82..765026b3 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -466,20 +466,6 @@ public A append(A a1, A a2) { }); } - /** - * Constructs a monoid from the given semigroup and zero value, which must follow the monoidal laws. - * @deprecated since 4.7. Use {@link #monoidDef(Semigroup.Definition, Object)} or {@link Semigroup#monoid(Object)} instead. - * - * @param s The semigroup for the monoid. - * @param zero The zero for the monoid. - * @return A monoid instance that uses the given sun function and zero value. - */ - @Deprecated - public static Monoid monoid(final Semigroup s, final A zero) { - return s.monoid(zero); - } - - /** * A monoid that adds integers. */ @@ -528,19 +514,7 @@ public Integer multiply(int n, Integer integer) { return n <= 0 ? 1 : (int) StrictMath.pow(integer.doubleValue(), n); } }); - - /** - * @deprecated Since 4.7. Due to rounding errors, addition of doubles does not comply with monoid laws - */ - @Deprecated - public static final Monoid doubleAdditionMonoid = monoidDef((d1, d2) -> d1 + d2, 0.0); - - /** - * @deprecated Since 4.7. Due to rounding errors, multiplication of doubles does not comply with monoid laws - */ - @Deprecated - public static final Monoid doubleMultiplicationMonoid = monoidDef((d1, d2) -> d1 * d2, 1.0); - + /** * A monoid that adds big integers. */ @@ -889,17 +863,6 @@ public Option sum(F0>> oas) { }); } - /** - * A monoid for options. - * @deprecated since 4.7. Use {@link #firstOptionMonoid()}. - * - * @return A monoid for options. - */ - @Deprecated - public static Monoid> optionMonoid() { - return firstOptionMonoid(); - } - /** * A monoid for options that take the first available value. * @@ -1121,16 +1084,4 @@ public Set append(Set a1, Set a2) { }); } - /** - * A monoid for the maximum of elements with ordering o. - * @deprecated since 4.7. Use {@link Ord#maxMonoid(Object)} - * - * @param o An ordering of elements. - * @param zero The minimum element. - */ - @Deprecated - public static Monoid ordMaxMonoid(final Ord o, final A zero) { - return o.maxMonoid(zero); - } - } From 3b0f9b951f0a503b6326c1e40f48c43d6d381683 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 5 Apr 2021 13:27:22 +1000 Subject: [PATCH 769/811] Removed deprecated methods from core --- core/src/main/java/fj/Monoid.java | 2 +- core/src/main/java/fj/Ord.java | 38 ---------- core/src/main/java/fj/P.java | 7 ++ core/src/main/java/fj/P1.java | 31 +------- core/src/main/java/fj/Semigroup.java | 23 ------ core/src/main/java/fj/data/Array.java | 13 ---- core/src/main/java/fj/data/HashMap.java | 20 ----- core/src/main/java/fj/data/Java.java | 11 --- core/src/main/java/fj/data/List.java | 90 ----------------------- core/src/main/java/fj/data/Seq.java | 16 ---- core/src/main/java/fj/data/Set.java | 24 ------ core/src/main/java/fj/data/Stream.java | 53 ------------- core/src/main/java/fj/data/TreeMap.java | 20 +---- core/src/test/java/fj/data/ArrayTest.java | 1 + 14 files changed, 13 insertions(+), 336 deletions(-) diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index 765026b3..bc09250d 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -514,7 +514,7 @@ public Integer multiply(int n, Integer integer) { return n <= 0 ? 1 : (int) StrictMath.pow(integer.doubleValue(), n); } }); - + /** * A monoid that adds big integers. */ diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index eef729c4..ae4d3fda 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -687,44 +687,6 @@ public static > Ord comparableOrd() { return ordDef((a1, a2) -> Ordering.fromInt(a1.compareTo(a2))); } - /** - * An order instance that uses {@link Object#hashCode()} for computing the order and equality, - * thus objects returning the same hashCode are considered to be equals. - * This is not safe and therefore this method is deprecated. - * - * @return An order instance that is based on {@link Object#hashCode()}. - * - * @deprecated As of release 4.7. - */ - @Deprecated - public static Ord hashOrd() { - return ordDef(a -> { - int aHash = a.hashCode(); - return a2 -> Ordering.fromInt(Integer.valueOf(aHash).compareTo(a2.hashCode())); - }); - } - - /** - * An order instance that uses {@link Object#hashCode()} and {@link Object#equals} for computing - * the order and equality. First the hashCode is compared, if this is equal, objects are compared - * using {@link Object#equals}. - * WARNING: This ordering violate antisymmetry on hash collisions. - * - * @return An order instance that is based on {@link Object#hashCode()} and {@link Object#equals}. - * - * @deprecated As of release 4.7. - */ - @Deprecated - public static Ord hashEqualsOrd() { - return ordDef(a -> { - int aHash = a.hashCode(); - return a2 -> { - final int a2Hash = a2.hashCode(); - return aHash < a2Hash ? Ordering.LT : aHash == a2Hash && a.equals(a2) ? Ordering.EQ : Ordering.GT; - }; - }); - } - class OrdComparator implements Comparator { @Override public final int compare(A o1, A o2) { diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 6d174ed7..587cdc9d 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -65,6 +65,13 @@ public static P1 softMemo(F0 f) { return new P1.SoftReferenceMemo<>(f); } + /** + * Convert a F0 into a P1, using weak call-by-need semantic using {@link #weakMemo(F0)}. + */ + public static P1 memo(F0 f) { + return weakMemo(f); + } + /** * Convert a F0 into a P1, using call-by-name semantic: * function f is evaluated at each call to {@link P1#_1()}. diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 420b820b..810e484d 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -39,18 +39,6 @@ public static F, A> __1() { return P1::_1; } - /** - * Promote any function to a transformation between P1s. - * - * @deprecated As of release 4.5, use {@link #map_} - * @param f A function to promote to a transformation between P1s. - * @return A function promoted to operate on P1s. - */ - @Deprecated - public static F, P1> fmap(final F f) { - return map_(f); - } - /** * Promote any function to a transformation between P1s. * @@ -243,9 +231,8 @@ public final P1 map(final F f) { } /** - * @deprecated since 4.7. Use {@link P1#weakMemo()} instead. + * Wrap the memoized value into a WeakReference. */ - @Deprecated public final P1 memo() { return weakMemo(); } @@ -267,22 +254,6 @@ public final P1 memo() { */ public P1 softMemo() { return new SoftReferenceMemo<>(this); } - /** - * @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead. - */ - @Deprecated - public static P1 memo(F f) { - return P.weakMemo(() -> f.f(unit())); - } - - /** - * @deprecated since 4.7. Use {@link P#weakMemo(F0)} instead. - */ - @Deprecated - public static P1 memo(F0 f) { - return P.weakMemo(f); - } - static final class Memo extends P1 { private volatile F0 fa; private A value; diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 6fbc5fc6..1d767385 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -292,23 +292,11 @@ public static Semigroup semigroup(final F2 sum) { */ public static final Semigroup intAdditionSemigroup = intAdditionMonoid.semigroup(); - /** - * @deprecated Since 4.7. Due to rounding errors, addition of doubles does not comply with monoid laws - */ - @Deprecated - public static final Semigroup doubleAdditionSemigroup = semigroupDef((d1, d2) -> d1 + d2); - /** * A semigroup that multiplies integers. */ public static final Semigroup intMultiplicationSemigroup = intMultiplicationMonoid.semigroup(); - /** - * @deprecated Since 4.7. Due to rounding errors, addition of doubles does not comply with monoid laws - */ - @Deprecated - public static final Semigroup doubleMultiplicationSemigroup = semigroupDef((d1, d2) -> d1 * d2); - /** * A semigroup that yields the maximum of integers. */ @@ -520,17 +508,6 @@ public NonEmptyList sum(NonEmptyList nea, F0>> neas }); } - /** - * A semigroup for optional values. - * @deprecated since 4.7. Use {@link #firstOptionSemigroup()}. - * - * @return A semigroup for optional values. - */ - @Deprecated - public static Semigroup> optionSemigroup() { - return firstOptionSemigroup(); - } - /** * A semigroup for optional values that take the first available value. * diff --git a/core/src/main/java/fj/data/Array.java b/core/src/main/java/fj/data/Array.java index 7e937200..fb245f3f 100755 --- a/core/src/main/java/fj/data/Array.java +++ b/core/src/main/java/fj/data/Array.java @@ -130,19 +130,6 @@ public Object[] array() { return copyOf(a, a.length); } - /** - * To be removed in future release: - * affectation of the result of this method to a non generic array - * will result in runtime error (ClassCastException). - * - * @deprecated As of release 4.6, use {@link #array(Class)}. - */ - @SuppressWarnings("unchecked") - @Deprecated - public A[] toJavaArray() { - return (A[]) array(); - } - /** * Returns an option projection of this array; None if empty, or the first element in * Some. diff --git a/core/src/main/java/fj/data/HashMap.java b/core/src/main/java/fj/data/HashMap.java index 400cf415..455c529c 100755 --- a/core/src/main/java/fj/data/HashMap.java +++ b/core/src/main/java/fj/data/HashMap.java @@ -325,16 +325,6 @@ public java.util.Map toMap() { return result; } - /** - * Converts the Iterable to a HashMap - * - * @deprecated As of release 4.5, use {@link #iterableHashMap(Iterable)} - */ - @Deprecated - public static HashMap from(final Iterable> entries) { - return iterableHashMap(entries); - } - public static HashMap fromMap(java.util.Map map) { return fromMap(Equal.anyEqual(), Hash.anyHash(), map); } @@ -347,16 +337,6 @@ public static HashMap fromMap(Equal eq, Hash h, java.util.Map return m; } - /** - * Converts the Iterable to a HashMap - * - * @deprecated As of release 4.5, use {@link #iterableHashMap} - */ - @Deprecated - public static HashMap from(final Iterable> entries, final Equal equal, final Hash hash) { - return iterableHashMap(equal, hash, entries); - } - /** * Converts the Iterable to a HashMap */ diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index ae7fcf6a..8691c09d 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -1414,17 +1414,6 @@ public static F, List> ArrayList_List() { // END ArrayList -> - /** - * A function that converts Java lists to lists. - * @deprecated As of 4.3, use {@link #JavaList_List} - * - * @return A function that converts Java lists to lists. - */ - @Deprecated - public static F, List> JUList_List() { - return Java::JavaList_List; - } - public static F, List> JavaList_List() { return Java::JavaList_List; } diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 5b5fff67..447f76a5 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -86,19 +86,6 @@ public final boolean isNotEmpty() { return this instanceof Cons; } - /** - * Performs a reduction on this list using the given arguments. - * @deprecated As of release 4.5, use {@link #uncons} - * - * @param nil The value to return if this list is empty. - * @param cons The function to apply to the head and tail of this list if it is not empty. - * @return A reduction on this list. - */ - @Deprecated - public final B list(final B nil, final F, B>> cons) { - return uncons(uncurryF2(cons), nil); - } - public final B uncons(final F2, B> cons, final B nil) { return isEmpty() ? nil : cons.f(head(), tail()); } @@ -123,18 +110,6 @@ public final List orTail(final F0> as) { return isEmpty() ? as.f() : tail(); } - /** - * Returns an option projection of this list; None if empty, or the first element in - * Some. Equivalent to {@link #headOption()}. - * @deprecated As of release 4.5, use {@link #headOption()} - * @return An option projection of this list. - */ - @Deprecated - public final Option toOption() { - return headOption(); - - } - /** * Returns the head of the list, if any. Equivalent to {@link #toOption()} . * @@ -185,19 +160,6 @@ public final Object[] toArrayObject() { return a; } - /** - * To be removed in future release: - * affectation of the result of this method to a non generic array - * will result in runtime error (ClassCastException). - * - * @deprecated As of release 4.6, use {@link #array(Class)}. - */ - @SuppressWarnings("unchecked") - @Deprecated - public final A[] toJavaArray() { - return (A[]) toArrayObject(); - } - /** * Returns a array projection of this list. * @@ -1529,21 +1491,6 @@ public final A mode(final Ord o) { return sort(o).group(o.equal()).maximum(intOrd.contramap(List.length_())).head(); } - /** - * Groups the elements of this list by a given keyFunction into a {@link TreeMap}. - * The ordering of the keys is determined by {@link fj.Ord#hashOrd()} (ie. Object#hasCode). - * This is not safe and therefore this method is deprecated. - * - * @param keyFunction The function to select the keys for the map. - * @return A TreeMap containing the keys with the accumulated list of matched elements. - * - * @deprecated As of release 4.7, use {@link #groupBy(F, Ord)} - */ - @Deprecated - public final TreeMap> groupBy(final F keyFunction) { - return groupBy(keyFunction, Ord.hashOrd()); - } - /** * Groups the elements of this list by a given keyFunction into a {@link TreeMap}. * @@ -1555,25 +1502,6 @@ public final TreeMap> groupBy(final F keyFunction, final Or return groupBy(keyFunction, identity(), keyOrd); } - /** - * Groups the elements of this list by a given keyFunction into a {@link TreeMap} and transforms - * the matching elements with the given valueFunction. The ordering of the keys is determined by - * {@link fj.Ord#hashOrd()} (ie. Object#hasCode). - * This is not safe and therefore this method is deprecated. - * - * @param keyFunction The function to select the keys for the map. - * @param valueFunction The function to apply on each matching value. - * @return A TreeMap containing the keys with the accumulated list of matched and mapped elements. - * - * @deprecated As of release 4.7, use {@link #groupBy(F, F, Ord)} - */ - @Deprecated - public final TreeMap> groupBy( - final F keyFunction, - final F valueFunction) { - return this.groupBy(keyFunction, valueFunction, Ord.hashOrd()); - } - /** * Groups the elements of this list by a given keyFunction into a {@link TreeMap} and transforms * the matching elements with the given valueFunction. The ordering of the keys is determined by @@ -1821,24 +1749,6 @@ public static List arrayList(final A... as) { return Array.array(as).toList(); } - /** - * Constructs a list from the given Iterable. - * @deprecated As of release 4.5, use {@link #iterableList(Iterable)} - */ - @Deprecated - public static List list(final Iterable i) { - return iterableList(i); - } - - /** - * Constructs a list from the given Iterator. - * @deprecated As of release 4.5, use {@link #iteratorList(Iterator)} - */ - @Deprecated - public static List list(final Iterator it) { - return iteratorList(it); - } - /** * Constructs a list from the given Iterator. */ diff --git a/core/src/main/java/fj/data/Seq.java b/core/src/main/java/fj/data/Seq.java index 3bcb7033..59a46df7 100644 --- a/core/src/main/java/fj/data/Seq.java +++ b/core/src/main/java/fj/data/Seq.java @@ -78,25 +78,9 @@ public static Seq single(final A a) { /** * Constructs a sequence from the given list. * - * @deprecated As of release 4.5, use {@link #listSeq(List)} - * - * @param list The list to create the sequence from. - * @return A sequence with the given elements in the list. - */ - @Deprecated - public static Seq seq(final List list) { - return iterableSeq(list); - } - - /** - * Constructs a sequence from the given list. - * - * @deprecated As of release 4.5, use {@link #iterableSeq} - * * @param list The list to create the sequence from. * @return A sequence with the elements of the list. */ - @Deprecated public static Seq listSeq(final List list) { return iterableSeq(list); } diff --git a/core/src/main/java/fj/data/Set.java b/core/src/main/java/fj/data/Set.java index 15207d83..4c0aeaa0 100644 --- a/core/src/main/java/fj/data/Set.java +++ b/core/src/main/java/fj/data/Set.java @@ -713,28 +713,4 @@ public static Set arraySet(final Ord o, final A...as) { return arraySet(o, as); } - /** - * Constructs a set from the list. - * - * @deprecated As of release 4.5, use {@link #iterableSet} - * - * @param o An order for the elements of the new set. - * @param list The elements to add to a set. - * @return A new set containing the elements of the given list. - */ - @Deprecated - public static Set set(final Ord o, List list) { - return iterableSet(o, list); - } - - /** - * Constructs a set from the list. - * - * @deprecated As of release 4.5, use {@link #iterableSet} - */ - @Deprecated - public static Set fromList(final Ord o, List list) { - return iterableSet(o, list); - } - } diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index e05e26bf..bcf87dcf 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -89,20 +89,6 @@ public final boolean isNotEmpty() { return this instanceof Cons; } - /** - * Performs a reduction on this stream using the given arguments. Equivalent to {@link #uncons}. - * - * @deprecated As of release 4.5, use {@link #uncons} - * - * @param nil The value to return if this stream is empty. - * @param cons The function to apply to the head and tail of this stream if it is not empty. - * @return A reduction on this stream. - */ - @Deprecated - public final B stream(final B nil, final F>, B>> cons) { - return uncons(nil, cons); - } - /** * Performs a reduction on this stream using the given arguments. * @@ -712,26 +698,6 @@ public static Stream range(final int from, final long to) { return arrayStream(as); } - /** - * Constructs a stream with the given elements in the Iterable. Equivalent to {@link #iterableStream(Iterable)} . - * - * @deprecated As of release 4.5, use {@link #iterableStream(Iterable)} - */ - @Deprecated - public static Stream stream(Iterable it) { - return iterableStream(it); - } - - /** - * Constructs a stream with the given elements in the Iterator. Equivalent to {@link #iteratorStream(Iterator)} . - * - * @deprecated As of release 4.5, use {@link #iteratorStream(Iterator)} - */ - @Deprecated - public static Stream stream(final Iterator it) { - return iteratorStream(it); - } - /** * Constructs a stream with the given elements in the Iterator. */ @@ -916,25 +882,6 @@ public final Option toOption() { return isEmpty() ? Option.none() : some(head()); } - /** - * To be removed in future release: - * affectation of the result of this method to a non generic array - * will result in runtime error (ClassCastException). - * - * @deprecated As of release 4.6, use {@link #array(Class)}. - */ - @Deprecated - public final A[] toJavaArray() { - @SuppressWarnings("unchecked") - final A[] array = (A[]) new Object[length()]; - int i = 0; - for (A a: this) { - array[i] = a; - i++; - } - return array; - } - /** * Returns a list projection of this stream. * diff --git a/core/src/main/java/fj/data/TreeMap.java b/core/src/main/java/fj/data/TreeMap.java index 38607dbc..e1af4d91 100644 --- a/core/src/main/java/fj/data/TreeMap.java +++ b/core/src/main/java/fj/data/TreeMap.java @@ -69,20 +69,6 @@ public String toString() { return arrayTreeMap(keyOrd, p2s); } - /** - * Constructs a tree map from the given elements. - * - * @deprecated As of release 4.5, use {@link #iterableTreeMap(Ord, Iterable)} - * - * @param keyOrd An order for the keys of the tree map. - * @param list The elements to construct the tree map with. - * @return a TreeMap with the given elements. - */ - @Deprecated - public static TreeMap treeMap(final Ord keyOrd, final List> list) { - return iterableTreeMap(keyOrd, list); - } - /** * Constructs a tree map from the given elements. * @@ -313,12 +299,12 @@ public P3, Option, Set> split(Ord ord, final K k) { } /** - * Internal construction of a TreeMap from the given set. + * Constructs a TreeMap from the given set. * @param ord An order for the keys of the tree map. * @param s The elements to construct the tree map with. * @return a TreeMap with the given elements. */ - private static TreeMap treeMap(Ord ord, Set>> s) { + public static TreeMap setTreeMap(Ord ord, Set>> s) { TreeMap empty = TreeMap.empty(ord); TreeMap tree = s.toList().foldLeft((tm, p2) -> { Option opt = p2._2(); @@ -347,7 +333,7 @@ private static TreeMap treeMap(Ord ord, Set>> s) public P3, Option, TreeMap> splitLookup(final K k) { P3>>, Option>>, Set>>> p3 = tree.split(p(k, get(k))); Ord o = tree.ord().contramap(k2 -> p(k2, Option.none())); - return p(treeMap(o, p3._1()), get(k), treeMap(o, p3._3())); + return p(setTreeMap(o, p3._1()), get(k), setTreeMap(o, p3._3())); } /** diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java index 886031b3..883fc835 100644 --- a/core/src/test/java/fj/data/ArrayTest.java +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -1,5 +1,6 @@ package fj.data; +import org.hamcrest.CoreMatchers; import org.junit.Test; import static org.hamcrest.CoreMatchers.equalTo; From e6234b801de460ff759aafeb4674edaf3c32c503 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 5 Apr 2021 15:54:41 +1000 Subject: [PATCH 770/811] Removed deprecated methods from quickcheck --- quickcheck/src/main/java/fj/test/Gen.java | 33 ------------------ quickcheck/src/main/java/fj/test/Rand.java | 39 +++------------------- 2 files changed, 5 insertions(+), 67 deletions(-) diff --git a/quickcheck/src/main/java/fj/test/Gen.java b/quickcheck/src/main/java/fj/test/Gen.java index dabaf9a6..8fe1e6f5 100644 --- a/quickcheck/src/main/java/fj/test/Gen.java +++ b/quickcheck/src/main/java/fj/test/Gen.java @@ -536,24 +536,6 @@ public static Gen pickOne(List as) { return wordOf(1, as).map(List::head); } - /** - * Returns a generator of lists that picks the given number of elements from the given list. If - * the given number is less than zero or greater than the length of the given list, then the - * returned generator will never produce a value. - *

      - * Note: pick is synonymous with combinationOf - * - * @deprecated As of release 4.6, use {@link #combinationOf} - * - * @param n The number of elements to pick from the given list. - * @param as The list from which to pick elements. - * @return A generator of lists that picks the given number of elements from the given list. - */ - @Deprecated - public static Gen> pick(int n, List as) { - return combinationOf(n, as); - } - /** * Returns a generator of lists that picks the given number of elements from the given list. The selection is * a combination without replacement of elements from the given list, i.e. @@ -678,21 +660,6 @@ private static Gen> pick(Gen> indexesGen, Array as) indexes.foldLeft((acc, index) -> cons(as.get(index), acc), List.nil()).reverse()); } - /** - * Returns a generator of lists that produces some of the values of the given list. - *

      - * Note: someOf is synonymous with someCombinationOf - * - * @deprecated As of release 4.6, use {@link #someCombinationOf} - * - * @param as The list from which to pick values. - * @return A generator of lists that produces some of the values of the given list. - */ - @Deprecated - public static Gen> someOf(List as) { - return someCombinationOf(as); - } - /** * Returns a generator of lists that produces some of the values of the given list. The selection is * a combination without replacement of elements from the given list, i.e. diff --git a/quickcheck/src/main/java/fj/test/Rand.java b/quickcheck/src/main/java/fj/test/Rand.java index b622dfe7..e47aa8a8 100644 --- a/quickcheck/src/main/java/fj/test/Rand.java +++ b/quickcheck/src/main/java/fj/test/Rand.java @@ -5,7 +5,6 @@ import java.util.Random; -import static fj.data.Option.none; import static fj.data.Option.some; import static java.lang.Math.max; import static java.lang.Math.min; @@ -18,18 +17,16 @@ public final class Rand { private final F, F>> f; private final F, F>> g; - - // TODO Change to F when rand(f,g) is removed - private final Option> optOnReseed; + private final F onReseed; private Rand( F, F>> f, F, F>> g, - Option> optOnReseed) { + F onReseed) { this.f = f; this.g = g; - this.optOnReseed = optOnReseed; + this.onReseed = onReseed; } /** @@ -88,33 +85,7 @@ public double choose(final double from, final double to) { * @return A random generator with the given seed. */ public Rand reseed(long seed) { - return optOnReseed.option( - () -> { - throw new IllegalStateException("reseed() called on a Rand created with deprecated rand() method"); - }, - onReseed -> onReseed.f(seed)); - } - - /** - * Constructs a random generator from the given functions that supply a range to produce a - * result. - *

      - * Calling {@link #reseed(long)} on an instance returned from this method will - * result in an exception being thrown. - * - * @deprecated As of release 4.6, use {@link #rand(F, F, F)}. - * - * @param f The integer random generator. - * @param g The floating-point random generator. - * @return A random generator from the given functions that supply a range to produce a result. - */ - // TODO Change Option> optOnReseed to F onReseed when removing this method - @Deprecated - public static Rand rand( - F, F>> f, - F, F>> g) { - - return new Rand(f, g, none()); + return onReseed.f(seed); } /** @@ -131,7 +102,7 @@ public static Rand rand( F, F>> g, F onReseed) { - return new Rand(f, g, some(onReseed)); + return new Rand(f, g, onReseed); } /** From 4859b75a3837c4c772c65c46596f388e7c1627b3 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 6 Apr 2021 01:53:30 +1000 Subject: [PATCH 771/811] Added partial Either3 implementation --- core/src/main/java/fj/Equal.java | 8 + core/src/main/java/fj/Hash.java | 7 +- core/src/main/java/fj/Show.java | 10 + core/src/main/java/fj/data/Either3.java | 226 ++++++++++++++++++++ core/src/test/java/fj/data/Either3Test.java | 6 + 5 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/fj/data/Either3.java create mode 100644 core/src/test/java/fj/data/Either3Test.java diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 5cd31aeb..9179cc43 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -357,6 +357,14 @@ public static Equal> eitherEqual(final Equal ea, final Eq )); } + public static Equal> either3Equal(Equal ea, Equal eb, Equal ec) { + return equalDef((e1, e2) -> + optionEqual(ea).eq(e1.leftOption(), e2.leftOption()) && + optionEqual(eb).eq(e1.middleOption(), e2.middleOption()) && + optionEqual(ec).eq(e1.rightOption(), e2.rightOption()) + ); + } + public static Equal> resultEqual(final Equal ea, final Equal ei) { Definition eaDef = ea.def; Definition eiDef= ei.def; diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 8d0a4e4c..703d96ee 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -163,7 +163,12 @@ public static Hash> eitherHash(final Hash ha, final Hash< return hash(e -> e.isLeft() ? ha.hash(e.left().value()) : hb.hash(e.right().value())); } - /** + public static Hash> either3Hash(final Hash ha, final Hash hb, final Hash hc) { + return hash(e -> e.either(a -> ha.hash(a), b -> hb.hash(b), c -> hc.hash(c))); + } + + + /** * A hash instance for the {@link Result} type. * * @param ha Hash the Result value. diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index cd57897b..62da5273 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -256,6 +256,16 @@ public static Show> eitherShow(final Show sa, final Show< fromString("Right(").append(sb.f.f(e.right().value())).append(single(')'))); } + public static Show> eitherShow(final Show sa, final Show sb, final Show sc) { + return show(e -> + e.either( + a -> fromString("Left(").append(sa.f.f(a)).append(single(')')), + b -> fromString("Middle(").append(sb.f.f(b)).append(single(')')), + c -> fromString("Right(").append(sc.f.f(c)).append(single(')')) + ) + ); + } + /** * A show instance for the {@link Result} type. * diff --git a/core/src/main/java/fj/data/Either3.java b/core/src/main/java/fj/data/Either3.java new file mode 100644 index 00000000..8c6b7344 --- /dev/null +++ b/core/src/main/java/fj/data/Either3.java @@ -0,0 +1,226 @@ +package fj.data; + +import fj.Equal; +import fj.F; +import fj.F0; +import fj.Hash; + +import static fj.data.Option.none; +import static fj.data.Option.some; + +public abstract class Either3 { + + private Either3() {} + + private static final class Left extends Either3 { + A a; + Left(A a) { + this.a = a; + } + + @Override + public boolean isLeft() { + return true; + } + + @Override + public boolean isMiddle() { + return false; + } + + @Override + public boolean isRight() { + return false; + } + + @Override + public D either(F fa, F fb, F fc) { + return fa.f(a); + } + } + + private static final class Middle extends Either3 { + B b; + Middle(B b) { + this.b = b; + } + + @Override + public boolean isLeft() { + return false; + } + + @Override + public boolean isMiddle() { + return true; + } + + @Override + public boolean isRight() { + return false; + } + + @Override + public D either(F fa, F fb, F fc) { + return fb.f(b); + } + } + + private static final class Right extends Either3 { + C c; + Right(C c) { + this.c = c; + } + + @Override + public boolean isLeft() { + return false; + } + + @Override + public boolean isMiddle() { + return false; + } + + @Override + public boolean isRight() { + return true; + } + + @Override + public D either(F fa, F fb, F fc) { + return fc.f(c); + } + + } + + public static final class LeftProjection { + private final Either3 e; + + private LeftProjection(final Either3 e) { + this.e = e; + } + + public Either3 apply(final Either3, B, C> e) { + return e.left().bind(this::map); + } + + public boolean exists(final F f) { + return e.either(a -> f.f(a), b -> false, c -> false); + } + + public Either3 bind(F> f) { + return e.either(a -> f.f(a), b -> middle(b), c -> right(c)); + } + + public Option> filter(final F f) { + return e.either(a -> f.f(a) ? some(left(a)) : none(), b -> none(), c -> none()); + } + + + public Either3 map(final F f) { + return e.either(a -> left(f.f(a)), b -> middle(b), c -> right(c)); + } + + } + + public static final class MiddleProjection { + private final Either3 e; + + private MiddleProjection(final Either3 e) { + this.e = e; + } + + public Either3 bind(F> f) { + return e.either(a -> left(a), b -> f.f(b), c -> right(c)); + } + + } + + public static final class RightProjection { + private final Either3 e; + + private RightProjection(final Either3 e) { + this.e = e; + } + + public Either3 bind(F> f) { + return e.either(a -> left(a), b -> middle(b), c -> f.f(c)); + } + } + + public static Either3 left(A a) { + return new Left<>(a); + } + + public static Either3 middle(B b) { + return new Middle<>(b); + } + + public static Either3 right(C c) { + return new Right<>(c); + } + + public abstract boolean isLeft(); + + public abstract boolean isMiddle(); + + public abstract boolean isRight(); + + public Either3 map3(F fl, F fm, F fr) { + return either( + a -> left(fl.f(a)), + b -> middle(fm.f(b)), + c -> right(fr.f(c)) + ); + } + + public abstract D either(F fa, F fb, F fc); + + public Either3 moveLeft() { + return either(a -> right(a), b -> left(b), c -> middle(c)); + } + + public Either3 moveRight() { + return either(a -> middle(a), b -> right(b), c -> left(c)); + } + + public Either3 swap() { + return either(a -> right(a), b -> middle(b), c -> left(c)); + } + + public Option leftOption() { + return either(a -> some(a), b -> none(), c -> none()); + } + + public Option middleOption() { + return either(a -> none(), b -> some(b), c -> none()); + } + + public Option rightOption() { + return either(a -> none(), b -> none(), c -> some(c)); + } + + public final LeftProjection left() { + return new LeftProjection<>(this); + } + + public final MiddleProjection middle() { + return new MiddleProjection<>(this); + } + + public final RightProjection right() { + return new RightProjection<>(this); + } + + @Override + public final boolean equals(Object other) { + return Equal.equals0(Either3.class, this, other, () -> Equal.either3Equal(Equal.anyEqual(), Equal.anyEqual(), Equal.anyEqual())); + } + + @Override + public final int hashCode() { + return Hash.either3Hash(Hash.anyHash(), Hash.anyHash(), Hash.anyHash()).hash(this); + } + +} diff --git a/core/src/test/java/fj/data/Either3Test.java b/core/src/test/java/fj/data/Either3Test.java new file mode 100644 index 00000000..1507bf41 --- /dev/null +++ b/core/src/test/java/fj/data/Either3Test.java @@ -0,0 +1,6 @@ +package fj.data; + +public final class Either3Test { + + +} From d2f777d7ee57b48fe8dfe71317ec0790d39c76ab Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 6 Apr 2021 13:37:52 +1000 Subject: [PATCH 772/811] Fixed javadoc on headOption. --- core/src/main/java/fj/data/List.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 447f76a5..9259900f 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -111,7 +111,7 @@ public final List orTail(final F0> as) { } /** - * Returns the head of the list, if any. Equivalent to {@link #toOption()} . + * Returns the head of the list, if any. * * @return The optional head of the list. */ From d3af2373fc02278ea76a11237b0c9d3c5fb5effa Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Tue, 6 Apr 2021 13:38:50 +1000 Subject: [PATCH 773/811] Implemented isLeft, isRight, isMiddle in terms of either. Added swap methods. --- core/src/main/java/fj/data/Either3.java | 75 ++++++++----------------- 1 file changed, 23 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/fj/data/Either3.java b/core/src/main/java/fj/data/Either3.java index 8c6b7344..15b1f419 100644 --- a/core/src/main/java/fj/data/Either3.java +++ b/core/src/main/java/fj/data/Either3.java @@ -2,7 +2,6 @@ import fj.Equal; import fj.F; -import fj.F0; import fj.Hash; import static fj.data.Option.none; @@ -13,53 +12,26 @@ public abstract class Either3 { private Either3() {} private static final class Left extends Either3 { - A a; + private final A a; + Left(A a) { this.a = a; } - @Override - public boolean isLeft() { - return true; - } - - @Override - public boolean isMiddle() { - return false; - } - - @Override - public boolean isRight() { - return false; - } - @Override public D either(F fa, F fb, F fc) { return fa.f(a); } + } private static final class Middle extends Either3 { - B b; + private final B b; + Middle(B b) { this.b = b; } - @Override - public boolean isLeft() { - return false; - } - - @Override - public boolean isMiddle() { - return true; - } - - @Override - public boolean isRight() { - return false; - } - @Override public D either(F fa, F fb, F fc) { return fb.f(b); @@ -67,26 +39,11 @@ public D either(F fa, F fb, F fc) { } private static final class Right extends Either3 { - C c; + private final C c; Right(C c) { this.c = c; } - @Override - public boolean isLeft() { - return false; - } - - @Override - public boolean isMiddle() { - return false; - } - - @Override - public boolean isRight() { - return true; - } - @Override public D either(F fa, F fb, F fc) { return fc.f(c); @@ -161,11 +118,17 @@ public static Either3 right(C c) { return new Right<>(c); } - public abstract boolean isLeft(); + public boolean isLeft() { + return either(a -> true, b -> false, c -> false); + } - public abstract boolean isMiddle(); + public boolean isMiddle() { + return either(a -> false, b -> true, c -> false); + } - public abstract boolean isRight(); + public boolean isRight() { + return either(a -> false, b -> false, c -> true); + } public Either3 map3(F fl, F fm, F fr) { return either( @@ -189,6 +152,14 @@ public Either3 swap() { return either(a -> right(a), b -> middle(b), c -> left(c)); } + public Either3 swapLefts() { + return either(a -> middle(a), b -> left(b), c -> right(c)); + } + + public Either3 swapRights() { + return either(a -> left(a), b -> right(b), c -> middle(c)); + } + public Option leftOption() { return either(a -> some(a), b -> none(), c -> none()); } From ef79720aa0afc1fd679198e652d8d478984dff75 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 7 Apr 2021 21:39:52 +1000 Subject: [PATCH 774/811] Updated inheritance of interfaces to Java 8 interfaces --- core/src/main/java/fj/F0.java | 8 +++++++- core/src/main/java/fj/data/IO.java | 7 ++++++- core/src/main/java/fj/function/Effect0.java | 2 ++ core/src/main/java/fj/function/Effect1.java | 20 +++++++++++++++++++- core/src/main/java/fj/function/Effect2.java | 8 +++++++- 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/fj/F0.java b/core/src/main/java/fj/F0.java index 14c00ca2..c260992f 100644 --- a/core/src/main/java/fj/F0.java +++ b/core/src/main/java/fj/F0.java @@ -1,11 +1,17 @@ package fj; +import java.util.function.Supplier; + /** * Created by MarkPerry on 21/01/2015. */ @FunctionalInterface -public interface F0 { +public interface F0 extends Supplier { A f(); + default A get() { + return f(); + } + } diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index 992abaf2..e2a94a38 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -6,6 +6,7 @@ import fj.F; import fj.Unit; +import fj.function.Try0; import java.io.IOException; @@ -17,10 +18,14 @@ * @param the type of the result produced by the IO */ @FunctionalInterface -public interface IO { +public interface IO extends Try0 { A run() throws IOException; + default A f() throws IOException { + return run(); + } + default SafeIO> safe() { return IOFunctions.toSafeValidation(this); } diff --git a/core/src/main/java/fj/function/Effect0.java b/core/src/main/java/fj/function/Effect0.java index c5d4fe50..57800eb0 100644 --- a/core/src/main/java/fj/function/Effect0.java +++ b/core/src/main/java/fj/function/Effect0.java @@ -1,5 +1,7 @@ package fj.function; +import fj.F0; + /** * Created by mperry on 28/08/2014. */ diff --git a/core/src/main/java/fj/function/Effect1.java b/core/src/main/java/fj/function/Effect1.java index 8c89b715..0cc35a39 100644 --- a/core/src/main/java/fj/function/Effect1.java +++ b/core/src/main/java/fj/function/Effect1.java @@ -1,10 +1,28 @@ package fj.function; +import fj.F; +import fj.Unit; + +import java.util.function.Consumer; + +import static fj.Unit.unit; + /** * Created by mperry on 28/08/2014. */ -public interface Effect1 { +public interface Effect1 extends Consumer { void f(A a); + default void accept(A a) { + f(a); + } + + default F toF() { + return a -> { + f(a); + return unit(); + }; + } + } diff --git a/core/src/main/java/fj/function/Effect2.java b/core/src/main/java/fj/function/Effect2.java index c0735043..40d8abd8 100644 --- a/core/src/main/java/fj/function/Effect2.java +++ b/core/src/main/java/fj/function/Effect2.java @@ -1,10 +1,16 @@ package fj.function; +import java.util.function.BiConsumer; + /** * Created by mperry on 28/08/2014. */ -public interface Effect2 { +public interface Effect2 extends BiConsumer { void f(A a, B b); + default void accept(A a, B b) { + f(a, b); + } + } From 7d3f6130c4ab6cafe7fe81e5c21ceacdb8a8b375 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 7 Apr 2021 21:40:49 +1000 Subject: [PATCH 775/811] Implemented left and middle projections of Either3. --- core/src/main/java/fj/data/Either3.java | 286 +++++++++++++++++++++++- 1 file changed, 279 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/fj/data/Either3.java b/core/src/main/java/fj/data/Either3.java index 15b1f419..0c7b7371 100644 --- a/core/src/main/java/fj/data/Either3.java +++ b/core/src/main/java/fj/data/Either3.java @@ -1,9 +1,16 @@ package fj.data; -import fj.Equal; -import fj.F; -import fj.Hash; +import fj.*; +import fj.function.Effect1; +import java.util.Collection; +import java.util.Iterator; + +import static fj.Function.identity; +import static fj.P.p; +import static fj.Unit.unit; +import static fj.data.Array.mkArray; +import static fj.data.List.*; import static fj.data.Option.none; import static fj.data.Option.some; @@ -49,6 +56,8 @@ public D either(F fa, F fb, F fc) { return fc.f(c); } + + } public static final class LeftProjection { @@ -62,23 +71,121 @@ public Either3 apply(final Either3, B, C> e) { return e.left().bind(this::map); } - public boolean exists(final F f) { - return e.either(a -> f.f(a), b -> false, c -> false); - } - public Either3 bind(F> f) { return e.either(a -> f.f(a), b -> middle(b), c -> right(c)); } + public Either3 either() { + return e; + } + + public boolean exists(final F f) { + return e.either(a -> f.f(a), b -> false, c -> false); + } + public Option> filter(final F f) { return e.either(a -> f.f(a) ? some(left(a)) : none(), b -> none(), c -> none()); } + public boolean forall(final F f) { + return e.either(a -> f.f(a), b -> true, c -> true); + } + + public Unit foreach(final F f) { + return e.either(a -> f.f(a), b -> unit(), c -> unit()); + } + + public void foreachDoEffect(final Effect1 f) { + e.either(a -> f.toF().f(a), b -> unit(), c -> unit()); + } + + public Iterator iterator() { + return toList().iterator(); + } public Either3 map(final F f) { return e.either(a -> left(f.f(a)), b -> middle(b), c -> right(c)); } + public A orValue(final A value) { + return orValue(() -> value); + } + + public A orValue(final F0 f) { + return e.either(a -> a, b -> f.f(), c -> f.f()); + } + + public Either3 sequence(final Either3 e) { + return bind(Function.constant(e)); + } + + public Array toArray() { + return e.either( + a -> Array.single(a), + b -> Array.empty(), + c -> Array.empty() + ); + } + + public Collection toCollection() { + return toList().toCollection(); + } + + public List toList() { + return e.either(a -> single(a), b -> nil(), c -> nil()); + } + + public Option toOption() { + return e.either(a -> some(a), b -> none(), c -> none()); + } + + public Stream toStream() { + return e.either(a -> Stream.single(a), b -> Stream.nil(), c -> Stream.nil()); + } + + public IO> traverseIO(final F> f) { + return e.either( + a -> f.f(a).map(Either3::left), + b -> IOFunctions.unit(middle(b)), + c -> IOFunctions.unit(right(c)) + ); + } + + public List> traverseList1(final F> f) { + return e.either( + a -> f.f(a).map(Either3::left), + b -> single(middle(b)), + c -> single(right(c)) + ); + } + + public Option> traverseOption(final F> f) { + return e.either( + a -> f.f(a).map(Either3::left), + b -> some(middle(b)), + c -> some(right(c)) + ); + + } + + public P1> traverseP1(final F> f) { + return e.either( + a -> f.f(a).map(Either3::left), + b -> p(middle(b)), + c -> p(right(c)) + ); + + } + + public Stream> traverseStream(final F> f) { + return e.either( + a -> f.f(a).map(Either3::left), + b -> Stream.single(middle(b)), + c -> Stream.single(right(c)) + ); + + } + } public static final class MiddleProjection { @@ -88,10 +195,150 @@ private MiddleProjection(final Either3 e) { this.e = e; } + public Either3 apply(final Either3, C> e) { + return e.middle().bind(this::map); + } + public Either3 bind(F> f) { return e.either(a -> left(a), b -> f.f(b), c -> right(c)); } + public Either3 either() { + return e; + } + + public boolean exists(final F f) { + return e.either(a -> false, b -> f.f(b), c -> false); + } + + public Option> filter(final F f) { + return e.either(a -> none(), b -> f.f(b) ? some(middle(b)) : none(), c -> none()); + } + + public boolean forall(final F f) { + return e.either(a -> true, b -> f.f(b), c -> true); + } + + public Unit foreach(final F f) { + return e.either(a -> unit(), b -> f.f(b), c -> unit()); + } + + public void foreachDoEffect(final Effect1 f) { + e.either(a -> unit(), b -> f.toF().f(b), c -> unit()); + } + + public Iterator iterator() { + return toList().iterator(); + } + + public Either3 map(final F f) { + return e.either(a -> left(a), b -> middle(f.f(b)), c -> right(c)); + } + + public B orValue(final B value) { + return orValue(() -> value); + } + + public B orValue(final F0 f) { + return e.either(a -> f.f(), b -> b, c -> f.f()); + } + + public Either3 sequence(final Either3 e) { + return bind(Function.constant(e)); + } + + public Array toArray() { + return e.either( + a -> Array.empty(), + b -> Array.single(b), + c -> Array.empty() + ); + } + + public Collection toCollection() { + return toList().toCollection(); + } + + public List toList() { + return e.either(a -> nil(), b -> single(b), c -> nil()); + } + + public Option toOption() { + return e.either(a -> none(), b -> some(b), c -> none()); + } + + public Stream toStream() { + return e.either(a -> Stream.nil(), b -> Stream.single(b), c -> Stream.nil()); + } + + public IO> traverseIO(final F> f) { + return e.either( + a -> IOFunctions.unit(left(a)), + b -> f.f(b).map(Either3::middle), + c -> IOFunctions.unit(right(c)) + ); + } + + public List> traverseList1(final F> f) { + return e.either( + a -> single(left(a)), + b -> f.f(b).map(Either3::middle), + c -> single(right(c)) + ); + } + + public Option> traverseOption(final F> f) { + return e.either( + a -> some(left(a)), + b -> f.f(b).map(Either3::middle), + c -> some(right(c)) + ); + + } + + public P1> traverseP1(final F> f) { + return e.either( + a -> p(left(a)), + b -> f.f(b).map(Either3::middle), + c -> p(right(c)) + ); + + } + + public Stream> traverseStream(final F> f) { + return e.either( + a -> Stream.single(left(a)), + b -> f.f(b).map(Either3::middle), + c -> Stream.single(right(c)) + ); + + } + + + } + + public final Either3 leftMap(F f) { + return left().map(f); + } + + public final F, Either3> leftMap_() { + return this::leftMap; + } + + public final Either3 middleMap(F f) { + return middle().map(f); + } + + public final F, Either3> middleMap_() { + return this::middleMap; + } + + public final Either3 rightMap(F f) { + return right().map(f); + } + + public final F, Either3> rightMap_() { + return this::rightMap; } public static final class RightProjection { @@ -104,12 +351,21 @@ private RightProjection(final Either3 e) { public Either3 bind(F> f) { return e.either(a -> left(a), b -> middle(b), c -> f.f(c)); } + + public Either3 map(final F f) { + return e.either(a -> left(a), b -> middle(b), c -> right(f.f(c))); + } + } public static Either3 left(A a) { return new Left<>(a); } + public static F> left_() { + return Either3::left; + } + public static Either3 middle(B b) { return new Middle<>(b); } @@ -140,6 +396,22 @@ public Either3 map3(F fl, F fm, F fr) { public abstract D either(F fa, F fb, F fc); + public static F, D> either_(F fa, F fb, F fc) { + return e -> e.either(fa, fb, fc); + } + + public static Either3 joinLeft(final Either3, B, C> e) { + return e.left().bind(identity()); + } + + public static Either3 joinMiddle(final Either3, C> e) { + return e.middle().bind(identity()); + } + + public static Either3 joinRight(final Either3> e) { + return e.right().bind(identity()); + } + public Either3 moveLeft() { return either(a -> right(a), b -> left(b), c -> middle(c)); } From eedacf0010d8db853fd18c5ba59384d7740f9a9c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 7 Apr 2021 21:53:53 +1000 Subject: [PATCH 776/811] Implemented the right projection of Either3. --- core/src/main/java/fj/data/Either3.java | 111 ++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/core/src/main/java/fj/data/Either3.java b/core/src/main/java/fj/data/Either3.java index 0c7b7371..9b545f7e 100644 --- a/core/src/main/java/fj/data/Either3.java +++ b/core/src/main/java/fj/data/Either3.java @@ -347,15 +347,126 @@ public static final class RightProjection { private RightProjection(final Either3 e) { this.e = e; } + public Either3 apply(final Either3> e) { + return e.right().bind(this::map); + } public Either3 bind(F> f) { return e.either(a -> left(a), b -> middle(b), c -> f.f(c)); } + public Either3 either() { + return e; + } + + public boolean exists(final F f) { + return e.either(a -> false, b -> false, c -> f.f(c)); + } + + public Option> filter(final F f) { + return e.either(a -> none(), b -> none(), c -> f.f(c) ? some(right(c)) : none()); + } + + public boolean forall(final F f) { + return e.either(a -> true, b -> true, c -> f.f(c)); + } + + public Unit foreach(final F f) { + return e.either(a -> unit(), b -> unit(), c -> f.f(c)); + } + + public void foreachDoEffect(final Effect1 f) { + e.either(a -> unit(), b -> unit(), c -> f.toF().f(c)); + } + + public Iterator iterator() { + return toList().iterator(); + } + public Either3 map(final F f) { return e.either(a -> left(a), b -> middle(b), c -> right(f.f(c))); } + public C orValue(final C value) { + return orValue(() -> value); + } + + public C orValue(final F0 f) { + return e.either(a -> f.f(), b -> f.f(), c -> c); + } + + public Either3 sequence(final Either3 e) { + return bind(Function.constant(e)); + } + + public Array toArray() { + return e.either( + a -> Array.empty(), + b -> Array.empty(), + c -> Array.single(c) + ); + } + + public Collection toCollection() { + return toList().toCollection(); + } + + public List toList() { + return e.either(a -> nil(), b -> nil(), c -> single(c)); + } + + public Option toOption() { + return e.either(a -> none(), b -> none(), c -> some(c)); + } + + public Stream toStream() { + return e.either(a -> Stream.nil(), b -> Stream.nil(), c -> Stream.single(c)); + } + + public IO> traverseIO(final F> f) { + return e.either( + a -> IOFunctions.unit(left(a)), + b -> IOFunctions.unit(middle(b)), + c -> f.f(c).map(Either3::right) + ); + } + + public List> traverseList1(final F> f) { + return e.either( + a -> single(left(a)), + b -> single(middle(b)), + c -> f.f(c).map(Either3::right) + ); + } + + public Option> traverseOption(final F> f) { + return e.either( + a -> some(left(a)), + b -> some(middle(b)), + c -> f.f(c).map(Either3::right) + ); + + } + + public P1> traverseP1(final F> f) { + return e.either( + a -> p(left(a)), + b -> p(middle(b)), + c -> f.f(c).map(Either3::right) + ); + + } + + public Stream> traverseStream(final F> f) { + return e.either( + a -> Stream.single(left(a)), + b -> Stream.single(middle(b)), + c -> f.f(c).map(Either3::right) + ); + + } + + } public static Either3 left(A a) { From 546647277325db569386141681eefc99a889ec25 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 16 Apr 2021 22:39:20 +1000 Subject: [PATCH 777/811] Speed up Gradle tests by not generating test reports and running in parallel. --- build.gradle | 10 ++++++++++ gradle.properties | 3 +++ 2 files changed, 13 insertions(+) diff --git a/build.gradle b/build.gradle index 57c36c18..8e390f9c 100644 --- a/build.gradle +++ b/build.gradle @@ -70,6 +70,7 @@ allprojects { junitRuntime = "org.junit.vintage:junit-vintage-engine:5.5.2" displayCompilerWarnings = true + generateTestReports = false } repositories { @@ -112,6 +113,15 @@ subprojects { } } + tasks.withType(Test).configureEach { + maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 + if (!generateTestReports) { + reports.html.enabled = false + reports.junitXml.enabled = false + } + } + + } task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { diff --git a/gradle.properties b/gradle.properties index d4552a30..8f904ddb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,3 +3,6 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd signingEnabled = false + +org.gradle.parallel = true + From 8cef774bf2fbd850bf0a5e13bb76d2fab8380ade Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 16 Apr 2021 22:44:17 +1000 Subject: [PATCH 778/811] Renamed show for Either3. --- core/src/main/java/fj/Show.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index 62da5273..bfb2e151 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -256,7 +256,7 @@ public static Show> eitherShow(final Show sa, final Show< fromString("Right(").append(sb.f.f(e.right().value())).append(single(')'))); } - public static Show> eitherShow(final Show sa, final Show sb, final Show sc) { + public static Show> either3Show(final Show sa, final Show sb, final Show sc) { return show(e -> e.either( a -> fromString("Left(").append(sa.f.f(a)).append(single(')')), From 250aa82edd48edca4a315ee27f89cfc1bbb88e5b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 18 Apr 2021 21:54:27 +1000 Subject: [PATCH 779/811] Make SafeIO inherit of F0. --- core/src/main/java/fj/data/SafeIO.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index 11fdc31a..0643e886 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -1,13 +1,20 @@ package fj.data; +import fj.F0; + /** * Created by MarkPerry on 3/07/2014. */ @FunctionalInterface -public interface SafeIO extends IO { +public interface SafeIO extends IO, F0 { @Override A run(); + @Override + default A f() { + return run(); + } + } From 2cad57e8c28f3f61dc929adf1387b0a48a1c354b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 18 Apr 2021 21:56:05 +1000 Subject: [PATCH 780/811] Added conversions from Effect0 to Try, TryEffect and F0. --- core/src/main/java/fj/function/Effect0.java | 29 ++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/function/Effect0.java b/core/src/main/java/fj/function/Effect0.java index 57800eb0..5e499d2d 100644 --- a/core/src/main/java/fj/function/Effect0.java +++ b/core/src/main/java/fj/function/Effect0.java @@ -1,6 +1,8 @@ package fj.function; -import fj.F0; +import fj.*; + +import static fj.Unit.unit; /** * Created by mperry on 28/08/2014. @@ -9,4 +11,29 @@ public interface Effect0 { void f(); + default F0 toF0() { + return () -> { + f(); + return unit(); + }; + } + + default TryEffect0 toTryEffect0() { + return () -> f(); + } + + default Try0 toTry0() { + return () -> { + f(); + return unit(); + }; + } + + default P1 toP1() { + return P.lazy(() -> { + f(); + return unit(); + }); + } + } From 0f4f8548635e74c4fb9582887ad15c51acb1601f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 18 Apr 2021 22:51:23 +1000 Subject: [PATCH 781/811] Implemented primary functions from F in Effect1. --- core/src/main/java/fj/function/Effect1.java | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/core/src/main/java/fj/function/Effect1.java b/core/src/main/java/fj/function/Effect1.java index 0cc35a39..64abed44 100644 --- a/core/src/main/java/fj/function/Effect1.java +++ b/core/src/main/java/fj/function/Effect1.java @@ -1,6 +1,8 @@ package fj.function; import fj.F; +import fj.P; +import fj.P1; import fj.Unit; import java.util.function.Consumer; @@ -18,6 +20,32 @@ default void accept(A a) { f(a); } + default F bind(final F> g) { + return a -> { + return g.f(toF().f(a)).f(a); + }; + } + + default void apply(A a) { + f(a); + } + + default Effect1 contramap(F f) { + return o(f); + } + + default F map(F f) { + return a -> f.f(toF().f(a)); + } + + default F andThen(final F f) { + return map(f); + } + + default Effect1 o(final F f) { + return c -> f(f.f(c)); + } + default F toF() { return a -> { f(a); @@ -25,4 +53,16 @@ default F toF() { }; } + static Effect1 fromF(F f) { + return a -> f.f(a); + } + + default F dimap(F f, F g) { + return c -> g.f(toF().f(f.f(c))); + } + + default P1 partial(final A a) { + return P.lazy(() -> toF().f(a)); + } + } From 53ab41a58021a17a109772918c9c02f08ed32f8f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 19 Apr 2021 00:40:18 +1000 Subject: [PATCH 782/811] Added conversion functions between Effect, F, Try and TryEffect for low arities. --- core/src/main/java/fj/F0.java | 20 ++++++++ core/src/main/java/fj/data/SafeIO.java | 6 ++- core/src/main/java/fj/function/Effect1.java | 11 ++++ core/src/main/java/fj/function/Effect2.java | 12 +++++ core/src/main/java/fj/function/Try0.java | 37 ++++++++++++++ .../src/main/java/fj/function/TryEffect0.java | 50 +++++++++++++++++++ 6 files changed, 135 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/fj/F0.java b/core/src/main/java/fj/F0.java index c260992f..9354568c 100644 --- a/core/src/main/java/fj/F0.java +++ b/core/src/main/java/fj/F0.java @@ -1,5 +1,9 @@ package fj; +import fj.function.Effect0; +import fj.function.Try0; +import fj.function.TryEffect0; + import java.util.function.Supplier; /** @@ -14,4 +18,20 @@ default A get() { return f(); } + default Effect0 toEffect0() { + return () -> f(); + } + + default TryEffect0 toTryEffect0() { + return () -> f(); + } + + default Try0 toTry0() { + return () -> f(); + } + + default P1 toP1() { + return P.lazy(() -> f()); + } + } diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index 0643e886..eeef79f9 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -1,12 +1,16 @@ package fj.data; import fj.F0; +import fj.P; +import fj.P1; + +import java.io.IOException; /** * Created by MarkPerry on 3/07/2014. */ @FunctionalInterface -public interface SafeIO extends IO, F0 { +public interface SafeIO extends IO { @Override A run(); diff --git a/core/src/main/java/fj/function/Effect1.java b/core/src/main/java/fj/function/Effect1.java index 64abed44..aff85774 100644 --- a/core/src/main/java/fj/function/Effect1.java +++ b/core/src/main/java/fj/function/Effect1.java @@ -53,6 +53,15 @@ default F toF() { }; } + default TryEffect1 toTryEffect1() { + return a -> f(a); + } + + + default Try1 toTry1() { + return a -> toF().f(a); + } + static Effect1 fromF(F f) { return a -> f.f(a); } @@ -65,4 +74,6 @@ default P1 partial(final A a) { return P.lazy(() -> toF().f(a)); } + + } diff --git a/core/src/main/java/fj/function/Effect2.java b/core/src/main/java/fj/function/Effect2.java index 40d8abd8..e4d7701a 100644 --- a/core/src/main/java/fj/function/Effect2.java +++ b/core/src/main/java/fj/function/Effect2.java @@ -1,7 +1,12 @@ package fj.function; +import fj.F2; +import fj.Unit; + import java.util.function.BiConsumer; +import static fj.Unit.unit; + /** * Created by mperry on 28/08/2014. */ @@ -13,4 +18,11 @@ default void accept(A a, B b) { f(a, b); } + default F2 toF2() { + return (a, b) -> { + f(a, b); + return unit(); + }; + } + } diff --git a/core/src/main/java/fj/function/Try0.java b/core/src/main/java/fj/function/Try0.java index e218f0a7..9abfa6cd 100644 --- a/core/src/main/java/fj/function/Try0.java +++ b/core/src/main/java/fj/function/Try0.java @@ -1,5 +1,14 @@ package fj.function; +import fj.F0; +import fj.P; +import fj.P1; +import fj.data.Option; +import fj.data.Validation; + +import static fj.data.Validation.fail; +import static fj.data.Validation.success; + /** * A product of A which may throw an Exception. * @@ -13,4 +22,32 @@ public interface Try0 { A f() throws Z; + @SuppressWarnings("unchecked") + default F0> toF0() { + return () -> { + try { + return success(f()); + } catch (Exception e) { + return fail((Z) e); + } + }; + } + + default TryEffect0 toTryEffect0() { + return () -> f(); + } + + default Effect0 toEffect0() { + return () -> { + try { + f(); + } catch (Exception e) { + } + }; + } + + default P1> toP1() { + return P.lazy(() -> toF0().f()); + } + } diff --git a/core/src/main/java/fj/function/TryEffect0.java b/core/src/main/java/fj/function/TryEffect0.java index a6c9cbee..9a955c89 100644 --- a/core/src/main/java/fj/function/TryEffect0.java +++ b/core/src/main/java/fj/function/TryEffect0.java @@ -1,5 +1,15 @@ package fj.function; +import fj.F0; +import fj.P; +import fj.P1; +import fj.Unit; +import fj.data.Option; + +import static fj.Unit.unit; +import static fj.data.Option.none; +import static fj.data.Option.some; + /** * Created by mperry on 28/08/2014. */ @@ -7,4 +17,44 @@ public interface TryEffect0 { void f() throws Z; + @SuppressWarnings("unchecked") + default F0> toF0() { + return () -> { + try { + f(); + return none(); + } catch (Exception e) { + return some((Z) e); + } + }; + } + + @SuppressWarnings("unchecked") + default Try0 toTry0() { + return () -> { + try { + f(); + return unit(); + } catch (Exception e) { + throw ((Z) e); + } + }; + } + + default Effect0 toEffect0() { + return () -> { + try { + f(); + } catch (Exception e) { + } + }; + } + + default P1 toP1() { + return P.lazy(() -> { + toEffect0().f(); + return Unit.unit(); + }); + } + } From 19a70d92b43dfea29ae219a994230562d9375708 Mon Sep 17 00:00:00 2001 From: Chen Zhang <340355960@qq.com> Date: Tue, 17 Aug 2021 10:09:52 +0800 Subject: [PATCH 783/811] Improve Travis CI build Performance --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 8e7c52c9..89680bd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ jdk: - openjdk-ea matrix: + fast_finish: true include: - jdk: openjdk12 @@ -31,3 +32,8 @@ env: global: - secure: Bun+1FZ29Q3dR9gZ/5brxcSf+zcY5tWrsqOA4GUb5bYCMyORuXQB0FYXuhKR4wB1pFrk1a9EYwRwSu3GwRJVWb+UzF0CNOWF/QG5tGPx32IOXScwlL/KonI4Vhs7Oc0fF4Wdb7euNrT27BU61jbUugjJ642b3n0VBYFYDdquprU= - secure: QAxhjqLRa+WHKIzgIJPZ/rM5a5uzqG7E5rsC0YvB25cO712oYXmzsYPia/oSp0chXlYLYMfk2UnLeQCSx2e6ogXRRRa977Q+B33Nt0Hd9SGLtduv6DBrbA2ehLU12Ib4DWe5VhF5eueAunycYcllTvqA5h+pzTtEVbd68ZHncM4= + +cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ From da4cd6264e102c96d2c78eba56fa57af12655d08 Mon Sep 17 00:00:00 2001 From: YunLemon <340355960@qq.com> Date: Wed, 18 Aug 2021 08:23:20 +0800 Subject: [PATCH 784/811] Update .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 89680bd8..a7465305 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,6 @@ matrix: script: - ./gradlew clean test - env: global: - secure: Bun+1FZ29Q3dR9gZ/5brxcSf+zcY5tWrsqOA4GUb5bYCMyORuXQB0FYXuhKR4wB1pFrk1a9EYwRwSu3GwRJVWb+UzF0CNOWF/QG5tGPx32IOXScwlL/KonI4Vhs7Oc0fF4Wdb7euNrT27BU61jbUugjJ642b3n0VBYFYDdquprU= From 20f6248c8a7ac7a8e0cedece07aca6b6de4306e1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Wed, 9 Feb 2022 22:28:28 +1000 Subject: [PATCH 785/811] Set the default to signing disabled as per the 5.x branch --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 07c2b60c..d4552a30 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = true +signingEnabled = false From 2387c3d3e8ff9c7899eda5e85365737477636edb Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Feb 2022 20:34:40 +1000 Subject: [PATCH 786/811] Removed Java 9 options so the 5.x branch works with Java 8 --- build.gradle | 2 -- 1 file changed, 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8e390f9c..81d2c1f1 100644 --- a/build.gradle +++ b/build.gradle @@ -107,7 +107,6 @@ subprojects { } tasks.withType(JavaCompile) { - options.compilerArgs.addAll(['--release', '8']) if (displayCompilerWarnings) { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" } @@ -146,7 +145,6 @@ configure(subprojects.findAll { it.name != "props-core" }) { sourceCompatibility = "1.8" javadoc { - options.addBooleanOption('html5', true) } task javadocJar(type: Jar, dependsOn: "javadoc") { From baf69e9c359f8ee909b50fcddd0ed3b4eab438ce Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Feb 2022 20:54:43 +1000 Subject: [PATCH 787/811] Template for version 5.0 release notes --- etc/release-notes/release-notes-5.0.adoc | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 etc/release-notes/release-notes-5.0.adoc diff --git a/etc/release-notes/release-notes-5.0.adoc b/etc/release-notes/release-notes-5.0.adoc new file mode 100644 index 00000000..89138acd --- /dev/null +++ b/etc/release-notes/release-notes-5.0.adoc @@ -0,0 +1,22 @@ + += Release 5.0 + +Released: TODO + +== Enhancements + +== Fixes + + +== Internal + + +== Breaking Changes + + +== Documentation + + + +== Contributors + From ed841cd150b552d11234baecbbd87adf5db135ed Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 10 Feb 2022 23:26:45 +1000 Subject: [PATCH 788/811] Added FJ 5.0 doc release notes --- etc/release-notes/release-notes-5.0.adoc | 37 ++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/etc/release-notes/release-notes-5.0.adoc b/etc/release-notes/release-notes-5.0.adoc index 89138acd..86cfc69e 100644 --- a/etc/release-notes/release-notes-5.0.adoc +++ b/etc/release-notes/release-notes-5.0.adoc @@ -4,19 +4,46 @@ Released: TODO == Enhancements +* The functions classes F, F2, F0, Effect1 and Effect2 extend the corresponding Java 8 function interface. Removed the corresponding classes F1W, F1Functions, F2W and F2Functions. Similarly for IO and IOW. +* Moved the function wrapper classes F1W and F2W into F and F2 as default functions. +* Added lifting a semigroup to an option monoid, using none as zero. +* Added Trampoline.suspend(F0>) +* Added sum, product and fromString to Longs. +* Added Bounded definition. +* Added toStream of Bounded in Enumerator. +* Added intersection monoid for sets. +* Added set intersection semigroup. +* Added FunctionalInterface annotations for interfaces F0, F, F2 to F8, IO and SafeIO. +* Added functions to IO. +* Added Either3. +* Updated IO and SafeIO inheritance. +* Added conversion functions for Effect, F, Try and TryEffect for low arities. == Fixes - +* Fixed BitSet properties test. == Internal - +* Upgraded to Gradle 6.8.3. +* Added Strategy, Validation, Integers, monoid, semigroup and monoid tests. +* Switch from the uptodate-gradle-plugin to gradle-versions-plugin. +* Speed up Gradle tests by running in parallel and not generating reports. == Breaking Changes - +* Removed Ord parameter from Monoid's setIntersectionMonoid function. +* Removed the classes F1W, F1Functions, F2W, F2Functions, F3W, F3Functions, F4W, F4Functions, F5W, F5Functions, F6W, F6Functions, F7W, F7Functions, F8W and F8Functions. +* Removed deprecated Monoid, Ord, P, P1, Semigroup, Array, HashMap, Java, List, Seq, Set, Stream, Gen, Rand and TreeMap functions. == Documentation - - +* Fixed the javadoc on Either's iif function. +* Fixed doc for union and intersection monoid for sets. +* Fixed semigroup docs. +* Fixed List.headOption. == Contributors +* Gabor Liptak +* Jean-Baptiste Giraudeau +* Soundharya Kamaraj +* Yaroslav Atroshenko +* Mark Perry +* Chen Zhang From f7a29a5be2df6dad22e4606a246e9b586d28f64b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 00:09:54 +1000 Subject: [PATCH 789/811] Removed build.number in the javadoc and created by Mark Perry --- build.gradle | 2 +- consume/src/test/java/fj/EmptyTest.java | 3 --- core/src/main/java/fj/Bottom.java | 2 -- core/src/main/java/fj/Class.java | 2 -- core/src/main/java/fj/Digit.java | 2 -- core/src/main/java/fj/Effect.java | 2 -- core/src/main/java/fj/Equal.java | 2 -- core/src/main/java/fj/F.java | 5 +---- core/src/main/java/fj/F0.java | 3 --- core/src/main/java/fj/F2.java | 3 --- core/src/main/java/fj/F3.java | 4 +--- core/src/main/java/fj/F4.java | 4 +--- core/src/main/java/fj/F5.java | 5 +---- core/src/main/java/fj/F6.java | 5 +---- core/src/main/java/fj/F7.java | 5 +---- core/src/main/java/fj/F8.java | 4 +--- core/src/main/java/fj/Function.java | 2 -- core/src/main/java/fj/Hash.java | 2 -- core/src/main/java/fj/LcgRng.java | 2 -- core/src/main/java/fj/Monoid.java | 2 -- core/src/main/java/fj/Ord.java | 2 -- core/src/main/java/fj/Ordering.java | 2 -- core/src/main/java/fj/P.java | 2 -- core/src/main/java/fj/P1.java | 10 +--------- core/src/main/java/fj/P2.java | 2 -- core/src/main/java/fj/P3.java | 2 -- core/src/main/java/fj/P4.java | 2 -- core/src/main/java/fj/P5.java | 2 -- core/src/main/java/fj/P6.java | 2 -- core/src/main/java/fj/P7.java | 2 -- core/src/main/java/fj/P8.java | 2 -- core/src/main/java/fj/Primitive.java | 2 -- core/src/main/java/fj/Rng.java | 3 --- core/src/main/java/fj/Semigroup.java | 2 -- core/src/main/java/fj/Show.java | 2 -- core/src/main/java/fj/Try.java | 3 --- core/src/main/java/fj/TryEffect.java | 3 --- core/src/main/java/fj/Unit.java | 2 -- core/src/main/java/fj/control/Trampoline.java | 2 +- core/src/main/java/fj/data/IO.java | 4 ---- core/src/main/java/fj/data/Iteratee.java | 3 --- core/src/main/java/fj/data/Java.java | 2 -- core/src/main/java/fj/data/Java8.java | 3 --- core/src/main/java/fj/data/List.java | 2 -- core/src/main/java/fj/data/NonEmptyList.java | 2 -- core/src/main/java/fj/data/Option.java | 2 -- core/src/main/java/fj/data/PriorityQueue.java | 2 -- core/src/main/java/fj/data/Reader.java | 1 - core/src/main/java/fj/data/SafeIO.java | 9 --------- core/src/main/java/fj/data/State.java | 3 --- core/src/main/java/fj/data/Stream.java | 2 -- core/src/main/java/fj/data/Tree.java | 2 -- core/src/main/java/fj/data/Validation.java | 2 -- core/src/main/java/fj/data/Writer.java | 3 --- core/src/main/java/fj/data/hamt/BitSet.java | 2 -- .../main/java/fj/data/hamt/HashArrayMappedTrie.java | 2 -- core/src/main/java/fj/data/hamt/Node.java | 2 -- core/src/main/java/fj/data/package-info.java | 2 -- core/src/main/java/fj/function/BigIntegers.java | 2 -- core/src/main/java/fj/function/Booleans.java | 2 -- core/src/main/java/fj/function/Doubles.java | 2 -- core/src/main/java/fj/function/Effect0.java | 3 --- core/src/main/java/fj/function/Effect1.java | 3 --- core/src/main/java/fj/function/Effect2.java | 3 --- core/src/main/java/fj/function/Effect3.java | 3 --- core/src/main/java/fj/function/Effect4.java | 3 --- core/src/main/java/fj/function/Effect5.java | 3 --- core/src/main/java/fj/function/Effect6.java | 3 --- core/src/main/java/fj/function/Effect7.java | 3 --- core/src/main/java/fj/function/Effect8.java | 3 --- core/src/main/java/fj/function/Integers.java | 2 -- core/src/main/java/fj/function/Longs.java | 2 -- core/src/main/java/fj/function/Strings.java | 2 -- core/src/main/java/fj/function/Try0.java | 1 - core/src/main/java/fj/function/Try1.java | 1 - core/src/main/java/fj/function/Try2.java | 1 - core/src/main/java/fj/function/Try3.java | 1 - core/src/main/java/fj/function/Try4.java | 1 - core/src/main/java/fj/function/Try5.java | 1 - core/src/main/java/fj/function/Try6.java | 1 - core/src/main/java/fj/function/Try7.java | 1 - core/src/main/java/fj/function/Try8.java | 1 - core/src/main/java/fj/function/TryEffect0.java | 3 --- core/src/main/java/fj/function/TryEffect1.java | 3 --- core/src/main/java/fj/function/TryEffect2.java | 3 --- core/src/main/java/fj/function/TryEffect3.java | 3 --- core/src/main/java/fj/function/TryEffect4.java | 3 --- core/src/main/java/fj/function/TryEffect5.java | 3 --- core/src/main/java/fj/function/TryEffect6.java | 3 --- core/src/main/java/fj/function/TryEffect7.java | 3 --- core/src/main/java/fj/function/TryEffect8.java | 3 --- core/src/main/java/fj/function/Visitor.java | 2 -- core/src/main/java/fj/function/package-info.java | 2 -- core/src/main/java/fj/package-info.java | 2 -- core/src/main/java/fj/parser/Parser.java | 2 -- core/src/main/java/fj/parser/Result.java | 2 -- core/src/main/java/fj/parser/package-info.java | 2 -- core/src/test/java/fj/P2Test.java | 3 --- core/src/test/java/fj/ShowTest.java | 3 --- core/src/test/java/fj/data/ArrayTest.java | 3 --- core/src/test/java/fj/data/BooleansTest.java | 3 --- core/src/test/java/fj/data/JavaTest.java | 3 --- core/src/test/java/fj/data/LazyStringTest.java | 3 --- core/src/test/java/fj/data/ListBufferTest.java | 3 --- core/src/test/java/fj/data/ListTest.java | 3 --- core/src/test/java/fj/data/List_Traverse_Tests.java | 3 --- core/src/test/java/fj/data/OptionTest.java | 3 --- core/src/test/java/fj/data/SeqTest.java | 3 --- core/src/test/java/fj/data/SetTest.java | 3 --- core/src/test/java/fj/data/StateTest.java | 3 --- core/src/test/java/fj/data/StreamTest.java | 3 --- core/src/test/java/fj/data/TreeMapTest.java | 3 --- core/src/test/java/fj/data/TreeTest.java | 6 +----- core/src/test/java/fj/data/UnitTest.java | 3 --- core/src/test/java/fj/function/TestEffect.java | 4 ---- demo/src/main/java/fj/demo/IODemo.java | 3 --- demo/src/main/java/fj/demo/StateDemo_Greeter.java | 3 --- .../main/java/fj/demo/StateDemo_VendingMachine.java | 3 --- demo/src/main/java/fj/demo/WriterDemo_Halver.java | 3 --- demo/src/main/java/fj/demo/optic/LensPerson.java | 3 --- demo/src/main/java/fj/demo/realworld/Chapter7.java | 2 -- demo/src/test/java/fj/EmptyTest.java | 3 --- java-core/src/main/java/fj/java/util/ListUtil.java | 3 --- java-core/src/test/java/fj/EmptyTest.java | 3 --- .../src/main/java/fj/data/dummy/DummyClass.java | 3 --- performance/src/test/java/fj/data/dummy/DummyTest.java | 3 --- props-core/src/test/java/fj/MemoisationTest.java | 3 --- props-core/src/test/java/fj/data/ReaderTest.java | 3 --- props-core/src/test/java/fj/data/TestRngState.java | 3 --- props-core/src/test/java/fj/data/WriterTest.java | 3 --- .../java/fj/data/fingertrees/FingerTreeProperties.java | 4 ---- .../test/java/fj/data/fingertrees/FingerTreeTest.java | 4 ---- .../src/test/java/fj/data/hamt/BitSetProperties.java | 4 ---- .../fj/data/properties/NonEmptyListProperties.java | 3 --- .../fj/data/properties/PriorityQueueProperties.java | 3 --- .../test/java/fj/data/properties/SetProperties.java | 3 --- .../java/fj/data/properties/TreeMapProperties.java | 3 --- .../java/fj/data/properties/ValidationProperties.java | 3 --- .../src/main/java/fj/data/test/PropertyAssert.java | 3 --- quickcheck/src/test/java/fj/data/test/TestNull.java | 3 --- quickcheck/src/test/java/fj/test/TestRand.java | 3 --- 141 files changed, 11 insertions(+), 374 deletions(-) diff --git a/build.gradle b/build.gradle index 81d2c1f1..1ceb4fb9 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.8.1" + fjConsumeVersion = "4.9" signModule = false diff --git a/consume/src/test/java/fj/EmptyTest.java b/consume/src/test/java/fj/EmptyTest.java index e112a97a..13675822 100644 --- a/consume/src/test/java/fj/EmptyTest.java +++ b/consume/src/test/java/fj/EmptyTest.java @@ -5,9 +5,6 @@ import org.junit.Assert; -/** - * Created by MarkPerry on 30/08/2015. - */ public class EmptyTest { @Ignore @Test diff --git a/core/src/main/java/fj/Bottom.java b/core/src/main/java/fj/Bottom.java index a70629f1..5cc7f4e4 100644 --- a/core/src/main/java/fj/Bottom.java +++ b/core/src/main/java/fj/Bottom.java @@ -2,8 +2,6 @@ /** * Represents the bottom _|_ value. - * - * @version %build.number% */ public final class Bottom { private Bottom() { diff --git a/core/src/main/java/fj/Class.java b/core/src/main/java/fj/Class.java index 56222de1..8bee1951 100644 --- a/core/src/main/java/fj/Class.java +++ b/core/src/main/java/fj/Class.java @@ -11,8 +11,6 @@ /** * A wrapper for a {@link java.lang.Class} that provides additional methods. - * - * @version %build.number% */ public final class Class { private final java.lang.Class c; diff --git a/core/src/main/java/fj/Digit.java b/core/src/main/java/fj/Digit.java index 7213e278..4fec7b0c 100644 --- a/core/src/main/java/fj/Digit.java +++ b/core/src/main/java/fj/Digit.java @@ -6,8 +6,6 @@ /** * The digits zero to nine. - * - * @version %build.number% */ public enum Digit { /** diff --git a/core/src/main/java/fj/Effect.java b/core/src/main/java/fj/Effect.java index 80680cac..2b5dcd6f 100644 --- a/core/src/main/java/fj/Effect.java +++ b/core/src/main/java/fj/Effect.java @@ -14,8 +14,6 @@ /** * Represents a side-effect. - * - * @version %build.number% */ public final class Effect { diff --git a/core/src/main/java/fj/Equal.java b/core/src/main/java/fj/Equal.java index 9179cc43..cba4a589 100644 --- a/core/src/main/java/fj/Equal.java +++ b/core/src/main/java/fj/Equal.java @@ -22,8 +22,6 @@ /** * Tests for equality between two objects. - * - * @version %build.number% */ public final class Equal { diff --git a/core/src/main/java/fj/F.java b/core/src/main/java/fj/F.java index 45cec4fe..1736f97b 100644 --- a/core/src/main/java/fj/F.java +++ b/core/src/main/java/fj/F.java @@ -16,10 +16,7 @@ import static fj.data.Zipper.fromStream; /** - * A transformation or function from A to B. This type can be represented - * using the Java 7 closure syntax. - * - * @version %build.number% + * A transformation or function from A to B. */ @FunctionalInterface public interface F extends Function { diff --git a/core/src/main/java/fj/F0.java b/core/src/main/java/fj/F0.java index 9354568c..88d60a9e 100644 --- a/core/src/main/java/fj/F0.java +++ b/core/src/main/java/fj/F0.java @@ -6,9 +6,6 @@ import java.util.function.Supplier; -/** - * Created by MarkPerry on 21/01/2015. - */ @FunctionalInterface public interface F0 extends Supplier { diff --git a/core/src/main/java/fj/F2.java b/core/src/main/java/fj/F2.java index 4f7c306d..8b1aac20 100644 --- a/core/src/main/java/fj/F2.java +++ b/core/src/main/java/fj/F2.java @@ -14,9 +14,6 @@ /** * A transformation function of arity-2 from A and B to C. - * This type can be represented using the Java 7 closure syntax. - * - * @version %build.number% */ @FunctionalInterface public interface F2 extends BiFunction { diff --git a/core/src/main/java/fj/F3.java b/core/src/main/java/fj/F3.java index b8c4dcf3..b7efeb3a 100644 --- a/core/src/main/java/fj/F3.java +++ b/core/src/main/java/fj/F3.java @@ -2,9 +2,7 @@ /** * A transformation function of arity-3 from A, B and C to - * D. This type can be represented using the Java 7 closure syntax. - * - * @version %build.number% + * D. */ @FunctionalInterface public interface F3 { diff --git a/core/src/main/java/fj/F4.java b/core/src/main/java/fj/F4.java index d63f03a7..c3c5f882 100644 --- a/core/src/main/java/fj/F4.java +++ b/core/src/main/java/fj/F4.java @@ -2,9 +2,7 @@ /** * A transformation function of arity-4 from A, B, C and - * D to E. This type can be represented using the Java 7 closure syntax. - * - * @version %build.number% + * D to E. */ @FunctionalInterface public interface F4 { diff --git a/core/src/main/java/fj/F5.java b/core/src/main/java/fj/F5.java index f63ae797..574afb15 100644 --- a/core/src/main/java/fj/F5.java +++ b/core/src/main/java/fj/F5.java @@ -2,10 +2,7 @@ /** * A transformation function of arity-5 from A, B, C, - * D and E to F$. This type can be represented using the Java - * 7 closure syntax. - * - * @version %build.number% + * D and E to F$. */ @FunctionalInterface public interface F5 { diff --git a/core/src/main/java/fj/F6.java b/core/src/main/java/fj/F6.java index 558c17fc..135e28fe 100644 --- a/core/src/main/java/fj/F6.java +++ b/core/src/main/java/fj/F6.java @@ -2,10 +2,7 @@ /** * A transformation function of arity-6 from A, B, C, - * D, E and F$ to G. This type can be - * represented using the Java 7 closure syntax. - * - * @version %build.number% + * D, E and F$ to G. */ @FunctionalInterface public interface F6 { diff --git a/core/src/main/java/fj/F7.java b/core/src/main/java/fj/F7.java index 05caefb4..a2542700 100644 --- a/core/src/main/java/fj/F7.java +++ b/core/src/main/java/fj/F7.java @@ -2,10 +2,7 @@ /** * A transformation function of arity-7 from A, B, C, - * D, E, F$ and G to H. This type - * can be represented using the Java 7 closure syntax. - * - * @version %build.number% + * D, E, F$ and G to H. */ @FunctionalInterface public interface F7 { diff --git a/core/src/main/java/fj/F8.java b/core/src/main/java/fj/F8.java index 5aa103f2..647fc14c 100644 --- a/core/src/main/java/fj/F8.java +++ b/core/src/main/java/fj/F8.java @@ -3,9 +3,7 @@ /** * A transformation function of arity-8 from A, B, C, * D, E, F$, G and H to - * I. This type can be represented using the Java 7 closure syntax. - * - * @version %build.number% + * I. */ @FunctionalInterface public interface F8 { diff --git a/core/src/main/java/fj/Function.java b/core/src/main/java/fj/Function.java index 995c179d..52819377 100644 --- a/core/src/main/java/fj/Function.java +++ b/core/src/main/java/fj/Function.java @@ -4,8 +4,6 @@ /** * Transformations on functions. - * - * @version %build.number% */ public final class Function { private Function() { diff --git a/core/src/main/java/fj/Hash.java b/core/src/main/java/fj/Hash.java index 703d96ee..241bcefb 100644 --- a/core/src/main/java/fj/Hash.java +++ b/core/src/main/java/fj/Hash.java @@ -17,8 +17,6 @@ /** * Produces a hash code for an object which should attempt uniqueness. - * - * @version %build.number% */ public final class Hash { private final F f; diff --git a/core/src/main/java/fj/LcgRng.java b/core/src/main/java/fj/LcgRng.java index 215b3572..cd918f5b 100644 --- a/core/src/main/java/fj/LcgRng.java +++ b/core/src/main/java/fj/LcgRng.java @@ -1,8 +1,6 @@ package fj; /** - * Created by MarkPerry on 7/07/2014. - * * https://en.wikipedia.org/wiki/Linear_congruential_generator */ public class LcgRng extends Rng { diff --git a/core/src/main/java/fj/Monoid.java b/core/src/main/java/fj/Monoid.java index bc09250d..bc05f33e 100644 --- a/core/src/main/java/fj/Monoid.java +++ b/core/src/main/java/fj/Monoid.java @@ -22,8 +22,6 @@ *

    1. Right Identity; forall x. sum(x, zero()) == x
    2. *
    3. Associativity; forall x y z. sum(sum(x, y), z) == sum(x, sum(y, z))
    4. * - * - * @version %build.number% */ public final class Monoid
      { diff --git a/core/src/main/java/fj/Ord.java b/core/src/main/java/fj/Ord.java index ae4d3fda..2bf90450 100644 --- a/core/src/main/java/fj/Ord.java +++ b/core/src/main/java/fj/Ord.java @@ -10,8 +10,6 @@ /** * Tests for ordering between two objects. - * - * @version %build.number% */ public final class Ord { diff --git a/core/src/main/java/fj/Ordering.java b/core/src/main/java/fj/Ordering.java index b22bcfcb..1828f69a 100644 --- a/core/src/main/java/fj/Ordering.java +++ b/core/src/main/java/fj/Ordering.java @@ -3,8 +3,6 @@ /** * The comparison of two instances of a type may have one of three orderings; less than, equal or * greater than. - * - * @version %build.number% */ public enum Ordering { /** diff --git a/core/src/main/java/fj/P.java b/core/src/main/java/fj/P.java index 587cdc9d..3e6efb74 100644 --- a/core/src/main/java/fj/P.java +++ b/core/src/main/java/fj/P.java @@ -4,8 +4,6 @@ /** * Functions across products. - * - * @version %build.number% */ public final class P { private P() { diff --git a/core/src/main/java/fj/P1.java b/core/src/main/java/fj/P1.java index 810e484d..5e575a4d 100644 --- a/core/src/main/java/fj/P1.java +++ b/core/src/main/java/fj/P1.java @@ -1,20 +1,12 @@ package fj; -import fj.data.Array; -import fj.data.Either; -import fj.data.List; -import fj.data.Option; -import fj.data.Stream; -import fj.data.Validation; +import fj.data.*; import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import static fj.P.p; -import static fj.Unit.unit; -//import fj.data.*; - public abstract class P1 implements F0 { diff --git a/core/src/main/java/fj/P2.java b/core/src/main/java/fj/P2.java index 841b356e..b4979f03 100644 --- a/core/src/main/java/fj/P2.java +++ b/core/src/main/java/fj/P2.java @@ -9,8 +9,6 @@ /** * A product-2. - * - * @version %build.number% */ public abstract class P2 { /** diff --git a/core/src/main/java/fj/P3.java b/core/src/main/java/fj/P3.java index 6e08a0ba..fff39ed8 100644 --- a/core/src/main/java/fj/P3.java +++ b/core/src/main/java/fj/P3.java @@ -4,8 +4,6 @@ /** * A product-3. - * - * @version %build.number% */ public abstract class P3 { /** diff --git a/core/src/main/java/fj/P4.java b/core/src/main/java/fj/P4.java index 4fa2ef8c..d2dca64b 100644 --- a/core/src/main/java/fj/P4.java +++ b/core/src/main/java/fj/P4.java @@ -4,8 +4,6 @@ /** * A product-4. - * - * @version %build.number% */ public abstract class P4 { /** diff --git a/core/src/main/java/fj/P5.java b/core/src/main/java/fj/P5.java index fabc4227..07138cb3 100644 --- a/core/src/main/java/fj/P5.java +++ b/core/src/main/java/fj/P5.java @@ -4,8 +4,6 @@ /** * A product-5. - * - * @version %build.number% */ public abstract class P5 { /** diff --git a/core/src/main/java/fj/P6.java b/core/src/main/java/fj/P6.java index 670622c7..295b5427 100644 --- a/core/src/main/java/fj/P6.java +++ b/core/src/main/java/fj/P6.java @@ -4,8 +4,6 @@ /** * A product-6. - * - * @version %build.number% */ @SuppressWarnings("UnnecessaryFullyQualifiedName") public abstract class P6 { diff --git a/core/src/main/java/fj/P7.java b/core/src/main/java/fj/P7.java index 6c9ac804..17161f5d 100644 --- a/core/src/main/java/fj/P7.java +++ b/core/src/main/java/fj/P7.java @@ -4,8 +4,6 @@ /** * A product-7. - * - * @version %build.number% */ @SuppressWarnings("UnnecessaryFullyQualifiedName") public abstract class P7 { diff --git a/core/src/main/java/fj/P8.java b/core/src/main/java/fj/P8.java index f3902c5e..571d6a15 100644 --- a/core/src/main/java/fj/P8.java +++ b/core/src/main/java/fj/P8.java @@ -4,8 +4,6 @@ /** * A product-8. - * - * @version %build.number% */ @SuppressWarnings("UnnecessaryFullyQualifiedName") public abstract class P8 { diff --git a/core/src/main/java/fj/Primitive.java b/core/src/main/java/fj/Primitive.java index 2007c03c..6ded797e 100644 --- a/core/src/main/java/fj/Primitive.java +++ b/core/src/main/java/fj/Primitive.java @@ -2,8 +2,6 @@ /** * Functions that convert between Java primitive types. - * - * @version %build.number% */ public final class Primitive { private Primitive() { diff --git a/core/src/main/java/fj/Rng.java b/core/src/main/java/fj/Rng.java index 20b3358f..46c31b27 100644 --- a/core/src/main/java/fj/Rng.java +++ b/core/src/main/java/fj/Rng.java @@ -1,8 +1,5 @@ package fj; -/** - * Created by MarkPerry on 7/07/2014. - */ public abstract class Rng { public abstract P2 nextInt(); diff --git a/core/src/main/java/fj/Semigroup.java b/core/src/main/java/fj/Semigroup.java index 1d767385..cd31e1e3 100644 --- a/core/src/main/java/fj/Semigroup.java +++ b/core/src/main/java/fj/Semigroup.java @@ -23,8 +23,6 @@ *
        *
      • Associativity; forall x. forall y. forall z. sum(sum(x, y), z) == sum(x, sum(y, z))
      • *
      - * - * @version %build.number% */ public final class Semigroup
      { diff --git a/core/src/main/java/fj/Show.java b/core/src/main/java/fj/Show.java index bfb2e151..8a21a281 100644 --- a/core/src/main/java/fj/Show.java +++ b/core/src/main/java/fj/Show.java @@ -27,8 +27,6 @@ /** * Renders an object for display. - * - * @version %build.number% */ public final class Show { private final F> f; diff --git a/core/src/main/java/fj/Try.java b/core/src/main/java/fj/Try.java index d8a30130..8418a621 100644 --- a/core/src/main/java/fj/Try.java +++ b/core/src/main/java/fj/Try.java @@ -10,9 +10,6 @@ import static fj.data.Validation.fail; import static fj.data.Validation.success; -/** - * Created by mperry on 24/07/2014. - */ public final class Try { private Try() { diff --git a/core/src/main/java/fj/TryEffect.java b/core/src/main/java/fj/TryEffect.java index cd1f75ab..a240e638 100644 --- a/core/src/main/java/fj/TryEffect.java +++ b/core/src/main/java/fj/TryEffect.java @@ -3,9 +3,6 @@ import fj.data.Validation; import fj.function.*; -/** - * Created by mperry on 29/08/2014. - */ public final class TryEffect { private TryEffect(){} diff --git a/core/src/main/java/fj/Unit.java b/core/src/main/java/fj/Unit.java index c7471f21..76463ec1 100644 --- a/core/src/main/java/fj/Unit.java +++ b/core/src/main/java/fj/Unit.java @@ -2,8 +2,6 @@ /** * The unit type which has only one value. - * - * @version %build.number% */ public final class Unit { private static final Unit u = new Unit(); diff --git a/core/src/main/java/fj/control/Trampoline.java b/core/src/main/java/fj/control/Trampoline.java index e3b58e1c..5c787f04 100644 --- a/core/src/main/java/fj/control/Trampoline.java +++ b/core/src/main/java/fj/control/Trampoline.java @@ -9,7 +9,7 @@ /** * A Trampoline is a potentially branching computation that can be stepped through and executed in constant stack. - * It represent suspendable coroutines with subroutine calls, reified as a data structure. + * It represents suspendable coroutines with subroutine calls, reified as a data structure. */ public abstract class Trampoline { diff --git a/core/src/main/java/fj/data/IO.java b/core/src/main/java/fj/data/IO.java index e2a94a38..69434728 100644 --- a/core/src/main/java/fj/data/IO.java +++ b/core/src/main/java/fj/data/IO.java @@ -1,9 +1,5 @@ package fj.data; -/** - * Created by MarkPerry on 19/06/2014. - */ - import fj.F; import fj.Unit; import fj.function.Try0; diff --git a/core/src/main/java/fj/data/Iteratee.java b/core/src/main/java/fj/data/Iteratee.java index be68ed02..e6177068 100644 --- a/core/src/main/java/fj/data/Iteratee.java +++ b/core/src/main/java/fj/data/Iteratee.java @@ -7,9 +7,6 @@ import fj.P2; import fj.Unit; -/** - * - */ public final class Iteratee { /** The input to an iteratee. */ diff --git a/core/src/main/java/fj/data/Java.java b/core/src/main/java/fj/data/Java.java index 8691c09d..b3cb7e7f 100644 --- a/core/src/main/java/fj/data/Java.java +++ b/core/src/main/java/fj/data/Java.java @@ -35,8 +35,6 @@ /** * Functions that convert between types from the core Java API. - * - * @version %build.number% */ public final class Java { private Java() { diff --git a/core/src/main/java/fj/data/Java8.java b/core/src/main/java/fj/data/Java8.java index 46c5ca2a..184c01c5 100644 --- a/core/src/main/java/fj/data/Java8.java +++ b/core/src/main/java/fj/data/Java8.java @@ -19,9 +19,6 @@ import java.util.function.Supplier; import java.util.stream.StreamSupport; -/** - * Created by mperry on 3/06/2014. - */ public final class Java8 { private Java8() { diff --git a/core/src/main/java/fj/data/List.java b/core/src/main/java/fj/data/List.java index 9259900f..721ee9f1 100644 --- a/core/src/main/java/fj/data/List.java +++ b/core/src/main/java/fj/data/List.java @@ -28,8 +28,6 @@ /** * Provides an in-memory, immutable, singly linked list. - * - * @version %build.number% */ public abstract class List implements Iterable { private List() { diff --git a/core/src/main/java/fj/data/NonEmptyList.java b/core/src/main/java/fj/data/NonEmptyList.java index 34c8b957..96bf444a 100644 --- a/core/src/main/java/fj/data/NonEmptyList.java +++ b/core/src/main/java/fj/data/NonEmptyList.java @@ -14,8 +14,6 @@ /** * Provides an in-memory, immutable, singly linked list with total head and tail. - * - * @version %build.number% */ public final class NonEmptyList implements Iterable { /** diff --git a/core/src/main/java/fj/data/Option.java b/core/src/main/java/fj/data/Option.java index b6876c63..9831c48c 100644 --- a/core/src/main/java/fj/data/Option.java +++ b/core/src/main/java/fj/data/Option.java @@ -23,8 +23,6 @@ /** * An optional value that may be none (no value) or some (a value). This type is a replacement for * the use of null with better type checks. - * - * @version %build.number% */ public abstract class Option implements Iterable { private Option() { diff --git a/core/src/main/java/fj/data/PriorityQueue.java b/core/src/main/java/fj/data/PriorityQueue.java index 21f6ed6f..f685c36d 100644 --- a/core/src/main/java/fj/data/PriorityQueue.java +++ b/core/src/main/java/fj/data/PriorityQueue.java @@ -20,8 +20,6 @@ * annotated with type K, are combined using a monoid of K and both the * key and value are stored in the leaf. Priorities of the same value * are returned FIFO (first in, first out). - * - * Created by MarkPerry on 31 May 16. */ public final class PriorityQueue { diff --git a/core/src/main/java/fj/data/Reader.java b/core/src/main/java/fj/data/Reader.java index 9374e300..49010e31 100644 --- a/core/src/main/java/fj/data/Reader.java +++ b/core/src/main/java/fj/data/Reader.java @@ -4,7 +4,6 @@ /** * The Reader monad (also called the function monad, so equivalent to the idea of F). - * Created by MarkPerry on 7/07/2014. */ public class Reader { diff --git a/core/src/main/java/fj/data/SafeIO.java b/core/src/main/java/fj/data/SafeIO.java index eeef79f9..bcc16bf6 100644 --- a/core/src/main/java/fj/data/SafeIO.java +++ b/core/src/main/java/fj/data/SafeIO.java @@ -1,14 +1,5 @@ package fj.data; -import fj.F0; -import fj.P; -import fj.P1; - -import java.io.IOException; - -/** - * Created by MarkPerry on 3/07/2014. - */ @FunctionalInterface public interface SafeIO extends IO { diff --git a/core/src/main/java/fj/data/State.java b/core/src/main/java/fj/data/State.java index f0156b36..c5b638a3 100644 --- a/core/src/main/java/fj/data/State.java +++ b/core/src/main/java/fj/data/State.java @@ -9,9 +9,6 @@ import static fj.control.Trampoline.suspend; import static fj.data.List.cons; -/** - * Created by MarkPerry on 7/07/2014. - */ public final class State { public static State unit(F> runF) { diff --git a/core/src/main/java/fj/data/Stream.java b/core/src/main/java/fj/data/Stream.java index bcf87dcf..8afa36ee 100644 --- a/core/src/main/java/fj/data/Stream.java +++ b/core/src/main/java/fj/data/Stream.java @@ -40,8 +40,6 @@ /** * A lazy (not yet evaluated), immutable, singly linked list. - * - * @version %build.number% */ public abstract class Stream implements Iterable { private Stream() { diff --git a/core/src/main/java/fj/data/Tree.java b/core/src/main/java/fj/data/Tree.java index f430d6d2..3b12d506 100644 --- a/core/src/main/java/fj/data/Tree.java +++ b/core/src/main/java/fj/data/Tree.java @@ -10,8 +10,6 @@ /** * Provides a lazy, immutable, non-empty, multi-way tree (a rose tree). - * - * @version %build.number% */ public final class Tree implements Iterable { /** diff --git a/core/src/main/java/fj/data/Validation.java b/core/src/main/java/fj/data/Validation.java index 60d8d2b2..5c1985a4 100644 --- a/core/src/main/java/fj/data/Validation.java +++ b/core/src/main/java/fj/data/Validation.java @@ -17,8 +17,6 @@ * Isomorphic to {@link Either} but has renamed functions and represents failure on the left and success on the right. * This type also has accumulating functions that accept a {@link Semigroup} for binding computation while keeping error * values - * - * @version %build.number% */ public class Validation implements Iterable { private final Either e; diff --git a/core/src/main/java/fj/data/Writer.java b/core/src/main/java/fj/data/Writer.java index b6b4579b..ba2cded5 100644 --- a/core/src/main/java/fj/data/Writer.java +++ b/core/src/main/java/fj/data/Writer.java @@ -2,9 +2,6 @@ import fj.*; -/** - * Created by MarkPerry on 7/07/2014. - */ public final class Writer { private final A val; diff --git a/core/src/main/java/fj/data/hamt/BitSet.java b/core/src/main/java/fj/data/hamt/BitSet.java index d164642d..9efbab34 100644 --- a/core/src/main/java/fj/data/hamt/BitSet.java +++ b/core/src/main/java/fj/data/hamt/BitSet.java @@ -13,8 +13,6 @@ * For example, the BitSet("1011") represents the decimal number 11 and has * indices [3, 0] inclusive where the bit with the lowest value has the lowest * index and is the rightmost bit. - * - * Created by maperr on 31/05/2016. */ public final class BitSet { diff --git a/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java b/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java index f13ae90f..371f5435 100644 --- a/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java +++ b/core/src/main/java/fj/data/hamt/HashArrayMappedTrie.java @@ -22,8 +22,6 @@ * mapped trie. It is a refined version of the more general notion of * a hash tree. * - * @author Mark Perry - * * Based on "Ideal Hash Trees" by Phil Bagwell, available from * http://lampwww.epfl.ch/papers/idealhashtrees.pdf */ diff --git a/core/src/main/java/fj/data/hamt/Node.java b/core/src/main/java/fj/data/hamt/Node.java index f8a1ff40..af453925 100644 --- a/core/src/main/java/fj/data/hamt/Node.java +++ b/core/src/main/java/fj/data/hamt/Node.java @@ -10,8 +10,6 @@ /** * A Hash Array Mapped Trie node that is either a key-value pair or a * Hash Array Mapped Trie. - * - * Created by maperr on 31/05/2016. */ public final class Node { diff --git a/core/src/main/java/fj/data/package-info.java b/core/src/main/java/fj/data/package-info.java index 911ef492..ae9577a7 100644 --- a/core/src/main/java/fj/data/package-info.java +++ b/core/src/main/java/fj/data/package-info.java @@ -1,6 +1,4 @@ /** * Common algebraic data types. - * - * @version %build.number% */ package fj.data; diff --git a/core/src/main/java/fj/function/BigIntegers.java b/core/src/main/java/fj/function/BigIntegers.java index 30d07a10..ac6584fc 100644 --- a/core/src/main/java/fj/function/BigIntegers.java +++ b/core/src/main/java/fj/function/BigIntegers.java @@ -10,8 +10,6 @@ /** * Curried functions over Integers. - * - * @version %build.number% */ public final class BigIntegers { private BigIntegers() { diff --git a/core/src/main/java/fj/function/Booleans.java b/core/src/main/java/fj/function/Booleans.java index 6211e870..bef1b347 100644 --- a/core/src/main/java/fj/function/Booleans.java +++ b/core/src/main/java/fj/function/Booleans.java @@ -15,8 +15,6 @@ /** * Curried logical functions. - * - * @version %build.number% */ public final class Booleans { private Booleans() { diff --git a/core/src/main/java/fj/function/Doubles.java b/core/src/main/java/fj/function/Doubles.java index 6fe1b033..aefcbfdc 100644 --- a/core/src/main/java/fj/function/Doubles.java +++ b/core/src/main/java/fj/function/Doubles.java @@ -11,8 +11,6 @@ /** * Curried functions over Doubles. - * - * @version %build.number% */ public final class Doubles { private Doubles() { diff --git a/core/src/main/java/fj/function/Effect0.java b/core/src/main/java/fj/function/Effect0.java index 5e499d2d..7644d394 100644 --- a/core/src/main/java/fj/function/Effect0.java +++ b/core/src/main/java/fj/function/Effect0.java @@ -4,9 +4,6 @@ import static fj.Unit.unit; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect0 { void f(); diff --git a/core/src/main/java/fj/function/Effect1.java b/core/src/main/java/fj/function/Effect1.java index aff85774..1f3be909 100644 --- a/core/src/main/java/fj/function/Effect1.java +++ b/core/src/main/java/fj/function/Effect1.java @@ -9,9 +9,6 @@ import static fj.Unit.unit; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect1 extends Consumer { void f(A a); diff --git a/core/src/main/java/fj/function/Effect2.java b/core/src/main/java/fj/function/Effect2.java index e4d7701a..b9a5ad5a 100644 --- a/core/src/main/java/fj/function/Effect2.java +++ b/core/src/main/java/fj/function/Effect2.java @@ -7,9 +7,6 @@ import static fj.Unit.unit; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect2 extends BiConsumer { void f(A a, B b); diff --git a/core/src/main/java/fj/function/Effect3.java b/core/src/main/java/fj/function/Effect3.java index 0609584b..675d2301 100644 --- a/core/src/main/java/fj/function/Effect3.java +++ b/core/src/main/java/fj/function/Effect3.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect3 { void f(A a, B b, C c); diff --git a/core/src/main/java/fj/function/Effect4.java b/core/src/main/java/fj/function/Effect4.java index b24a7624..fdd20af8 100644 --- a/core/src/main/java/fj/function/Effect4.java +++ b/core/src/main/java/fj/function/Effect4.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect4 { void f(A a, B b, C c, D d); diff --git a/core/src/main/java/fj/function/Effect5.java b/core/src/main/java/fj/function/Effect5.java index 142be280..48634ac8 100644 --- a/core/src/main/java/fj/function/Effect5.java +++ b/core/src/main/java/fj/function/Effect5.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect5 { void f(A a, B b, C c, D d, E e); diff --git a/core/src/main/java/fj/function/Effect6.java b/core/src/main/java/fj/function/Effect6.java index fe72314b..f81cdf25 100644 --- a/core/src/main/java/fj/function/Effect6.java +++ b/core/src/main/java/fj/function/Effect6.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect6 { void f(A a, B b, C c, D d, E e, F f); diff --git a/core/src/main/java/fj/function/Effect7.java b/core/src/main/java/fj/function/Effect7.java index 944273af..4c77e4f4 100644 --- a/core/src/main/java/fj/function/Effect7.java +++ b/core/src/main/java/fj/function/Effect7.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect7 { void f(A a, B b, C c, D d, E e, F f, G g); diff --git a/core/src/main/java/fj/function/Effect8.java b/core/src/main/java/fj/function/Effect8.java index a8cfd3bb..d8b970ec 100644 --- a/core/src/main/java/fj/function/Effect8.java +++ b/core/src/main/java/fj/function/Effect8.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface Effect8 { void f(A a, B b, C c, D d, E e, F f, G g, H h); diff --git a/core/src/main/java/fj/function/Integers.java b/core/src/main/java/fj/function/Integers.java index 4b1b14b5..7f8fd0e8 100644 --- a/core/src/main/java/fj/function/Integers.java +++ b/core/src/main/java/fj/function/Integers.java @@ -16,8 +16,6 @@ /** * Curried functions over Integers. - * - * @version %build.number% */ public final class Integers { private Integers() { diff --git a/core/src/main/java/fj/function/Longs.java b/core/src/main/java/fj/function/Longs.java index 0989e8c0..2762f3e2 100644 --- a/core/src/main/java/fj/function/Longs.java +++ b/core/src/main/java/fj/function/Longs.java @@ -15,8 +15,6 @@ /** * Curried functions over Longs. - * - * @version %build.number% */ public final class Longs { private Longs() { diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index dadbfd22..1c239e85 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -12,8 +12,6 @@ /** * Curried string functions. - * - * @version %build.number% */ public final class Strings { private Strings() { diff --git a/core/src/main/java/fj/function/Try0.java b/core/src/main/java/fj/function/Try0.java index 9abfa6cd..7cdacfc1 100644 --- a/core/src/main/java/fj/function/Try0.java +++ b/core/src/main/java/fj/function/Try0.java @@ -15,7 +15,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to a P1. * * @see fj.Try#f(Try0) - * @version %build.number% */ public interface Try0 { diff --git a/core/src/main/java/fj/function/Try1.java b/core/src/main/java/fj/function/Try1.java index b626890b..53f5d048 100644 --- a/core/src/main/java/fj/function/Try1.java +++ b/core/src/main/java/fj/function/Try1.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F. * * @see fj.Try#f(Try1) - * @version %build.number% */ public interface Try1 { diff --git a/core/src/main/java/fj/function/Try2.java b/core/src/main/java/fj/function/Try2.java index 94438ccb..24e6a099 100644 --- a/core/src/main/java/fj/function/Try2.java +++ b/core/src/main/java/fj/function/Try2.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F2. * * @see fj.Try#f(Try2) - * @version %build.number% */ public interface Try2 { diff --git a/core/src/main/java/fj/function/Try3.java b/core/src/main/java/fj/function/Try3.java index 7464c013..7c0de0eb 100644 --- a/core/src/main/java/fj/function/Try3.java +++ b/core/src/main/java/fj/function/Try3.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F3. * * @see fj.Try#f(Try3) - * @version %build.number% */ public interface Try3 { diff --git a/core/src/main/java/fj/function/Try4.java b/core/src/main/java/fj/function/Try4.java index a7d969ed..d2b79d2c 100644 --- a/core/src/main/java/fj/function/Try4.java +++ b/core/src/main/java/fj/function/Try4.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F4. * * @see fj.Try#f(Try4) - * @version %build.number% */ public interface Try4 { diff --git a/core/src/main/java/fj/function/Try5.java b/core/src/main/java/fj/function/Try5.java index b9855fd7..cbc1a93d 100644 --- a/core/src/main/java/fj/function/Try5.java +++ b/core/src/main/java/fj/function/Try5.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F5. * * @see fj.Try#f(Try5) - * @version %build.number% */ public interface Try5 { diff --git a/core/src/main/java/fj/function/Try6.java b/core/src/main/java/fj/function/Try6.java index b66775c6..39bffbcb 100644 --- a/core/src/main/java/fj/function/Try6.java +++ b/core/src/main/java/fj/function/Try6.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F6. * * @see fj.Try#f(Try6) - * @version %build.number% */ public interface Try6 { diff --git a/core/src/main/java/fj/function/Try7.java b/core/src/main/java/fj/function/Try7.java index 3bc09cd9..ab56ffcd 100644 --- a/core/src/main/java/fj/function/Try7.java +++ b/core/src/main/java/fj/function/Try7.java @@ -7,7 +7,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F7. * * @see fj.Try#f(Try7) - * @version %build.number% */ public interface Try7 { diff --git a/core/src/main/java/fj/function/Try8.java b/core/src/main/java/fj/function/Try8.java index 5b2f1b55..1486de3c 100644 --- a/core/src/main/java/fj/function/Try8.java +++ b/core/src/main/java/fj/function/Try8.java @@ -6,7 +6,6 @@ * Used to instantiate a lambda that may throw an Exception before converting to an F8. * * @see fj.Try#f(Try8) - * @version %build.number% */ public interface Try8 { diff --git a/core/src/main/java/fj/function/TryEffect0.java b/core/src/main/java/fj/function/TryEffect0.java index 9a955c89..1ccaa9af 100644 --- a/core/src/main/java/fj/function/TryEffect0.java +++ b/core/src/main/java/fj/function/TryEffect0.java @@ -10,9 +10,6 @@ import static fj.data.Option.none; import static fj.data.Option.some; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect0 { void f() throws Z; diff --git a/core/src/main/java/fj/function/TryEffect1.java b/core/src/main/java/fj/function/TryEffect1.java index 40db423d..1ddaca08 100644 --- a/core/src/main/java/fj/function/TryEffect1.java +++ b/core/src/main/java/fj/function/TryEffect1.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect1 { void f(A a) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect2.java b/core/src/main/java/fj/function/TryEffect2.java index c9c13da9..c54f3fe7 100644 --- a/core/src/main/java/fj/function/TryEffect2.java +++ b/core/src/main/java/fj/function/TryEffect2.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect2 { void f(A a, B b) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect3.java b/core/src/main/java/fj/function/TryEffect3.java index c581221e..4c3f19d0 100644 --- a/core/src/main/java/fj/function/TryEffect3.java +++ b/core/src/main/java/fj/function/TryEffect3.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect3 { void f(A a, B b, C c) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect4.java b/core/src/main/java/fj/function/TryEffect4.java index f99900ca..8b04ed5f 100644 --- a/core/src/main/java/fj/function/TryEffect4.java +++ b/core/src/main/java/fj/function/TryEffect4.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect4 { void f(A a, B b, C c, D d) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect5.java b/core/src/main/java/fj/function/TryEffect5.java index d0445e3e..0bca874a 100644 --- a/core/src/main/java/fj/function/TryEffect5.java +++ b/core/src/main/java/fj/function/TryEffect5.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect5 { void f(A a, B b, C c, D d, E e) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect6.java b/core/src/main/java/fj/function/TryEffect6.java index b4d81a41..d8f1f468 100644 --- a/core/src/main/java/fj/function/TryEffect6.java +++ b/core/src/main/java/fj/function/TryEffect6.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect6 { void f(A a, B b, C c, D d, E e, F f) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect7.java b/core/src/main/java/fj/function/TryEffect7.java index 2e6004e9..133212dc 100644 --- a/core/src/main/java/fj/function/TryEffect7.java +++ b/core/src/main/java/fj/function/TryEffect7.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect7 { void f(A a, B b, C c, D d, E e, F f, G g) throws Z; diff --git a/core/src/main/java/fj/function/TryEffect8.java b/core/src/main/java/fj/function/TryEffect8.java index 4424bf00..d9c8c384 100644 --- a/core/src/main/java/fj/function/TryEffect8.java +++ b/core/src/main/java/fj/function/TryEffect8.java @@ -1,8 +1,5 @@ package fj.function; -/** - * Created by mperry on 28/08/2014. - */ public interface TryEffect8 { void f(A a, B b, C c, D d, E e, F f, G g, H h) throws Z; diff --git a/core/src/main/java/fj/function/Visitor.java b/core/src/main/java/fj/function/Visitor.java index bdca3b5e..ed0e7b53 100644 --- a/core/src/main/java/fj/function/Visitor.java +++ b/core/src/main/java/fj/function/Visitor.java @@ -15,8 +15,6 @@ /** * The essence of the visitor design pattern expressed polymorphically. - * - * @version %build.number% */ public final class Visitor { private Visitor() { diff --git a/core/src/main/java/fj/function/package-info.java b/core/src/main/java/fj/function/package-info.java index 6698bd5d..851bb534 100644 --- a/core/src/main/java/fj/function/package-info.java +++ b/core/src/main/java/fj/function/package-info.java @@ -1,6 +1,4 @@ /** * A prelude of commonly used first-class functions - * - * @version %build.number% */ package fj.function; diff --git a/core/src/main/java/fj/package-info.java b/core/src/main/java/fj/package-info.java index abeffe0f..c457d1e9 100644 --- a/core/src/main/java/fj/package-info.java +++ b/core/src/main/java/fj/package-info.java @@ -1,6 +1,4 @@ /** * Types that set the premise for the existence of Functional Java. - * - * @version %build.number% */ package fj; diff --git a/core/src/main/java/fj/parser/Parser.java b/core/src/main/java/fj/parser/Parser.java index 3ea6dd15..b5753f23 100644 --- a/core/src/main/java/fj/parser/Parser.java +++ b/core/src/main/java/fj/parser/Parser.java @@ -14,8 +14,6 @@ /** * A parser is a function that takes some input (I) and produces either an error (E) or a parse result (A) and the * remainder of the input. - * - * @version %build.number% */ public final class Parser { private final F>> f; diff --git a/core/src/main/java/fj/parser/Result.java b/core/src/main/java/fj/parser/Result.java index b8acc6c4..843dd558 100644 --- a/core/src/main/java/fj/parser/Result.java +++ b/core/src/main/java/fj/parser/Result.java @@ -12,8 +12,6 @@ /** * A parse result made up of a value (A) and the remainder of the parse input (I). - * - * @version %build.number% */ public final class Result implements Iterable { private final I i; diff --git a/core/src/main/java/fj/parser/package-info.java b/core/src/main/java/fj/parser/package-info.java index 08140f0b..8f31c204 100644 --- a/core/src/main/java/fj/parser/package-info.java +++ b/core/src/main/java/fj/parser/package-info.java @@ -1,6 +1,4 @@ /** * Parser combinators. - * - * @version %build.number% */ package fj.parser; diff --git a/core/src/test/java/fj/P2Test.java b/core/src/test/java/fj/P2Test.java index dc25a3e0..d14b6199 100644 --- a/core/src/test/java/fj/P2Test.java +++ b/core/src/test/java/fj/P2Test.java @@ -3,9 +3,6 @@ import org.junit.Assert; import org.junit.Test; -/** - * Created by MarkPerry on 22/07/2014. - */ public class P2Test { @Test diff --git a/core/src/test/java/fj/ShowTest.java b/core/src/test/java/fj/ShowTest.java index c516c0df..3d6d8354 100644 --- a/core/src/test/java/fj/ShowTest.java +++ b/core/src/test/java/fj/ShowTest.java @@ -6,9 +6,6 @@ import static fj.data.Array.array; import static org.junit.Assert.assertTrue; -/** - * Created by MarkPerry on 4/06/2015. - */ public class ShowTest { @Test public void arrayShow() { diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java index 883fc835..5713e5c3 100644 --- a/core/src/test/java/fj/data/ArrayTest.java +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -7,9 +7,6 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertThat; -/** - * Created by MarkPerry on 14 Feb 16. - */ public class ArrayTest { @Test diff --git a/core/src/test/java/fj/data/BooleansTest.java b/core/src/test/java/fj/data/BooleansTest.java index b0d3f969..84f7676f 100644 --- a/core/src/test/java/fj/data/BooleansTest.java +++ b/core/src/test/java/fj/data/BooleansTest.java @@ -10,9 +10,6 @@ import static fj.function.Booleans.isnot; import static org.hamcrest.core.Is.is; -/** - * Created by amar on 28/01/15. - */ public class BooleansTest { @Test diff --git a/core/src/test/java/fj/data/JavaTest.java b/core/src/test/java/fj/data/JavaTest.java index 2a9b6bfd..b8d99510 100644 --- a/core/src/test/java/fj/data/JavaTest.java +++ b/core/src/test/java/fj/data/JavaTest.java @@ -9,9 +9,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -/** - * Created by MarkPerry on 14/07/2014. - */ public class JavaTest { @Test diff --git a/core/src/test/java/fj/data/LazyStringTest.java b/core/src/test/java/fj/data/LazyStringTest.java index 4f6325af..1adef2bd 100644 --- a/core/src/test/java/fj/data/LazyStringTest.java +++ b/core/src/test/java/fj/data/LazyStringTest.java @@ -6,9 +6,6 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -/** - * Created by MarkPerry on 11/06/2015. - */ public class LazyStringTest { @Test diff --git a/core/src/test/java/fj/data/ListBufferTest.java b/core/src/test/java/fj/data/ListBufferTest.java index 1dfbbc39..f2ed8286 100644 --- a/core/src/test/java/fj/data/ListBufferTest.java +++ b/core/src/test/java/fj/data/ListBufferTest.java @@ -5,9 +5,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; -/** - * Created by MarkPerry on 17/08/2015. - */ public class ListBufferTest { @Test diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index ca7d0f22..9f09de0f 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -32,9 +32,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.*; -/** - * Created by MarkPerry on 16/01/2015. - */ public class ListTest { @Test diff --git a/core/src/test/java/fj/data/List_Traverse_Tests.java b/core/src/test/java/fj/data/List_Traverse_Tests.java index 3d964f45..5b7c0d19 100644 --- a/core/src/test/java/fj/data/List_Traverse_Tests.java +++ b/core/src/test/java/fj/data/List_Traverse_Tests.java @@ -9,9 +9,6 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -/** - * Created by amar on 28/12/14. - */ public class List_Traverse_Tests { @Test diff --git a/core/src/test/java/fj/data/OptionTest.java b/core/src/test/java/fj/data/OptionTest.java index 5a7bbdbf..e03d7aae 100644 --- a/core/src/test/java/fj/data/OptionTest.java +++ b/core/src/test/java/fj/data/OptionTest.java @@ -31,9 +31,6 @@ import static fj.data.Validation.*; import static org.junit.Assert.*; -/** - * Created by MarkPerry on 15/01/2015. - */ public final class OptionTest { @Test diff --git a/core/src/test/java/fj/data/SeqTest.java b/core/src/test/java/fj/data/SeqTest.java index 0b62db00..8a78ab31 100644 --- a/core/src/test/java/fj/data/SeqTest.java +++ b/core/src/test/java/fj/data/SeqTest.java @@ -33,9 +33,6 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; -/** - * Created by MarkPerry on 16/01/2015. - */ public class SeqTest { @Test diff --git a/core/src/test/java/fj/data/SetTest.java b/core/src/test/java/fj/data/SetTest.java index cdf2519c..ae65b687 100644 --- a/core/src/test/java/fj/data/SetTest.java +++ b/core/src/test/java/fj/data/SetTest.java @@ -8,9 +8,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; -/** - * Created by MarkPerry on 18/08/2015. - */ public class SetTest { @Test diff --git a/core/src/test/java/fj/data/StateTest.java b/core/src/test/java/fj/data/StateTest.java index 37b21030..479efc38 100644 --- a/core/src/test/java/fj/data/StateTest.java +++ b/core/src/test/java/fj/data/StateTest.java @@ -5,9 +5,6 @@ import static fj.P.p; import static org.junit.Assert.assertEquals; -/** - * Created by MarkPerry on 18/12/2014. - */ public class StateTest { @Test diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index 313678aa..f320f27a 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -38,9 +38,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; -/** - * Created by Zheka Kozlov on 27.05.2015. - */ public class StreamTest { @Test diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 96cb95b2..77352989 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -19,9 +19,6 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -/** - * Created by MarkPerry on 11/01/2015. - */ public class TreeMapTest { @Test diff --git a/core/src/test/java/fj/data/TreeTest.java b/core/src/test/java/fj/data/TreeTest.java index 811826fb..fd43c852 100644 --- a/core/src/test/java/fj/data/TreeTest.java +++ b/core/src/test/java/fj/data/TreeTest.java @@ -1,15 +1,11 @@ package fj.data; -import org.junit.Assert; import org.junit.Test; import static fj.data.Tree.leaf; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.*; +import static org.junit.Assert.assertThat; -/** - * Created by MarkPerry on 29/08/2015. - */ public class TreeTest { @Test diff --git a/core/src/test/java/fj/data/UnitTest.java b/core/src/test/java/fj/data/UnitTest.java index eef15887..1fab0a7b 100644 --- a/core/src/test/java/fj/data/UnitTest.java +++ b/core/src/test/java/fj/data/UnitTest.java @@ -4,9 +4,6 @@ import org.junit.Assert; import org.junit.Test; -/** - * Created by MarkPerry on 17/01/2015. - */ public class UnitTest { @Test diff --git a/core/src/test/java/fj/function/TestEffect.java b/core/src/test/java/fj/function/TestEffect.java index 00da26f0..de2f5c5f 100644 --- a/core/src/test/java/fj/function/TestEffect.java +++ b/core/src/test/java/fj/function/TestEffect.java @@ -1,11 +1,7 @@ package fj.function; -import fj.F; import org.junit.Test; -/** - * Created by mperry on 28/08/2014. - */ public class TestEffect { @Test diff --git a/demo/src/main/java/fj/demo/IODemo.java b/demo/src/main/java/fj/demo/IODemo.java index ea313e77..aad8e41b 100644 --- a/demo/src/main/java/fj/demo/IODemo.java +++ b/demo/src/main/java/fj/demo/IODemo.java @@ -10,9 +10,6 @@ import static fj.data.LazyString.unlines_; import static java.lang.System.out; -/** - * Created by MarkPerry on 13/06/2015. - */ public class IODemo { public static void main(String[] args) { diff --git a/demo/src/main/java/fj/demo/StateDemo_Greeter.java b/demo/src/main/java/fj/demo/StateDemo_Greeter.java index 578f414e..707a1f9f 100644 --- a/demo/src/main/java/fj/demo/StateDemo_Greeter.java +++ b/demo/src/main/java/fj/demo/StateDemo_Greeter.java @@ -3,9 +3,6 @@ import fj.P; import fj.data.State; -/** - * Created by mperry on 4/08/2014. - */ public class StateDemo_Greeter { public static void main(String args[]) { diff --git a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java index ef1a09cd..75de4823 100644 --- a/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java +++ b/demo/src/main/java/fj/demo/StateDemo_VendingMachine.java @@ -6,9 +6,6 @@ import static fj.demo.StateDemo_VendingMachine.Input.COIN; import static fj.demo.StateDemo_VendingMachine.Input.TURN; -/** - * Created by MarkPerry on 20/07/2014. - */ public class StateDemo_VendingMachine { public enum Input { COIN, TURN } diff --git a/demo/src/main/java/fj/demo/WriterDemo_Halver.java b/demo/src/main/java/fj/demo/WriterDemo_Halver.java index 8473e588..9e6c6dac 100644 --- a/demo/src/main/java/fj/demo/WriterDemo_Halver.java +++ b/demo/src/main/java/fj/demo/WriterDemo_Halver.java @@ -6,9 +6,6 @@ import static fj.Monoid.stringMonoid; -/** - * Created by mperry on 4/08/2014. - */ public class WriterDemo_Halver { public static void main(String args[]) { diff --git a/demo/src/main/java/fj/demo/optic/LensPerson.java b/demo/src/main/java/fj/demo/optic/LensPerson.java index 51f5e103..641543e9 100644 --- a/demo/src/main/java/fj/demo/optic/LensPerson.java +++ b/demo/src/main/java/fj/demo/optic/LensPerson.java @@ -6,9 +6,6 @@ import static org.junit.Assert.assertTrue; -/** - * Created by MarkPerry on 23/06/2015. - */ public class LensPerson { static final class Person { diff --git a/demo/src/main/java/fj/demo/realworld/Chapter7.java b/demo/src/main/java/fj/demo/realworld/Chapter7.java index c239a5bf..bc414e4f 100644 --- a/demo/src/main/java/fj/demo/realworld/Chapter7.java +++ b/demo/src/main/java/fj/demo/realworld/Chapter7.java @@ -8,8 +8,6 @@ import static fj.data.IOFunctions.*; /** - * Created by MarkPerry on 11/06/2015. - * * Examples from Chapter 7 of Real World Haskell, http://book.realworldhaskell.org/. * * Currently just ch07/toupper-lazy4.hs. diff --git a/demo/src/test/java/fj/EmptyTest.java b/demo/src/test/java/fj/EmptyTest.java index e112a97a..13675822 100644 --- a/demo/src/test/java/fj/EmptyTest.java +++ b/demo/src/test/java/fj/EmptyTest.java @@ -5,9 +5,6 @@ import org.junit.Assert; -/** - * Created by MarkPerry on 30/08/2015. - */ public class EmptyTest { @Ignore @Test diff --git a/java-core/src/main/java/fj/java/util/ListUtil.java b/java-core/src/main/java/fj/java/util/ListUtil.java index 17fb5519..ffab7968 100644 --- a/java-core/src/main/java/fj/java/util/ListUtil.java +++ b/java-core/src/main/java/fj/java/util/ListUtil.java @@ -5,9 +5,6 @@ import java.util.List; -/** - * Created by MarkPerry on 28/08/2015. - */ public class ListUtil { public static List map(List list, F f) { diff --git a/java-core/src/test/java/fj/EmptyTest.java b/java-core/src/test/java/fj/EmptyTest.java index d1088c03..1c126bfa 100644 --- a/java-core/src/test/java/fj/EmptyTest.java +++ b/java-core/src/test/java/fj/EmptyTest.java @@ -4,9 +4,6 @@ import org.junit.Test; import org.junit.Assert; -/** - * Created by MarkPerry on 30/08/2015. - */ public class EmptyTest { @Ignore @Test diff --git a/performance/src/main/java/fj/data/dummy/DummyClass.java b/performance/src/main/java/fj/data/dummy/DummyClass.java index 72cc5c34..a94dcdde 100644 --- a/performance/src/main/java/fj/data/dummy/DummyClass.java +++ b/performance/src/main/java/fj/data/dummy/DummyClass.java @@ -1,8 +1,5 @@ package fj.data.dummy; -/** - * Created by MarkPerry on 5 Feb 16. - */ public class DummyClass { } diff --git a/performance/src/test/java/fj/data/dummy/DummyTest.java b/performance/src/test/java/fj/data/dummy/DummyTest.java index d3865433..49722bcd 100644 --- a/performance/src/test/java/fj/data/dummy/DummyTest.java +++ b/performance/src/test/java/fj/data/dummy/DummyTest.java @@ -3,9 +3,6 @@ import org.junit.Ignore; import org.junit.Test; -/** - * Created by MarkPerry on 5 Feb 16. - */ public class DummyTest { @Test diff --git a/props-core/src/test/java/fj/MemoisationTest.java b/props-core/src/test/java/fj/MemoisationTest.java index 865f76a3..605546ef 100644 --- a/props-core/src/test/java/fj/MemoisationTest.java +++ b/props-core/src/test/java/fj/MemoisationTest.java @@ -12,9 +12,6 @@ import static fj.test.Property.property; import static org.junit.Assert.assertTrue; -/** - * Created by mperry on 14/07/2014. - */ @RunWith(PropertyTestRunner.class) public class MemoisationTest { diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index 044595d0..accc3394 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -13,9 +13,6 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -/** - * Created by MarkPerry on 4/12/2014. - */ public class ReaderTest { @Test diff --git a/props-core/src/test/java/fj/data/TestRngState.java b/props-core/src/test/java/fj/data/TestRngState.java index 5f5f81bb..41143c17 100644 --- a/props-core/src/test/java/fj/data/TestRngState.java +++ b/props-core/src/test/java/fj/data/TestRngState.java @@ -17,9 +17,6 @@ import static fj.test.Property.property; import static fj.test.Variant.variant; -/** - * Created by mperry on 4/08/2014. - */ public class TestRngState { static List expected1 = List.list(4,4,2,2,2,5,3,3,1,5); diff --git a/props-core/src/test/java/fj/data/WriterTest.java b/props-core/src/test/java/fj/data/WriterTest.java index 25f99b22..50134da3 100644 --- a/props-core/src/test/java/fj/data/WriterTest.java +++ b/props-core/src/test/java/fj/data/WriterTest.java @@ -16,9 +16,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; -/** - * Created by MarkPerry on 17/12/2014. - */ public class WriterTest { @Test diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java index b7ed83f5..446716c2 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeProperties.java @@ -1,6 +1,5 @@ package fj.data.fingertrees; -import fj.P2; import fj.data.Stream; import fj.test.Property; import fj.test.reflect.CheckParams; @@ -12,9 +11,6 @@ import static fj.test.Property.prop; import static fj.test.Property.property; -/** - * Created by MarkPerry on 10/10/2015. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class FingerTreeProperties { diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index b25fff51..a26fdc89 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -14,10 +14,6 @@ import static org.junit.Assert.assertThat; import static org.hamcrest.core.Is.is; - -/** - * Created by MarkPerry on 10/10/2015. - */ public class FingerTreeTest { public static final int SIZE = 10; diff --git a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java index 6c3f91a9..fbda987b 100644 --- a/props-core/src/test/java/fj/data/hamt/BitSetProperties.java +++ b/props-core/src/test/java/fj/data/hamt/BitSetProperties.java @@ -31,10 +31,6 @@ import static fj.test.Property.prop; import static fj.test.Property.property; -/** - * Created by maperr on 31/05/2016. - */ - @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class BitSetProperties { diff --git a/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java index 256fb3a8..64ce1934 100644 --- a/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java +++ b/props-core/src/test/java/fj/data/properties/NonEmptyListProperties.java @@ -25,9 +25,6 @@ import static fj.test.Property.property; import static java.lang.Math.min; -/** - * Created by Zheka Kozlov on 02.06.2015. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class NonEmptyListProperties { diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java index 2bde7e6e..c2e46eca 100644 --- a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -26,9 +26,6 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; -/** - * Created by MarkPerry on 18 Jun 16. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 100) public class PriorityQueueProperties { diff --git a/props-core/src/test/java/fj/data/properties/SetProperties.java b/props-core/src/test/java/fj/data/properties/SetProperties.java index 5349b650..2657b937 100644 --- a/props-core/src/test/java/fj/data/properties/SetProperties.java +++ b/props-core/src/test/java/fj/data/properties/SetProperties.java @@ -15,9 +15,6 @@ import static fj.test.Property.prop; import static fj.test.Property.property; -/** - * Created by MarkPerry on 18/08/2015. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class SetProperties { diff --git a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java index eb71749b..50b323ff 100644 --- a/props-core/src/test/java/fj/data/properties/TreeMapProperties.java +++ b/props-core/src/test/java/fj/data/properties/TreeMapProperties.java @@ -23,9 +23,6 @@ import static fj.test.Arbitrary.arbTreeMap; import static fj.test.Property.*; -/** - * Created by MarkPerry on 29/08/2015. - */ @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 10000) public class TreeMapProperties { diff --git a/props-core/src/test/java/fj/data/properties/ValidationProperties.java b/props-core/src/test/java/fj/data/properties/ValidationProperties.java index f5205d73..a47383ab 100644 --- a/props-core/src/test/java/fj/data/properties/ValidationProperties.java +++ b/props-core/src/test/java/fj/data/properties/ValidationProperties.java @@ -13,9 +13,6 @@ import static fj.test.Property.implies; import static fj.test.Property.prop; -/** - * Created by MarkPerry on 3/07/2015. - */ @RunWith(PropertyTestRunner.class) public class ValidationProperties { diff --git a/quickcheck/src/main/java/fj/data/test/PropertyAssert.java b/quickcheck/src/main/java/fj/data/test/PropertyAssert.java index 00187b15..d37c69a3 100644 --- a/quickcheck/src/main/java/fj/data/test/PropertyAssert.java +++ b/quickcheck/src/main/java/fj/data/test/PropertyAssert.java @@ -5,9 +5,6 @@ import fj.test.Property; import org.junit.Assert; -/** - * Created by MarkPerry on 18/12/2014. - */ public final class PropertyAssert { private PropertyAssert(){} diff --git a/quickcheck/src/test/java/fj/data/test/TestNull.java b/quickcheck/src/test/java/fj/data/test/TestNull.java index fe9dc843..0d547149 100644 --- a/quickcheck/src/test/java/fj/data/test/TestNull.java +++ b/quickcheck/src/test/java/fj/data/test/TestNull.java @@ -8,9 +8,6 @@ import static fj.test.Property.prop; import static fj.test.Property.property; -/** - * Created by MarkPerry on 3/07/2014. - */ public class TestNull { @Test diff --git a/quickcheck/src/test/java/fj/test/TestRand.java b/quickcheck/src/test/java/fj/test/TestRand.java index 1ca7c749..ea2cbce8 100644 --- a/quickcheck/src/test/java/fj/test/TestRand.java +++ b/quickcheck/src/test/java/fj/test/TestRand.java @@ -9,9 +9,6 @@ import static org.junit.Assert.assertTrue; -/** - * Created by MarkPerry on 4/06/2015. - */ public class TestRand { @Test From 8c8663a039959b07daf8c14c9a974dc5bf389960 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 18:50:17 +1000 Subject: [PATCH 790/811] Updated release process --- etc/release-process.txt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/etc/release-process.txt b/etc/release-process.txt index b22ec4e4..3bfb7bbd 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -45,12 +45,10 @@ Setup Artifact Signing ====================== The below text is a summary from https://gist.github.com/phit/bd3c6d156a2fa5f3b1bc15fa94b3256c. -As of 2021-02-12, for Windows download Gpg4win 3.1.15 at https://gpg4win.org/index.html. You need to provide 3 things: -- the public key id -- the path to the secret key ring file for your private key -- the passphrase for your private key +As of 2022-02-11, for Windows download Gpg4win 3.1.16 from https://files.gpg4win.org/. Open a command prompt and run "gpg --gen-key" and follow the prompts. + Get your key id by running: "gpg --list-key" Example output: @@ -68,9 +66,9 @@ sub rsa2048 2017-06-17 [E] [expires: 2019-06-17] In this case we only have one key, 77273D57FA5140E5A91905087A1B92B81840D019 or short* 1840D019 which is basically just the last 8 characters of the long ID. -Export the key using "gpg --export-secret-key > %UserProfile%\secring.gpg" +Export the key using "gpg --export-secret-key >%UserProfile%\secring.gpg" -In %UserProfile%\.gradle\gradle.properties, set the values below: +Create the file %UserProfile%\.gradle\gradle.properties, set the values below: signing.keyId=XXXXXXXX signing.password=mypassword @@ -90,6 +88,7 @@ sub rsa3072 2021-02-12 [E] [expires: 2023-02-12] C:\repos\functionaljava>gpg --keyserver hkp://keyserver.ubuntu.com --send-keys E86A4EC34F25A9CF6118582A7985AAE03F41B2F9 gpg: sending key 7985AAE03F41B2F9 to hkp://keyserver.ubuntu.com + gradle upload (takes about 3 mins) From 3eea643f16a7f98127f7818c900f25a5752c1781 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 20:56:10 +1000 Subject: [PATCH 791/811] Update release doc and Github readme --- README.adoc | 25 +++++++++++++------------ build.gradle | 1 - etc/release-process.txt | 10 ++++------ gradle.properties | 5 +++-- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/README.adoc b/README.adoc index cb53d003..d57b22b4 100644 --- a/README.adoc +++ b/README.adoc @@ -22,8 +22,9 @@ Important URLs for the project are: * Website, http://www.functionaljava.org * Website repository, http://github.com/functionaljava/functionaljava.github.io -* Travis continuous integration build, https://travis-ci.org/functionaljava/functionaljava -* Sonatype Repository, https://oss.sonatype.org/content/groups/public/org/functionaljava/ +* Travis continuous integration build, https://app.travis-ci.com/github/functionaljava/functionaljava +* Sonatype repository, https://oss.sonatype.org/content/groups/public/org/functionaljava/ +* Maven Central repository, https://mvnrepository.com/artifact/org.functionaljava/functionaljava == Downloading @@ -35,12 +36,12 @@ The Functional Java artifact is published to Maven Central using the group `org. * Java 8 specific support (`functionaljava-java8`) * property based testing (`functionaljava-quickcheck` or `functionaljava-quickcheck_1.8` if you use Java 8+) -The latest stable version is `4.8.1`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `4.9`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.8.1" -compile "org.functionaljava:functionaljava-java8:4.8.1" -compile "org.functionaljava:functionaljava-quickcheck:4.8.1" -compile "org.functionaljava:functionaljava-java-core:4.8.1" +compile "org.functionaljava:functionaljava:4.9" +compile "org.functionaljava:functionaljava-java8:4.9" +compile "org.functionaljava:functionaljava-quickcheck:4.9" +compile "org.functionaljava:functionaljava-java-core:4.9" ---- and in Maven: @@ -48,22 +49,22 @@ and in Maven: org.functionaljava functionaljava - 4.8.1 + 4.9 org.functionaljava functionaljava-java8 - 4.8.1 + 4.9 org.functionaljava functionaljava-quickcheck - 4.8.1 + 4.9 org.functionaljava functionaljava-java-core - 4.8.1 + 4.9 ---- @@ -71,7 +72,7 @@ and in Maven: FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 6 bytecode. This requires access to both JDK 6 and 8. The build system requires the environment variables `JAVA6_HOME` and `JAVA8_HOME` to refer to the appropriate directories. -Building is done using Gradle 2.13. In the root directory run: +Building is done using Gradle 6.8.3. In the root directory run: ---- ./gradlew ---- diff --git a/build.gradle b/build.gradle index 1ceb4fb9..cc2e265c 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,6 @@ allprojects { defaultTasks "build" ext { - isSnapshot = true fjBaseVersion = "5.0" snapshotAppendix = "-SNAPSHOT" diff --git a/etc/release-process.txt b/etc/release-process.txt index 3bfb7bbd..e4b35e2d 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -4,13 +4,11 @@ Current Release Process Go through the issues and pull requests and set the Label and Milestone field. Add information to /etc/release-notes/release-notes-.adoc. -Update build.gradle: -* set isSnapshot to false -* set useRetroLambda to true - Update gradle.properties: +* set isSnapshot to false * Set signingEnabled to true + Run the build command: gradlew clean build upload @@ -24,8 +22,8 @@ Login to Sonatype and verify the release: Commit changes Increase the version: -* Edit build.gradle: update isSnapshot to true, increase fjBaseVersion, update fjConsumeVersion, update useRetroLambda. -* Edit gradle.properties: set signingEnabled to false +* Edit build.gradle: increase fjBaseVersion, update fjConsumeVersion. +* Edit gradle.properties: set signingEnabled to false, set isSnapshot to true Commit changes and push. Notes that CI builds using Travis and Jenkins will fail with the release due to lack of configured signing. diff --git a/gradle.properties b/gradle.properties index 1f1f4ed9..1171b13a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,8 @@ +signingEnabled = false +isSnapshot = true + sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signingEnabled = false - org.gradle.parallel = true From ce361b4466565cd4b074c7a11937f804b470bcba Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 20:56:42 +1000 Subject: [PATCH 792/811] Re-added openjdk8 for FJ 5 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a7465305..fa0798a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ sudo: false language: java jdk: - - openjdk10 + - openjdk8 - openjdk11 - openjdk-ea From ba209425860e146c95386e9de314698c71e8e3cf Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 21:05:36 +1000 Subject: [PATCH 793/811] Updated Travis CI link at the top of the readme --- README.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.adoc b/README.adoc index d57b22b4..4ede16b7 100644 --- a/README.adoc +++ b/README.adoc @@ -1,6 +1,6 @@ = Functional Java -image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://travis-ci.org/functionaljava/functionaljava"] +image:https://travis-ci.org/functionaljava/functionaljava.svg?branch=master["Build Status", link="https://app.travis-ci.com/github/functionaljava/functionaljava"] image:https://codecov.io/gh/functionaljava/functionaljava/branch/master/graph/badge.svg["Code Coverage", link="https://codecov.io/gh/functionaljava/functionaljava"] image:https://badges.gitter.im/functionaljava/functionaljava.svg[link="https://gitter.im/functionaljava/functionaljava?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"] @@ -8,7 +8,7 @@ image::http://www.functionaljava.org/img/logo-600x144.png[] Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. -The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are backported with the Retro Lambda library, supporting Java versions 6 to 8. +The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are back ported with the Retro Lambda library, supporting Java versions 6 to 8. Functional Java provides abstractions for the following types: From 80862115da1e0d065b95e394bd517851b314d821 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 21:47:41 +1000 Subject: [PATCH 794/811] Prep for 5.0 release --- build.gradle | 1 + gradle.properties | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index cc2e265c..1e7bf98c 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,7 @@ allprojects { defaultTasks "build" ext { + isSnapshot = false fjBaseVersion = "5.0" snapshotAppendix = "-SNAPSHOT" diff --git a/gradle.properties b/gradle.properties index 1171b13a..d18e6a6f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,5 @@ -signingEnabled = false -isSnapshot = true +signingEnabled = true sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd From a4ff75ed351c2e0996399d2b059a76fa158317fc Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 11 Feb 2022 22:11:47 +1000 Subject: [PATCH 795/811] Prep for FJ 5.1 --- build.gradle | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1e7bf98c..70485ec9 100644 --- a/build.gradle +++ b/build.gradle @@ -41,8 +41,8 @@ allprojects { defaultTasks "build" ext { - isSnapshot = false - fjBaseVersion = "5.0" + isSnapshot = true + fjBaseVersion = "5.1" snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") diff --git a/gradle.properties b/gradle.properties index d18e6a6f..50202eda 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ -signingEnabled = true +signingEnabled = false sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd From 56a9a51594e1a4030ff27f4db345e7b736489c8d Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sun, 13 Feb 2022 23:14:27 +1000 Subject: [PATCH 796/811] Added signing parameters to the properties file --- gradle.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gradle.properties b/gradle.properties index 50202eda..dde4512b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,4 +4,8 @@ signingEnabled = false sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd +signing.keyId= +signing.password= +signing.secretKeyRingFile= + org.gradle.parallel = true From 3c254bb3b6840512f896bb3348e3e5401837929e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Feb 2022 20:46:29 +1000 Subject: [PATCH 797/811] Fix series/5.x build. Removed extra jdk's for series 5.x. --- .travis.yml | 11 ----------- gradle.properties | 6 +++--- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa0798a4..bc3fc57f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,24 +5,13 @@ language: java jdk: - openjdk8 - - openjdk11 - - openjdk-ea matrix: fast_finish: true include: - - jdk: openjdk12 - script: - - ./gradlew build coverage -s -i - after_success: - - bash <(curl -s https://codecov.io/bash) - - '[ "$TRAVIS_BRANCH" = "series/5.x" -a "$TRAVIS_PULL_REQUEST" = "false" -a -z "$TRAVIS_TAG" ] - && ./gradlew uploadArchives' allow_failures: - - jdk: openjdk10 - - jdk: openjdk-ea script: - ./gradlew clean test diff --git a/gradle.properties b/gradle.properties index dde4512b..6ee9a768 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,8 +4,8 @@ signingEnabled = false sonatypeUsername = incorrectUser sonatypePassword = incorrectPwd -signing.keyId= -signing.password= -signing.secretKeyRingFile= +#signing.keyId= +#signing.password= +#signing.secretKeyRingFile= org.gradle.parallel = true From 474a49ca5b7760cd79243ca4b428ea7ddef0b72e Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Feb 2022 22:18:36 +1000 Subject: [PATCH 798/811] Upgrade Junit to 4.13.2, fixed deprecations. Update gradle-versions-plugin, junit-vintage-engine --- build.gradle | 8 ++++---- core/src/test/java/fj/ClassTest.java | 2 +- core/src/test/java/fj/DigitTest.java | 2 +- core/src/test/java/fj/MonoidTest.java | 2 +- core/src/test/java/fj/TryTest.java | 2 +- core/src/test/java/fj/control/db/TestDbState.java | 2 +- core/src/test/java/fj/data/ArrayTest.java | 2 +- core/src/test/java/fj/data/DListTest.java | 2 +- core/src/test/java/fj/data/LazyStringTest.java | 2 +- core/src/test/java/fj/data/ListBufferTest.java | 2 +- core/src/test/java/fj/data/SetTest.java | 2 +- core/src/test/java/fj/data/StreamTest.java | 2 +- core/src/test/java/fj/data/TreeMapTest.java | 2 +- core/src/test/java/fj/data/TreeTest.java | 2 +- core/src/test/java/fj/data/TreeZipperTest.java | 2 +- core/src/test/java/fj/data/ValidationTest.java | 2 +- core/src/test/java/fj/data/ZipperTest.java | 2 +- core/src/test/java/fj/data/hamt/HamtTest.java | 2 +- core/src/test/java/fj/data/optic/IsoTest.java | 2 +- core/src/test/java/fj/data/optic/LensTest.java | 2 +- core/src/test/java/fj/data/optic/OptionalTest.java | 2 +- core/src/test/java/fj/data/optic/PrismTest.java | 2 +- core/src/test/java/fj/data/optic/TraversalTest.java | 2 +- core/src/test/java/fj/data/vector/VTest.java | 2 +- core/src/test/java/fj/function/VisitorTest.java | 2 +- props-core/src/test/java/fj/data/ReaderTest.java | 2 +- .../src/test/java/fj/data/fingertrees/FingerTreeTest.java | 3 +-- .../java/fj/data/properties/PriorityQueueProperties.java | 2 +- 28 files changed, 31 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index 70485ec9..93dafa67 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { } dependencies { - classpath "com.github.ben-manes:gradle-versions-plugin:0.27.0" + classpath "com.github.ben-manes:gradle-versions-plugin:0.36.0" classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:5.3.0" } @@ -46,7 +46,7 @@ allprojects { snapshotAppendix = "-SNAPSHOT" fjVersion = fjBaseVersion + (isSnapshot ? snapshotAppendix : "") - fjConsumeVersion = "4.9" + fjConsumeVersion = "5.0" signModule = false @@ -66,8 +66,8 @@ allprojects { sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl primaryEmail = "functionaljava@googlegroups.com" - junitCompile = "junit:junit:4.12" - junitRuntime = "org.junit.vintage:junit-vintage-engine:5.5.2" + junitCompile = "junit:junit:4.13.2" + junitRuntime = "org.junit.vintage:junit-vintage-engine:5.8.2" displayCompilerWarnings = true generateTestReports = false diff --git a/core/src/test/java/fj/ClassTest.java b/core/src/test/java/fj/ClassTest.java index 2959e351..dfbc7f00 100644 --- a/core/src/test/java/fj/ClassTest.java +++ b/core/src/test/java/fj/ClassTest.java @@ -11,7 +11,7 @@ import java.util.Iterator; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class ClassTest { @Test diff --git a/core/src/test/java/fj/DigitTest.java b/core/src/test/java/fj/DigitTest.java index 9fc98d4c..13169aca 100644 --- a/core/src/test/java/fj/DigitTest.java +++ b/core/src/test/java/fj/DigitTest.java @@ -5,7 +5,7 @@ import static fj.data.Array.range; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class DigitTest { @Test diff --git a/core/src/test/java/fj/MonoidTest.java b/core/src/test/java/fj/MonoidTest.java index 1156e729..68457f09 100644 --- a/core/src/test/java/fj/MonoidTest.java +++ b/core/src/test/java/fj/MonoidTest.java @@ -8,7 +8,7 @@ import static fj.data.Option.some; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class MonoidTest { diff --git a/core/src/test/java/fj/TryTest.java b/core/src/test/java/fj/TryTest.java index bd94e986..46fb2dd3 100644 --- a/core/src/test/java/fj/TryTest.java +++ b/core/src/test/java/fj/TryTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class TryTest { diff --git a/core/src/test/java/fj/control/db/TestDbState.java b/core/src/test/java/fj/control/db/TestDbState.java index 188eae3d..2a942e1a 100644 --- a/core/src/test/java/fj/control/db/TestDbState.java +++ b/core/src/test/java/fj/control/db/TestDbState.java @@ -9,7 +9,7 @@ import java.sql.*; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class TestDbState { @Test diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java index 5713e5c3..e686a02b 100644 --- a/core/src/test/java/fj/data/ArrayTest.java +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -5,7 +5,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class ArrayTest { diff --git a/core/src/test/java/fj/data/DListTest.java b/core/src/test/java/fj/data/DListTest.java index 6846ca2d..48c0c2fe 100644 --- a/core/src/test/java/fj/data/DListTest.java +++ b/core/src/test/java/fj/data/DListTest.java @@ -4,7 +4,7 @@ import static fj.data.DList.*; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class DListTest { @Test diff --git a/core/src/test/java/fj/data/LazyStringTest.java b/core/src/test/java/fj/data/LazyStringTest.java index 1adef2bd..14a88c14 100644 --- a/core/src/test/java/fj/data/LazyStringTest.java +++ b/core/src/test/java/fj/data/LazyStringTest.java @@ -4,7 +4,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class LazyStringTest { diff --git a/core/src/test/java/fj/data/ListBufferTest.java b/core/src/test/java/fj/data/ListBufferTest.java index f2ed8286..6b16f1ca 100644 --- a/core/src/test/java/fj/data/ListBufferTest.java +++ b/core/src/test/java/fj/data/ListBufferTest.java @@ -3,7 +3,7 @@ import org.junit.Test; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class ListBufferTest { diff --git a/core/src/test/java/fj/data/SetTest.java b/core/src/test/java/fj/data/SetTest.java index ae65b687..e30d166a 100644 --- a/core/src/test/java/fj/data/SetTest.java +++ b/core/src/test/java/fj/data/SetTest.java @@ -6,7 +6,7 @@ import static fj.data.Option.some; import static fj.Ord.intOrd; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class SetTest { diff --git a/core/src/test/java/fj/data/StreamTest.java b/core/src/test/java/fj/data/StreamTest.java index f320f27a..febd4567 100644 --- a/core/src/test/java/fj/data/StreamTest.java +++ b/core/src/test/java/fj/data/StreamTest.java @@ -36,7 +36,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class StreamTest { diff --git a/core/src/test/java/fj/data/TreeMapTest.java b/core/src/test/java/fj/data/TreeMapTest.java index 77352989..051f0773 100644 --- a/core/src/test/java/fj/data/TreeMapTest.java +++ b/core/src/test/java/fj/data/TreeMapTest.java @@ -16,7 +16,7 @@ import static fj.data.TreeMap.iterableTreeMap; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; public class TreeMapTest { diff --git a/core/src/test/java/fj/data/TreeTest.java b/core/src/test/java/fj/data/TreeTest.java index fd43c852..a6028f37 100644 --- a/core/src/test/java/fj/data/TreeTest.java +++ b/core/src/test/java/fj/data/TreeTest.java @@ -4,7 +4,7 @@ import static fj.data.Tree.leaf; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class TreeTest { diff --git a/core/src/test/java/fj/data/TreeZipperTest.java b/core/src/test/java/fj/data/TreeZipperTest.java index c52f4111..c2549963 100644 --- a/core/src/test/java/fj/data/TreeZipperTest.java +++ b/core/src/test/java/fj/data/TreeZipperTest.java @@ -4,7 +4,7 @@ import static fj.data.Option.none; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class TreeZipperTest { @Test diff --git a/core/src/test/java/fj/data/ValidationTest.java b/core/src/test/java/fj/data/ValidationTest.java index 37a51bcc..4505499c 100644 --- a/core/src/test/java/fj/data/ValidationTest.java +++ b/core/src/test/java/fj/data/ValidationTest.java @@ -37,7 +37,7 @@ import static fj.data.Validation.*; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class ValidationTest { diff --git a/core/src/test/java/fj/data/ZipperTest.java b/core/src/test/java/fj/data/ZipperTest.java index 51c7b4ea..78d837aa 100644 --- a/core/src/test/java/fj/data/ZipperTest.java +++ b/core/src/test/java/fj/data/ZipperTest.java @@ -3,7 +3,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class ZipperTest { @Test diff --git a/core/src/test/java/fj/data/hamt/HamtTest.java b/core/src/test/java/fj/data/hamt/HamtTest.java index 1e601f24..19a22411 100644 --- a/core/src/test/java/fj/data/hamt/HamtTest.java +++ b/core/src/test/java/fj/data/hamt/HamtTest.java @@ -12,7 +12,7 @@ import static fj.P.p; import static fj.data.List.list; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author Mark Perry diff --git a/core/src/test/java/fj/data/optic/IsoTest.java b/core/src/test/java/fj/data/optic/IsoTest.java index 6cace533..7aace4d8 100644 --- a/core/src/test/java/fj/data/optic/IsoTest.java +++ b/core/src/test/java/fj/data/optic/IsoTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class IsoTest { @Test diff --git a/core/src/test/java/fj/data/optic/LensTest.java b/core/src/test/java/fj/data/optic/LensTest.java index d78fa0d0..60513651 100644 --- a/core/src/test/java/fj/data/optic/LensTest.java +++ b/core/src/test/java/fj/data/optic/LensTest.java @@ -4,7 +4,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class LensTest { @Test diff --git a/core/src/test/java/fj/data/optic/OptionalTest.java b/core/src/test/java/fj/data/optic/OptionalTest.java index 07c3f79a..5bea2864 100644 --- a/core/src/test/java/fj/data/optic/OptionalTest.java +++ b/core/src/test/java/fj/data/optic/OptionalTest.java @@ -4,7 +4,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class OptionalTest { @Test diff --git a/core/src/test/java/fj/data/optic/PrismTest.java b/core/src/test/java/fj/data/optic/PrismTest.java index da128d72..ce6dddb4 100644 --- a/core/src/test/java/fj/data/optic/PrismTest.java +++ b/core/src/test/java/fj/data/optic/PrismTest.java @@ -4,7 +4,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class PrismTest { @Test diff --git a/core/src/test/java/fj/data/optic/TraversalTest.java b/core/src/test/java/fj/data/optic/TraversalTest.java index cadd6ccf..9cfc25cc 100644 --- a/core/src/test/java/fj/data/optic/TraversalTest.java +++ b/core/src/test/java/fj/data/optic/TraversalTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class TraversalTest { @Test diff --git a/core/src/test/java/fj/data/vector/VTest.java b/core/src/test/java/fj/data/vector/VTest.java index 9a3709ac..8dabd66e 100644 --- a/core/src/test/java/fj/data/vector/VTest.java +++ b/core/src/test/java/fj/data/vector/VTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class VTest { @Test diff --git a/core/src/test/java/fj/function/VisitorTest.java b/core/src/test/java/fj/function/VisitorTest.java index 54efcf24..da92a4bb 100644 --- a/core/src/test/java/fj/function/VisitorTest.java +++ b/core/src/test/java/fj/function/VisitorTest.java @@ -11,7 +11,7 @@ import static fj.data.Option.some; import static fj.function.Visitor.*; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class VisitorTest { @Test diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index accc3394..4817e41c 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -10,7 +10,7 @@ import static fj.test.Property.prop; import static fj.test.Property.property; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; public class ReaderTest { diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index a26fdc89..7f02288c 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -8,10 +8,9 @@ import org.junit.Test; import static fj.Monoid.intAdditionMonoid; -import static fj.Monoid.intMinMonoid; import static fj.data.fingertrees.FingerTree.measured; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; public class FingerTreeTest { diff --git a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java index c2e46eca..5460bfdf 100644 --- a/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java +++ b/props-core/src/test/java/fj/data/properties/PriorityQueueProperties.java @@ -24,7 +24,7 @@ import static fj.test.Property.prop; import static fj.test.Property.property; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; @RunWith(PropertyTestRunner.class) @CheckParams(maxSize = 100) From c4ebbb541a40bcbf8a17e6ef1f1cae7a3a463ff4 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Feb 2022 22:22:45 +1000 Subject: [PATCH 799/811] Updated bnd to 6.1.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 93dafa67..3b627e85 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { dependencies { classpath "com.github.ben-manes:gradle-versions-plugin:0.36.0" - classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:5.3.0" + classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:6.1.0" } wrapper { From df6e6f8ea2fee836794c365f93fc8839388fd02b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Feb 2022 22:49:54 +1000 Subject: [PATCH 800/811] Updated H2 lib to 2.1.210. Updated deprecated Assert.assertThat to MatcherAssert.assertThat --- core/build.gradle | 2 +- core/src/test/java/fj/FFunctionsTest.java | 2 +- core/src/test/java/fj/OrderingTest.java | 2 +- core/src/test/java/fj/PTest.java | 2 +- core/src/test/java/fj/TryEffectTest.java | 2 +- .../test/java/fj/control/parallel/StrategyTest.java | 3 ++- core/src/test/java/fj/data/BooleansTest.java | 3 ++- core/src/test/java/fj/data/IOFunctionsTest.java | 11 ++++++----- core/src/test/java/fj/data/ListTest.java | 5 ++++- core/src/test/java/fj/data/List_Traverse_Tests.java | 2 +- core/src/test/java/fj/function/DoublesTest.java | 5 ++++- core/src/test/java/fj/function/IntegersTest.java | 5 ++++- core/src/test/java/fj/function/LongsTest.java | 5 ++++- core/src/test/java/fj/function/StringsTest.java | 2 +- core/src/test/java/fj/parser/ParserTest.java | 2 +- 15 files changed, 34 insertions(+), 19 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index cbdad60b..9ee293a9 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,7 +8,7 @@ archivesBaseName = project.projectName dependencies { testCompile junitCompile testRuntime junitRuntime - testCompile 'com.h2database:h2:1.4.199' + testCompile 'com.h2database:h2:2.1.210' testCompile 'commons-dbutils:commons-dbutils:1.7' } diff --git a/core/src/test/java/fj/FFunctionsTest.java b/core/src/test/java/fj/FFunctionsTest.java index b235ff67..4f01a0db 100644 --- a/core/src/test/java/fj/FFunctionsTest.java +++ b/core/src/test/java/fj/FFunctionsTest.java @@ -4,7 +4,7 @@ import fj.data.TreeZipper; import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; public class FFunctionsTest { diff --git a/core/src/test/java/fj/OrderingTest.java b/core/src/test/java/fj/OrderingTest.java index 9b980e67..640bc1d3 100644 --- a/core/src/test/java/fj/OrderingTest.java +++ b/core/src/test/java/fj/OrderingTest.java @@ -8,7 +8,7 @@ import static fj.Ordering.GT; import static fj.Ordering.LT; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; public class OrderingTest { diff --git a/core/src/test/java/fj/PTest.java b/core/src/test/java/fj/PTest.java index 2a97303f..00220f9d 100644 --- a/core/src/test/java/fj/PTest.java +++ b/core/src/test/java/fj/PTest.java @@ -4,7 +4,7 @@ import static fj.Function.identity; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class PTest { @Test diff --git a/core/src/test/java/fj/TryEffectTest.java b/core/src/test/java/fj/TryEffectTest.java index ea92b8f2..6fd46fd1 100644 --- a/core/src/test/java/fj/TryEffectTest.java +++ b/core/src/test/java/fj/TryEffectTest.java @@ -5,7 +5,7 @@ import fj.function.TryEffect1; import org.junit.Test; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; public class TryEffectTest { diff --git a/core/src/test/java/fj/control/parallel/StrategyTest.java b/core/src/test/java/fj/control/parallel/StrategyTest.java index 0c605829..b4d21320 100644 --- a/core/src/test/java/fj/control/parallel/StrategyTest.java +++ b/core/src/test/java/fj/control/parallel/StrategyTest.java @@ -16,7 +16,8 @@ import static fj.control.parallel.Strategy.*; import static fj.data.Stream.range; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; + public class StrategyTest { diff --git a/core/src/test/java/fj/data/BooleansTest.java b/core/src/test/java/fj/data/BooleansTest.java index 84f7676f..61325df0 100644 --- a/core/src/test/java/fj/data/BooleansTest.java +++ b/core/src/test/java/fj/data/BooleansTest.java @@ -9,6 +9,7 @@ import static fj.data.List.list; import static fj.function.Booleans.isnot; import static org.hamcrest.core.Is.is; +import static org.hamcrest.MatcherAssert.assertThat; public class BooleansTest { @@ -70,7 +71,7 @@ public void testIsNot(){ F f1 = a -> a == 4; List result = list("some", "come", "done!").filter(isnot(String::length, f1)); - Assert.assertThat(result.length(), is(1)); + assertThat(result.length(), is(1)); Assert.assertEquals(result, list("done!")); } diff --git a/core/src/test/java/fj/data/IOFunctionsTest.java b/core/src/test/java/fj/data/IOFunctionsTest.java index adad0d11..8ae18b1a 100644 --- a/core/src/test/java/fj/data/IOFunctionsTest.java +++ b/core/src/test/java/fj/data/IOFunctionsTest.java @@ -12,7 +12,8 @@ import static fj.data.Stream.cons; import static fj.data.Stream.nil_; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; public class IOFunctionsTest { @@ -33,8 +34,8 @@ public void close() { r -> () -> new BufferedReader(r).readLine() ); - Assert.assertThat(bracketed.run(), is("Read OK")); - Assert.assertThat(closed.get(), is(true)); + assertThat(bracketed.run(), is("Read OK")); + assertThat(closed.get(), is(true)); } @Test @@ -59,9 +60,9 @@ public void close() { bracketed.run(); fail("Exception expected"); } catch (IllegalArgumentException e) { - Assert.assertThat(e.getMessage(), is("OoO")); + assertThat(e.getMessage(), is("OoO")); } - Assert.assertThat(closed.get(), is(true)); + assertThat(closed.get(), is(true)); } @Test diff --git a/core/src/test/java/fj/data/ListTest.java b/core/src/test/java/fj/data/ListTest.java index 9f09de0f..720157e8 100644 --- a/core/src/test/java/fj/data/ListTest.java +++ b/core/src/test/java/fj/data/ListTest.java @@ -30,7 +30,10 @@ import static fj.data.Validation.fail; import static fj.data.Validation.*; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.*; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; public class ListTest { diff --git a/core/src/test/java/fj/data/List_Traverse_Tests.java b/core/src/test/java/fj/data/List_Traverse_Tests.java index 5b7c0d19..ad925847 100644 --- a/core/src/test/java/fj/data/List_Traverse_Tests.java +++ b/core/src/test/java/fj/data/List_Traverse_Tests.java @@ -7,7 +7,7 @@ import static fj.data.List.list; import static fj.data.Option.some; import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; +import static org.hamcrest.MatcherAssert.assertThat; public class List_Traverse_Tests { diff --git a/core/src/test/java/fj/function/DoublesTest.java b/core/src/test/java/fj/function/DoublesTest.java index 6ba98fa2..09ca4bbe 100644 --- a/core/src/test/java/fj/function/DoublesTest.java +++ b/core/src/test/java/fj/function/DoublesTest.java @@ -1,6 +1,9 @@ package fj.function; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import fj.F; import org.junit.Test; diff --git a/core/src/test/java/fj/function/IntegersTest.java b/core/src/test/java/fj/function/IntegersTest.java index 985afba9..c07197af 100644 --- a/core/src/test/java/fj/function/IntegersTest.java +++ b/core/src/test/java/fj/function/IntegersTest.java @@ -8,7 +8,10 @@ import static fj.data.List.list; import static fj.data.Option.none; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; +import static org.junit.Assert.assertTrue; public class IntegersTest { diff --git a/core/src/test/java/fj/function/LongsTest.java b/core/src/test/java/fj/function/LongsTest.java index d59fc07c..196da20f 100644 --- a/core/src/test/java/fj/function/LongsTest.java +++ b/core/src/test/java/fj/function/LongsTest.java @@ -8,7 +8,10 @@ import static fj.data.List.list; import static fj.data.Option.none; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + public class LongsTest { diff --git a/core/src/test/java/fj/function/StringsTest.java b/core/src/test/java/fj/function/StringsTest.java index c13e1b81..79cb8a3d 100644 --- a/core/src/test/java/fj/function/StringsTest.java +++ b/core/src/test/java/fj/function/StringsTest.java @@ -5,7 +5,7 @@ import static fj.Function.compose; import static fj.function.Strings.*; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; public class StringsTest { diff --git a/core/src/test/java/fj/parser/ParserTest.java b/core/src/test/java/fj/parser/ParserTest.java index a3f623f5..f2664a1f 100644 --- a/core/src/test/java/fj/parser/ParserTest.java +++ b/core/src/test/java/fj/parser/ParserTest.java @@ -8,7 +8,7 @@ import static fj.parser.Result.result; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.*; +import static org.hamcrest.MatcherAssert.assertThat; public class ParserTest { @Test From 5ecd37c0b30b383ed8788b62190b4efce6b0feab Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 14 Feb 2022 23:54:44 +1000 Subject: [PATCH 801/811] Upgrade Gradle to 7.3, jacoco to 0.8.7. Upgrade plugin from java to java-library, maven to maven-publish --- build.gradle | 19 ++- consume/build.gradle | 6 +- core/build.gradle | 14 +- .../fj/control/parallel/StrategyTest.java | 1 - core/src/test/java/fj/data/ArrayTest.java | 1 + core/src/test/java/fj/data/BooleansTest.java | 1 + core/src/test/java/fj/data/DListTest.java | 1 + .../src/test/java/fj/data/LazyStringTest.java | 1 + .../src/test/java/fj/data/ListBufferTest.java | 1 + .../java/fj/data/List_Traverse_Tests.java | 1 + core/src/test/java/fj/data/hamt/HamtTest.java | 1 + core/src/test/java/fj/data/optic/IsoTest.java | 1 + .../src/test/java/fj/data/optic/LensTest.java | 1 + .../test/java/fj/data/optic/OptionalTest.java | 1 + core/src/test/java/fj/data/vector/VTest.java | 1 + .../test/java/fj/function/DoublesTest.java | 2 +- .../test/java/fj/function/StringsTest.java | 4 +- demo/build.gradle | 8 +- gradle/wrapper/gradle-wrapper.properties | 2 +- java-core/build.gradle | 11 +- lib.gradle | 138 +++++++++++++----- performance/build.gradle | 6 +- props-core-scalacheck/build.gradle | 12 +- props-core/build.gradle | 6 +- .../src/test/java/fj/data/ReaderTest.java | 1 + .../fj/data/fingertrees/FingerTreeTest.java | 3 +- quickcheck/build.gradle | 9 +- 27 files changed, 173 insertions(+), 80 deletions(-) diff --git a/build.gradle b/build.gradle index 3b627e85..9556b473 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { } wrapper { - gradleVersion = "6.8.3" + gradleVersion = "7.3" distributionType = Wrapper.DistributionType.ALL } } @@ -35,7 +35,7 @@ allprojects { apply plugin: "jacoco" jacoco { - toolVersion = "0.8.2" + toolVersion = "0.8.7" } defaultTasks "build" @@ -49,6 +49,7 @@ allprojects { fjConsumeVersion = "5.0" signModule = false + uploadModule = false projectTitle = "Functional Java" projectName = "functionaljava" @@ -58,12 +59,20 @@ allprojects { projectUrl = "http://functionaljava.org/" scmUrl = "git://github.com/functionaljava/functionaljava.git" scmGitFile = "scm:git@github.com:functionaljava/functionaljava.git" + scmSshGitFile = "scm:git:ssh://git@github.com/functionaljava/functionaljava.git" + licenseUrl = "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" + licenseName = "The BSD3 License" + + issueUrl = "https://github.com/functionaljava/functionaljava/issues" + githubUrl = "https://github.com/functionaljava/functionaljava" sonatypeBaseUrl = "https://oss.sonatype.org" sonatypeSnapshotUrl = "$sonatypeBaseUrl/content/repositories/snapshots/" sonatypeRepositoryUrl = "$sonatypeBaseUrl/content/groups/public" sonatypeReleaseUrl = "$sonatypeBaseUrl/service/local/staging/deploy/maven2/" + sonatypeUploadUrl = isSnapshot ? sonatypeSnapshotUrl : sonatypeReleaseUrl + primaryEmail = "functionaljava@googlegroups.com" junitCompile = "junit:junit:4.13.2" @@ -94,7 +103,7 @@ subprojects { } apply from: "$rootDir/lib.gradle" - apply plugin: "java" + apply plugin: "java-library" apply plugin: "eclipse" repositories { @@ -139,7 +148,7 @@ task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { configure(subprojects.findAll { it.name != "props-core" }) { - apply plugin: "maven" + apply plugin: "maven-publish" apply plugin: "signing" apply plugin: "biz.aQute.bnd.builder" sourceCompatibility = "1.8" @@ -164,7 +173,7 @@ configure(subprojects.findAll { it.name != "props-core" }) { } jar { - version project.fjVersion + archiveVersion = project.fjVersion bnd ( 'Bundle-Name': 'Functional Java', 'Signature-Version': project.fjVersion, diff --git a/consume/build.gradle b/consume/build.gradle index 370ebfbf..45dadefb 100644 --- a/consume/build.gradle +++ b/consume/build.gradle @@ -2,8 +2,8 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { - compile("$group:$projectName:$fjConsumeVersion") + api "$group:$projectName:$fjConsumeVersion" - testCompile junitCompile - testRuntime junitRuntime + testImplementation junitCompile + testRuntimeOnly junitRuntime } diff --git a/core/build.gradle b/core/build.gradle index 9ee293a9..282ec191 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,18 +1,18 @@ ext { signModule = true + uploadModule = true + } archivesBaseName = project.projectName dependencies { - testCompile junitCompile - testRuntime junitRuntime - testCompile 'com.h2database:h2:2.1.210' - testCompile 'commons-dbutils:commons-dbutils:1.7' + testImplementation junitCompile + testRuntimeOnly junitRuntime + testImplementation 'com.h2database:h2:2.1.210' + testImplementation 'commons-dbutils:commons-dbutils:1.7' } performSigning(signingEnabled, signModule) -configureUpload(signingEnabled, signModule) - -uploadArchives.enabled = true +configureUpload(signingEnabled, signModule, uploadModule) diff --git a/core/src/test/java/fj/control/parallel/StrategyTest.java b/core/src/test/java/fj/control/parallel/StrategyTest.java index b4d21320..1f5e7bba 100644 --- a/core/src/test/java/fj/control/parallel/StrategyTest.java +++ b/core/src/test/java/fj/control/parallel/StrategyTest.java @@ -18,7 +18,6 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; - public class StrategyTest { @Test diff --git a/core/src/test/java/fj/data/ArrayTest.java b/core/src/test/java/fj/data/ArrayTest.java index e686a02b..11683fbf 100644 --- a/core/src/test/java/fj/data/ArrayTest.java +++ b/core/src/test/java/fj/data/ArrayTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; + public class ArrayTest { @Test diff --git a/core/src/test/java/fj/data/BooleansTest.java b/core/src/test/java/fj/data/BooleansTest.java index 61325df0..e5dbeb12 100644 --- a/core/src/test/java/fj/data/BooleansTest.java +++ b/core/src/test/java/fj/data/BooleansTest.java @@ -11,6 +11,7 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; + public class BooleansTest { @Test diff --git a/core/src/test/java/fj/data/DListTest.java b/core/src/test/java/fj/data/DListTest.java index 48c0c2fe..77f4db6c 100644 --- a/core/src/test/java/fj/data/DListTest.java +++ b/core/src/test/java/fj/data/DListTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; + public class DListTest { @Test public void testConsSnoc() { diff --git a/core/src/test/java/fj/data/LazyStringTest.java b/core/src/test/java/fj/data/LazyStringTest.java index 14a88c14..060c5394 100644 --- a/core/src/test/java/fj/data/LazyStringTest.java +++ b/core/src/test/java/fj/data/LazyStringTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; + public class LazyStringTest { @Test diff --git a/core/src/test/java/fj/data/ListBufferTest.java b/core/src/test/java/fj/data/ListBufferTest.java index 6b16f1ca..784b9510 100644 --- a/core/src/test/java/fj/data/ListBufferTest.java +++ b/core/src/test/java/fj/data/ListBufferTest.java @@ -5,6 +5,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; + public class ListBufferTest { @Test diff --git a/core/src/test/java/fj/data/List_Traverse_Tests.java b/core/src/test/java/fj/data/List_Traverse_Tests.java index ad925847..eee5752d 100644 --- a/core/src/test/java/fj/data/List_Traverse_Tests.java +++ b/core/src/test/java/fj/data/List_Traverse_Tests.java @@ -9,6 +9,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; + public class List_Traverse_Tests { @Test diff --git a/core/src/test/java/fj/data/hamt/HamtTest.java b/core/src/test/java/fj/data/hamt/HamtTest.java index 19a22411..ce901e6e 100644 --- a/core/src/test/java/fj/data/hamt/HamtTest.java +++ b/core/src/test/java/fj/data/hamt/HamtTest.java @@ -14,6 +14,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; + /** * @author Mark Perry */ diff --git a/core/src/test/java/fj/data/optic/IsoTest.java b/core/src/test/java/fj/data/optic/IsoTest.java index 7aace4d8..f9559d3f 100644 --- a/core/src/test/java/fj/data/optic/IsoTest.java +++ b/core/src/test/java/fj/data/optic/IsoTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; + public class IsoTest { @Test public void testIso() { diff --git a/core/src/test/java/fj/data/optic/LensTest.java b/core/src/test/java/fj/data/optic/LensTest.java index 60513651..98be7fca 100644 --- a/core/src/test/java/fj/data/optic/LensTest.java +++ b/core/src/test/java/fj/data/optic/LensTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; + public class LensTest { @Test public void testLensPersonGet() { diff --git a/core/src/test/java/fj/data/optic/OptionalTest.java b/core/src/test/java/fj/data/optic/OptionalTest.java index 5bea2864..7fddb31b 100644 --- a/core/src/test/java/fj/data/optic/OptionalTest.java +++ b/core/src/test/java/fj/data/optic/OptionalTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.MatcherAssert.assertThat; + public class OptionalTest { @Test public void testOptionalSome() { diff --git a/core/src/test/java/fj/data/vector/VTest.java b/core/src/test/java/fj/data/vector/VTest.java index 8dabd66e..34f8686c 100644 --- a/core/src/test/java/fj/data/vector/VTest.java +++ b/core/src/test/java/fj/data/vector/VTest.java @@ -7,6 +7,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; + public class VTest { @Test public void testVectorUp(){ diff --git a/core/src/test/java/fj/function/DoublesTest.java b/core/src/test/java/fj/function/DoublesTest.java index 09ca4bbe..53b74e52 100644 --- a/core/src/test/java/fj/function/DoublesTest.java +++ b/core/src/test/java/fj/function/DoublesTest.java @@ -1,7 +1,6 @@ package fj.function; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -12,6 +11,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import static org.junit.Assert.assertTrue; import static org.hamcrest.core.Is.is; import static fj.data.List.list; diff --git a/core/src/test/java/fj/function/StringsTest.java b/core/src/test/java/fj/function/StringsTest.java index 79cb8a3d..db20fd68 100644 --- a/core/src/test/java/fj/function/StringsTest.java +++ b/core/src/test/java/fj/function/StringsTest.java @@ -5,8 +5,10 @@ import static fj.Function.compose; import static fj.function.Strings.*; -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; import static org.hamcrest.core.Is.is; +import static org.hamcrest.MatcherAssert.assertThat; + public class StringsTest { @Test diff --git a/demo/build.gradle b/demo/build.gradle index f19e765f..87bf7a5c 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -6,10 +6,10 @@ mainClassName = "fj.demo.euler.Problem2" archivesBaseName = "${project.projectName}-${project.name}" dependencies { - compile project(":core") - compile project(":quickcheck") - testCompile junitCompile - testRuntime junitRuntime + api project(":core") + api project(":quickcheck") + testImplementation junitCompile + testImplementation junitRuntime } test { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8cf6eb5a..fbce071a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/java-core/build.gradle b/java-core/build.gradle index e7b40bb9..f6a6146a 100644 --- a/java-core/build.gradle +++ b/java-core/build.gradle @@ -3,16 +3,15 @@ archivesBaseName = "${project.projectName}-${project.name}" ext { signModule = true + uploadModule = true } dependencies { - compile project(":core") - testCompile junitCompile - testRuntime junitRuntime + api project(":core") + testImplementation junitCompile + testRuntimeOnly junitRuntime } performSigning(signingEnabled, signModule) -configureUpload(signingEnabled, signModule) +configureUpload(signingEnabled, signModule, uploadModule) - -uploadArchives.enabled = true diff --git a/lib.gradle b/lib.gradle index 39ce7a7e..5ff91f01 100644 --- a/lib.gradle +++ b/lib.gradle @@ -20,7 +20,7 @@ String findJavaCommand(String command) { Boolean doSigning(String signingAllowed, Boolean doModule) { def b = signingAllowed.trim() == "true" && doModule -// println("signModule: ${project.name} signingEnabled: $signingAllowed module: $doModule") +// println("signModule: ${project.name} signingAllowed: $signingAllowed doModule: $doModule") b } @@ -31,50 +31,122 @@ void performSigning(String signingAllowed, Boolean doModule) { } } -void configureUpload(String signingEnabled, Boolean signModule) { +def customisePom(pom, gradleProject) { + pom.withXml { + def root = asNode() - uploadArchives { - enabled = false - repositories { - mavenDeployer { - if (doSigning(signingEnabled, signModule)) { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - } + // add all items necessary for maven central publication + root.children().last() + { + resolveStrategy = Closure.DELEGATE_FIRST - repository(url: sonatypeUploadUrl) { - authentication(userName: sonatypeUsername, password: sonatypePassword) + name project.pomProjectName + description project.projectDescription + url project.projectUrl + organization { + name project.pomOrganisation + url project.projectUrl + } + issueManagement { + system 'GitHub' + url project.issueUrl + } + licenses { + license { + name project.licenseName + url project.licenseUrl + distribution 'repo' } - pom { - groupId = project.group - project { - name pomProjectName - packaging 'jar' - description projectDescription - url projectUrl - organization { - name pomOrganisation - url projectUrl - } - scm { - url scmUrl - } - licenses { - license { - name "The BSD3 License" - url "https://github.com/functionaljava/functionaljava/blob/master/etc/LICENCE" - distribution 'repo' + } + scm { + url project.githubUrl + connection project.scmGitFile + developerConnection project.scmSshGitFile + } + } + } +} + + +void configureUpload(String signingEnabled, Boolean signModule, Boolean uploadModule) { + + if (uploadModule) { + + publishing { + + publications { + + mavenJava(MavenPublication) { + groupId project.group + artifactId project.name + version project.version + + from components.java + + customisePom(pom, rootProject) + + artifact sourcesJar + artifact javadocJar + + if (doSigning(signingEnabled, signModule)) { + // sign the pom + pom.withXml { + def pomFile = file("${project.buildDir}/generated-pom.xml.asc") + writeTo(pomFile) + def pomAscFile = signing.sign(pomFile).signatureFiles[0] + artifact(pomAscFile) { + classifier = null + extension = 'pom.asc' } + pomFile.delete() } - developers { - developer { - email primaryEmail + + // sign the artifacts + project.tasks.signArchives.signatureFiles.each { + artifact(it) { + def matcher = it.file =~ /-(sources|javadoc|jre8|jre9)\.jar\.asc$/ + if (matcher.find()) { + classifier = matcher.group(1) + } else { + classifier = null + } + extension = 'jar.asc' } } } + + } + + } + + repositories { + maven { + url project.sonatypeUploadUrl + credentials { + username sonatypeUsername + password sonatypePassword + } } } + + } + + model { + tasks.publishMavenJavaPublicationToMavenLocal { + dependsOn(project.tasks.signArchives) + } + tasks.publishMavenJavaPublicationToMavenRepository { + dependsOn(project.tasks.signArchives) + } + tasks.publish { + dependsOn(project.tasks.build) + } +// tasks.install { +// dependsOn(project.tasks.build) +// } } + } + } ext { diff --git a/performance/build.gradle b/performance/build.gradle index c6f4c8a6..7efbde2e 100644 --- a/performance/build.gradle +++ b/performance/build.gradle @@ -1,6 +1,6 @@ dependencies { - compile project(":core") - testCompile junitCompile - testRuntime junitRuntime + api project(":core") + testImplementation junitCompile + testRuntimeOnly junitRuntime } diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index f26b5425..358b365b 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -11,12 +11,12 @@ ext { } dependencies { - compile project(":core") - compile "org.scala-lang:scala-library:$scalaVersion" - compile "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" + api project(":core") + api "org.scala-lang:scala-library:$scalaVersion" + api "org.scalacheck:scalacheck_$scalacheckScalaVersion:$scalacheckVersion" - testCompile junitCompile - testRuntime junitRuntime + testImplementation junitCompile + testRuntimeOnly junitRuntime } tasks.withType(ScalaCompile) { @@ -24,4 +24,4 @@ tasks.withType(ScalaCompile) { } performSigning(signingEnabled, signModule) -configureUpload(signingEnabled, signModule) +configureUpload(signingEnabled, signModule, project.uploadModule) diff --git a/props-core/build.gradle b/props-core/build.gradle index b991bd47..534a051b 100644 --- a/props-core/build.gradle +++ b/props-core/build.gradle @@ -2,7 +2,7 @@ archivesBaseName = "${project.projectName}-${project.name}" dependencies { - compile project(":quickcheck") - testCompile junitCompile - testRuntime junitRuntime + api project(":quickcheck") + testImplementation junitCompile + testRuntimeOnly junitRuntime } diff --git a/props-core/src/test/java/fj/data/ReaderTest.java b/props-core/src/test/java/fj/data/ReaderTest.java index 4817e41c..48352620 100644 --- a/props-core/src/test/java/fj/data/ReaderTest.java +++ b/props-core/src/test/java/fj/data/ReaderTest.java @@ -13,6 +13,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertTrue; + public class ReaderTest { @Test diff --git a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java index 7f02288c..8cc94825 100644 --- a/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java +++ b/props-core/src/test/java/fj/data/fingertrees/FingerTreeTest.java @@ -8,10 +8,11 @@ import org.junit.Test; import static fj.Monoid.intAdditionMonoid; +import static fj.Monoid.intMinMonoid; import static fj.data.fingertrees.FingerTree.measured; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import static org.hamcrest.MatcherAssert.assertThat; public class FingerTreeTest { diff --git a/quickcheck/build.gradle b/quickcheck/build.gradle index 2e5dbe4c..c9851596 100644 --- a/quickcheck/build.gradle +++ b/quickcheck/build.gradle @@ -1,16 +1,15 @@ ext { signModule = true + uploadModule = true } archivesBaseName = "${project.projectName}-${project.name}" dependencies { - compile project(":core") - compile junitCompile + api project(":core") + api junitCompile } performSigning(signingEnabled, signModule) -configureUpload(signingEnabled, signModule) - -uploadArchives.enabled = true +configureUpload(signingEnabled, signModule, uploadModule) From 93c0403576becdffce91fdd9382b831725f6d795 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 17 Feb 2022 23:25:47 +1000 Subject: [PATCH 802/811] Removed deprecated jcenter. Added mavenLocal before mavenCentral in some missing cases. Fixed deprecated reports html enabled to required. --- build.gradle | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 9556b473..43e7ae5b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ apply plugin: "com.github.ben-manes.versions" buildscript { repositories { mavenLocal() - jcenter() mavenCentral() + gradlePluginPortal() } dependencies { @@ -83,9 +83,8 @@ allprojects { } repositories { - jcenter() - mavenCentral() mavenLocal() + mavenCentral() } version = fjVersion @@ -98,6 +97,7 @@ subprojects { buildscript { repositories { + mavenLocal() mavenCentral() } } @@ -108,7 +108,6 @@ subprojects { repositories { mavenLocal() - jcenter() mavenCentral() maven { url sonatypeRepositoryUrl @@ -124,8 +123,8 @@ subprojects { tasks.withType(Test).configureEach { maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 if (!generateTestReports) { - reports.html.enabled = false - reports.junitXml.enabled = false + reports.html.required = false + reports.junitXml.required = false } } @@ -141,8 +140,8 @@ task coverage(type: org.gradle.testing.jacoco.tasks.JacocoReport) { getSourceDirectories().from(files(subprojects.findAll {subproject -> subproject.name in projectForFoverage} .sourceSets.main.allSource.srcDirs)) reports { - html.enabled = true - xml.enabled = true + html.required = true + xml.required = true } } From 0c7f70139917f46c1f855a7258678e6c1377bf0b Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Thu, 17 Feb 2022 23:39:00 +1000 Subject: [PATCH 803/811] Upgrade from Gradle 7.3 t o7.4 --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 43e7ae5b..08204ba9 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ buildscript { } wrapper { - gradleVersion = "7.3" + gradleVersion = "7.4" distributionType = Wrapper.DistributionType.ALL } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fbce071a..b1159fc5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 2ad5cd9f098b574f4e72d4f1924f6c0962621397 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 18 Feb 2022 00:25:11 +1000 Subject: [PATCH 804/811] Do some Travis optimisation --- .travis.yml | 6 +++++- gradle.properties | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bc3fc57f..2fb30bf7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,17 @@ matrix: allow_failures: script: - - ./gradlew clean test + - ./gradlew build --no-daemon env: global: - secure: Bun+1FZ29Q3dR9gZ/5brxcSf+zcY5tWrsqOA4GUb5bYCMyORuXQB0FYXuhKR4wB1pFrk1a9EYwRwSu3GwRJVWb+UzF0CNOWF/QG5tGPx32IOXScwlL/KonI4Vhs7Oc0fF4Wdb7euNrT27BU61jbUugjJ642b3n0VBYFYDdquprU= - secure: QAxhjqLRa+WHKIzgIJPZ/rM5a5uzqG7E5rsC0YvB25cO712oYXmzsYPia/oSp0chXlYLYMfk2UnLeQCSx2e6ogXRRRa977Q+B33Nt0Hd9SGLtduv6DBrbA2ehLU12Ib4DWe5VhF5eueAunycYcllTvqA5h+pzTtEVbd68ZHncM4= +before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ + cache: directories: - $HOME/.gradle/caches/ diff --git a/gradle.properties b/gradle.properties index 6ee9a768..e96743fd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,3 +9,4 @@ sonatypePassword = incorrectPwd #signing.secretKeyRingFile= org.gradle.parallel = true +org.gradle.caching = true From 1dd3b3e8aa84df1d7788d74bcc17457efbc2511f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 18 Feb 2022 00:49:23 +1000 Subject: [PATCH 805/811] Update readme for FJ 5.0 --- README.adoc | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/README.adoc b/README.adoc index 4ede16b7..e24b3e6f 100644 --- a/README.adoc +++ b/README.adoc @@ -8,7 +8,7 @@ image::http://www.functionaljava.org/img/logo-600x144.png[] Functional Java is an open source library facilitating functional programming in Java. The library implements numerous basic and advanced programming abstractions that assist composition oriented development. Functional Java also serves as a platform for learning functional programming concepts by introducing these concepts using a familiar language. -The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java is compiled with Java 8 targeting Java 7 bytecode. The use of lambdas within the project are back ported with the Retro Lambda library, supporting Java versions 6 to 8. +The library is intended for use in production applications and is thoroughly tested using the technique of automated specification-based testing with ScalaCheck and Functional Java's quickcheck module. Functional Java provides abstractions for the following types: @@ -32,16 +32,13 @@ The recommended way to download and use the project is through your build tool. The Functional Java artifact is published to Maven Central using the group `org.functionaljava` with three published artifacts: -* the core library (`functionaljava` or `functionaljava_1.8` if you use Java 8+) -* Java 8 specific support (`functionaljava-java8`) -* property based testing (`functionaljava-quickcheck` or `functionaljava-quickcheck_1.8` if you use Java 8+) +* the core library (`functionaljava`) +* property based testing (`functionaljava-quickcheck`) -The latest stable version is `4.9`. This can be added to your Gradle project by adding the dependencies: +The latest stable version is `5.0`. This can be added to your Gradle project by adding the dependencies: ---- -compile "org.functionaljava:functionaljava:4.9" -compile "org.functionaljava:functionaljava-java8:4.9" -compile "org.functionaljava:functionaljava-quickcheck:4.9" -compile "org.functionaljava:functionaljava-java-core:4.9" +compile "org.functionaljava:functionaljava:5.0" +compile "org.functionaljava:functionaljava-quickcheck:5.0" ---- and in Maven: @@ -49,34 +46,22 @@ and in Maven: org.functionaljava functionaljava - 4.9 - - - org.functionaljava - functionaljava-java8 - 4.9 + 5.0 org.functionaljava functionaljava-quickcheck - 4.9 - - - org.functionaljava - functionaljava-java-core - 4.9 + 5.0 ---- == Building -FunctionalJava uses the Retro Lambda project to backport Java 8 lambdas to Java 6 bytecode. This requires access to both JDK 6 and 8. The build system requires the environment variables `JAVA6_HOME` and `JAVA8_HOME` to refer to the appropriate directories. - -Building is done using Gradle 6.8.3. In the root directory run: +Building is done using Gradle 7.4. In the root directory run: ---- ./gradlew ---- -This requires access to Java and will download the Gradle build tool and necessary dependencies and build FunctionalJava. +This requires access to Java 8 and will download the Gradle build tool and necessary dependencies and build FunctionalJava. == Features @@ -126,4 +111,4 @@ link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause l == Release Notes -For release notes for each version, see the directory etc/release-notes. \ No newline at end of file +For release notes for each version, see the directory etc/release-notes. From 1bcfaa1cb1e4a2e1db710984dc3a1ebd374a09c1 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 18 Feb 2022 23:48:22 +1000 Subject: [PATCH 806/811] Updated gradle versions plugin to 0.42.0. Added arb values for ParModule to help with upgrading Scala and Scalacheck --- build.gradle | 2 +- .../src/main/java/fj/test/Arbitrary.java | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 08204ba9..c89c9536 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,7 @@ buildscript { } dependencies { - classpath "com.github.ben-manes:gradle-versions-plugin:0.36.0" + classpath "com.github.ben-manes:gradle-versions-plugin:0.42.0" classpath "biz.aQute.bnd:biz.aQute.bnd.gradle:6.1.0" } diff --git a/quickcheck/src/main/java/fj/test/Arbitrary.java b/quickcheck/src/main/java/fj/test/Arbitrary.java index 146d0a9b..04f1e20b 100644 --- a/quickcheck/src/main/java/fj/test/Arbitrary.java +++ b/quickcheck/src/main/java/fj/test/Arbitrary.java @@ -23,6 +23,9 @@ import fj.P6; import fj.P7; import fj.P8; +import fj.Unit; +import fj.control.parallel.ParModule; +import fj.control.parallel.Strategy; import fj.data.*; import fj.LcgRng; import fj.Ord; @@ -65,9 +68,12 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; /** * Common Gen helper functions. @@ -98,6 +104,24 @@ public static Gen> arbState(Gen as, Cogen cs, Gen aa return arbF(cs, arbP2(as, aa)).map(State::unit); } + public static Gen arbParModule() { + return Arbitrary.arbStrategy().map(s -> ParModule.parModule(s)); + } + + public static Gen> arbStrategy() { + Strategy s = Strategy.executorStrategy(fixedThreadsExecutorService(2)); + return Gen.elements(s); + } + + private static ExecutorService fixedThreadsExecutorService(int n) { + return Executors.newFixedThreadPool(n, r -> { + ThreadFactory tf = Executors.defaultThreadFactory(); + Thread t = tf.newThread(r); + t.setDaemon(true); + return t; + }); + } + /** * An arbitrary for the LcgRng. */ From aad325739af7dae57c921506a66ee8e4f6ddd026 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 18 Feb 2022 23:50:55 +1000 Subject: [PATCH 807/811] Added problematic upgrade tests from CheckParModule.scala to CheckParModuleTest.java --- .../control/parallel/CheckParModuleTest.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java diff --git a/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java b/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java new file mode 100644 index 00000000..dfbbdda5 --- /dev/null +++ b/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java @@ -0,0 +1,48 @@ +package fj.control.parallel; + +import fj.Equal; +import fj.F; +import fj.Monoid; +import fj.P; +import fj.P1; +import fj.P2; +import fj.data.Stream; +import fj.test.Arbitrary; +import fj.test.Property; +import fj.test.runner.PropertyTestRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static fj.Equal.stringEqual; +import static fj.Monoid.stringMonoid; +import static fj.test.Arbitrary.arbInteger; +import static fj.test.Arbitrary.arbP1; +import static fj.test.Arbitrary.arbParModule; +import static fj.test.Arbitrary.arbStream; +import static fj.test.Arbitrary.arbString; +import static fj.test.Property.prop; +import static fj.test.Property.property; + +@RunWith(PropertyTestRunner.class) +public class CheckParModuleTest { + + public Property parFlatMap() { + return property(arbStream(arbString), arbParModule(), (str, pm) -> { + F> f = s3 -> Stream.stream(s3, reverse().f(s3)); + return prop(Equal.streamEqual(stringEqual).eq(str.bind(f), pm.parFlatMap(str, f).claim())); + }); + } + + private F reverse() { + return s2 -> new StringBuilder(s2).reverse().toString(); + } + + public Property parFoldMap() { + return property(arbStream(arbString), arbParModule(), (str, pm) -> { + F, P2, Stream>> chunk = x -> P.p(Stream.stream(x.head()), x.tail()._1()); + return prop(stringEqual.eq(stringMonoid.sumLeft(str.map(reverse())), pm.parFoldMap(str, reverse(), stringMonoid, chunk).claim())); + }); + } + + +} From 3bced817e36f54c1191f378d9fc9380fb477b567 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Fri, 18 Feb 2022 23:59:51 +1000 Subject: [PATCH 808/811] Removed problematic properties for Scala 2.12 that were moved to Java. --- .../test/scala/fj/control/parallel/CheckParModule.scala | 7 ------- 1 file changed, 7 deletions(-) diff --git a/props-core-scalacheck/src/test/scala/fj/control/parallel/CheckParModule.scala b/props-core-scalacheck/src/test/scala/fj/control/parallel/CheckParModule.scala index 8e13eb1b..bba1feff 100644 --- a/props-core-scalacheck/src/test/scala/fj/control/parallel/CheckParModule.scala +++ b/props-core-scalacheck/src/test/scala/fj/control/parallel/CheckParModule.scala @@ -46,11 +46,4 @@ object CheckParModule extends Properties("ParModule") { property("parMapArray") = forAll((s: Array[String], p: ParModule) => arrayEqual(stringEqual).eq(s.map(rev), p.parMap(s, rev).claim)) - property("parFlatMap") = forAll((s: Stream[String], p: ParModule) => { - val f = (x: String) => Stream.stream(x, rev(x)) : Stream[String] - streamEqual(stringEqual).eq(s.bind(f), p.parFlatMap(s, f).claim)}) - - property("parFoldMap") = forAll((s: Stream[String], p: ParModule) => { - val chunk = (x: Stream[String]) => P.p(Stream.stream(x.head), x.tail._1) - stringEqual.eq(stringMonoid.sumLeft(s.map(rev)), p.parFoldMap(s, rev, stringMonoid, chunk).claim)}) } From 835ca0fb9ae5278aa3371dfdf73562002747c72c Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 19 Feb 2022 01:02:47 +1000 Subject: [PATCH 809/811] Upgrade to Gradle 2.12. Removed CheckHashMap no null values test as the semantics changed with Scala 2.12 so that null.asInstanceOf[Int] returns 0 instead of null --- core/src/main/java/fj/function/Strings.java | 4 ++++ props-core-scalacheck/build.gradle | 12 ++++++++++-- .../src/test/scala/fj/data/CheckArray.scala | 4 ++-- .../src/test/scala/fj/data/CheckHashMap.scala | 11 ----------- .../java/fj/control/parallel/CheckParModuleTest.java | 12 ++++++------ 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/fj/function/Strings.java b/core/src/main/java/fj/function/Strings.java index 1c239e85..d9815248 100644 --- a/core/src/main/java/fj/function/Strings.java +++ b/core/src/main/java/fj/function/Strings.java @@ -96,4 +96,8 @@ public static F, String> unlines() { return Strings::unlines; } + public static F reverse() { + return s -> new StringBuilder(s).reverse().toString(); + } + } diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index 358b365b..faa7d737 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -4,9 +4,17 @@ archivesBaseName = "${project.projectName}-${project.name}" apply plugin: 'scala' ext { - scalaVersion = "2.11.12" - scalacheckScalaVersion = "2.11" +// scalaVersion = "2.11.12" +// scalacheckScalaVersion = "2.11" + scalaVersion = "2.12.15" + scalacheckScalaVersion = "2.12" +// scalaVersion = "2.13.8" +// scalacheckScalaVersion = "2.13" + scalacheckVersion = "1.12.6" +// scalacheckVersion = "1.13.5" +// scalacheckVersion = "1.15.2" + signModule = true } diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckArray.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckArray.scala index f8cce111..b116a6a9 100755 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckArray.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckArray.scala @@ -63,7 +63,7 @@ object CheckArray extends Properties("Array") { a.reverse.foldRight((a: String, b: Array[String]) => array[String](scala.Array(a): _*).append(b), empty[String]))) property("scans") = forAll((a: Array[Int], z: Int) => { - val add = (x: Int, y: Int) => x + y + val add: F2[Int, Int, Int] = (x: Int, y: Int) => x + y val left = a.scanLeft(add, z) val right = a.reverse().scanRight(add, z).reverse() @@ -72,7 +72,7 @@ object CheckArray extends Properties("Array") { property("scans1") = forAll((a: Array[Int]) => (a.length() > 0) ==> { - val add = (x: Int, y: Int) => x + y + val add: F2[Int, Int, Int] = (x: Int, y: Int) => x + y val left = a.scanLeft1(add) val right = a.reverse().scanRight1(add).reverse() diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala index dfde81e3..6ebd060d 100755 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala @@ -105,15 +105,4 @@ object CheckHashMap extends Properties("HashMap") { keysAreEqual && valuesAreEqual }) - property("No null values") = forAll((list: List[Int]) => { - val m = HashMap.hashMap[Int, Int]() - list.foreachDoEffect(new Effect1[Int] { - def f(a: Int) { - m.set(a, null.asInstanceOf[Int]) - } - }) - list.forall(new F[Int, java.lang.Boolean]() { - def f(a: Int) = m.contains(a) == false - }) - }) } \ No newline at end of file diff --git a/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java b/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java index dfbbdda5..0c4f418f 100644 --- a/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java +++ b/props-core/src/test/java/fj/control/parallel/CheckParModuleTest.java @@ -7,6 +7,7 @@ import fj.P1; import fj.P2; import fj.data.Stream; +import fj.function.Strings; import fj.test.Arbitrary; import fj.test.Property; import fj.test.runner.PropertyTestRunner; @@ -28,19 +29,18 @@ public class CheckParModuleTest { public Property parFlatMap() { return property(arbStream(arbString), arbParModule(), (str, pm) -> { - F> f = s3 -> Stream.stream(s3, reverse().f(s3)); + F> f = s3 -> Stream.stream(s3, Strings.reverse().f(s3)); return prop(Equal.streamEqual(stringEqual).eq(str.bind(f), pm.parFlatMap(str, f).claim())); }); } - private F reverse() { - return s2 -> new StringBuilder(s2).reverse().toString(); - } - public Property parFoldMap() { return property(arbStream(arbString), arbParModule(), (str, pm) -> { F, P2, Stream>> chunk = x -> P.p(Stream.stream(x.head()), x.tail()._1()); - return prop(stringEqual.eq(stringMonoid.sumLeft(str.map(reverse())), pm.parFoldMap(str, reverse(), stringMonoid, chunk).claim())); + return prop(stringEqual.eq( + stringMonoid.sumLeft(str.map(Strings.reverse())), + pm.parFoldMap(str, Strings.reverse(), stringMonoid, chunk).claim() + )); }); } From 4671564744bd18e6d9c77ff03f47d8e3900cf28f Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Sat, 19 Feb 2022 01:22:40 +1000 Subject: [PATCH 810/811] Prep for next Scala version --- props-core-scalacheck/build.gradle | 1 + props-core-scalacheck/src/test/scala/fj/Tests.scala | 2 +- props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/props-core-scalacheck/build.gradle b/props-core-scalacheck/build.gradle index faa7d737..396d19d4 100644 --- a/props-core-scalacheck/build.gradle +++ b/props-core-scalacheck/build.gradle @@ -13,6 +13,7 @@ ext { scalacheckVersion = "1.12.6" // scalacheckVersion = "1.13.5" +// scalacheckVersion = "1.14.0" // scalacheckVersion = "1.15.2" signModule = true diff --git a/props-core-scalacheck/src/test/scala/fj/Tests.scala b/props-core-scalacheck/src/test/scala/fj/Tests.scala index d94661f9..c5ec3977 100644 --- a/props-core-scalacheck/src/test/scala/fj/Tests.scala +++ b/props-core-scalacheck/src/test/scala/fj/Tests.scala @@ -18,7 +18,7 @@ object Tests { fj.control.parallel.CheckParModule.properties ).flatten - def main(args: Array[String]) { + def main(args: Array[String]): scala.Unit = { run(tests) // System.exit(0) } diff --git a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala index 6ebd060d..c629a10f 100755 --- a/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala +++ b/props-core-scalacheck/src/test/scala/fj/data/CheckHashMap.scala @@ -9,6 +9,8 @@ import Hash._ import Ord._ import fj.data.Option._ import scala.collection.JavaConversions._ +//import scala.collection.JavaConverters._ + import org.scalacheck.{Arbitrary, Properties} import data.ArbitraryList._ import org.scalacheck.Arbitrary._ From a2f7ebe5ef319df492f547e0be4cc965af667e35 Mon Sep 17 00:00:00 2001 From: Mark Perry Date: Mon, 7 Mar 2022 18:38:31 +1000 Subject: [PATCH 811/811] Updated doc when releasing FJ 5.0 --- README.adoc | 11 ++++++++-- etc/release-notes/release-notes-5.1.adoc | 28 ++++++++++++++++++++++++ etc/release-process.txt | 24 ++++++++++++++++---- 3 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 etc/release-notes/release-notes-5.1.adoc diff --git a/README.adoc b/README.adoc index e24b3e6f..ecf403e2 100644 --- a/README.adoc +++ b/README.adoc @@ -34,11 +34,13 @@ The Functional Java artifact is published to Maven Central using the group `org. * the core library (`functionaljava`) * property based testing (`functionaljava-quickcheck`) +* a small amount of Java 8 support (`functionaljava-java-core`) The latest stable version is `5.0`. This can be added to your Gradle project by adding the dependencies: ---- compile "org.functionaljava:functionaljava:5.0" compile "org.functionaljava:functionaljava-quickcheck:5.0" +compile "org.functionaljava:functionaljava-java-core:5.0" ---- and in Maven: @@ -53,11 +55,16 @@ and in Maven: functionaljava-quickcheck 5.0 + + org.functionaljava + functionaljava-java-core + 5.0 + ---- == Building -Building is done using Gradle 7.4. In the root directory run: +Building is done using Java 8 and Gradle 7.4. In the root directory run: ---- ./gradlew ---- @@ -111,4 +118,4 @@ link:etc/LICENCE[The Functional Java license] uses the BSD 3 license (3-clause l == Release Notes -For release notes for each version, see the directory etc/release-notes. +For release notes for each version, see the directory link:etc/release-notes. diff --git a/etc/release-notes/release-notes-5.1.adoc b/etc/release-notes/release-notes-5.1.adoc new file mode 100644 index 00000000..22dbc552 --- /dev/null +++ b/etc/release-notes/release-notes-5.1.adoc @@ -0,0 +1,28 @@ + += Release + +Proposed release: + +== Enhancements + +* TODO. + +== Fixes + +* TODO. + +== Internal + +* TODO. + +== Breaking Changes + +* TODO. + +== Documentation + +* TODO. + +== Contributors + +* TODO. diff --git a/etc/release-process.txt b/etc/release-process.txt index e4b35e2d..f5699a5b 100644 --- a/etc/release-process.txt +++ b/etc/release-process.txt @@ -1,6 +1,6 @@ -Current Release Process -======================= +Release Process +=============== Go through the issues and pull requests and set the Label and Milestone field. Add information to /etc/release-notes/release-notes-.adoc. @@ -10,7 +10,7 @@ Update gradle.properties: Run the build command: -gradlew clean build upload +gradlew clean build publishAllPublicationsToMavenRepository Login to Sonatype and verify the release: * Login to https://oss.sonatype.org @@ -18,6 +18,7 @@ Login to Sonatype and verify the release: * Tick the release and click Close * Wait until closed * Tick the release and click Release +* It takes ~24 hours for Sonatype to sync to Maven Central where it should appear Commit changes @@ -33,12 +34,27 @@ Create tag: Create the next version of the release notes with empty fields using the template. -Copy the generated javadoc for each component to the website repositories' master branch under /javadoc/. Commit the javadoc and push. +Copy the generated javadoc for each component to the website repositories' master branch, see https://github.com/functionaljava/functionaljava.github.io, under /javadoc/. Copy: +- core to functionaljava +- java-core to functionaljava-java-core +- quickcheck to functionaljava-quickcheck + +Commit the javadoc and push. Update the website and Github README.adoc. This includes adding any features to the home page and features page. Updating the doc page with javadoc links. Update the download page with a link to the latest release notes. Send a message to the group and social media about the release, TODO. +Setup Sonatype +====================== +You need to be able to login to https://oss.sonatype.org. Register or check your login details. + +Create/edit the file %UserProfile%\.gradle\gradle.properties, set the values below: + +sonatypeUsername = +sonatypePassword = + + Setup Artifact Signing ====================== The below text is a summary from https://gist.github.com/phit/bd3c6d156a2fa5f3b1bc15fa94b3256c.

{projectNameFull} {version.toString} API Specification