From c786ff840e9de781fc2121ce6529576f914378b9 Mon Sep 17 00:00:00 2001 From: jnape Date: Mon, 16 Jul 2018 23:28:57 -0500 Subject: [PATCH 01/31] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6f0a6e0aa..94275b818 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ lambda - 3.1.0 + 3.1.1-SNAPSHOT jar Lambda From a2c084c0b7f22c73f0c3c8a73fc96eed2ca2fd5e Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 22 Jul 2018 17:16:06 -0500 Subject: [PATCH 02/31] Updating README and CHANGELOG to reflect latest version --- CHANGELOG.md | 6 +++++- README.md | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c49b53a53..286016b8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/). ## [Unreleased] +_No changes yet_ + +## [3.1.0] - 2018-07-16 ### Added - `Fn3-8` static factory overloads to aid in coercing lambdas - Adding composition guarantees to `LensLike` @@ -368,7 +371,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Monadic/Dyadic/TriadicFunction`, `Predicate`, `Tuple2`, `Tuple3` - `Functor`, `BiFunctor`, `ProFunctor` -[Unreleased]: https://github.com/palatable/lambda/compare/lambda-3.0.3...HEAD +[Unreleased]: https://github.com/palatable/lambda/compare/lambda-3.1.0...HEAD +[3.1.0]: https://github.com/palatable/lambda/compare/lambda-3.0.3...lambda-3.1.0 [3.0.3]: https://github.com/palatable/lambda/compare/lambda-3.0.2...lambda-3.0.3 [3.0.2]: https://github.com/palatable/lambda/compare/lambda-3.0.1...lambda-3.0.2 [3.0.1]: https://github.com/palatable/lambda/compare/lambda-3.0.0...lambda-3.0.1 diff --git a/README.md b/README.md index 13892496a..1d2dc60b0 100644 --- a/README.md +++ b/README.md @@ -57,14 +57,14 @@ Add the following dependency to your: com.jnape.palatable lambda - 3.0.3 + 3.1.0 ``` `build.gradle` ([Gradle](https://docs.gradle.org/current/userguide/dependency_management.html)): ```gradle -compile group: 'com.jnape.palatable', name: 'lambda', version: '3.0.3' +compile group: 'com.jnape.palatable', name: 'lambda', version: '3.1.0' ``` Examples From 00c35f703db1c26f09f51d44b8e0dca87086895c Mon Sep 17 00:00:00 2001 From: jnape Date: Sat, 28 Jul 2018 15:22:36 -0500 Subject: [PATCH 03/31] Difference and Intersection were never meant to implement Semigroup. Time for semigroup assertion helpers. --- CHANGELOG.md | 3 ++- .../builtin => functions/builtin/fn2}/Difference.java | 6 +++--- .../builtin => functions/builtin/fn2}/Intersection.java | 6 +++--- .../builtin => functions/builtin/fn2}/DifferenceTest.java | 4 ++-- .../builtin => functions/builtin/fn2}/IntersectionTest.java | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) rename src/main/java/com/jnape/palatable/lambda/{semigroup/builtin => functions/builtin/fn2}/Difference.java (90%) rename src/main/java/com/jnape/palatable/lambda/{semigroup/builtin => functions/builtin/fn2}/Intersection.java (89%) rename src/test/java/com/jnape/palatable/lambda/{semigroup/builtin => functions/builtin/fn2}/DifferenceTest.java (91%) rename src/test/java/com/jnape/palatable/lambda/{semigroup/builtin => functions/builtin/fn2}/IntersectionTest.java (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 286016b8a..007ec4552 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/). ## [Unreleased] -_No changes yet_ +### Changed +- ***Breaking Change***: `Difference` and `Intersection` no longer instances of `Semigroup` and moved to `functions.builtin.fn2` package ## [3.1.0] - 2018-07-16 ### Added diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Difference.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Difference.java similarity index 90% rename from src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Difference.java rename to src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Difference.java index b1df01f77..777279597 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Difference.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Difference.java @@ -1,8 +1,8 @@ -package com.jnape.palatable.lambda.semigroup.builtin; +package com.jnape.palatable.lambda.functions.builtin.fn2; import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; import com.jnape.palatable.lambda.functions.builtin.fn1.Distinct; -import com.jnape.palatable.lambda.semigroup.Semigroup; import java.util.HashSet; @@ -21,7 +21,7 @@ * * @param the {@link Iterable} element type */ -public final class Difference implements Semigroup> { +public final class Difference implements Fn2, Iterable, Iterable> { private static final Difference INSTANCE = new Difference(); diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Intersection.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java similarity index 89% rename from src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Intersection.java rename to src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java index 044763f83..1124ce61f 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Intersection.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java @@ -1,8 +1,8 @@ -package com.jnape.palatable.lambda.semigroup.builtin; +package com.jnape.palatable.lambda.functions.builtin.fn2; import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; import com.jnape.palatable.lambda.functions.builtin.fn1.Distinct; -import com.jnape.palatable.lambda.semigroup.Semigroup; import java.util.HashSet; import java.util.Set; @@ -19,7 +19,7 @@ * * @param the {@link Iterable} element type */ -public final class Intersection implements Semigroup> { +public final class Intersection implements Fn2, Iterable, Iterable> { private static final Intersection INSTANCE = new Intersection(); diff --git a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/DifferenceTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DifferenceTest.java similarity index 91% rename from src/test/java/com/jnape/palatable/lambda/semigroup/builtin/DifferenceTest.java rename to src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DifferenceTest.java index 929a2b9f8..2b1dd6ecc 100644 --- a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/DifferenceTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/DifferenceTest.java @@ -1,4 +1,4 @@ -package com.jnape.palatable.lambda.semigroup.builtin; +package com.jnape.palatable.lambda.functions.builtin.fn2; import com.jnape.palatable.lambda.functions.Fn1; import com.jnape.palatable.traitor.annotations.TestTraits; @@ -11,7 +11,7 @@ import testsupport.traits.InfiniteIterableSupport; import testsupport.traits.Laziness; -import static com.jnape.palatable.lambda.semigroup.builtin.Difference.difference; +import static com.jnape.palatable.lambda.functions.builtin.fn2.Difference.difference; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; diff --git a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/IntersectionTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/IntersectionTest.java similarity index 92% rename from src/test/java/com/jnape/palatable/lambda/semigroup/builtin/IntersectionTest.java rename to src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/IntersectionTest.java index 0ecd33c71..13c16ace3 100644 --- a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/IntersectionTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/IntersectionTest.java @@ -1,4 +1,4 @@ -package com.jnape.palatable.lambda.semigroup.builtin; +package com.jnape.palatable.lambda.functions.builtin.fn2; import com.jnape.palatable.lambda.functions.Fn1; import com.jnape.palatable.traitor.annotations.TestTraits; @@ -10,7 +10,7 @@ import testsupport.traits.InfiniteIterableSupport; import testsupport.traits.Laziness; -import static com.jnape.palatable.lambda.semigroup.builtin.Intersection.intersection; +import static com.jnape.palatable.lambda.functions.builtin.fn2.Intersection.intersection; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; From 9e517426974a90f44c23b0a5606529ffc775241f Mon Sep 17 00:00:00 2001 From: jnape Date: Sat, 28 Jul 2018 15:24:48 -0500 Subject: [PATCH 04/31] Better implementation of Intersection --- .../lambda/functions/builtin/fn2/Intersection.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java index 1124ce61f..178b7be8c 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Intersection.java @@ -4,9 +4,6 @@ import com.jnape.palatable.lambda.functions.Fn2; import com.jnape.palatable.lambda.functions.builtin.fn1.Distinct; -import java.util.HashSet; -import java.util.Set; - import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; import static com.jnape.palatable.lambda.functions.builtin.fn1.Distinct.distinct; import static com.jnape.palatable.lambda.functions.builtin.fn2.Eq.eq; @@ -28,8 +25,7 @@ private Intersection() { @Override public Iterable apply(Iterable xs, Iterable ys) { - Set seen = new HashSet<>(); - return distinct(filter(a -> seen.contains(a) || find(eq(a), ys).peek(seen::add).fmap(constantly(true)).orElse(false), xs)); + return filter(x -> find(eq(x), ys).fmap(constantly(true)).orElse(false), distinct(xs)); } @SuppressWarnings("unchecked") From 7d5ff797636461567b25ede718857876234aa12f Mon Sep 17 00:00:00 2001 From: jnape Date: Tue, 31 Jul 2018 20:36:06 -0500 Subject: [PATCH 05/31] Moving Absent to semigroups --- CHANGELOG.md | 1 + .../com/jnape/palatable/lambda/monoid/builtin/Present.java | 1 + .../lambda/{monoid => semigroup}/builtin/Absent.java | 3 ++- .../lambda/{monoid => semigroup}/builtin/AbsentTest.java | 6 +++--- 4 files changed, 7 insertions(+), 4 deletions(-) rename src/main/java/com/jnape/palatable/lambda/{monoid => semigroup}/builtin/Absent.java (94%) rename src/test/java/com/jnape/palatable/lambda/{monoid => semigroup}/builtin/AbsentTest.java (81%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 007ec4552..9ba882791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ## [Unreleased] ### Changed - ***Breaking Change***: `Difference` and `Intersection` no longer instances of `Semigroup` and moved to `functions.builtin.fn2` package +- ***Breaking Change***: `Absent` moved to `semigroup.builtin` package ## [3.1.0] - 2018-07-16 ### Added diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Present.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Present.java index af2a51ee5..cccf15d1b 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Present.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Present.java @@ -5,6 +5,7 @@ import com.jnape.palatable.lambda.functions.specialized.MonoidFactory; import com.jnape.palatable.lambda.monoid.Monoid; import com.jnape.palatable.lambda.semigroup.Semigroup; +import com.jnape.palatable.lambda.semigroup.builtin.Absent; import static com.jnape.palatable.lambda.adt.Maybe.nothing; import static com.jnape.palatable.lambda.monoid.Monoid.monoid; diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Absent.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java similarity index 94% rename from src/main/java/com/jnape/palatable/lambda/monoid/builtin/Absent.java rename to src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java index db38aad3e..9c5392860 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Absent.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/Absent.java @@ -1,9 +1,10 @@ -package com.jnape.palatable.lambda.monoid.builtin; +package com.jnape.palatable.lambda.semigroup.builtin; import com.jnape.palatable.lambda.adt.Maybe; import com.jnape.palatable.lambda.functions.Fn1; import com.jnape.palatable.lambda.functions.builtin.fn3.LiftA2; import com.jnape.palatable.lambda.functions.specialized.SemigroupFactory; +import com.jnape.palatable.lambda.monoid.builtin.Present; import com.jnape.palatable.lambda.semigroup.Semigroup; /** diff --git a/src/test/java/com/jnape/palatable/lambda/monoid/builtin/AbsentTest.java b/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AbsentTest.java similarity index 81% rename from src/test/java/com/jnape/palatable/lambda/monoid/builtin/AbsentTest.java rename to src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AbsentTest.java index 6a0196daa..7df46e6e2 100644 --- a/src/test/java/com/jnape/palatable/lambda/monoid/builtin/AbsentTest.java +++ b/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AbsentTest.java @@ -1,17 +1,17 @@ -package com.jnape.palatable.lambda.monoid.builtin; +package com.jnape.palatable.lambda.semigroup.builtin; import com.jnape.palatable.lambda.semigroup.Semigroup; import org.junit.Test; import static com.jnape.palatable.lambda.adt.Maybe.just; import static com.jnape.palatable.lambda.adt.Maybe.nothing; -import static com.jnape.palatable.lambda.monoid.builtin.Absent.absent; +import static com.jnape.palatable.lambda.semigroup.builtin.Absent.absent; import static org.junit.Assert.assertEquals; public class AbsentTest { @Test - public void monoid() { + public void semigroup() { Absent absent = absent(); Semigroup addition = (x, y) -> x + y; From 24949f16a911ca81eefbae19534137b6abde1ad2 Mon Sep 17 00:00:00 2001 From: jnape Date: Wed, 1 Aug 2018 21:55:31 -0500 Subject: [PATCH 06/31] RightAny returns a Monoid --- CHANGELOG.md | 1 + .../com/jnape/palatable/lambda/monoid/builtin/RightAny.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ba882791..9553f995b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Changed - ***Breaking Change***: `Difference` and `Intersection` no longer instances of `Semigroup` and moved to `functions.builtin.fn2` package - ***Breaking Change***: `Absent` moved to `semigroup.builtin` package +- `RightAny` overload returns `Monoid` ## [3.1.0] - 2018-07-16 ### Added diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RightAny.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RightAny.java index ad812cffd..f357d5da4 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RightAny.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RightAny.java @@ -45,7 +45,7 @@ public static RightAny rightAny() { return INSTANCE; } - public static Semigroup> rightAny(Monoid rMonoid) { + public static Monoid> rightAny(Monoid rMonoid) { return RightAny.rightAny().apply(rMonoid); } From fc83731365d9dd7aa9f91e0a15412584b2a56d25 Mon Sep 17 00:00:00 2001 From: jnape Date: Wed, 1 Aug 2018 22:28:42 -0500 Subject: [PATCH 07/31] Product2#invert and static factory method --- .../lambda/adt/product/Product2.java | 32 +++++++++++++++++++ .../lambda/adt/product/Product2Test.java | 23 +++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java index e9619203b..8b44cf309 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java @@ -43,6 +43,15 @@ default R into(BiFunction fn) { return fn.apply(_1(), _2()); } + /** + * Flip the slots of this {@link Product2}. + * + * @return the flipped {@link Product2} + */ + default Product2<_2, _1> invert() { + return into((_1, _2) -> product(_2, _1)); + } + @Override default _1 getKey() { return _1(); @@ -57,4 +66,27 @@ default _2 getValue() { default _2 setValue(_2 value) { throw new UnsupportedOperationException(); } + + /** + * Static factory method for creating a generic {@link Product2}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @return the {@link Product2} + */ + static <_1, _2> Product2<_1, _2> product(_1 _1, _2 _2) { + return new Product2<_1, _2>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + }; + } } diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java new file mode 100644 index 000000000..d094cd39d --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java @@ -0,0 +1,23 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product2.product; +import static org.junit.Assert.assertEquals; + +public class Product2Test { + + @Test + public void staticFactoryMethod() { + Product2 product = product("a", "b"); + assertEquals("a", product._1()); + assertEquals("b", product._2()); + } + + @Test + public void invert() { + Product2 inverted = product("a", "b").invert(); + assertEquals("b", inverted._1()); + assertEquals("a", inverted._2()); + } +} \ No newline at end of file From e86e212811a7dcc3c6ef08bf6407d22ae72d28ca Mon Sep 17 00:00:00 2001 From: jnape Date: Thu, 2 Aug 2018 22:51:13 -0500 Subject: [PATCH 08/31] Adding predicate static factory method --- CHANGELOG.md | 3 +++ .../lambda/functions/specialized/Predicate.java | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9553f995b..cbee0a87b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - ***Breaking Change***: `Absent` moved to `semigroup.builtin` package - `RightAny` overload returns `Monoid` +### Added +- `Predicate#predicate` static factory method + ## [3.1.0] - 2018-07-16 ### Added - `Fn3-8` static factory overloads to aid in coercing lambdas diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java index 89e3e5e93..a9d0de708 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java @@ -82,4 +82,15 @@ default Predicate or(java.util.function.Predicate other) { default Predicate negate() { return a -> !apply(a); } + + /** + * Static factory method to create a predicate from a function. + * + * @param predicate the function + * @param the input type + * @return the predicate + */ + static Predicate predicate(Function predicate) { + return predicate::apply; + } } From c1c4893246f3f7e083b0e216f1078b4ea89959f8 Mon Sep 17 00:00:00 2001 From: jnape Date: Sat, 4 Aug 2018 17:43:55 -0500 Subject: [PATCH 09/31] Product invert/rotateL/R cardinality variants with tuple specializations --- CHANGELOG.md | 2 + .../palatable/lambda/adt/hlist/Tuple2.java | 5 + .../palatable/lambda/adt/hlist/Tuple3.java | 15 ++ .../palatable/lambda/adt/hlist/Tuple4.java | 34 ++++- .../palatable/lambda/adt/hlist/Tuple5.java | 35 +++++ .../palatable/lambda/adt/hlist/Tuple6.java | 45 ++++++ .../palatable/lambda/adt/hlist/Tuple7.java | 55 +++++++ .../palatable/lambda/adt/hlist/Tuple8.java | 65 ++++++++ .../lambda/adt/product/Product2.java | 4 +- .../lambda/adt/product/Product3.java | 53 +++++++ .../lambda/adt/product/Product4.java | 70 +++++++++ .../lambda/adt/product/Product5.java | 87 +++++++++++ .../lambda/adt/product/Product6.java | 105 +++++++++++++ .../lambda/adt/product/Product7.java | 122 +++++++++++++++ .../lambda/adt/product/Product8.java | 140 ++++++++++++++++++ .../lambda/adt/product/Product2Test.java | 13 +- .../lambda/adt/product/Product3Test.java | 31 ++++ .../lambda/adt/product/Product4Test.java | 34 +++++ .../lambda/adt/product/Product5Test.java | 37 +++++ .../lambda/adt/product/Product6Test.java | 40 +++++ .../lambda/adt/product/Product7Test.java | 43 ++++++ .../lambda/adt/product/Product8Test.java | 46 ++++++ 22 files changed, 1069 insertions(+), 12 deletions(-) create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product3Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product4Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product5Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product6Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product7Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/adt/product/Product8Test.java diff --git a/CHANGELOG.md b/CHANGELOG.md index cbee0a87b..baf77d010 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Added - `Predicate#predicate` static factory method +- `Product2-8` left/right rotation methods +- `Tuple2-8` specializations of left/right product rotation ## [3.1.0] - 2018-07-16 ### Added diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple2.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple2.java index f59f77d71..621537198 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple2.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple2.java @@ -70,6 +70,11 @@ public _2 setValue(_2 value) { throw new UnsupportedOperationException(); } + @Override + public Tuple2<_2, _1> invert() { + return tuple(_2, _1); + } + @Override public <_2Prime> Tuple2<_1, _2Prime> fmap(Function fn) { return Monad.super.<_2Prime>fmap(fn).coerce(); diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java index 235b5bf30..32d8a5359 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple3.java @@ -61,6 +61,21 @@ public _3 _3() { return _3; } + @Override + public Tuple3<_2, _3, _1> rotateL3() { + return tuple(_2, _3, _1); + } + + @Override + public Tuple3<_3, _1, _2> rotateR3() { + return tuple(_3, _1, _2); + } + + @Override + public Tuple3<_2, _1, _3> invert() { + return tuple(_2, _1, _3); + } + @Override @SuppressWarnings("unchecked") public <_3Prime> Tuple3<_1, _2, _3Prime> fmap(Function fn) { diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java index f24d1cca2..af141c9f3 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple4.java @@ -70,21 +70,43 @@ public _4 _4() { } @Override - @SuppressWarnings("unchecked") + public Tuple4<_2, _3, _4, _1> rotateL4() { + return tuple(_2, _3, _4, _1); + } + + @Override + public Tuple4<_4, _1, _2, _3> rotateR4() { + return tuple(_4, _1, _2, _3); + } + + @Override + public Tuple4<_2, _3, _1, _4> rotateL3() { + return tuple(_2, _3, _1, _4); + } + + @Override + public Tuple4<_3, _1, _2, _4> rotateR3() { + return tuple(_3, _1, _2, _4); + } + + @Override + public Tuple4<_2, _1, _3, _4> invert() { + return tuple(_2, _1, _3, _4); + } + + @Override public <_4Prime> Tuple4<_1, _2, _3, _4Prime> fmap(Function fn) { - return (Tuple4<_1, _2, _3, _4Prime>) Monad.super.fmap(fn); + return (Tuple4<_1, _2, _3, _4Prime>) Monad.super.<_4Prime>fmap(fn); } @Override - @SuppressWarnings("unchecked") public <_3Prime> Tuple4<_1, _2, _3Prime, _4> biMapL(Function fn) { - return (Tuple4<_1, _2, _3Prime, _4>) Bifunctor.super.biMapL(fn); + return (Tuple4<_1, _2, _3Prime, _4>) Bifunctor.super.<_3Prime>biMapL(fn); } @Override - @SuppressWarnings("unchecked") public <_4Prime> Tuple4<_1, _2, _3, _4Prime> biMapR(Function fn) { - return (Tuple4<_1, _2, _3, _4Prime>) Bifunctor.super.biMapR(fn); + return (Tuple4<_1, _2, _3, _4Prime>) Bifunctor.super.<_4Prime>biMapR(fn); } @Override diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java index 9936cc243..65dfb3c7a 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple5.java @@ -77,6 +77,41 @@ public _5 _5() { return _5; } + @Override + public Tuple5<_2, _3, _4, _5, _1> rotateL5() { + return tuple(_2, _3, _4, _5, _1); + } + + @Override + public Tuple5<_5, _1, _2, _3, _4> rotateR5() { + return tuple(_5, _1, _2, _3, _4); + } + + @Override + public Tuple5<_2, _3, _4, _1, _5> rotateL4() { + return tuple(_2, _3, _4, _1, _5); + } + + @Override + public Tuple5<_4, _1, _2, _3, _5> rotateR4() { + return tuple(_4, _1, _2, _3, _5); + } + + @Override + public Tuple5<_2, _3, _1, _4, _5> rotateL3() { + return tuple(_2, _3, _1, _4, _5); + } + + @Override + public Tuple5<_3, _1, _2, _4, _5> rotateR3() { + return tuple(_3, _1, _2, _4, _5); + } + + @Override + public Tuple5<_2, _1, _3, _4, _5> invert() { + return tuple(_2, _1, _3, _4, _5); + } + @Override public <_5Prime> Tuple5<_1, _2, _3, _4, _5Prime> fmap(Function fn) { return Monad.super.<_5Prime>fmap(fn).coerce(); diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java index 1cdbbb343..0f3046ace 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple6.java @@ -86,6 +86,51 @@ public _6 _6() { return _6; } + @Override + public Tuple6<_2, _3, _4, _5, _6, _1> rotateL6() { + return tuple(_2, _3, _4, _5, _6, _1); + } + + @Override + public Tuple6<_6, _1, _2, _3, _4, _5> rotateR6() { + return tuple(_6, _1, _2, _3, _4, _5); + } + + @Override + public Tuple6<_2, _3, _4, _5, _1, _6> rotateL5() { + return tuple(_2, _3, _4, _5, _1, _6); + } + + @Override + public Tuple6<_5, _1, _2, _3, _4, _6> rotateR5() { + return tuple(_5, _1, _2, _3, _4, _6); + } + + @Override + public Tuple6<_2, _3, _4, _1, _5, _6> rotateL4() { + return tuple(_2, _3, _4, _1, _5, _6); + } + + @Override + public Tuple6<_4, _1, _2, _3, _5, _6> rotateR4() { + return tuple(_4, _1, _2, _3, _5, _6); + } + + @Override + public Tuple6<_2, _3, _1, _4, _5, _6> rotateL3() { + return tuple(_2, _3, _1, _4, _5, _6); + } + + @Override + public Tuple6<_3, _1, _2, _4, _5, _6> rotateR3() { + return tuple(_3, _1, _2, _4, _5, _6); + } + + @Override + public Tuple6<_2, _1, _3, _4, _5, _6> invert() { + return tuple(_2, _1, _3, _4, _5, _6); + } + @Override public <_6Prime> Tuple6<_1, _2, _3, _4, _5, _6Prime> fmap(Function fn) { return Monad.super.<_6Prime>fmap(fn).coerce(); diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java index 439137c20..1910381d1 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple7.java @@ -95,6 +95,61 @@ public _7 _7() { return _7; } + @Override + public Tuple7<_2, _3, _4, _5, _6, _7, _1> rotateL7() { + return tuple(_2, _3, _4, _5, _6, _7, _1); + } + + @Override + public Tuple7<_7, _1, _2, _3, _4, _5, _6> rotateR7() { + return tuple(_7, _1, _2, _3, _4, _5, _6); + } + + @Override + public Tuple7<_2, _3, _4, _5, _6, _1, _7> rotateL6() { + return tuple(_2, _3, _4, _5, _6, _1, _7); + } + + @Override + public Tuple7<_6, _1, _2, _3, _4, _5, _7> rotateR6() { + return tuple(_6, _1, _2, _3, _4, _5, _7); + } + + @Override + public Tuple7<_2, _3, _4, _5, _1, _6, _7> rotateL5() { + return tuple(_2, _3, _4, _5, _1, _6, _7); + } + + @Override + public Tuple7<_5, _1, _2, _3, _4, _6, _7> rotateR5() { + return tuple(_5, _1, _2, _3, _4, _6, _7); + } + + @Override + public Tuple7<_2, _3, _4, _1, _5, _6, _7> rotateL4() { + return tuple(_2, _3, _4, _1, _5, _6, _7); + } + + @Override + public Tuple7<_4, _1, _2, _3, _5, _6, _7> rotateR4() { + return tuple(_4, _1, _2, _3, _5, _6, _7); + } + + @Override + public Tuple7<_2, _3, _1, _4, _5, _6, _7> rotateL3() { + return tuple(_2, _3, _1, _4, _5, _6, _7); + } + + @Override + public Tuple7<_3, _1, _2, _4, _5, _6, _7> rotateR3() { + return tuple(_3, _1, _2, _4, _5, _6, _7); + } + + @Override + public Tuple7<_2, _1, _3, _4, _5, _6, _7> invert() { + return tuple(_2, _1, _3, _4, _5, _6, _7); + } + @Override public <_7Prime> Tuple7<_1, _2, _3, _4, _5, _6, _7Prime> fmap(Function fn) { return Monad.super.<_7Prime>fmap(fn).coerce(); diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java index 63b0279f4..30a9eba61 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hlist/Tuple8.java @@ -104,6 +104,71 @@ public _8 _8() { return _8; } + @Override + public Tuple8<_2, _3, _4, _5, _6, _7, _8, _1> rotateL8() { + return tuple(_2, _3, _4, _5, _6, _7, _8, _1); + } + + @Override + public Tuple8<_8, _1, _2, _3, _4, _5, _6, _7> rotateR8() { + return tuple(_8, _1, _2, _3, _4, _5, _6, _7); + } + + @Override + public Tuple8<_2, _3, _4, _5, _6, _7, _1, _8> rotateL7() { + return tuple(_2, _3, _4, _5, _6, _7, _1, _8); + } + + @Override + public Tuple8<_7, _1, _2, _3, _4, _5, _6, _8> rotateR7() { + return tuple(_7, _1, _2, _3, _4, _5, _6, _8); + } + + @Override + public Tuple8<_2, _3, _4, _5, _6, _1, _7, _8> rotateL6() { + return tuple(_2, _3, _4, _5, _6, _1, _7, _8); + } + + @Override + public Tuple8<_6, _1, _2, _3, _4, _5, _7, _8> rotateR6() { + return tuple(_6, _1, _2, _3, _4, _5, _7, _8); + } + + @Override + public Tuple8<_2, _3, _4, _5, _1, _6, _7, _8> rotateL5() { + return tuple(_2, _3, _4, _5, _1, _6, _7, _8); + } + + @Override + public Tuple8<_5, _1, _2, _3, _4, _6, _7, _8> rotateR5() { + return tuple(_5, _1, _2, _3, _4, _6, _7, _8); + } + + @Override + public Tuple8<_2, _3, _4, _1, _5, _6, _7, _8> rotateL4() { + return tuple(_2, _3, _4, _1, _5, _6, _7, _8); + } + + @Override + public Tuple8<_4, _1, _2, _3, _5, _6, _7, _8> rotateR4() { + return tuple(_4, _1, _2, _3, _5, _6, _7, _8); + } + + @Override + public Tuple8<_2, _3, _1, _4, _5, _6, _7, _8> rotateL3() { + return tuple(_2, _3, _1, _4, _5, _6, _7, _8); + } + + @Override + public Tuple8<_3, _1, _2, _4, _5, _6, _7, _8> rotateR3() { + return tuple(_3, _1, _2, _4, _5, _6, _7, _8); + } + + @Override + public Tuple8<_2, _1, _3, _4, _5, _6, _7, _8> invert() { + return tuple(_2, _1, _3, _4, _5, _6, _7, _8); + } + @Override public <_8Prime> Tuple8<_1, _2, _3, _4, _5, _6, _7, _8Prime> fmap(Function fn) { return Monad.super.<_8Prime>fmap(fn).coerce(); diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java index 8b44cf309..4c3d64da0 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product2.java @@ -44,9 +44,9 @@ default R into(BiFunction fn) { } /** - * Flip the slots of this {@link Product2}. + * Rotate the first two slots of this product. * - * @return the flipped {@link Product2} + * @return the rotated product */ default Product2<_2, _1> invert() { return into((_1, _2) -> product(_2, _1)); diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product3.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product3.java index 241c97c5f..063456453 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product3.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product3.java @@ -32,4 +32,57 @@ public interface Product3<_1, _2, _3> extends Product2<_1, _2> { default R into(Fn3 fn) { return Product2.super.into(fn.toBiFunction()).apply(_3()); } + + /** + * Rotate the first three values of this product one slot to the left. + * + * @return the left-rotated product + */ + default Product3<_2, _3, _1> rotateL3() { + return into((_1, _2, _3) -> product(_2, _3, _1)); + } + + /** + * Rotate the first three values of this product one slot to the right. + * + * @return the right-rotated product + */ + default Product3<_3, _1, _2> rotateR3() { + return into((_1, _2, _3) -> product(_3, _1, _2)); + } + + @Override + default Product3<_2, _1, _3> invert() { + return into((_1, _2, _3) -> product(_2, _1, _3)); + } + + /** + * Static factory method for creating a generic {@link Product3}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param _3 the third slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @param <_3> the third slot type + * @return the {@link Product3} + */ + static <_1, _2, _3> Product3<_1, _2, _3> product(_1 _1, _2 _2, _3 _3) { + return new Product3<_1, _2, _3>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + + @Override + public _3 _3() { + return _3; + } + }; + } } diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product4.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product4.java index 554591ed5..2703f8229 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product4.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product4.java @@ -33,4 +33,74 @@ public interface Product4<_1, _2, _3, _4> extends Product3<_1, _2, _3> { default R into(Fn4 fn) { return Product3.super.into(fn).apply(_4()); } + + /** + * Rotate the first four values of this product one slot to the left. + * + * @return the left-rotated product + */ + default Product4<_2, _3, _4, _1> rotateL4() { + return into((_1, _2, _3, _4) -> product(_2, _3, _4, _1)); + } + + /** + * Rotate the first four values of this product one slot to the right. + * + * @return the right-rotated product + */ + default Product4<_4, _1, _2, _3> rotateR4() { + return into((_1, _2, _3, _4) -> product(_4, _1, _2, _3)); + } + + @Override + default Product4<_2, _3, _1, _4> rotateL3() { + return into((_1, _2, _3, _4) -> product(_2, _3, _1, _4)); + } + + @Override + default Product4<_3, _1, _2, _4> rotateR3() { + return into((_1, _2, _3, _4) -> product(_3, _1, _2, _4)); + } + + @Override + default Product4<_2, _1, _3, _4> invert() { + return into((_1, _2, _3, _4) -> product(_2, _1, _3, _4)); + } + + /** + * Static factory method for creating a generic {@link Product4}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param _3 the third slot + * @param _4 the fourth slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @param <_3> the third slot type + * @param <_4> the fourth slot type + * @return the {@link Product4} + */ + static <_1, _2, _3, _4> Product4<_1, _2, _3, _4> product(_1 _1, _2 _2, _3 _3, _4 _4) { + return new Product4<_1, _2, _3, _4>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + + @Override + public _3 _3() { + return _3; + } + + @Override + public _4 _4() { + return _4; + } + }; + } } diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product5.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product5.java index 144fc296c..864671bbe 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product5.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product5.java @@ -35,4 +35,91 @@ public interface Product5<_1, _2, _3, _4, _5> extends Product4<_1, _2, _3, _4> { default R into(Fn5 fn) { return Product4.super.>into(fn).apply(_5()); } + + /** + * Rotate the first five values of this product one slot to the left. + * + * @return the left-rotated product + */ + default Product5<_2, _3, _4, _5, _1> rotateL5() { + return into((_1, _2, _3, _4, _5) -> product(_2, _3, _4, _5, _1)); + } + + /** + * Rotate the first five values of this product one slot to the right. + * + * @return the right-rotated product + */ + default Product5<_5, _1, _2, _3, _4> rotateR5() { + return into((_1, _2, _3, _4, _5) -> product(_5, _1, _2, _3, _4)); + } + + @Override + default Product5<_2, _3, _4, _1, _5> rotateL4() { + return into((_1, _2, _3, _4, _5) -> product(_2, _3, _4, _1, _5)); + } + + @Override + default Product5<_4, _1, _2, _3, _5> rotateR4() { + return into((_1, _2, _3, _4, _5) -> product(_4, _1, _2, _3, _5)); + } + + @Override + default Product5<_2, _3, _1, _4, _5> rotateL3() { + return into((_1, _2, _3, _4, _5) -> product(_2, _3, _1, _4, _5)); + } + + @Override + default Product5<_3, _1, _2, _4, _5> rotateR3() { + return into((_1, _2, _3, _4, _5) -> product(_3, _1, _2, _4, _5)); + } + + @Override + default Product5<_2, _1, _3, _4, _5> invert() { + return into((_1, _2, _3, _4, _5) -> product(_2, _1, _3, _4, _5)); + } + + /** + * Static factory method for creating a generic {@link Product5}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param _3 the third slot + * @param _4 the fourth slot + * @param _5 the fifth slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @param <_3> the third slot type + * @param <_4> the fourth slot type + * @param <_5> the fifth slot type + * @return the {@link Product5} + */ + static <_1, _2, _3, _4, _5> Product5<_1, _2, _3, _4, _5> product(_1 _1, _2 _2, _3 _3, _4 _4, _5 _5) { + return new Product5<_1, _2, _3, _4, _5>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + + @Override + public _3 _3() { + return _3; + } + + @Override + public _4 _4() { + return _4; + } + + @Override + public _5 _5() { + return _5; + } + }; + } } diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product6.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product6.java index 07b14a307..2ea16a9a5 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product6.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product6.java @@ -36,4 +36,109 @@ public interface Product6<_1, _2, _3, _4, _5, _6> extends Product5<_1, _2, _3, _ default R into(Fn6 fn) { return Product5.super.>into(fn).apply(_6()); } + + /** + * Rotate the first six values of this product one slot to the left. + * + * @return the left-rotated product + */ + default Product6<_2, _3, _4, _5, _6, _1> rotateL6() { + return into((_1, _2, _3, _4, _5, _6) -> product(_2, _3, _4, _5, _6, _1)); + } + + /** + * Rotate the first six values of this product one slot to the right. + * + * @return the right-rotated product + */ + default Product6<_6, _1, _2, _3, _4, _5> rotateR6() { + return into((_1, _2, _3, _4, _5, _6) -> product(_6, _1, _2, _3, _4, _5)); + } + + @Override + default Product6<_2, _3, _4, _5, _1, _6> rotateL5() { + return into((_1, _2, _3, _4, _5, _6) -> product(_2, _3, _4, _5, _1, _6)); + } + + @Override + default Product6<_5, _1, _2, _3, _4, _6> rotateR5() { + return into((_1, _2, _3, _4, _5, _6) -> product(_5, _1, _2, _3, _4, _6)); + } + + @Override + default Product6<_2, _3, _4, _1, _5, _6> rotateL4() { + return into((_1, _2, _3, _4, _5, _6) -> product(_2, _3, _4, _1, _5, _6)); + } + + @Override + default Product6<_4, _1, _2, _3, _5, _6> rotateR4() { + return into((_1, _2, _3, _4, _5, _6) -> product(_4, _1, _2, _3, _5, _6)); + } + + @Override + default Product6<_2, _3, _1, _4, _5, _6> rotateL3() { + return into((_1, _2, _3, _4, _5, _6) -> product(_2, _3, _1, _4, _5, _6)); + } + + @Override + default Product6<_3, _1, _2, _4, _5, _6> rotateR3() { + return into((_1, _2, _3, _4, _5, _6) -> product(_3, _1, _2, _4, _5, _6)); + } + + @Override + default Product6<_2, _1, _3, _4, _5, _6> invert() { + return into((_1, _2, _3, _4, _5, _6) -> product(_2, _1, _3, _4, _5, _6)); + } + + /** + * Static factory method for creating a generic {@link Product6}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param _3 the third slot + * @param _4 the fourth slot + * @param _5 the fifth slot + * @param _6 the sixth slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @param <_3> the third slot type + * @param <_4> the fourth slot type + * @param <_5> the fifth slot type + * @param <_6> the sixth slot type + * @return the {@link Product6} + */ + static <_1, _2, _3, _4, _5, _6> Product6<_1, _2, _3, _4, _5, _6> product(_1 _1, _2 _2, _3 _3, _4 _4, _5 _5, + _6 _6) { + return new Product6<_1, _2, _3, _4, _5, _6>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + + @Override + public _3 _3() { + return _3; + } + + @Override + public _4 _4() { + return _4; + } + + @Override + public _5 _5() { + return _5; + } + + @Override + public _6 _6() { + return _6; + } + }; + } } diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product7.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product7.java index 0ea905148..75b9fc1d8 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product7.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product7.java @@ -38,4 +38,126 @@ default R into( Fn7 fn) { return Product6.super.>into(fn).apply(_7()); } + + /** + * Rotate the first seven values of this product one slot to the left. + * + * @return the left-rotated product + */ + default Product7<_2, _3, _4, _5, _6, _7, _1> rotateL7() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_2, _3, _4, _5, _6, _7, _1)); + } + + /** + * Rotate the first seven values of this product one slot to the right. + * + * @return the right-rotated product + */ + default Product7<_7, _1, _2, _3, _4, _5, _6> rotateR7() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_7, _1, _2, _3, _4, _5, _6)); + } + + @Override + default Product7<_2, _3, _4, _5, _6, _1, _7> rotateL6() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_2, _3, _4, _5, _6, _1, _7)); + } + + @Override + default Product7<_6, _1, _2, _3, _4, _5, _7> rotateR6() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_6, _1, _2, _3, _4, _5, _7)); + } + + @Override + default Product7<_2, _3, _4, _5, _1, _6, _7> rotateL5() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_2, _3, _4, _5, _1, _6, _7)); + } + + @Override + default Product7<_5, _1, _2, _3, _4, _6, _7> rotateR5() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_5, _1, _2, _3, _4, _6, _7)); + } + + @Override + default Product7<_2, _3, _4, _1, _5, _6, _7> rotateL4() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_2, _3, _4, _1, _5, _6, _7)); + } + + @Override + default Product7<_4, _1, _2, _3, _5, _6, _7> rotateR4() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_4, _1, _2, _3, _5, _6, _7)); + } + + @Override + default Product7<_2, _3, _1, _4, _5, _6, _7> rotateL3() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_2, _3, _1, _4, _5, _6, _7)); + } + + @Override + default Product7<_3, _1, _2, _4, _5, _6, _7> rotateR3() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_3, _1, _2, _4, _5, _6, _7)); + } + + @Override + default Product7<_2, _1, _3, _4, _5, _6, _7> invert() { + return into((_1, _2, _3, _4, _5, _6, _7) -> product(_2, _1, _3, _4, _5, _6, _7)); + } + + /** + * Static factory method for creating a generic {@link Product7}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param _3 the third slot + * @param _4 the fourth slot + * @param _5 the fifth slot + * @param _6 the sixth slot + * @param _7 the seventh slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @param <_3> the third slot type + * @param <_4> the fourth slot type + * @param <_5> the fifth slot type + * @param <_6> the sixth slot type + * @param <_7> the seventh slot type + * @return the {@link Product7} + */ + static <_1, _2, _3, _4, _5, _6, _7> Product7<_1, _2, _3, _4, _5, _6, _7> product(_1 _1, _2 _2, _3 _3, _4 _4, _5 _5, + _6 _6, _7 _7) { + return new Product7<_1, _2, _3, _4, _5, _6, _7>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + + @Override + public _3 _3() { + return _3; + } + + @Override + public _4 _4() { + return _4; + } + + @Override + public _5 _5() { + return _5; + } + + @Override + public _6 _6() { + return _6; + } + + @Override + public _7 _7() { + return _7; + } + }; + } } diff --git a/src/main/java/com/jnape/palatable/lambda/adt/product/Product8.java b/src/main/java/com/jnape/palatable/lambda/adt/product/Product8.java index 46fef4b86..2b51e1bf0 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/product/Product8.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/product/Product8.java @@ -39,4 +39,144 @@ default R into( Fn8 fn) { return Product7.super.>into(fn).apply(_8()); } + + /** + * Rotate all eight values of this product one slot to the left. + * + * @return the left-rotated product + */ + default Product8<_2, _3, _4, _5, _6, _7, _8, _1> rotateL8() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _3, _4, _5, _6, _7, _8, _1)); + } + + /** + * Rotate all eight values of this product one slot to the right. + * + * @return the right-rotated product + */ + default Product8<_8, _1, _2, _3, _4, _5, _6, _7> rotateR8() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_8, _1, _2, _3, _4, _5, _6, _7)); + } + + @Override + default Product8<_2, _3, _4, _5, _6, _7, _1, _8> rotateL7() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _3, _4, _5, _6, _7, _1, _8)); + } + + @Override + default Product8<_7, _1, _2, _3, _4, _5, _6, _8> rotateR7() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_7, _1, _2, _3, _4, _5, _6, _8)); + } + + @Override + default Product8<_2, _3, _4, _5, _6, _1, _7, _8> rotateL6() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _3, _4, _5, _6, _1, _7, _8)); + } + + @Override + default Product8<_6, _1, _2, _3, _4, _5, _7, _8> rotateR6() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_6, _1, _2, _3, _4, _5, _7, _8)); + } + + @Override + default Product8<_2, _3, _4, _5, _1, _6, _7, _8> rotateL5() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _3, _4, _5, _1, _6, _7, _8)); + } + + @Override + default Product8<_5, _1, _2, _3, _4, _6, _7, _8> rotateR5() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_5, _1, _2, _3, _4, _6, _7, _8)); + } + + @Override + default Product8<_2, _3, _4, _1, _5, _6, _7, _8> rotateL4() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _3, _4, _1, _5, _6, _7, _8)); + } + + @Override + default Product8<_4, _1, _2, _3, _5, _6, _7, _8> rotateR4() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_4, _1, _2, _3, _5, _6, _7, _8)); + } + + @Override + default Product8<_2, _3, _1, _4, _5, _6, _7, _8> rotateL3() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _3, _1, _4, _5, _6, _7, _8)); + } + + @Override + default Product8<_3, _1, _2, _4, _5, _6, _7, _8> rotateR3() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_3, _1, _2, _4, _5, _6, _7, _8)); + } + + @Override + default Product8<_2, _1, _3, _4, _5, _6, _7, _8> invert() { + return into((_1, _2, _3, _4, _5, _6, _7, _8) -> product(_2, _1, _3, _4, _5, _6, _7, _8)); + } + + /** + * Static factory method for creating a generic {@link Product8}. + * + * @param _1 the first slot + * @param _2 the second slot + * @param _3 the third slot + * @param _4 the fourth slot + * @param _5 the fifth slot + * @param _6 the sixth slot + * @param _7 the seventh slot + * @param _8 the eighth slot + * @param <_1> the first slot type + * @param <_2> the second slot type + * @param <_3> the third slot type + * @param <_4> the fourth slot type + * @param <_5> the fifth slot type + * @param <_6> the sixth slot type + * @param <_7> the seventh slot type + * @param <_8> the eighth slot type + * @return the {@link Product8} + */ + static <_1, _2, _3, _4, _5, _6, _7, _8> Product8<_1, _2, _3, _4, _5, _6, _7, _8> product(_1 _1, _2 _2, _3 _3, _4 _4, + _5 _5, _6 _6, _7 _7, + _8 _8) { + return new Product8<_1, _2, _3, _4, _5, _6, _7, _8>() { + @Override + public _1 _1() { + return _1; + } + + @Override + public _2 _2() { + return _2; + } + + @Override + public _3 _3() { + return _3; + } + + @Override + public _4 _4() { + return _4; + } + + @Override + public _5 _5() { + return _5; + } + + @Override + public _6 _6() { + return _6; + } + + @Override + public _7 _7() { + return _7; + } + + @Override + public _8 _8() { + return _8; + } + }; + } } diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java index d094cd39d..4fe4837e0 100644 --- a/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product2Test.java @@ -1,5 +1,6 @@ package com.jnape.palatable.lambda.adt.product; +import org.junit.Before; import org.junit.Test; import static com.jnape.palatable.lambda.adt.product.Product2.product; @@ -7,17 +8,21 @@ public class Product2Test { + private Product2 product; + + @Before + public void setUp() { + product = product("a", "b"); + } + @Test public void staticFactoryMethod() { - Product2 product = product("a", "b"); assertEquals("a", product._1()); assertEquals("b", product._2()); } @Test public void invert() { - Product2 inverted = product("a", "b").invert(); - assertEquals("b", inverted._1()); - assertEquals("a", inverted._2()); + assertEquals("ba", product.invert().into((a, b) -> a + b)); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product3Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product3Test.java new file mode 100644 index 000000000..f6533e682 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product3Test.java @@ -0,0 +1,31 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Before; +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product3.product; +import static org.junit.Assert.assertEquals; + +public class Product3Test { + + private Product3 product; + + @Before + public void setUp() { + product = product("a", "b", "c"); + } + + @Test + public void staticFactoryMethod() { + assertEquals("a", product._1()); + assertEquals("b", product._2()); + assertEquals("c", product._3()); + } + + @Test + public void rotations() { + assertEquals("bac", product.invert().into((a, b, c) -> a + b + c)); + assertEquals("bca", product.rotateL3().into((a, b, c) -> a + b + c)); + assertEquals("cab", product.rotateR3().into((a, b, c) -> a + b + c)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product4Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product4Test.java new file mode 100644 index 000000000..12d6b3c19 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product4Test.java @@ -0,0 +1,34 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Before; +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product4.product; +import static org.junit.Assert.assertEquals; + +public class Product4Test { + + private Product4 product; + + @Before + public void setUp() { + product = product("a", "b", "c", "d"); + } + + @Test + public void staticFactoryMethod() { + assertEquals("a", product._1()); + assertEquals("b", product._2()); + assertEquals("c", product._3()); + assertEquals("d", product._4()); + } + + @Test + public void rotations() { + assertEquals("bacd", product.invert().into((a, b, c, d) -> a + b + c + d)); + assertEquals("bcad", product.rotateL3().into((a, b, c, d) -> a + b + c + d)); + assertEquals("cabd", product.rotateR3().into((a, b, c, d) -> a + b + c + d)); + assertEquals("bcda", product.rotateL4().into((a, b, c, d) -> a + b + c + d)); + assertEquals("dabc", product.rotateR4().into((a, b, c, d) -> a + b + c + d)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product5Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product5Test.java new file mode 100644 index 000000000..63723741f --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product5Test.java @@ -0,0 +1,37 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Before; +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product5.product; +import static org.junit.Assert.assertEquals; + +public class Product5Test { + + private Product5 product; + + @Before + public void setUp() { + product = product("a", "b", "c", "d", "e"); + } + + @Test + public void staticFactoryMethod() { + assertEquals("a", product._1()); + assertEquals("b", product._2()); + assertEquals("c", product._3()); + assertEquals("d", product._4()); + assertEquals("e", product._5()); + } + + @Test + public void rotations() { + assertEquals("bacde", product.invert().into((a, b, c, d, e) -> a + b + c + d + e)); + assertEquals("bcade", product.rotateL3().into((a, b, c, d, e) -> a + b + c + d + e)); + assertEquals("cabde", product.rotateR3().into((a, b, c, d, e) -> a + b + c + d + e)); + assertEquals("bcdae", product.rotateL4().into((a, b, c, d, e) -> a + b + c + d + e)); + assertEquals("dabce", product.rotateR4().into((a, b, c, d, e) -> a + b + c + d + e)); + assertEquals("bcdea", product.rotateL5().into((a, b, c, d, e) -> a + b + c + d + e)); + assertEquals("eabcd", product.rotateR5().into((a, b, c, d, e) -> a + b + c + d + e)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product6Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product6Test.java new file mode 100644 index 000000000..aa6e0ceb7 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product6Test.java @@ -0,0 +1,40 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Before; +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product6.product; +import static org.junit.Assert.assertEquals; + +public class Product6Test { + + private Product6 product; + + @Before + public void setUp() { + product = product("a", "b", "c", "d", "e", "f"); + } + + @Test + public void staticFactoryMethod() { + assertEquals("a", product._1()); + assertEquals("b", product._2()); + assertEquals("c", product._3()); + assertEquals("d", product._4()); + assertEquals("e", product._5()); + assertEquals("f", product._6()); + } + + @Test + public void rotations() { + assertEquals("bacdef", product.invert().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("bcadef", product.rotateL3().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("cabdef", product.rotateR3().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("bcdaef", product.rotateL4().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("dabcef", product.rotateR4().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("bcdeaf", product.rotateL5().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("eabcdf", product.rotateR5().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("bcdefa", product.rotateL6().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + assertEquals("fabcde", product.rotateR6().into((a, b, c, d, e, f) -> a + b + c + d + e + f)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product7Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product7Test.java new file mode 100644 index 000000000..a5cd04b5f --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product7Test.java @@ -0,0 +1,43 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Before; +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product7.product; +import static org.junit.Assert.assertEquals; + +public class Product7Test { + + private Product7 product; + + @Before + public void setUp() { + product = product("a", "b", "c", "d", "e", "f", "g"); + } + + @Test + public void staticFactoryMethod() { + assertEquals("a", product._1()); + assertEquals("b", product._2()); + assertEquals("c", product._3()); + assertEquals("d", product._4()); + assertEquals("e", product._5()); + assertEquals("f", product._6()); + assertEquals("g", product._7()); + } + + @Test + public void rotations() { + assertEquals("bacdefg", product.invert().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("bcadefg", product.rotateL3().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("cabdefg", product.rotateR3().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("bcdaefg", product.rotateL4().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("dabcefg", product.rotateR4().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("bcdeafg", product.rotateL5().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("eabcdfg", product.rotateR5().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("bcdefag", product.rotateL6().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("fabcdeg", product.rotateR6().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("bcdefga", product.rotateL7().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + assertEquals("gabcdef", product.rotateR7().into((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/adt/product/Product8Test.java b/src/test/java/com/jnape/palatable/lambda/adt/product/Product8Test.java new file mode 100644 index 000000000..64360b763 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/adt/product/Product8Test.java @@ -0,0 +1,46 @@ +package com.jnape.palatable.lambda.adt.product; + +import org.junit.Before; +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.product.Product8.product; +import static org.junit.Assert.assertEquals; + +public class Product8Test { + + private Product8 product; + + @Before + public void setUp() { + product = product("a", "b", "c", "d", "e", "f", "g", "h"); + } + + @Test + public void staticFactoryMethod() { + assertEquals("a", product._1()); + assertEquals("b", product._2()); + assertEquals("c", product._3()); + assertEquals("d", product._4()); + assertEquals("e", product._5()); + assertEquals("f", product._6()); + assertEquals("g", product._7()); + assertEquals("h", product._8()); + } + + @Test + public void rotations() { + assertEquals("bacdefgh", product.invert().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("bcadefgh", product.rotateL3().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("cabdefgh", product.rotateR3().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("bcdaefgh", product.rotateL4().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("dabcefgh", product.rotateR4().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("bcdeafgh", product.rotateL5().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("eabcdfgh", product.rotateR5().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("bcdefagh", product.rotateL6().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("fabcdegh", product.rotateR6().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("bcdefgah", product.rotateL7().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("gabcdefh", product.rotateR7().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("bcdefgha", product.rotateL8().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + assertEquals("habcdefg", product.rotateR8().into((a, b, c, d, e, f, g, h) -> a + b + c + d + e + f + g + h)); + } +} \ No newline at end of file From d64c078a21d07a13b196b93469758a70d2f9b724 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 5 Aug 2018 17:37:07 -0500 Subject: [PATCH 10/31] Effect#apply() now the required method to implement --- CHANGELOG.md | 1 + .../palatable/lambda/functions/Effect.java | 33 +++++++++++++++---- .../lambda/functions/specialized/Noop.java | 6 +--- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index baf77d010..7670e2229 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - ***Breaking Change***: `Difference` and `Intersection` no longer instances of `Semigroup` and moved to `functions.builtin.fn2` package - ***Breaking Change***: `Absent` moved to `semigroup.builtin` package - `RightAny` overload returns `Monoid` +- `Effect#apply()` is now the required method to implement in the functional interface ### Added - `Predicate#predicate` static factory method diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Effect.java b/src/main/java/com/jnape/palatable/lambda/functions/Effect.java index 62bfb941e..ead5d645f 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Effect.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Effect.java @@ -20,8 +20,9 @@ public interface Effect extends Fn1, Consumer { @Override - default void accept(A a) { - apply(a); + default Unit apply(A a) { + accept(a); + return UNIT; } @Override @@ -46,9 +47,27 @@ default Effect discardR(Applicative> appB) { @Override default Effect andThen(Consumer after) { - return a -> { - Consumer.super.andThen(after).accept(a); - return UNIT; - }; + return Consumer.super.andThen(after)::accept; } -} + + /** + * Static factory method to aid in inference. + * + * @param effect the effect + * @param the effect argument type + * @return the effect + */ + static Effect effect(Consumer effect) { + return effect::accept; + } + + /** + * Create an {@link Effect} from a {@link Runnable}; + * + * @param runnable the runnable + * @return the effect + */ + static Effect effect(Runnable runnable) { + return effect(__ -> runnable.run()); + } +} \ No newline at end of file diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/Noop.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/Noop.java index 2977f5f58..62c5192f4 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/specialized/Noop.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/Noop.java @@ -1,10 +1,7 @@ package com.jnape.palatable.lambda.functions.specialized; -import com.jnape.palatable.lambda.adt.Unit; import com.jnape.palatable.lambda.functions.Effect; -import static com.jnape.palatable.lambda.adt.Unit.UNIT; - /** * As the name might suggest, this is an {@link Effect} that, *ahem*, has no effect. * @@ -17,8 +14,7 @@ private Noop() { } @Override - public Unit apply(A a) { - return UNIT; + public void accept(A a) { } /** From 32e084b20dce602c28d21506c66d9dd09521f0fb Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 5 Aug 2018 17:47:15 -0500 Subject: [PATCH 11/31] Fn0#apply() is now the method to implement --- CHANGELOG.md | 3 +- .../jnape/palatable/lambda/functions/Fn0.java | 39 ++++++++----------- .../jnape/palatable/lambda/functions/Fn1.java | 2 +- .../palatable/lambda/functions/Fn0Test.java | 3 +- .../java/testsupport/EqualityAwareFn0.java | 7 +++- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7670e2229..82cf09770 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Changed - ***Breaking Change***: `Difference` and `Intersection` no longer instances of `Semigroup` and moved to `functions.builtin.fn2` package - ***Breaking Change***: `Absent` moved to `semigroup.builtin` package +- ***Breaking Change***: `Effect#accept()` is now the required method to implement in the functional interface +- ***Breaking Change***: `Fn0#apply()` is now the required method to implement in the functional interface - `RightAny` overload returns `Monoid` -- `Effect#apply()` is now the required method to implement in the functional interface ### Added - `Predicate#predicate` static factory method diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java b/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java index c3599b84f..357a28a3c 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java @@ -8,6 +8,7 @@ import java.util.function.Supplier; import static com.jnape.palatable.lambda.adt.Unit.UNIT; +import static com.jnape.palatable.lambda.functions.Effect.effect; /** * A function taking "no arguments", implemented as an {@link Fn1}<{@link Unit}, A>. @@ -19,6 +20,8 @@ @FunctionalInterface public interface Fn0 extends Fn1, Supplier { + A apply(); + /** * Invoke this function with {@link Unit}. * @@ -26,55 +29,48 @@ public interface Fn0 extends Fn1, Supplier { * @return the result value */ @Override - A apply(Unit unit); - - /** - * Apply this {@link Fn0}, supplying {@link Unit} as the input. - * - * @return the output - */ - default A apply() { - return apply(UNIT); + default A apply(Unit unit) { + return apply(); } @Override default Fn0 flatMap(Function>> f) { - return Fn1.super.flatMap(f)::apply; + return Fn1.super.flatMap(f).thunk(UNIT); } @Override default Fn0 fmap(Function f) { - return Fn1.super.fmap(f)::apply; + return Fn1.super.fmap(f).thunk(UNIT); } @Override default Fn0 pure(B b) { - return Fn1.super.pure(b)::apply; + return Fn1.super.pure(b).thunk(UNIT); } @Override default Fn0 zip(Applicative, Fn1> appFn) { - return Fn1.super.zip(appFn)::apply; + return Fn1.super.zip(appFn).thunk(UNIT); } @Override default Fn0 zip(Fn2 appFn) { - return Fn1.super.zip(appFn)::apply; + return Fn1.super.zip(appFn).thunk(UNIT); } @Override default Fn0 discardL(Applicative> appB) { - return Fn1.super.discardL(appB)::apply; + return Fn1.super.discardL(appB).thunk(UNIT); } @Override default Fn0 discardR(Applicative> appB) { - return Fn1.super.discardR(appB)::apply; + return Fn1.super.discardR(appB).thunk(UNIT); } @Override default Fn0 diMapR(Function fn) { - return Fn1.super.diMapR(fn)::apply; + return Fn1.super.diMapR(fn).thunk(UNIT); } @Override @@ -84,7 +80,7 @@ default Fn1 compose(Function before) { @Override default Fn0 andThen(Function after) { - return Fn1.super.andThen(after)::apply; + return Fn1.super.andThen(after).thunk(UNIT); } @Override @@ -100,7 +96,7 @@ default A get() { * @return the {@link Fn0} */ static Fn0 fn0(Supplier supplier) { - return __ -> supplier.get(); + return supplier::get; } /** @@ -121,10 +117,7 @@ static Fn0 fn0(Fn0 fn) { * @return the {@link Fn0} */ static Fn0 fn0(Runnable fn) { - return unit -> { - fn.run(); - return unit; - }; + return effect(fn).thunk(UNIT); } /** diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java b/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java index 2d52031ce..092b5b953 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java @@ -36,7 +36,7 @@ public interface Fn1 extends Monad>, Profunctor, F * @return an {@link Fn0} */ default Fn0 thunk(A a) { - return __ -> apply(a); + return () -> apply(a); } /** diff --git a/src/test/java/com/jnape/palatable/lambda/functions/Fn0Test.java b/src/test/java/com/jnape/palatable/lambda/functions/Fn0Test.java index d57027c70..d04084205 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/Fn0Test.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/Fn0Test.java @@ -8,6 +8,7 @@ import testsupport.traits.FunctorLaws; import testsupport.traits.MonadLaws; +import static com.jnape.palatable.lambda.adt.Unit.UNIT; import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; @RunWith(Traits.class) @@ -15,6 +16,6 @@ public class Fn0Test { @TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class}) public Fn0 testSubject() { - return new EqualityAwareFn0<>(constantly(1)::apply); + return new EqualityAwareFn0<>(constantly(1).thunk(UNIT)); } } \ No newline at end of file diff --git a/src/test/java/testsupport/EqualityAwareFn0.java b/src/test/java/testsupport/EqualityAwareFn0.java index 188c5b49b..17b3318d5 100644 --- a/src/test/java/testsupport/EqualityAwareFn0.java +++ b/src/test/java/testsupport/EqualityAwareFn0.java @@ -18,9 +18,14 @@ public EqualityAwareFn0(Fn0 fn) { this.fn = fn; } + @Override + public A apply() { + return fn.apply(); + } + @Override public A apply(Unit unit) { - return fn.apply(unit); + return apply(); } @Override From dfa22e5ee803013a3fd637c11122a6ce4bf3c6bf Mon Sep 17 00:00:00 2001 From: jnape Date: Fri, 17 Aug 2018 17:58:27 -0500 Subject: [PATCH 12/31] Adding CheckedEffect1 and CheckedFn1 static factory method --- CHANGELOG.md | 4 +- .../specialized/checked/CheckedEffect1.java | 48 +++++++++++++++++++ .../specialized/checked/CheckedFn1.java | 14 ++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 82cf09770..0f25b3ac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Added - `Predicate#predicate` static factory method - `Product2-8` left/right rotation methods -- `Tuple2-8` specializations of left/right product rotation +- `Tuple2-8` specializations of left/right product rotation +- `CheckedEffect`, an `Effect` variant that can throw checked exceptions +- `CheckedFn1#checked`, convenience static factory method to aid inference ## [3.1.0] - 2018-07-16 ### Added diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java new file mode 100644 index 000000000..aa459b4da --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java @@ -0,0 +1,48 @@ +package com.jnape.palatable.lambda.functions.specialized.checked; + +import com.jnape.palatable.lambda.functions.Effect; + +import static com.jnape.palatable.lambda.functions.specialized.checked.Runtime.throwChecked; + +/** + * Specialized {@link Effect} that can throw any {@link Throwable}. + * + * @param The {@link Throwable} type + * @param The input type + * @see CheckedRunnable + * @see CheckedFn1 + * @see Effect + */ +@FunctionalInterface +public interface CheckedEffect1 extends Effect { + + @Override + default void accept(A a) { + try { + checkedAccept(a); + } catch (Throwable t) { + throw throwChecked(t); + } + } + + /** + * A version of {@link Effect#accept} that can throw checked exceptions. + * + * @param a the effect argument + * @throws T any exception that can be thrown by this method + */ + void checkedAccept(A a) throws T; + + /** + * Convenience static factory method for constructing a {@link CheckedEffect1} without an explicit cast or type + * attribution at the call site. + * + * @param checkedEffect the checked effect + * @param the inferred Throwable type + * @param the input type + * @return the checked effect + */ + static CheckedEffect1 checked(CheckedEffect1 checkedEffect) { + return checkedEffect; + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedFn1.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedFn1.java index 3d5a9176c..e35dd70da 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedFn1.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedFn1.java @@ -34,4 +34,18 @@ default B apply(A a) { * @throws T any exception that can be thrown by this method */ B checkedApply(A a) throws T; + + /** + * Convenience static factory method for constructing a {@link CheckedFn1} without an explicit cast or type + * attribution at the call site. + * + * @param checkedFn1 the checked fn1 + * @param the inferred Throwable type + * @param the input type + * @param the output type + * @return the checked fn1 + */ + static CheckedFn1 checked(CheckedFn1 checkedFn1) { + return checkedFn1; + } } From 6c608b415c7249d0937a2ec4203a63a4be620f17 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 19 Aug 2018 16:59:21 -0500 Subject: [PATCH 13/31] Reworking monoid folds to rely on foldmap monoid folding now implicitly starts with identity AddAll monoid no longer mutates argument references AddAll semigroup deprecated in favor of monoid --- CHANGELOG.md | 7 +++++ .../jnape/palatable/lambda/adt/Either.java | 5 +-- .../com/jnape/palatable/lambda/adt/Try.java | 2 +- .../lambda/functions/builtin/fn1/Not.java | 8 ++--- .../lambda/functions/builtin/fn2/All.java | 8 ++--- .../lambda/functions/builtin/fn2/Any.java | 8 ++--- .../functions/builtin/fn2/DropWhile.java | 8 ++--- .../lambda/functions/builtin/fn2/Filter.java | 8 ++--- .../lambda/functions/builtin/fn2/Find.java | 8 ++--- .../functions/builtin/fn2/MagnetizeBy.java | 8 ++--- .../lambda/functions/builtin/fn2/Span.java | 9 +++--- .../functions/builtin/fn2/TakeWhile.java | 8 ++--- .../functions/builtin/fn4/IfThenElse.java | 12 +++---- .../functions/specialized/Predicate.java | 2 +- .../lambda/iteration/FilteringIterable.java | 10 +++--- .../lambda/iteration/FilteringIterator.java | 6 ++-- .../iteration/PredicatedDroppingIterable.java | 10 +++--- .../iteration/PredicatedDroppingIterator.java | 8 ++--- .../iteration/PredicatedTakingIterable.java | 10 +++--- .../iteration/PredicatedTakingIterator.java | 8 ++--- .../jnape/palatable/lambda/monoid/Monoid.java | 14 +++++---- .../lambda/monoid/builtin/AddAll.java | 31 ++++++++++++++++--- .../palatable/lambda/monoid/builtin/And.java | 8 +++-- .../lambda/monoid/builtin/Concat.java | 9 ++++++ .../lambda/monoid/builtin/First.java | 7 +++-- .../palatable/lambda/monoid/builtin/Or.java | 8 +++-- .../lambda/semigroup/builtin/AddAll.java | 2 ++ .../lambda/functions/builtin/fn2/AllTest.java | 4 +-- .../lambda/functions/builtin/fn2/AnyTest.java | 2 +- .../lambda/semigroup/builtin/AddAllTest.java | 20 ------------ 30 files changed, 144 insertions(+), 114 deletions(-) delete mode 100644 src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AddAllTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f25b3ac8..889c223eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - ***Breaking Change***: `Effect#accept()` is now the required method to implement in the functional interface - ***Breaking Change***: `Fn0#apply()` is now the required method to implement in the functional interface - `RightAny` overload returns `Monoid` +- monoids now all fold with respect to `foldMap` +- monoid folding now implicitly starts with the identity, regardless of iterable population +- `Concat` monoid can now fold infinite iterables +- all `Function` are now `Function` for better compatibility ### Added - `Predicate#predicate` static factory method @@ -18,6 +22,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `CheckedEffect`, an `Effect` variant that can throw checked exceptions - `CheckedFn1#checked`, convenience static factory method to aid inference +### Deprecated +- `AddAll` semigroup, in favor of the monoid that no longer mutates any argument + ## [3.1.0] - 2018-07-16 ### Added - `Fn3-8` static factory overloads to aid in coercing lambdas diff --git a/src/main/java/com/jnape/palatable/lambda/adt/Either.java b/src/main/java/com/jnape/palatable/lambda/adt/Either.java index be6ed52ac..d9c9d2fa1 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/Either.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/Either.java @@ -92,7 +92,7 @@ public final R orThrow(Function th * @return this if a left value or a right value that pred matches; otherwise, the result of leftSupplier wrapped in * a left */ - public final Either filter(Function pred, Supplier leftSupplier) { + public final Either filter(Function pred, Supplier leftSupplier) { return filter(pred, __ -> leftSupplier.get()); } @@ -105,7 +105,8 @@ public final Either filter(Function pred, Supplier * @return this is a left value or a right value that pred matches; otherwise, the result of leftFn applied to the * right value, wrapped in a left */ - public final Either filter(Function pred, Function leftFn) { + public final Either filter(Function pred, + Function leftFn) { return flatMap(r -> pred.apply(r) ? right(r) : left(leftFn.apply(r))); } diff --git a/src/main/java/com/jnape/palatable/lambda/adt/Try.java b/src/main/java/com/jnape/palatable/lambda/adt/Try.java index 74dded5cb..d629a967b 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/Try.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/Try.java @@ -52,7 +52,7 @@ public final Try catching(Class throwableType, Function catching(Function predicate, + public final Try catching(Function predicate, Function recoveryFn) { return match(t -> predicate.apply(t) ? success(recoveryFn.apply(t)) : failure(t), Try::success); } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn1/Not.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn1/Not.java index 5f8718c8b..5f0bb8691 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn1/Not.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn1/Not.java @@ -10,14 +10,14 @@ * * @param the input argument type */ -public final class Not implements BiPredicate, A> { +public final class Not implements BiPredicate, A> { private static final Not INSTANCE = new Not(); private Not() { } @Override - public Boolean apply(Function pred, A a) { + public Boolean apply(Function pred, A a) { return !pred.apply(a); } @@ -26,11 +26,11 @@ public static Not not() { return INSTANCE; } - public static Predicate not(Function pred) { + public static Predicate not(Function pred) { return Not.not().apply(pred); } - public static Boolean not(Function pred, A a) { + public static Boolean not(Function pred, A a) { return not(pred).apply(a); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/All.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/All.java index 53ecac095..2aeb00eca 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/All.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/All.java @@ -13,7 +13,7 @@ * @param The input Iterable element type * @see Any */ -public final class All implements BiPredicate, Iterable> { +public final class All implements BiPredicate, Iterable> { private static final All INSTANCE = new All(); @@ -21,7 +21,7 @@ private All() { } @Override - public Boolean apply(Function predicate, Iterable as) { + public Boolean apply(Function predicate, Iterable as) { for (A a : as) if (!predicate.apply(a)) return false; @@ -34,11 +34,11 @@ public static All all() { return INSTANCE; } - public static Fn1, Boolean> all(Function predicate) { + public static Fn1, ? extends Boolean> all(Function predicate) { return All.all().apply(predicate); } - public static Boolean all(Function predicate, Iterable as) { + public static Boolean all(Function predicate, Iterable as) { return All.all(predicate).apply(as); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Any.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Any.java index fa8db83b4..6285084f5 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Any.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Any.java @@ -13,7 +13,7 @@ * @param The input Iterable element type * @see All */ -public final class Any implements BiPredicate, Iterable> { +public final class Any implements BiPredicate, Iterable> { private static final Any INSTANCE = new Any(); @@ -21,7 +21,7 @@ private Any() { } @Override - public Boolean apply(Function predicate, Iterable as) { + public Boolean apply(Function predicate, Iterable as) { for (A a : as) if (predicate.apply(a)) return true; @@ -34,11 +34,11 @@ public static Any any() { return INSTANCE; } - public static Predicate> any(Function predicate) { + public static Predicate> any(Function predicate) { return Any.any().apply(predicate); } - public static Boolean any(Function predicate, Iterable as) { + public static Boolean any(Function predicate, Iterable as) { return Any.any(predicate).apply(as); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhile.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhile.java index 9b87e63b0..560f35c5c 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhile.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/DropWhile.java @@ -16,7 +16,7 @@ * @see TakeWhile */ -public final class DropWhile implements Fn2, Iterable, Iterable> { +public final class DropWhile implements Fn2, Iterable, Iterable> { private static final DropWhile INSTANCE = new DropWhile(); @@ -24,7 +24,7 @@ private DropWhile() { } @Override - public Iterable apply(Function predicate, Iterable as) { + public Iterable apply(Function predicate, Iterable as) { return new PredicatedDroppingIterable<>(predicate, as); } @@ -33,11 +33,11 @@ public static DropWhile dropWhile() { return INSTANCE; } - public static Fn1, Iterable> dropWhile(Function predicate) { + public static Fn1, Iterable> dropWhile(Function predicate) { return DropWhile.dropWhile().apply(predicate); } - public static Iterable dropWhile(Function predicate, Iterable as) { + public static Iterable dropWhile(Function predicate, Iterable as) { return DropWhile.dropWhile(predicate).apply(as); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Filter.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Filter.java index 787978318..fd0c70e7a 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Filter.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Filter.java @@ -14,7 +14,7 @@ * @see TakeWhile * @see DropWhile */ -public final class Filter implements Fn2, Iterable, Iterable> { +public final class Filter implements Fn2, Iterable, Iterable> { private static final Filter INSTANCE = new Filter(); @@ -22,7 +22,7 @@ private Filter() { } @Override - public Iterable apply(Function predicate, Iterable as) { + public Iterable apply(Function predicate, Iterable as) { return new FilteringIterable<>(predicate, as); } @@ -31,11 +31,11 @@ public static Filter filter() { return INSTANCE; } - public static Fn1, Iterable> filter(Function predicate) { + public static Fn1, Iterable> filter(Function predicate) { return Filter.filter().apply(predicate); } - public static Iterable filter(Function predicate, Iterable as) { + public static Iterable filter(Function predicate, Iterable as) { return Filter.filter(predicate).apply(as); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Find.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Find.java index e1bb57be7..716a4f3e8 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Find.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Find.java @@ -18,7 +18,7 @@ * * @param the Iterable element type */ -public final class Find implements Fn2, Iterable, Maybe> { +public final class Find implements Fn2, Iterable, Maybe> { private static final Find INSTANCE = new Find(); @@ -26,7 +26,7 @@ private Find() { } @Override - public Maybe apply(Function predicate, Iterable as) { + public Maybe apply(Function predicate, Iterable as) { return head(dropWhile(not(predicate), as)); } @@ -35,11 +35,11 @@ public static Find find() { return INSTANCE; } - public static Fn1, Maybe> find(Function predicate) { + public static Fn1, Maybe> find(Function predicate) { return Find.find().apply(predicate); } - public static Maybe find(Function predicate, Iterable as) { + public static Maybe find(Function predicate, Iterable as) { return Find.find(predicate).apply(as); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/MagnetizeBy.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/MagnetizeBy.java index a7e512cc7..ef94c372a 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/MagnetizeBy.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/MagnetizeBy.java @@ -25,7 +25,7 @@ * * @param the {@link Iterable} element type */ -public final class MagnetizeBy implements Fn2, Iterable, Iterable>> { +public final class MagnetizeBy implements Fn2, Iterable, Iterable>> { private static final MagnetizeBy INSTANCE = new MagnetizeBy(); @@ -33,7 +33,7 @@ private MagnetizeBy() { } @Override - public Iterable> apply(BiFunction predicate, Iterable as) { + public Iterable> apply(BiFunction predicate, Iterable as) { return () -> uncons(as).fmap(into((A head, Iterable tail) -> { Iterable group = cons(head, unfoldr(into((pivot, ys) -> uncons(ys) .flatMap(into((y, recurse) -> predicate.apply(pivot, y) @@ -49,12 +49,12 @@ public static MagnetizeBy magnetizeBy() { } public static Fn1, Iterable>> magnetizeBy( - BiFunction predicate) { + BiFunction predicate) { return MagnetizeBy.magnetizeBy().apply(predicate); } public static Iterable> magnetizeBy( - BiFunction predicate, + BiFunction predicate, Iterable as) { return MagnetizeBy.magnetizeBy(predicate).apply(as); } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Span.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Span.java index cd41bc74a..aea792d08 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Span.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Span.java @@ -15,7 +15,7 @@ * * @param the {@link Iterable} element type */ -public final class Span implements Fn2, Iterable, Tuple2, Iterable>> { +public final class Span implements Fn2, Iterable, Tuple2, Iterable>> { private static final Span INSTANCE = new Span(); @@ -23,7 +23,7 @@ private Span() { } @Override - public Tuple2, Iterable> apply(Function predicate, Iterable as) { + public Tuple2, Iterable> apply(Function predicate, Iterable as) { return Tuple2.fill(as).biMap(takeWhile(predicate), dropWhile(predicate)); } @@ -32,11 +32,12 @@ public static Span span() { return INSTANCE; } - public static Fn1, Tuple2, Iterable>> span(Function predicate) { + public static Fn1, Tuple2, Iterable>> span( + Function predicate) { return Span.span().apply(predicate); } - public static Tuple2, Iterable> span(Function predicate, + public static Tuple2, Iterable> span(Function predicate, Iterable as) { return Span.span(predicate).apply(as); } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/TakeWhile.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/TakeWhile.java index 0b7bc7621..8285d953c 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/TakeWhile.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/TakeWhile.java @@ -15,7 +15,7 @@ * @see Filter * @see DropWhile */ -public final class TakeWhile implements Fn2, Iterable, Iterable> { +public final class TakeWhile implements Fn2, Iterable, Iterable> { private static final TakeWhile INSTANCE = new TakeWhile(); @@ -23,7 +23,7 @@ private TakeWhile() { } @Override - public Iterable apply(Function predicate, Iterable as) { + public Iterable apply(Function predicate, Iterable as) { return new PredicatedTakingIterable<>(predicate, as); } @@ -32,11 +32,11 @@ public static TakeWhile takeWhile() { return INSTANCE; } - public static Fn1, Iterable> takeWhile(Function predicate) { + public static Fn1, Iterable> takeWhile(Function predicate) { return TakeWhile.takeWhile().apply(predicate); } - public static Iterable takeWhile(Function predicate, Iterable as) { + public static Iterable takeWhile(Function predicate, Iterable as) { return TakeWhile.takeWhile(predicate).apply(as); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/IfThenElse.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/IfThenElse.java index fe353a497..d67440595 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/IfThenElse.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/IfThenElse.java @@ -7,7 +7,7 @@ import java.util.function.Function; -public final class IfThenElse implements Fn4, Function, Function, A, B> { +public final class IfThenElse implements Fn4, Function, Function, A, B> { private static final IfThenElse INSTANCE = new IfThenElse(); @@ -15,7 +15,7 @@ private IfThenElse() { } @Override - public B apply(Function predicate, Function thenCase, + public B apply(Function predicate, Function thenCase, Function elseCase, A a) { return predicate.apply(a) ? thenCase.apply(a) : elseCase.apply(a); } @@ -26,23 +26,23 @@ public static IfThenElse ifThenElse() { } public static Fn3, Function, A, B> ifThenElse( - Function predicate) { + Function predicate) { return IfThenElse.ifThenElse().apply(predicate); } public static Fn2, A, B> ifThenElse( - Function predicate, Function thenCase) { + Function predicate, Function thenCase) { return IfThenElse.ifThenElse(predicate).apply(thenCase); } public static Fn1 ifThenElse( - Function predicate, Function thenCase, + Function predicate, Function thenCase, Function elseCase) { return IfThenElse.ifThenElse(predicate, thenCase).apply(elseCase); } public static B ifThenElse( - Function predicate, Function thenCase, + Function predicate, Function thenCase, Function elseCase, A a) { return ifThenElse(predicate, thenCase, elseCase).apply(a); diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java index a9d0de708..2138db821 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/Predicate.java @@ -90,7 +90,7 @@ default Predicate negate() { * @param the input type * @return the predicate */ - static Predicate predicate(Function predicate) { + static Predicate predicate(Function predicate) { return predicate::apply; } } diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterable.java b/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterable.java index 4d3096051..1b9f315ff 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterable.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterable.java @@ -9,11 +9,11 @@ import static java.util.Collections.singletonList; public final class FilteringIterable implements Iterable { - private final List> predicates; - private final Iterable as; + private final List> predicates; + private final Iterable as; - public FilteringIterable(Function predicate, Iterable as) { - List> predicates = new ArrayList<>(singletonList(predicate)); + public FilteringIterable(Function predicate, Iterable as) { + List> predicates = new ArrayList<>(singletonList(predicate)); while (as instanceof FilteringIterable) { FilteringIterable nested = (FilteringIterable) as; predicates.addAll(0, nested.predicates); @@ -25,7 +25,7 @@ public FilteringIterable(Function predicate, Iterable as) @Override public Iterator iterator() { - Function metaPredicate = a -> all(p -> p.apply(a), predicates); + Function metaPredicate = a -> all(p -> p.apply(a), predicates); return new FilteringIterator<>(metaPredicate, as.iterator()); } } diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterator.java b/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterator.java index cde34d842..5b9358c01 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterator.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/FilteringIterator.java @@ -6,10 +6,10 @@ public final class FilteringIterator extends ImmutableIterator { - private final Function predicate; - private final RewindableIterator rewindableIterator; + private final Function predicate; + private final RewindableIterator rewindableIterator; - public FilteringIterator(Function predicate, Iterator iterator) { + public FilteringIterator(Function predicate, Iterator iterator) { this.predicate = predicate; rewindableIterator = new RewindableIterator<>(iterator); } diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterable.java b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterable.java index 10338ca7c..bd3aa87b6 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterable.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterable.java @@ -9,11 +9,11 @@ import static java.util.Collections.singletonList; public final class PredicatedDroppingIterable implements Iterable { - private final List> predicates; - private final Iterable as; + private final List> predicates; + private final Iterable as; - public PredicatedDroppingIterable(Function predicate, Iterable as) { - List> predicates = new ArrayList<>(singletonList(predicate)); + public PredicatedDroppingIterable(Function predicate, Iterable as) { + List> predicates = new ArrayList<>(singletonList(predicate)); while (as instanceof PredicatedDroppingIterable) { PredicatedDroppingIterable nested = (PredicatedDroppingIterable) as; @@ -26,7 +26,7 @@ public PredicatedDroppingIterable(Function predicate, Iterab @Override public Iterator iterator() { - Function metaPredicate = a -> any(p -> p.apply(a), predicates); + Function metaPredicate = a -> any(p -> p.apply(a), predicates); return new PredicatedDroppingIterator<>(metaPredicate, as.iterator()); } } diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterator.java b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterator.java index 852ee37ed..7fe16c64b 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterator.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedDroppingIterator.java @@ -5,11 +5,11 @@ import java.util.function.Function; public final class PredicatedDroppingIterator extends ImmutableIterator { - private final Function predicate; - private final RewindableIterator rewindableIterator; - private boolean finishedDropping; + private final Function predicate; + private final RewindableIterator rewindableIterator; + private boolean finishedDropping; - public PredicatedDroppingIterator(Function predicate, Iterator asIterator) { + public PredicatedDroppingIterator(Function predicate, Iterator asIterator) { this.predicate = predicate; rewindableIterator = new RewindableIterator<>(asIterator); finishedDropping = false; diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterable.java b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterable.java index dc15675a7..14201849d 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterable.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterable.java @@ -9,11 +9,11 @@ import static java.util.Collections.singletonList; public final class PredicatedTakingIterable implements Iterable { - private final List> predicates; - private final Iterable as; + private final List> predicates; + private final Iterable as; - public PredicatedTakingIterable(Function predicate, Iterable as) { - List> predicates = new ArrayList<>(singletonList(predicate)); + public PredicatedTakingIterable(Function predicate, Iterable as) { + List> predicates = new ArrayList<>(singletonList(predicate)); while (as instanceof PredicatedTakingIterable) { PredicatedTakingIterable nested = (PredicatedTakingIterable) as; predicates.addAll(0, nested.predicates); @@ -25,7 +25,7 @@ public PredicatedTakingIterable(Function predicate, Iterable @Override public Iterator iterator() { - Function metaPredicate = a -> all(p -> p.apply(a), predicates); + Function metaPredicate = a -> all(p -> p.apply(a), predicates); return new PredicatedTakingIterator<>(metaPredicate, as.iterator()); } } diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterator.java b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterator.java index 6612b50d1..370ef1e84 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterator.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/PredicatedTakingIterator.java @@ -5,11 +5,11 @@ import java.util.function.Function; public final class PredicatedTakingIterator extends ImmutableIterator { - private final Function predicate; - private final RewindableIterator rewindableIterator; - private boolean stillTaking; + private final Function predicate; + private final RewindableIterator rewindableIterator; + private boolean stillTaking; - public PredicatedTakingIterator(Function predicate, + public PredicatedTakingIterator(Function predicate, Iterator asIterator) { this.predicate = predicate; rewindableIterator = new RewindableIterator<>(asIterator); diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java b/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java index 1a18a2f8a..6cdf12b1e 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/Monoid.java @@ -3,14 +3,16 @@ import com.jnape.palatable.lambda.functions.builtin.fn2.Map; import com.jnape.palatable.lambda.functions.builtin.fn2.ReduceLeft; import com.jnape.palatable.lambda.functions.builtin.fn2.ReduceRight; +import com.jnape.palatable.lambda.functions.builtin.fn3.FoldLeft; import com.jnape.palatable.lambda.semigroup.Semigroup; import java.util.function.Function; import java.util.function.Supplier; +import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id; +import static com.jnape.palatable.lambda.functions.builtin.fn1.Reverse.reverse; import static com.jnape.palatable.lambda.functions.builtin.fn2.Cons.cons; import static com.jnape.palatable.lambda.functions.builtin.fn2.Map.map; -import static com.jnape.palatable.lambda.functions.builtin.fn2.Snoc.snoc; /** * A {@link Monoid} is the pairing of a {@link Semigroup} with an identity element. @@ -35,7 +37,7 @@ public interface Monoid extends Semigroup { * @see ReduceLeft */ default A reduceLeft(Iterable as) { - return ReduceLeft.reduceLeft(toBiFunction(), as).orElse(identity()); + return foldMap(id(), as); } /** @@ -47,7 +49,7 @@ default A reduceLeft(Iterable as) { * @see ReduceRight */ default A reduceRight(Iterable as) { - return ReduceRight.reduceRight(toBiFunction(), as).orElse(identity()); + return flip().foldMap(id(), reverse(as)); } /** @@ -63,7 +65,7 @@ default A reduceRight(Iterable as) { * @see Monoid#reduceLeft(Iterable) */ default A foldMap(Function fn, Iterable bs) { - return reduceLeft(map(fn, bs)); + return FoldLeft.foldLeft(this.toBiFunction(), identity(), map(fn, bs)); } /** @@ -71,7 +73,7 @@ default A foldMap(Function fn, Iterable bs) { */ @Override default A foldLeft(A a, Iterable as) { - return reduceLeft(cons(a, as)); + return foldMap(id(), cons(a, as)); } /** @@ -79,7 +81,7 @@ default A foldLeft(A a, Iterable as) { */ @Override default A foldRight(A a, Iterable as) { - return reduceRight(snoc(a, as)); + return flip().foldMap(id(), reverse(cons(a, as))); } /** diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/AddAll.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/AddAll.java index fa0d0221d..6cce48bfd 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/AddAll.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/AddAll.java @@ -1,20 +1,21 @@ package com.jnape.palatable.lambda.monoid.builtin; import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.builtin.fn3.FoldLeft; import com.jnape.palatable.lambda.functions.specialized.MonoidFactory; import com.jnape.palatable.lambda.monoid.Monoid; -import com.jnape.palatable.lambda.semigroup.Semigroup; import java.util.Collection; +import java.util.function.Function; import java.util.function.Supplier; -import static com.jnape.palatable.lambda.monoid.Monoid.monoid; +import static com.jnape.palatable.lambda.functions.builtin.fn2.Map.map; /** * The {@link Monoid} instance formed under mutative concatenation for an arbitrary {@link Collection}. The collection * subtype (C) must support {@link Collection#addAll(Collection)}. *

- * For the {@link Semigroup}, see {@link com.jnape.palatable.lambda.semigroup.builtin.AddAll}. + * Note that the result is a new collection, and the inputs to this monoid are left unmodified. * * @see Monoid */ @@ -27,8 +28,28 @@ private AddAll() { @Override public Monoid apply(Supplier cSupplier) { - Semigroup semigroup = com.jnape.palatable.lambda.semigroup.builtin.AddAll.addAll(); - return monoid(semigroup, cSupplier); + return new Monoid() { + @Override + public C identity() { + return cSupplier.get(); + } + + @Override + public C apply(C xs, C ys) { + C c = identity(); + c.addAll(xs); + c.addAll(ys); + return c; + } + + @Override + public C foldMap(Function fn, Iterable bs) { + return FoldLeft.foldLeft((x, y) -> { + x.addAll(y); + return x; + }, identity(), map(fn, bs)); + } + }; } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/And.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/And.java index 9b4baec9b..3465ca0f8 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/And.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/And.java @@ -4,7 +4,9 @@ import com.jnape.palatable.lambda.functions.specialized.BiPredicate; import com.jnape.palatable.lambda.monoid.Monoid; -import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id; +import java.util.function.Function; + +import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; import static com.jnape.palatable.lambda.functions.builtin.fn1.Not.not; import static com.jnape.palatable.lambda.functions.builtin.fn2.Find.find; @@ -32,8 +34,8 @@ public Boolean apply(Boolean x, Boolean y) { } @Override - public Boolean reduceLeft(Iterable bools) { - return find(not(id()), bools).orElse(true); + public Boolean foldMap(Function fn, Iterable bs) { + return find(not(fn), bs).fmap(constantly(false)).orElse(true); } @Override diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Concat.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Concat.java index ec38b568b..2d164bbdc 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Concat.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Concat.java @@ -5,6 +5,10 @@ import com.jnape.palatable.lambda.monoid.Monoid; import java.util.Collections; +import java.util.function.Function; + +import static com.jnape.palatable.lambda.functions.builtin.fn1.Flatten.flatten; +import static com.jnape.palatable.lambda.functions.builtin.fn2.Map.map; /** * The {@link Monoid} instance formed under concatenation for an arbitrary {@link Iterable}. @@ -28,6 +32,11 @@ public Iterable apply(Iterable xs, Iterable ys) { return new ConcatenatingIterable<>(xs, ys); } + @Override + public Iterable foldMap(Function> fn, Iterable bs) { + return flatten(map(fn, bs)); + } + @SuppressWarnings("unchecked") public static Concat concat() { return INSTANCE; diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/First.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/First.java index 97028b692..cb3b65f4c 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/First.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/First.java @@ -4,9 +4,12 @@ import com.jnape.palatable.lambda.functions.Fn1; import com.jnape.palatable.lambda.monoid.Monoid; +import java.util.function.Function; + import static com.jnape.palatable.lambda.adt.Maybe.nothing; import static com.jnape.palatable.lambda.functions.builtin.fn1.CatMaybes.catMaybes; import static com.jnape.palatable.lambda.functions.builtin.fn1.Head.head; +import static com.jnape.palatable.lambda.functions.builtin.fn2.Map.map; /** * A {@link Monoid} instance formed by {@link Maybe}<A>. The application to two {@link Maybe} values @@ -36,8 +39,8 @@ public Maybe apply(Maybe x, Maybe y) { } @Override - public Maybe reduceLeft(Iterable> maybes) { - return head(catMaybes(maybes)); + public Maybe foldMap(Function> fn, Iterable bs) { + return head(catMaybes(map(fn, bs))); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Or.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Or.java index 951e555e6..a8157d0fb 100644 --- a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Or.java +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/Or.java @@ -4,7 +4,9 @@ import com.jnape.palatable.lambda.functions.specialized.BiPredicate; import com.jnape.palatable.lambda.monoid.Monoid; -import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id; +import java.util.function.Function; + +import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; import static com.jnape.palatable.lambda.functions.builtin.fn2.Find.find; /** @@ -36,8 +38,8 @@ public boolean test(Boolean x, Boolean y) { } @Override - public Boolean reduceLeft(Iterable bools) { - return find(id(), bools).orElse(false); + public Boolean foldMap(Function fn, Iterable bs) { + return find(fn::apply, bs).fmap(constantly(true)).orElse(false); } @Override diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/AddAll.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/AddAll.java index 557f9454b..fe22ba5c2 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/AddAll.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/AddAll.java @@ -13,7 +13,9 @@ * For the {@link Monoid}, see {@link com.jnape.palatable.lambda.monoid.builtin.AddAll}. * * @see Semigroup + * @deprecated in favor of the now non-modifying {@link com.jnape.palatable.lambda.monoid.builtin.AddAll monoid} */ +@Deprecated public final class AddAll> implements Semigroup { private static final AddAll INSTANCE = new AddAll(); diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AllTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AllTest.java index d746b0fc1..c266a4bfb 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AllTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AllTest.java @@ -19,10 +19,10 @@ @RunWith(Traits.class) public class AllTest { - private static final Function EVEN = x -> x.doubleValue() % 2 == 0; + private static final Function EVEN = x -> x.doubleValue() % 2 == 0; @TestTraits({EmptyIterableSupport.class}) - public Fn1, Boolean> createTestSubject() { + public Fn1, ? extends Boolean> createTestSubject() { return all(constantly(true)); } diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AnyTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AnyTest.java index aa8f8a118..ff632730b 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AnyTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AnyTest.java @@ -19,7 +19,7 @@ @RunWith(Traits.class) public class AnyTest { - public static final Function EVEN = x -> x % 2 == 0; + public static final Function EVEN = x -> x % 2 == 0; @TestTraits({EmptyIterableSupport.class}) public Fn1, Boolean> createTestSubject() { diff --git a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AddAllTest.java b/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AddAllTest.java deleted file mode 100644 index f1840b5de..000000000 --- a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/AddAllTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.jnape.palatable.lambda.semigroup.builtin; - -import org.junit.Test; - -import java.util.HashSet; - -import static com.jnape.palatable.lambda.semigroup.builtin.AddAll.addAll; -import static java.util.Collections.singleton; -import static org.junit.Assert.assertEquals; - -public class AddAllTest { - - @Test - public void semigroup() { - assertEquals(new HashSet() {{ - add(1); - add(2); - }}, addAll(new HashSet<>(singleton(1)), new HashSet<>(singleton(2)))); - } -} \ No newline at end of file From 7b48751936f9f68c6bb6825c173cfe1b98401d86 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 19 Aug 2018 17:28:31 -0500 Subject: [PATCH 14/31] Renaming CheckedEffect1 to CheckedEffect --- .../checked/{CheckedEffect1.java => CheckedEffect.java} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/{CheckedEffect1.java => CheckedEffect.java} (83%) diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect.java similarity index 83% rename from src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java rename to src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect.java index aa459b4da..0197295ee 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect1.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedEffect.java @@ -14,7 +14,7 @@ * @see Effect */ @FunctionalInterface -public interface CheckedEffect1 extends Effect { +public interface CheckedEffect extends Effect { @Override default void accept(A a) { @@ -34,7 +34,7 @@ default void accept(A a) { void checkedAccept(A a) throws T; /** - * Convenience static factory method for constructing a {@link CheckedEffect1} without an explicit cast or type + * Convenience static factory method for constructing a {@link CheckedEffect} without an explicit cast or type * attribution at the call site. * * @param checkedEffect the checked effect @@ -42,7 +42,7 @@ default void accept(A a) { * @param the input type * @return the checked effect */ - static CheckedEffect1 checked(CheckedEffect1 checkedEffect) { + static CheckedEffect checked(CheckedEffect checkedEffect) { return checkedEffect; } } From 1707283f13a8cc8f690a2005b1b42300172f0d3a Mon Sep 17 00:00:00 2001 From: jnape Date: Tue, 21 Aug 2018 20:18:15 -0500 Subject: [PATCH 15/31] inequality functions all take right-hand side argument first --- CHANGELOG.md | 1 + .../lambda/functions/builtin/fn2/GT.java | 12 ++++++------ .../lambda/functions/builtin/fn2/GTE.java | 12 ++++++------ .../lambda/functions/builtin/fn2/LT.java | 12 ++++++------ .../lambda/functions/builtin/fn2/LTE.java | 12 ++++++------ .../lambda/functions/builtin/fn3/GTBy.java | 10 +++++----- .../lambda/functions/builtin/fn3/GTEBy.java | 16 ++++++++-------- .../lambda/functions/builtin/fn3/LTBy.java | 14 +++++++------- .../lambda/functions/builtin/fn3/LTEBy.java | 16 ++++++++-------- .../lambda/iteration/RateLimitingIterator.java | 6 +++--- .../lambda/semigroup/builtin/MaxBy.java | 2 +- .../lambda/semigroup/builtin/MinBy.java | 2 +- .../lambda/functions/builtin/fn2/GTETest.java | 4 ++-- .../lambda/functions/builtin/fn2/GTTest.java | 7 ++++--- .../lambda/functions/builtin/fn2/LTETest.java | 4 ++-- .../lambda/functions/builtin/fn2/LTTest.java | 4 ++-- .../lambda/functions/builtin/fn3/GTByTest.java | 6 +++--- .../lambda/functions/builtin/fn3/GTEByTest.java | 8 ++++---- .../lambda/functions/builtin/fn3/LTByTest.java | 6 +++--- .../lambda/functions/builtin/fn3/LTEByTest.java | 8 ++++---- 20 files changed, 82 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 889c223eb..a70de3724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - ***Breaking Change***: `Absent` moved to `semigroup.builtin` package - ***Breaking Change***: `Effect#accept()` is now the required method to implement in the functional interface - ***Breaking Change***: `Fn0#apply()` is now the required method to implement in the functional interface +- ***Breaking Change***: `GTBy`, `GT`, `LTBy`, `LT`, `GTEBy`, `GTE`, `LTEBy`, and `LTE` take the right-hand side first for more intuitive partial application - `RightAny` overload returns `Monoid` - monoids now all fold with respect to `foldMap` - monoid folding now implicitly starts with the identity, regardless of iterable population diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GT.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GT.java index d59094c63..3c45e24cd 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GT.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GT.java @@ -23,8 +23,8 @@ private GT() { } @Override - public Boolean apply(A x, A y) { - return gtBy(id(), x, y); + public Boolean apply(A y, A x) { + return gtBy(id(), y, x); } @SuppressWarnings("unchecked") @@ -32,11 +32,11 @@ public static > GT gt() { return INSTANCE; } - public static > Predicate gt(A x) { - return GT.gt().apply(x); + public static > Predicate gt(A y) { + return GT.gt().apply(y); } - public static > Boolean gt(A x, A y) { - return gt(x).apply(y); + public static > Boolean gt(A y, A x) { + return gt(y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTE.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTE.java index 436285300..23069dd03 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTE.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTE.java @@ -23,8 +23,8 @@ private GTE() { } @Override - public Boolean apply(A x, A y) { - return gteBy(id(), x, y); + public Boolean apply(A y, A x) { + return gteBy(id(), y, x); } @SuppressWarnings("unchecked") @@ -32,11 +32,11 @@ public static > GTE gte() { return INSTANCE; } - public static > Predicate gte(A x) { - return GTE.gte().apply(x); + public static > Predicate gte(A y) { + return GTE.gte().apply(y); } - public static > Boolean gte(A x, A y) { - return gte(x).apply(y); + public static > Boolean gte(A y, A x) { + return gte(y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LT.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LT.java index f4906bf09..d6a1d6d99 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LT.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LT.java @@ -23,8 +23,8 @@ private LT() { } @Override - public Boolean apply(A x, A y) { - return ltBy(id(), x, y); + public Boolean apply(A y, A x) { + return ltBy(id(), y, x); } @SuppressWarnings("unchecked") @@ -32,11 +32,11 @@ public static > LT lt() { return INSTANCE; } - public static > Predicate lt(A x) { - return LT.lt().apply(x); + public static > Predicate lt(A y) { + return LT.lt().apply(y); } - public static > Boolean lt(A x, A y) { - return lt(x).apply(y); + public static > Boolean lt(A y, A x) { + return lt(y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTE.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTE.java index 8c0680cbe..19d2424c4 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTE.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTE.java @@ -23,8 +23,8 @@ private LTE() { } @Override - public Boolean apply(A x, A y) { - return lteBy(id(), x, y); + public Boolean apply(A y, A x) { + return lteBy(id(), y, x); } @SuppressWarnings("unchecked") @@ -32,11 +32,11 @@ public static > LTE lte() { return INSTANCE; } - public static > Predicate lte(A x) { - return LTE.lte().apply(x); + public static > Predicate lte(A y) { + return LTE.lte().apply(y); } - public static > Boolean lte(A x, A y) { - return lte(x).apply(y); + public static > Boolean lte(A y, A x) { + return lte(y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTBy.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTBy.java index e3df534df..4428784e1 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTBy.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTBy.java @@ -25,7 +25,7 @@ private GTBy() { } @Override - public Boolean apply(Function compareFn, A x, A y) { + public Boolean apply(Function compareFn, A y, A x) { return compareFn.apply(x).compareTo(compareFn.apply(y)) > 0; } @@ -48,11 +48,11 @@ public static > BiPredicate gtBy(FunctiongtBy().apply(fn); } - public static > Predicate gtBy(Function fn, A x) { - return GTBy.gtBy(fn).apply(x); + public static > Predicate gtBy(Function fn, A y) { + return GTBy.gtBy(fn).apply(y); } - public static > Boolean gtBy(Function fn, A x, A y) { - return gtBy(fn, x).apply(y); + public static > Boolean gtBy(Function fn, A y, A x) { + return gtBy(fn, y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEBy.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEBy.java index bbc26c686..2c5d8ae26 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEBy.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEBy.java @@ -28,8 +28,8 @@ private GTEBy() { } @Override - public Boolean apply(Function compareFn, A x, A y) { - return GTBy.gtBy(compareFn).or(cmpEqBy(compareFn)).apply(x, y); + public Boolean apply(Function compareFn, A y, A x) { + return GTBy.gtBy(compareFn).or(cmpEqBy(compareFn)).apply(y, x); } @Override @@ -38,8 +38,8 @@ public BiPredicate apply(Function compareFn) { } @Override - public Predicate apply(Function compareFn, A x) { - return Fn3.super.apply(compareFn, x)::apply; + public Predicate apply(Function compareFn, A y) { + return Fn3.super.apply(compareFn, y)::apply; } @SuppressWarnings("unchecked") @@ -51,11 +51,11 @@ public static > BiPredicate gteBy(FunctiongteBy().apply(fn); } - public static > Predicate gteBy(Function fn, A x) { - return GTEBy.gteBy(fn).apply(x); + public static > Predicate gteBy(Function fn, A y) { + return GTEBy.gteBy(fn).apply(y); } - public static > Boolean gteBy(Function fn, A x, A y) { - return gteBy(fn, x).apply(y); + public static > Boolean gteBy(Function fn, A y, A x) { + return gteBy(fn, y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTBy.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTBy.java index 5d7b57c79..220a600e8 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTBy.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTBy.java @@ -25,7 +25,7 @@ private LTBy() { } @Override - public Boolean apply(Function compareFn, A x, A y) { + public Boolean apply(Function compareFn, A y, A x) { return compareFn.apply(x).compareTo(compareFn.apply(y)) < 0; } @@ -35,8 +35,8 @@ public BiPredicate apply(Function compareFn) { } @Override - public Predicate apply(Function compareFn, A x) { - return Fn3.super.apply(compareFn, x)::apply; + public Predicate apply(Function compareFn, A y) { + return Fn3.super.apply(compareFn, y)::apply; } @SuppressWarnings("unchecked") @@ -48,11 +48,11 @@ public static > BiPredicate ltBy(FunctionltBy().apply(fn); } - public static > Predicate ltBy(Function fn, A x) { - return LTBy.ltBy(fn).apply(x); + public static > Predicate ltBy(Function fn, A y) { + return LTBy.ltBy(fn).apply(y); } - public static > Boolean ltBy(Function fn, A x, A y) { - return ltBy(fn, x).apply(y); + public static > Boolean ltBy(Function fn, A y, A x) { + return ltBy(fn, y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java index 14ea8d6b5..a83fdc9c5 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEBy.java @@ -28,8 +28,8 @@ private LTEBy() { } @Override - public Boolean apply(Function compareFn, A x, A y) { - return LTBy.ltBy(compareFn).or(cmpEqBy(compareFn)).apply(x, y); + public Boolean apply(Function compareFn, A y, A x) { + return LTBy.ltBy(compareFn).or(cmpEqBy(compareFn)).apply(y, x); } @Override @@ -38,8 +38,8 @@ public BiPredicate apply(Function compareFn) { } @Override - public Predicate apply(Function compareFn, A x) { - return Fn3.super.apply(compareFn, x)::apply; + public Predicate apply(Function compareFn, A y) { + return Fn3.super.apply(compareFn, y)::apply; } @SuppressWarnings("unchecked") @@ -51,11 +51,11 @@ public static > BiPredicate lteBy(FunctionlteBy().apply(fn); } - public static > Predicate lteBy(Function fn, A x) { - return LTEBy.lteBy(fn).apply(x); + public static > Predicate lteBy(Function fn, A y) { + return LTEBy.lteBy(fn).apply(y); } - public static > Boolean lteBy(Function fn, A x, A y) { - return lteBy(fn, x).apply(y); + public static > Boolean lteBy(Function fn, A y, A x) { + return lteBy(fn, y).apply(x); } } diff --git a/src/main/java/com/jnape/palatable/lambda/iteration/RateLimitingIterator.java b/src/main/java/com/jnape/palatable/lambda/iteration/RateLimitingIterator.java index de2e7b94c..f7b622bb8 100644 --- a/src/main/java/com/jnape/palatable/lambda/iteration/RateLimitingIterator.java +++ b/src/main/java/com/jnape/palatable/lambda/iteration/RateLimitingIterator.java @@ -16,8 +16,8 @@ import static com.jnape.palatable.lambda.adt.Try.trying; import static com.jnape.palatable.lambda.functions.builtin.fn1.Size.size; import static com.jnape.palatable.lambda.functions.builtin.fn2.Filter.filter; -import static com.jnape.palatable.lambda.functions.builtin.fn2.GT.gt; import static com.jnape.palatable.lambda.functions.builtin.fn2.GTE.gte; +import static com.jnape.palatable.lambda.functions.builtin.fn2.LT.lt; import static com.jnape.palatable.lambda.functions.builtin.fn2.LTE.lte; import static com.jnape.palatable.lambda.semigroup.builtin.Max.max; import static java.lang.Thread.sleep; @@ -67,8 +67,8 @@ private boolean rateLimitExhaustedInTimeSlice(Tuple3 { Instant timeSliceEnd = instantSupplier.get(); Instant previousTimeSliceEnd = timeSliceEnd.minus(duration); - timeSlicesForRateLimit.removeIf(gt(previousTimeSliceEnd)); - return max(0L, limit - size(filter(mark -> gte(mark, previousTimeSliceEnd) && lte(mark, timeSliceEnd), timeSlicesForRateLimit))) == 0; + timeSlicesForRateLimit.removeIf(lt(previousTimeSliceEnd)); + return max(0L, limit - size(filter(mark -> lte(mark, previousTimeSliceEnd) && gte(mark, timeSliceEnd), timeSlicesForRateLimit))) == 0; }); } diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MaxBy.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MaxBy.java index a5bbcce84..5e6cbbe5c 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MaxBy.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MaxBy.java @@ -31,7 +31,7 @@ private MaxBy() { @Override public Semigroup apply(Function compareFn) { - return (x, y) -> ltBy(compareFn, x, y) ? y : x; + return (x, y) -> ltBy(compareFn, y, x) ? y : x; } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MinBy.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MinBy.java index 7803d8ebd..3a7ea9a71 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MinBy.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/MinBy.java @@ -31,7 +31,7 @@ private MinBy() { @Override public Semigroup apply(Function compareFn) { - return (x, y) -> gtBy(compareFn, x, y) ? y : x; + return (x, y) -> gtBy(compareFn, y, x) ? y : x; } @SuppressWarnings("unchecked") diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTETest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTETest.java index 598869ab9..c3fd1f89b 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTETest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTETest.java @@ -10,8 +10,8 @@ public class GTETest { @Test public void comparisons() { - assertTrue(gte(2, 1)); + assertTrue(gte(1, 2)); assertTrue(gte(1, 1)); - assertFalse(gte(1, 2)); + assertFalse(gte(2, 1)); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTTest.java index 7e73795ea..4f448b695 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/GTTest.java @@ -2,6 +2,7 @@ import org.junit.Test; +import static com.jnape.palatable.lambda.functions.builtin.fn2.GT.gt; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -9,8 +10,8 @@ public class GTTest { @Test public void comparisons() { - assertTrue(GT.gt(2, 1)); - assertFalse(GT.gt(1, 1)); - assertFalse(GT.gt(1, 2)); + assertTrue(gt(1, 2)); + assertFalse(gt(1, 1)); + assertFalse(gt(2, 1)); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTETest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTETest.java index 14ba931c1..8fd684b31 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTETest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTETest.java @@ -10,8 +10,8 @@ public class LTETest { @Test public void comparisons() { - assertTrue(lte(1, 2)); + assertTrue(lte(2, 1)); assertTrue(lte(1, 1)); - assertFalse(lte(2, 1)); + assertFalse(lte(1, 2)); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTTest.java index a72ec158f..2c2229aa2 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/LTTest.java @@ -10,8 +10,8 @@ public class LTTest { @Test public void comparisons() { - assertTrue(lt(1, 2)); + assertTrue(lt(2, 1)); assertFalse(lt(1, 1)); - assertFalse(lt(2, 1)); + assertFalse(lt(1, 2)); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTByTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTByTest.java index 20e0c4e2a..a04ffb0b6 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTByTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTByTest.java @@ -11,10 +11,10 @@ public class GTByTest { @Test public void comparisons() { - assertTrue(gtBy(id(), 2, 1)); + assertTrue(gtBy(id(), 1, 2)); assertFalse(gtBy(id(), 1, 1)); - assertFalse(gtBy(id(), 1, 2)); + assertFalse(gtBy(id(), 2, 1)); - assertTrue(gtBy(String::length, "aaa", "bb")); + assertTrue(gtBy(String::length, "bb", "aaa")); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEByTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEByTest.java index f363ccb34..438d0cb84 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEByTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/GTEByTest.java @@ -11,11 +11,11 @@ public class GTEByTest { @Test public void comparisons() { - assertTrue(gteBy(id(), 2, 1)); + assertTrue(gteBy(id(), 1, 2)); assertTrue(gteBy(id(), 1, 1)); - assertFalse(gteBy(id(), 1, 2)); + assertFalse(gteBy(id(), 2, 1)); - assertTrue(gteBy(String::length, "ab", "b")); - assertTrue(gteBy(String::length, "ab", "bc")); + assertTrue(gteBy(String::length, "b", "ab")); + assertTrue(gteBy(String::length, "bc", "ab")); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTByTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTByTest.java index c06db00b9..dc511d7cf 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTByTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTByTest.java @@ -11,10 +11,10 @@ public class LTByTest { @Test public void comparisons() { - assertTrue(ltBy(id(), 1, 2)); + assertTrue(ltBy(id(), 2, 1)); assertFalse(ltBy(id(), 1, 1)); - assertFalse(ltBy(id(), 2, 1)); + assertFalse(ltBy(id(), 1, 2)); - assertTrue(ltBy(String::length, "b", "ab")); + assertTrue(ltBy(String::length, "ab", "b")); } } \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEByTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEByTest.java index 44cc71ef5..122c76070 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEByTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/LTEByTest.java @@ -11,11 +11,11 @@ public class LTEByTest { @Test public void comparisons() { - assertTrue(lteBy(id(), 1, 2)); + assertTrue(lteBy(id(), 2, 1)); assertTrue(lteBy(id(), 1, 1)); - assertFalse(lteBy(id(), 2, 1)); + assertFalse(lteBy(id(), 1, 2)); - assertTrue(lteBy(String::length, "b", "ab")); - assertTrue(lteBy(String::length, "bc", "ab")); + assertTrue(lteBy(String::length, "ab", "b")); + assertTrue(lteBy(String::length, "ab", "bc")); } } \ No newline at end of file From 36f8abdb30212da441cfe3a92e6e1ad14db05162 Mon Sep 17 00:00:00 2001 From: jnape Date: Thu, 23 Aug 2018 14:25:52 -0500 Subject: [PATCH 16/31] Fixing javadoc on Effect --- .../com/jnape/palatable/lambda/functions/Effect.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Effect.java b/src/main/java/com/jnape/palatable/lambda/functions/Effect.java index ead5d645f..f9adebe97 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Effect.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Effect.java @@ -5,16 +5,15 @@ import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Supplier; import static com.jnape.palatable.lambda.adt.Unit.UNIT; /** - * A function taking "no arguments", implemented as an {@link Fn1}<{@link Unit}, A>. + * A function returning "no result", and therefore only useful as a side-effect. * - * @param the result type - * @see Fn1 - * @see Supplier + * @param the argument type + * @see Fn0 + * @see Consumer */ @FunctionalInterface public interface Effect extends Fn1, Consumer { From f978218ab8fcb1eed1ee216b112176e32cbae7a4 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 2 Sep 2018 15:06:10 -0500 Subject: [PATCH 17/31] deprecating dyadic Either#flatMap in favor of match --- CHANGELOG.md | 1 + src/main/java/com/jnape/palatable/lambda/adt/Either.java | 6 ++++-- .../palatable/lambda/semigroup/builtin/LeftAll.java | 2 +- .../palatable/lambda/semigroup/builtin/LeftAny.java | 6 +++--- .../palatable/lambda/semigroup/builtin/RightAny.java | 6 +++--- .../java/com/jnape/palatable/lambda/adt/EitherTest.java | 9 --------- 6 files changed, 12 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a70de3724..0667f1a50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument +- Dyadic `Either#flatMap()`, in favor of `Either#match` ## [3.1.0] - 2018-07-16 ### Added diff --git a/src/main/java/com/jnape/palatable/lambda/adt/Either.java b/src/main/java/com/jnape/palatable/lambda/adt/Either.java index d9c9d2fa1..27d3408bd 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/Either.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/Either.java @@ -123,7 +123,7 @@ public final Either filter(Function pred, */ @Override public Either flatMap(Function>> rightFn) { - return flatMap(Either::left, rightFn.andThen(Applicative::coerce)); + return match(Either::left, rightFn.andThen(Applicative::coerce)); } /** @@ -136,7 +136,9 @@ public Either flatMap(Function the new left parameter type * @param the new right parameter type * @return the result of either rightFn or leftFn, depending on whether this is a right or a left + * @deprecated in favor of {@link Either#match(Function, Function)} */ + @Deprecated public final Either flatMap(Function> leftFn, Function> rightFn) { return match(leftFn, rightFn); @@ -144,7 +146,7 @@ public final Either flatMap(Function invert() { - return flatMap(Either::right, Either::left); + return match(Either::right, Either::left); } /** diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAll.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAll.java index 70ef187fd..b8955b2e0 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAll.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAll.java @@ -37,7 +37,7 @@ private LeftAll() { @Override public Semigroup> apply(Semigroup lSemigroup) { - return (x, y) -> x.flatMap(xL -> y.flatMap(yL -> left(lSemigroup.apply(xL, yL)), Either::right), Either::right); + return (x, y) -> x.match(xL -> y.match(yL -> left(lSemigroup.apply(xL, yL)), Either::right), Either::right); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAny.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAny.java index 1bc166dca..b93133143 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAny.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/LeftAny.java @@ -36,9 +36,9 @@ private LeftAny() { @Override public Semigroup> apply(Semigroup lSemigroup) { - return (x, y) -> x.flatMap(xL -> y.flatMap(yL -> left(lSemigroup.apply(xL, yL)), - yR -> left(xL)), - xR -> y); + return (x, y) -> x.match(xL -> y.match(yL -> left(lSemigroup.apply(xL, yL)), + yR -> left(xL)), + xR -> y); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RightAny.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RightAny.java index 04531cbfb..00f528054 100644 --- a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RightAny.java +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RightAny.java @@ -37,9 +37,9 @@ private RightAny() { @Override public Semigroup> apply(Semigroup rSemigroup) { - return (x, y) -> x.flatMap(constantly(y), - xR -> y.flatMap(constantly(right(xR)), - rSemigroup.apply(xR).andThen(Either::right))); + return (x, y) -> x.match(constantly(y), + xR -> y.match(constantly(right(xR)), + rSemigroup.apply(xR).andThen(Either::right))); } @SuppressWarnings("unchecked") diff --git a/src/test/java/com/jnape/palatable/lambda/adt/EitherTest.java b/src/test/java/com/jnape/palatable/lambda/adt/EitherTest.java index a06282ba6..e43e2438f 100644 --- a/src/test/java/com/jnape/palatable/lambda/adt/EitherTest.java +++ b/src/test/java/com/jnape/palatable/lambda/adt/EitherTest.java @@ -110,15 +110,6 @@ public void monadicFlatMapLiftsRightAndFlattensBackToEither() { assertThat(right.flatMap(r -> right(r + 1)), is(right(2))); } - @Test - public void dyadicFlatMapDuallyLiftsAndFlattensBackToEither() { - Either left = left("foo"); - Either right = right(1); - - assertThat(left.flatMap(l -> left(l + "bar"), r -> right(r + 1)), is(left("foobar"))); - assertThat(right.flatMap(l -> left(l + "bar"), r -> right(r + 1)), is(right(2))); - } - @Test public void mergeDuallyLiftsAndCombinesBiasingLeft() { Either left1 = left("foo"); From ba86af4df13cae82e129e469e58bc78273db9a7b Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 2 Sep 2018 16:34:08 -0500 Subject: [PATCH 18/31] simpler default discardR --- .../java/com/jnape/palatable/lambda/functor/Applicative.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/jnape/palatable/lambda/functor/Applicative.java b/src/main/java/com/jnape/palatable/lambda/functor/Applicative.java index 224963a83..c8eb56d7c 100644 --- a/src/main/java/com/jnape/palatable/lambda/functor/Applicative.java +++ b/src/main/java/com/jnape/palatable/lambda/functor/Applicative.java @@ -73,7 +73,7 @@ default Applicative discardL(Applicative appB) { * @return this Applicative */ default Applicative discardR(Applicative appB) { - return appB.zip(zip(pure(constantly()))); + return appB.zip(fmap(constantly())); } /** From 17e87623b627721cf84853cbae109fcc9453de3c Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 16 Sep 2018 15:44:44 -0500 Subject: [PATCH 19/31] Adding LiftA3-LiftA8 --- CHANGELOG.md | 1 + .../lambda/functions/builtin/fn3/LiftA2.java | 2 +- .../lambda/functions/builtin/fn4/LiftA3.java | 87 ++++++++ .../lambda/functions/builtin/fn5/LiftA4.java | 108 ++++++++++ .../lambda/functions/builtin/fn6/LiftA5.java | 132 +++++++++++++ .../lambda/functions/builtin/fn7/LiftA6.java | 162 +++++++++++++++ .../lambda/functions/builtin/fn8/LiftA7.java | 186 ++++++++++++++++++ .../functions/builtin/fn4/LiftA3Test.java | 15 ++ .../functions/builtin/fn5/LiftA4Test.java | 15 ++ .../functions/builtin/fn6/LiftA5Test.java | 15 ++ .../functions/builtin/fn7/LiftA6Test.java | 15 ++ .../functions/builtin/fn8/LiftA7Test.java | 15 ++ 12 files changed, 752 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3.java create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4.java create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5.java create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6.java create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6Test.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7Test.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 0667f1a50..87acd6d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Tuple2-8` specializations of left/right product rotation - `CheckedEffect`, an `Effect` variant that can throw checked exceptions - `CheckedFn1#checked`, convenience static factory method to aid inference +- `LiftA3-8`, higher-arity analogs to `LiftA2` ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LiftA2.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LiftA2.java index 51381ef58..7ba773691 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LiftA2.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/LiftA2.java @@ -12,7 +12,7 @@ * {@link Applicative} context. Functionally equivalent to appB.zip(appA.fmap(fn)). * * @param the function's first argument type - * @param the function's second argument typ + * @param the function's second argument type * @param the function's return type * @param the applicative unification type * @param the inferred first applicative argument type diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3.java new file mode 100644 index 000000000..a34a1aaae --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3.java @@ -0,0 +1,87 @@ +package com.jnape.palatable.lambda.functions.builtin.fn4; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.Fn3; +import com.jnape.palatable.lambda.functions.Fn4; +import com.jnape.palatable.lambda.functor.Applicative; + +/** + * Lift into and apply an {@link Fn3} to three {@link Applicative} values, returning the result inside the same + * {@link Applicative} context. + * + * @param the function's first argument type + * @param the function's second argument type + * @param the function's third argument type + * @param the function's return type + * @param the applicative unification type + * @param the inferred first applicative argument type + * @param the inferred second applicative argument type + * @param the inferred third applicative argument type + * @param the inferred applicative return type + * @see Applicative#zip(Applicative) + */ +public final class LiftA3, + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative> implements Fn4, AppA, AppB, AppC, AppD> { + + private static final LiftA3 INSTANCE = new LiftA3(); + + private LiftA3() { + } + + @Override + public AppD apply(Fn3 fn, AppA appA, AppB appB, AppC appC) { + return appC.zip(appB.zip(appA.fmap(fn))).coerce(); + } + + @SuppressWarnings("unchecked") + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative> LiftA3 liftA3() { + return INSTANCE; + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative> Fn3 liftA3(Fn3 fn) { + return LiftA3.liftA3().apply(fn); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative> Fn2 liftA3(Fn3 fn, AppA appA) { + return LiftA3.liftA3(fn).apply(appA); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative> Fn1 liftA3(Fn3 fn, AppA appA, AppB appB) { + return LiftA3.liftA3(fn, appA).apply(appB); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative> AppD liftA3(Fn3 fn, AppA appA, AppB appB, + AppC appC) { + return LiftA3.liftA3(fn, appA, appB).apply(appC); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4.java new file mode 100644 index 000000000..099d519ca --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4.java @@ -0,0 +1,108 @@ +package com.jnape.palatable.lambda.functions.builtin.fn5; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.Fn3; +import com.jnape.palatable.lambda.functions.Fn4; +import com.jnape.palatable.lambda.functions.Fn5; +import com.jnape.palatable.lambda.functor.Applicative; + +/** + * Lift into and apply an {@link Fn4} to four {@link Applicative} values, returning the result inside the same + * {@link Applicative} context. + * + * @param the function's first argument type + * @param the function's second argument type + * @param the function's third argument type + * @param the function's fourth argument type + * @param the function's return type + * @param the applicative unification type + * @param the inferred first applicative argument type + * @param the inferred second applicative argument type + * @param the inferred third applicative argument type + * @param the inferred fourth applicative argument type + * @param the inferred applicative return type + * @see Applicative#zip(Applicative) + */ +public final class LiftA4, + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> implements Fn5, AppA, AppB, AppC, AppD, AppE> { + + private static final LiftA4 INSTANCE = new LiftA4(); + + private LiftA4() { + } + + @Override + public AppE apply(Fn4 fn, AppA appA, AppB appB, AppC appC, AppD appD) { + return appD.zip(appC.zip(appB.zip(appA.fmap(fn)))).coerce(); + } + + @SuppressWarnings("unchecked") + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> LiftA4 liftA4() { + return INSTANCE; + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> Fn4 liftA4(Fn4 fn) { + return LiftA4.liftA4().apply(fn); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> Fn3 liftA4(Fn4 fn, AppA appA) { + return LiftA4.liftA4(fn).apply(appA); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> Fn2 liftA4(Fn4 fn, AppA appA, + AppB appB) { + return LiftA4.liftA4(fn, appA).apply(appB); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> Fn1 liftA4(Fn4 fn, AppA appA, AppB appB, + AppC appC) { + return LiftA4.liftA4(fn, appA, appB).apply(appC); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative> AppE liftA4(Fn4 fn, AppA appA, AppB appB, + AppC appC, AppD appD) { + return LiftA4.liftA4(fn, appA, appB, appC).apply(appD); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5.java new file mode 100644 index 000000000..f32d44569 --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5.java @@ -0,0 +1,132 @@ +package com.jnape.palatable.lambda.functions.builtin.fn6; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.Fn3; +import com.jnape.palatable.lambda.functions.Fn4; +import com.jnape.palatable.lambda.functions.Fn5; +import com.jnape.palatable.lambda.functions.Fn6; +import com.jnape.palatable.lambda.functor.Applicative; + +/** + * Lift into and apply an {@link Fn5} to five {@link Applicative} values, returning the result inside the same + * {@link Applicative} context. + * + * @param the function's first argument type + * @param the function's second argument type + * @param the function's third argument type + * @param the function's fourth argument type + * @param the function's fifth argument type + * @param the function's return type + * @param the applicative unification type + * @param the inferred first applicative argument type + * @param the inferred second applicative argument type + * @param the inferred third applicative argument type + * @param the inferred fourth applicative argument type + * @param the inferred fifth applicative argument type + * @param the inferred applicative return type + * @see Applicative#zip(Applicative) + */ +public final class LiftA5, + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> implements Fn6, AppA, AppB, AppC, AppD, AppE, AppF> { + + private static final LiftA5 INSTANCE = new LiftA5(); + + private LiftA5() { + } + + @Override + public AppF apply(Fn5 fn, AppA appA, AppB appB, AppC appC, AppD appD, AppE appE) { + return appE.zip(appD.zip(appC.zip(appB.zip(appA.fmap(fn))))).coerce(); + } + + @SuppressWarnings("unchecked") + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> LiftA5 liftA5() { + return INSTANCE; + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> Fn5 liftA5(Fn5 fn) { + return LiftA5.liftA5().apply(fn); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> Fn4 liftA5(Fn5 fn, + AppA appA) { + return LiftA5.liftA5(fn).apply(appA); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> Fn3 liftA5(Fn5 fn, AppA appA, + AppB appB) { + return LiftA5.liftA5(fn, appA).apply(appB); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> Fn2 liftA5(Fn5 fn, AppA appA, + AppB appB, + AppC appC) { + return LiftA5.liftA5(fn, appA, appB).apply(appC); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> Fn1 liftA5(Fn5 fn, AppA appA, AppB appB, + AppC appC, AppD appD) { + return LiftA5.liftA5(fn, appA, appB, appC).apply(appD); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative> AppF liftA5(Fn5 fn, AppA appA, AppB appB, + AppC appC, AppD appD, AppE appE) { + return LiftA5.liftA5(fn, appA, appB, appC, appD).apply(appE); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6.java new file mode 100644 index 000000000..72da45314 --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6.java @@ -0,0 +1,162 @@ +package com.jnape.palatable.lambda.functions.builtin.fn7; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.Fn3; +import com.jnape.palatable.lambda.functions.Fn4; +import com.jnape.palatable.lambda.functions.Fn5; +import com.jnape.palatable.lambda.functions.Fn6; +import com.jnape.palatable.lambda.functions.Fn7; +import com.jnape.palatable.lambda.functor.Applicative; + +/** + * Lift into and apply an {@link Fn6} to six {@link Applicative} values, returning the result inside the same + * {@link Applicative} context. + * + * @param the function's first argument type + * @param the function's second argument type + * @param the function's third argument type + * @param the function's fourth argument type + * @param the function's fifth argument type + * @param the function's sixth argument type + * @param the function's return type + * @param the applicative unification type + * @param the inferred first applicative argument type + * @param the inferred second applicative argument type + * @param the inferred third applicative argument type + * @param the inferred fourth applicative argument type + * @param the inferred fifth applicative argument type + * @param the inferred sixth applicative argument type + * @param the inferred applicative return type + * @see Applicative#zip(Applicative) + */ +public final class LiftA6, + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> implements Fn7, AppA, AppB, AppC, AppD, AppE, AppF, AppG> { + + private static final LiftA6 INSTANCE = new LiftA6(); + + private LiftA6() { + } + + @Override + public AppG apply(Fn6 fn, AppA appA, AppB appB, AppC appC, AppD appD, AppE appE, + AppF appF) { + return appF.zip(appE.zip(appD.zip(appC.zip(appB.zip(appA.fmap(fn)))))).coerce(); + } + + + @SuppressWarnings("unchecked") + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> LiftA6 liftA6() { + return INSTANCE; + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> Fn6 liftA6( + Fn6 fn) { + return LiftA6.liftA6().apply(fn); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> Fn5 liftA6( + Fn6 fn, + AppA appA) { + return LiftA6.liftA6(fn).apply(appA); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> Fn4 liftA6(Fn6 fn, + AppA appA, + AppB appB) { + return LiftA6.liftA6(fn, appA).apply(appB); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> Fn3 liftA6(Fn6 fn, AppA appA, + AppB appB, + AppC appC) { + return LiftA6.liftA6(fn, appA, appB).apply(appC); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> Fn2 liftA6(Fn6 fn, AppA appA, + AppB appB, + AppC appC, AppD appD) { + return LiftA6.liftA6(fn, appA, appB, appC).apply(appD); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> Fn1 liftA6(Fn6 fn, AppA appA, AppB appB, + AppC appC, AppD appD, AppE appE) { + return LiftA6.liftA6(fn, appA, appB, appC, appD).apply(appE); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative> AppG liftA6(Fn6 fn, AppA appA, AppB appB, + AppC appC, AppD appD, AppE appE, AppF appF) { + return LiftA6.liftA6(fn, appA, appB, appC, appD, appE).apply(appF); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7.java new file mode 100644 index 000000000..6d508f06d --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7.java @@ -0,0 +1,186 @@ +package com.jnape.palatable.lambda.functions.builtin.fn8; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.Fn3; +import com.jnape.palatable.lambda.functions.Fn4; +import com.jnape.palatable.lambda.functions.Fn5; +import com.jnape.palatable.lambda.functions.Fn6; +import com.jnape.palatable.lambda.functions.Fn7; +import com.jnape.palatable.lambda.functions.Fn8; +import com.jnape.palatable.lambda.functor.Applicative; + +/** + * Lift into and apply an {@link Fn7} to seven {@link Applicative} values, returning the result inside the same + * {@link Applicative} context. + * + * @param the function's first argument type + * @param the function's second argument type + * @param the function's third argument type + * @param the function's fourth argument type + * @param the function's fifth argument type + * @param the function's sixth argument type + * @param the function's seventh argument type + * @param the function's return type + * @param the applicative unification type + * @param the inferred first applicative argument type + * @param the inferred second applicative argument type + * @param the inferred third applicative argument type + * @param the inferred fourth applicative argument type + * @param the inferred fifth applicative argument type + * @param the inferred sixth applicative argument type + * @param the inferred seventh applicative argument type + * @param the inferred applicative return type + * @see Applicative#zip(Applicative) + */ +public final class LiftA7, + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> implements Fn8, AppA, AppB, AppC, AppD, AppE, AppF, AppG, AppH> { + + private static final LiftA7 INSTANCE = new LiftA7(); + + private LiftA7() { + } + + @Override + public AppH apply(Fn7 fn, AppA appA, AppB appB, AppC appC, AppD appD, AppE appE, + AppF appF, AppG appG) { + return appG.zip(appF.zip(appE.zip(appD.zip(appC.zip(appB.zip(appA.fmap(fn))))))).coerce(); + } + + @SuppressWarnings("unchecked") + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> LiftA7 liftA7() { + return INSTANCE; + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn7 liftA7( + Fn7 fn) { + return LiftA7.liftA7().apply(fn); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn6 liftA7( + Fn7 fn, AppA appA) { + return LiftA7.liftA7(fn).apply(appA); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn5 liftA7( + Fn7 fn, AppA appA, AppB appB) { + return LiftA7.liftA7(fn, appA).apply(appB); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn4 liftA7(Fn7 fn, + AppA appA, AppB appB, + AppC appC) { + return LiftA7.liftA7(fn, appA, appB).apply(appC); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn3 liftA7(Fn7 fn, + AppA appA, AppB appB, AppC appC, + AppD appD) { + return LiftA7.liftA7(fn, appA, appB, appC).apply(appD); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn2 liftA7(Fn7 fn, AppA appA, + AppB appB, AppC appC, AppD appD, AppE appE) { + return LiftA7.liftA7(fn, appA, appB, appC, appD).apply(appE); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> Fn1 liftA7(Fn7 fn, AppA appA, + AppB appB, AppC appC, AppD appD, AppE appE, + AppF appF) { + return LiftA7.liftA7(fn, appA, appB, appC, appD, appE).apply(appF); + } + + public static , + AppB extends Applicative, + AppC extends Applicative, + AppD extends Applicative, + AppE extends Applicative, + AppF extends Applicative, + AppG extends Applicative, + AppH extends Applicative> AppH liftA7(Fn7 fn, AppA appA, AppB appB, + AppC appC, AppD appD, AppE appE, AppF appF, AppG appG) { + return LiftA7.liftA7(fn, appA, appB, appC, appD, appE, appF).apply(appG); + } +} diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3Test.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3Test.java new file mode 100644 index 000000000..e6f65f814 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn4/LiftA3Test.java @@ -0,0 +1,15 @@ +package com.jnape.palatable.lambda.functions.builtin.fn4; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.Maybe.just; +import static com.jnape.palatable.lambda.functions.builtin.fn4.LiftA3.liftA3; +import static org.junit.Assert.assertEquals; + +public class LiftA3Test { + + @Test + public void lifting() { + assertEquals(just(6), liftA3((a, b, c) -> a + b + c, just(1), just(2), just(3))); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4Test.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4Test.java new file mode 100644 index 000000000..784e04fb6 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn5/LiftA4Test.java @@ -0,0 +1,15 @@ +package com.jnape.palatable.lambda.functions.builtin.fn5; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.Maybe.just; +import static com.jnape.palatable.lambda.functions.builtin.fn5.LiftA4.liftA4; +import static org.junit.Assert.assertEquals; + +public class LiftA4Test { + + @Test + public void lifting() { + assertEquals(just(10), liftA4((a, b, c, d) -> a + b + c + d, just(1), just(2), just(3), just(4))); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5Test.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5Test.java new file mode 100644 index 000000000..0d1851d34 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn6/LiftA5Test.java @@ -0,0 +1,15 @@ +package com.jnape.palatable.lambda.functions.builtin.fn6; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.Maybe.just; +import static com.jnape.palatable.lambda.functions.builtin.fn6.LiftA5.liftA5; +import static org.junit.Assert.assertEquals; + +public class LiftA5Test { + + @Test + public void lifting() { + assertEquals(just(15), liftA5((a, b, c, d, e) -> a + b + c + d + e, just(1), just(2), just(3), just(4), just(5))); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6Test.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6Test.java new file mode 100644 index 000000000..a247e5620 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn7/LiftA6Test.java @@ -0,0 +1,15 @@ +package com.jnape.palatable.lambda.functions.builtin.fn7; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.Maybe.just; +import static com.jnape.palatable.lambda.functions.builtin.fn7.LiftA6.liftA6; +import static org.junit.Assert.assertEquals; + +public class LiftA6Test { + + @Test + public void lifting() { + assertEquals(just(21), liftA6((a, b, c, d, e, f) -> a + b + c + d + e + f, just(1), just(2), just(3), just(4), just(5), just(6))); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7Test.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7Test.java new file mode 100644 index 000000000..73297afde --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn8/LiftA7Test.java @@ -0,0 +1,15 @@ +package com.jnape.palatable.lambda.functions.builtin.fn8; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.adt.Maybe.just; +import static com.jnape.palatable.lambda.functions.builtin.fn8.LiftA7.liftA7; +import static org.junit.Assert.assertEquals; + +public class LiftA7Test { + + @Test + public void lifting() { + assertEquals(just(28), liftA7((a, b, c, d, e, f, g) -> a + b + c + d + e + f + g, just(1), just(2), just(3), just(4), just(5), just(6), just(7))); + } +} \ No newline at end of file From 94aa2bcd9546395daf3a694c886cec35878a5a80 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 16 Sep 2018 15:47:33 -0500 Subject: [PATCH 20/31] Either#diverge returns a Choice3 --- CHANGELOG.md | 1 + src/main/java/com/jnape/palatable/lambda/adt/Either.java | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87acd6d70..e9c473ec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - monoid folding now implicitly starts with the identity, regardless of iterable population - `Concat` monoid can now fold infinite iterables - all `Function` are now `Function` for better compatibility +- `Either#diverge` returns a `Choice3` ### Added - `Predicate#predicate` static factory method diff --git a/src/main/java/com/jnape/palatable/lambda/adt/Either.java b/src/main/java/com/jnape/palatable/lambda/adt/Either.java index 27d3408bd..dfcb85973 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/Either.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/Either.java @@ -1,5 +1,6 @@ package com.jnape.palatable.lambda.adt; +import com.jnape.palatable.lambda.adt.choice.Choice3; import com.jnape.palatable.lambda.adt.coproduct.CoProduct2; import com.jnape.palatable.lambda.functions.builtin.fn2.Peek; import com.jnape.palatable.lambda.functions.builtin.fn2.Peek2; @@ -204,6 +205,11 @@ public Either peek(Consumer leftConsumer, Consumer rightConsumer) { @Override public abstract V match(Function leftFn, Function rightFn); + @Override + public Choice3 diverge() { + return match(Choice3::a, Choice3::b); + } + @Override public final Either fmap(Function fn) { return Monad.super.fmap(fn).coerce(); From 774d5b090c569ba27246caaf90f19c638c513e5a Mon Sep 17 00:00:00 2001 From: jnape Date: Sat, 6 Oct 2018 17:12:44 -0500 Subject: [PATCH 21/31] Adding Alter for applying an effect to an input and returning it --- CHANGELOG.md | 3 +- .../lambda/functions/builtin/fn2/Alter.java | 39 +++++++++++++++++++ .../functions/builtin/fn2/AlterTest.java | 20 ++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index e9c473ec7..fa46dde2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Tuple2-8` specializations of left/right product rotation - `CheckedEffect`, an `Effect` variant that can throw checked exceptions - `CheckedFn1#checked`, convenience static factory method to aid inference -- `LiftA3-8`, higher-arity analogs to `LiftA2` +- `LiftA3-8`, higher-arity analogs to `LiftA2` +- `Alter`, for applying an `Effect` to an input and returning it, presumably altered ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java new file mode 100644 index 000000000..5b122c5ff --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java @@ -0,0 +1,39 @@ +package com.jnape.palatable.lambda.functions.builtin.fn2; + +import com.jnape.palatable.lambda.functions.Effect; +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; + +import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; + +/** + * Given an {@link Effect}<A> and some A, perform the effect on the A and + * return it. + * + * @param the input and output + */ +public final class Alter implements Fn2, A, A> { + + private static final Alter INSTANCE = new Alter(); + + private Alter() { + } + + @Override + public A apply(Effect effect, A a) { + return effect.fmap(constantly(a)).apply(a); + } + + @SuppressWarnings("unchecked") + public static Alter alter() { + return INSTANCE; + } + + public static Fn1 alter(Effect effect) { + return Alter.alter().apply(effect); + } + + public static A alter(Effect effect, A a) { + return Alter.alter(effect).apply(a); + } +} diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java new file mode 100644 index 000000000..8a8031f61 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java @@ -0,0 +1,20 @@ +package com.jnape.palatable.lambda.functions.builtin.fn2; + +import org.junit.Test; + +import java.util.ArrayList; + +import static com.jnape.palatable.lambda.functions.builtin.fn2.Alter.alter; +import static java.util.Collections.singletonList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +public class AlterTest { + + @Test + public void altersInput() { + ArrayList input = new ArrayList<>(); + assertSame(input, alter(xs -> xs.add("foo"), input)); + assertEquals(singletonList("foo"), input); + } +} \ No newline at end of file From d6ac5bb7c7062a9cb4877c354818749b3e91d3e0 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 21 Oct 2018 17:16:30 -0500 Subject: [PATCH 22/31] Maybe is now a coproduct of Unit and A --- CHANGELOG.md | 3 +- .../com/jnape/palatable/lambda/adt/Maybe.java | 110 ++++++++++-------- .../jnape/palatable/lambda/adt/MaybeTest.java | 22 ++++ 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa46dde2e..3005acef9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - monoid folding now implicitly starts with the identity, regardless of iterable population - `Concat` monoid can now fold infinite iterables - all `Function` are now `Function` for better compatibility -- `Either#diverge` returns a `Choice3` +- `Either#diverge` returns a `Choice3` +- `Maybe` is now a `CoProduct2` of `Unit` and `A` ### Added - `Predicate#predicate` static factory method diff --git a/src/main/java/com/jnape/palatable/lambda/adt/Maybe.java b/src/main/java/com/jnape/palatable/lambda/adt/Maybe.java index 93a700061..ad0b81ad9 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/Maybe.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/Maybe.java @@ -1,5 +1,10 @@ package com.jnape.palatable.lambda.adt; +import com.jnape.palatable.lambda.adt.choice.Choice2; +import com.jnape.palatable.lambda.adt.choice.Choice3; +import com.jnape.palatable.lambda.adt.coproduct.CoProduct2; +import com.jnape.palatable.lambda.adt.hlist.HList; +import com.jnape.palatable.lambda.adt.hlist.Tuple2; import com.jnape.palatable.lambda.functions.builtin.fn2.Peek; import com.jnape.palatable.lambda.functions.specialized.checked.CheckedSupplier; import com.jnape.palatable.lambda.functor.Applicative; @@ -14,6 +19,9 @@ import java.util.function.Supplier; import static com.jnape.palatable.lambda.adt.Either.left; +import static com.jnape.palatable.lambda.adt.Unit.UNIT; +import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; +import static com.jnape.palatable.lambda.functions.builtin.fn1.Id.id; /** * The optional type, representing a potentially absent value. This is lambda's analog of {@link Optional}, supporting @@ -22,7 +30,8 @@ * @param the optional parameter type * @see Optional */ -public abstract class Maybe implements Monad, Traversable { +public abstract class Maybe implements CoProduct2>, Monad, Traversable { + private Maybe() { } @@ -32,7 +41,9 @@ private Maybe() { * @param otherSupplier the supplier for the other value * @return this value, or the supplied other value */ - public abstract A orElseGet(Supplier otherSupplier); + public final A orElseGet(Supplier otherSupplier) { + return match(__ -> otherSupplier.get(), id()); + } /** * If the value is present, return it; otherwise, return other. @@ -130,7 +141,24 @@ public final Maybe discardR(Applicative appB) { } @Override - public abstract Maybe flatMap(Function> f); + public final Maybe flatMap(Function> f) { + return match(constantly(nothing()), f.andThen(Applicative::coerce)); + } + + @Override + public Choice3 diverge() { + return match(Choice3::a, Choice3::b); + } + + @Override + public Tuple2, Maybe> project() { + return CoProduct2.super.project().into(HList::tuple); + } + + @Override + public Choice2 invert() { + return match(Choice2::b, Choice2::a); + } /** * If this value is present, accept it by consumer; otherwise, do nothing. @@ -142,6 +170,14 @@ public final Maybe peek(Consumer consumer) { return Peek.peek(consumer, this); } + @Override + @SuppressWarnings("unchecked") + public final , AppB extends Applicative, AppTrav extends Applicative> AppTrav traverse( + Function fn, + Function pure) { + return match(__ -> pure.apply((TravB) Maybe.nothing()), a -> (AppTrav) fn.apply(a).fmap(Maybe::just)); + } + /** * Convenience static factory method for creating a {@link Maybe} from an {@link Either}. If either is * a right value, wrap the value in a just and return it; otherwise, return {@link #nothing()}. @@ -192,80 +228,60 @@ public static Maybe just(A a) { return new Just<>(a); } + /** + * Return nothing. + * + * @param the type of the value, if there was one + * @return nothing + */ @SuppressWarnings("unchecked") public static Maybe nothing() { return Nothing.INSTANCE; } - private static final class Just extends Maybe { - - private final A a; - - private Just(A a) { - this.a = a; - } - - @Override - public A orElseGet(Supplier otherSupplier) { - return a; - } - - @Override - public Maybe flatMap(Function> f) { - return f.apply(a).coerce(); - } - - @Override - @SuppressWarnings("unchecked") - public , - AppB extends Applicative, AppTrav extends Applicative> AppTrav traverse( - Function fn, Function pure) { - return fn.apply(a).fmap(Just::new).fmap(Applicative::coerce).coerce(); - } + private static final class Nothing extends Maybe { + private static final Nothing INSTANCE = new Nothing(); - @Override - public boolean equals(Object other) { - return other instanceof Just && Objects.equals(this.a, ((Just) other).a); + private Nothing() { } @Override - public int hashCode() { - return Objects.hash(a); + public R match(Function aFn, Function bFn) { + return aFn.apply(UNIT); } @Override public String toString() { - return "Just " + a; + return "Nothing"; } } - private static final class Nothing extends Maybe { - private static final Nothing INSTANCE = new Nothing(); + private static final class Just extends Maybe { - private Nothing() { + private final A a; + + private Just(A a) { + this.a = a; } @Override - @SuppressWarnings("unchecked") - public Maybe flatMap(Function> f) { - return nothing(); + public R match(Function aFn, Function bFn) { + return bFn.apply(a); } @Override - @SuppressWarnings("unchecked") - public , AppB extends Applicative, AppTrav extends Applicative> AppTrav traverse( - Function fn, Function pure) { - return pure.apply((TravB) nothing()); + public boolean equals(Object other) { + return other instanceof Just && Objects.equals(this.a, ((Just) other).a); } @Override - public A orElseGet(Supplier otherSupplier) { - return otherSupplier.get(); + public int hashCode() { + return Objects.hash(a); } @Override public String toString() { - return "Nothing"; + return "Just " + a; } } } diff --git a/src/test/java/com/jnape/palatable/lambda/adt/MaybeTest.java b/src/test/java/com/jnape/palatable/lambda/adt/MaybeTest.java index 9205db543..1e747dc34 100644 --- a/src/test/java/com/jnape/palatable/lambda/adt/MaybeTest.java +++ b/src/test/java/com/jnape/palatable/lambda/adt/MaybeTest.java @@ -1,5 +1,7 @@ package com.jnape.palatable.lambda.adt; +import com.jnape.palatable.lambda.adt.choice.Choice2; +import com.jnape.palatable.lambda.adt.choice.Choice3; import com.jnape.palatable.traitor.annotations.TestTraits; import com.jnape.palatable.traitor.framework.Subjects; import com.jnape.palatable.traitor.runners.Traits; @@ -17,6 +19,8 @@ import static com.jnape.palatable.lambda.adt.Either.right; import static com.jnape.palatable.lambda.adt.Maybe.just; import static com.jnape.palatable.lambda.adt.Maybe.nothing; +import static com.jnape.palatable.lambda.adt.Unit.UNIT; +import static com.jnape.palatable.lambda.adt.hlist.HList.tuple; import static com.jnape.palatable.lambda.functions.builtin.fn2.Eq.eq; import static com.jnape.palatable.traitor.framework.Subjects.subjects; import static org.junit.Assert.assertEquals; @@ -108,4 +112,22 @@ public void justOrThrow() { public void nothingOrThrow() { nothing().orElseThrow(IllegalStateException::new); } + + @Test + public void divergesIntoChoice3() { + assertEquals(Choice3.a(UNIT), nothing().diverge()); + assertEquals(Choice3.b(1), just(1).diverge()); + } + + @Test + public void projectsIntoTuple2() { + assertEquals(tuple(just(UNIT), nothing()), nothing().project()); + assertEquals(tuple(nothing(), just(1)), just(1).project()); + } + + @Test + public void invertsIntoChoice2() { + assertEquals(Choice2.b(UNIT), nothing().invert()); + assertEquals(Choice2.a(1), just(1).invert()); + } } \ No newline at end of file From 6fed0ab2e785d628c0dfae9316ab53b3e8a980f2 Mon Sep 17 00:00:00 2001 From: jnape Date: Thu, 25 Oct 2018 00:51:46 -0500 Subject: [PATCH 23/31] Adding Between and Clamp --- CHANGELOG.md | 2 + .../lambda/functions/builtin/fn3/Between.java | 43 +++++++++++++++++ .../lambda/functions/builtin/fn3/Clamp.java | 46 +++++++++++++++++++ .../functions/builtin/fn3/BetweenTest.java | 19 ++++++++ .../functions/builtin/fn3/ClampTest.java | 16 +++++++ 5 files changed, 126 insertions(+) create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Between.java create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Clamp.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/BetweenTest.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/ClampTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 3005acef9..abfce5dad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `CheckedFn1#checked`, convenience static factory method to aid inference - `LiftA3-8`, higher-arity analogs to `LiftA2` - `Alter`, for applying an `Effect` to an input and returning it, presumably altered +- `Clamp`, for clamping a value between two bounds +- `Between`, for determining if a value is in a closed interval ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Between.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Between.java new file mode 100644 index 000000000..70dac2bce --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Between.java @@ -0,0 +1,43 @@ +package com.jnape.palatable.lambda.functions.builtin.fn3; + +import com.jnape.palatable.lambda.functions.Fn3; +import com.jnape.palatable.lambda.functions.specialized.BiPredicate; +import com.jnape.palatable.lambda.functions.specialized.Predicate; + +import static com.jnape.palatable.lambda.functions.builtin.fn3.Clamp.clamp; + +/** + * Given two bounds and a value, return whether or not the value is greater than or equal to the lower bound and less + * than or equal to the upper bound. + * + * @param the bounds and input type + */ +public final class Between> implements Fn3 { + + private static final Between INSTANCE = new Between<>(); + + private Between() { + } + + @Override + public Boolean apply(A lower, A upper, A a) { + return clamp(lower, upper, a).equals(a); + } + + @SuppressWarnings("unchecked") + public static > Between between() { + return INSTANCE; + } + + public static > BiPredicate between(A lower) { + return Between.between().apply(lower)::apply; + } + + public static > Predicate between(A lower, A upper) { + return between(lower).apply(upper); + } + + public static > Boolean between(A lower, A upper, A a) { + return between(lower, upper).apply(a); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Clamp.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Clamp.java new file mode 100644 index 000000000..62d0c21de --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn3/Clamp.java @@ -0,0 +1,46 @@ +package com.jnape.palatable.lambda.functions.builtin.fn3; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.Fn3; + +import static com.jnape.palatable.lambda.semigroup.builtin.Max.max; +import static com.jnape.palatable.lambda.semigroup.builtin.Min.min; + +/** + * Given two bounds and a value, "clamp" the value between the bounds via the following algorithm: + * - if the value is strictly less than the lower bound, return the lower bound + * - if the value is strictly greater than the upper bound, return the upper bound + * - otherwise, return the value + * + * @param the bounds and input type + */ +public final class Clamp> implements Fn3 { + + private static final Clamp INSTANCE = new Clamp<>(); + + private Clamp() { + } + + @Override + public A apply(A lower, A upper, A a) { + return max(min(lower, upper)).fmap(min(max(lower, upper))).apply(a); + } + + @SuppressWarnings("unchecked") + public static > Clamp clamp() { + return INSTANCE; + } + + public static > Fn2 clamp(A lower) { + return Clamp.clamp().apply(lower); + } + + public static > Fn1 clamp(A lower, A upper) { + return clamp(lower).apply(upper); + } + + public static > A clamp(A lower, A upper, A a) { + return clamp(lower, upper).apply(a); + } +} diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/BetweenTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/BetweenTest.java new file mode 100644 index 000000000..2638ee7f1 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/BetweenTest.java @@ -0,0 +1,19 @@ +package com.jnape.palatable.lambda.functions.builtin.fn3; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.functions.builtin.fn3.Between.between; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class BetweenTest { + + @Test + public void testsIfValueIsBetweenClosedBounds() { + assertFalse(between(1, 10, 0)); + assertTrue(between(1, 10, 1)); + assertTrue(between(1, 10, 5)); + assertTrue(between(1, 10, 10)); + assertFalse(between(1, 10, 11)); + } +} diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/ClampTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/ClampTest.java new file mode 100644 index 000000000..9b2bedde4 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn3/ClampTest.java @@ -0,0 +1,16 @@ +package com.jnape.palatable.lambda.functions.builtin.fn3; + +import org.junit.Test; + +import static com.jnape.palatable.lambda.functions.builtin.fn3.Clamp.clamp; +import static org.junit.Assert.assertEquals; + +public class ClampTest { + + @Test + public void clampsValueBetweenBounds() { + assertEquals((Integer) 5, clamp(1, 10, 5)); + assertEquals((Integer) 1, clamp(1, 10, -1)); + assertEquals((Integer) 10, clamp(1, 10, 11)); + } +} From 1e7ab1f0b36f6defee58fc1dec1abea4fdb094db Mon Sep 17 00:00:00 2001 From: jnape Date: Sat, 3 Nov 2018 22:33:35 -0500 Subject: [PATCH 24/31] Fn0 is now Callable --- CHANGELOG.md | 3 ++- .../com/jnape/palatable/lambda/functions/Fn0.java | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abfce5dad..1f1c0c6f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Concat` monoid can now fold infinite iterables - all `Function` are now `Function` for better compatibility - `Either#diverge` returns a `Choice3` -- `Maybe` is now a `CoProduct2` of `Unit` and `A` +- `Maybe` is now a `CoProduct2` of `Unit` and `A` +- `Fn0` now additionally implements `Callable` ### Added - `Predicate#predicate` static factory method diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java b/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java index 357a28a3c..023f531c3 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java @@ -4,6 +4,7 @@ import com.jnape.palatable.lambda.functor.Applicative; import com.jnape.palatable.lambda.monad.Monad; +import java.util.concurrent.Callable; import java.util.function.Function; import java.util.function.Supplier; @@ -16,9 +17,10 @@ * @param the result type * @see Fn1 * @see Supplier + * @see Callable */ @FunctionalInterface -public interface Fn0 extends Fn1, Supplier { +public interface Fn0 extends Fn1, Supplier, Callable { A apply(); @@ -85,7 +87,12 @@ default Fn0 andThen(Function after) { @Override default A get() { - return apply(UNIT); + return apply(); + } + + @Override + default A call() { + return apply(); } /** From 4a4f177d6607c2232d9f35fcbd16eb07e15999eb Mon Sep 17 00:00:00 2001 From: jnape Date: Fri, 16 Nov 2018 16:40:32 -0600 Subject: [PATCH 25/31] Profunctor strength --- CHANGELOG.md | 3 +- .../jnape/palatable/lambda/functions/Fn1.java | 26 +++++++-- .../palatable/lambda/functor/Strong.java | 53 +++++++++++++++++++ .../lambda/functor/builtin/Exchange.java | 9 ++-- .../palatable/lambda/functions/Fn1Test.java | 13 +++++ 5 files changed, 92 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/jnape/palatable/lambda/functor/Strong.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f1c0c6f7..47f9bc3d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `LiftA3-8`, higher-arity analogs to `LiftA2` - `Alter`, for applying an `Effect` to an input and returning it, presumably altered - `Clamp`, for clamping a value between two bounds -- `Between`, for determining if a value is in a closed interval +- `Between`, for determining if a value is in a closed interval +- `Strong`, profunctor strength ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java b/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java index 092b5b953..c9fa0ee26 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Fn1.java @@ -1,7 +1,8 @@ package com.jnape.palatable.lambda.functions; +import com.jnape.palatable.lambda.adt.hlist.Tuple2; import com.jnape.palatable.lambda.functor.Applicative; -import com.jnape.palatable.lambda.functor.Profunctor; +import com.jnape.palatable.lambda.functor.Strong; import com.jnape.palatable.lambda.monad.Monad; import java.util.function.BiFunction; @@ -18,7 +19,7 @@ * @param The result type */ @FunctionalInterface -public interface Fn1 extends Monad>, Profunctor, Function { +public interface Fn1 extends Monad>, Strong, Function { /** * Invoke this function with the given argument. @@ -116,7 +117,7 @@ default Fn1 discardR(Applicative> appB) { */ @Override default Fn1 diMapL(Function fn) { - return (Fn1) Profunctor.super.diMapL(fn); + return (Fn1) Strong.super.diMapL(fn); } /** @@ -129,7 +130,7 @@ default Fn1 diMapL(Function fn) { */ @Override default Fn1 diMapR(Function fn) { - return (Fn1) Profunctor.super.diMapR(fn); + return (Fn1) Strong.super.diMapR(fn); } /** @@ -146,9 +147,24 @@ default Fn1 diMap(Function lFn, Function the paired value + * @return the strengthened {@link Fn1} + */ + @Override + default Fn1, Tuple2> strengthen() { + return t -> t.fmap(this); + } + + default Fn1> carry() { + return (Fn1>) Strong.super.carry(); + } + @Override default Fn1 contraMap(Function fn) { - return (Fn1) Profunctor.super.contraMap(fn); + return (Fn1) Strong.super.contraMap(fn); } /** diff --git a/src/main/java/com/jnape/palatable/lambda/functor/Strong.java b/src/main/java/com/jnape/palatable/lambda/functor/Strong.java new file mode 100644 index 000000000..c31a605b4 --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functor/Strong.java @@ -0,0 +1,53 @@ +package com.jnape.palatable.lambda.functor; + +import com.jnape.palatable.lambda.adt.hlist.Tuple2; + +import java.util.function.Function; + +/** + * "Strong" {@link Profunctor profunctors} are profunctors that can be "strengthened" to preserve the pairing of an + * arbitrary type under dimap (p a b -> p (c, a) (c, b) for any type c). + * + * @param the type of the left parameter + * @param the type of the left parameter + * @param the unification parameter + * @see com.jnape.palatable.lambda.functions.Fn1 + */ +public interface Strong extends Profunctor { + + /** + * Pair some type C to this profunctor's carrier types. + * + * @param the paired type + * @return the strengthened profunctor + */ + Strong, Tuple2, S> strengthen(); + + /** + * Pair the covariantly-positioned carrier type with the contravariantly-positioned carrier type. This can be + * thought of as "carrying" or "inspecting" the left parameter. + * + * @return the profunctor with the first parameter carried + */ + default Strong, S> carry() { + return this.strengthen().contraMap(Tuple2::fill); + } + + @Override + Strong diMap(Function lFn, Function rFn); + + @Override + default Strong diMapL(Function fn) { + return (Strong) Profunctor.super.diMapL(fn); + } + + @Override + default Strong diMapR(Function fn) { + return (Strong) Profunctor.super.diMapR(fn); + } + + @Override + default Strong contraMap(Function fn) { + return (Strong) Profunctor.super.contraMap(fn); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functor/builtin/Exchange.java b/src/main/java/com/jnape/palatable/lambda/functor/builtin/Exchange.java index 1a9439d6b..6a317784c 100644 --- a/src/main/java/com/jnape/palatable/lambda/functor/builtin/Exchange.java +++ b/src/main/java/com/jnape/palatable/lambda/functor/builtin/Exchange.java @@ -37,20 +37,17 @@ public Exchange diMap(Function lFn, } @Override - @SuppressWarnings("unchecked") public Exchange diMapL(Function fn) { - return (Exchange) Profunctor.super.diMapL(fn); + return (Exchange) Profunctor.super.diMapL(fn); } @Override - @SuppressWarnings("unchecked") public Exchange diMapR(Function fn) { - return (Exchange) Profunctor.super.diMapR(fn); + return (Exchange) Profunctor.super.diMapR(fn); } @Override - @SuppressWarnings("unchecked") public Exchange contraMap(Function fn) { - return (Exchange) Profunctor.super.contraMap(fn); + return (Exchange) Profunctor.super.contraMap(fn); } } diff --git a/src/test/java/com/jnape/palatable/lambda/functions/Fn1Test.java b/src/test/java/com/jnape/palatable/lambda/functions/Fn1Test.java index b769d67d8..bd3237f2c 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/Fn1Test.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/Fn1Test.java @@ -12,6 +12,7 @@ import java.util.function.Function; import static com.jnape.palatable.lambda.adt.Maybe.just; +import static com.jnape.palatable.lambda.adt.hlist.HList.tuple; import static com.jnape.palatable.lambda.functions.builtin.fn2.ReduceLeft.reduceLeft; import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; @@ -50,4 +51,16 @@ public void widen() { Fn1 addOne = x -> x + 1; assertEquals(just(4), reduceLeft(addOne.widen().toBiFunction(), asList(1, 2, 3))); } + + @Test + public void strengthen() { + Fn1 add1 = x -> x + 1; + assertEquals(tuple("a", 2), add1.strengthen().apply(tuple("a", 1))); + } + + @Test + public void carry() { + Fn1 add1 = x -> x + 1; + assertEquals(tuple(1, 2), add1.carry().apply(1)); + } } From 794b3cebf48e332ef65d1170bde04937654da1c9 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 18 Nov 2018 18:45:03 -0600 Subject: [PATCH 26/31] Javadocs --- .../lambda/adt/coproduct/CoProduct2.java | 5 +++-- .../lambda/adt/coproduct/CoProduct3.java | 7 ++++--- .../lambda/adt/coproduct/CoProduct4.java | 9 +++++---- .../lambda/adt/coproduct/CoProduct5.java | 11 ++++++----- .../lambda/adt/coproduct/CoProduct6.java | 13 +++++++------ .../lambda/adt/coproduct/CoProduct7.java | 15 ++++++++------- .../lambda/adt/coproduct/CoProduct8.java | 17 +++++++++-------- .../jnape/palatable/lambda/adt/hmap/Schema.java | 9 +++++++++ 8 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct2.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct2.java index 6c2c43ee8..5ad1a9908 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct2.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct2.java @@ -20,8 +20,9 @@ *

* Learn more about Coproducts. * - * @param the first possible type - * @param the second possible type + * @param the first possible type + * @param the second possible type + * @param the recursive type of this coproduct (used for embedding) * @see Choice2 * @see Either */ diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct3.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct3.java index 967e950e2..23a97ac9c 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct3.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct3.java @@ -15,9 +15,10 @@ /** * A generalization of the coproduct of three types. * - * @param the first possible type - * @param the second possible type - * @param the third possible type + * @param the first possible type + * @param the second possible type + * @param the third possible type + * @param the recursive type of this coproduct (used for embedding) * @see CoProduct2 */ @FunctionalInterface diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct4.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct4.java index cc4f47b57..2ec2e113d 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct4.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct4.java @@ -15,10 +15,11 @@ /** * A generalization of the coproduct of four types. * - * @param the first possible type - * @param the second possible type - * @param the third possible type - * @param the fourth possible type + * @param the first possible type + * @param the second possible type + * @param the third possible type + * @param the fourth possible type + * @param the recursive type of this coproduct (used for embedding) * @see CoProduct2 */ @FunctionalInterface diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct5.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct5.java index aa64d58c0..b90aab2f5 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct5.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct5.java @@ -15,11 +15,12 @@ /** * A generalization of the coproduct of five types. * - * @param the first possible type - * @param the second possible type - * @param the third possible type - * @param the fourth possible type - * @param the fifth possible type + * @param the first possible type + * @param the second possible type + * @param the third possible type + * @param the fourth possible type + * @param the fifth possible type + * @param the recursive type of this coproduct (used for embedding) * @see CoProduct2 */ @FunctionalInterface diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct6.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct6.java index 2ff159c7b..a3aa40163 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct6.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct6.java @@ -16,12 +16,13 @@ /** * A generalization of the coproduct of six types. * - * @param the first possible type - * @param the second possible type - * @param the third possible type - * @param the fourth possible type - * @param the fifth possible type - * @param the sixth possible type + * @param the first possible type + * @param the second possible type + * @param the third possible type + * @param the fourth possible type + * @param the fifth possible type + * @param the sixth possible type + * @param the recursive type of this coproduct (used for embedding) * @see CoProduct2 */ @FunctionalInterface diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct7.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct7.java index 6c8444204..18086211c 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct7.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct7.java @@ -16,13 +16,14 @@ /** * A generalization of the coproduct of seven types. * - * @param the first possible type - * @param the second possible type - * @param the third possible type - * @param the fourth possible type - * @param the fifth possible type - * @param the sixth possible type - * @param the seventh possible type + * @param the first possible type + * @param the second possible type + * @param the third possible type + * @param the fourth possible type + * @param the fifth possible type + * @param the sixth possible type + * @param the seventh possible type + * @param the recursive type of this coproduct (used for embedding) * @see CoProduct2 */ @FunctionalInterface diff --git a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct8.java b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct8.java index a94ab4586..776f067e8 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct8.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/coproduct/CoProduct8.java @@ -16,14 +16,15 @@ /** * A generalization of the coproduct of eight types. * - * @param the first possible type - * @param the second possible type - * @param the third possible type - * @param the fourth possible type - * @param the fifth possible type - * @param the sixth possible type - * @param the seventh possible type - * @param the eighth possible type + * @param the first possible type + * @param the second possible type + * @param the third possible type + * @param the fourth possible type + * @param the fifth possible type + * @param the sixth possible type + * @param the seventh possible type + * @param the eighth possible type + * @param the recursive type of this coproduct (used for embedding) * @see CoProduct2 */ @FunctionalInterface diff --git a/src/main/java/com/jnape/palatable/lambda/adt/hmap/Schema.java b/src/main/java/com/jnape/palatable/lambda/adt/hmap/Schema.java index 52e4b0903..a7e3eb371 100644 --- a/src/main/java/com/jnape/palatable/lambda/adt/hmap/Schema.java +++ b/src/main/java/com/jnape/palatable/lambda/adt/hmap/Schema.java @@ -17,6 +17,14 @@ import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into; import static com.jnape.palatable.lambda.lens.lenses.HMapLens.valueAt; +/** + * A lens that focuses on the {@link HList heterogeneous list} of values pointed at by one or more + * {@link TypeSafeKey typesafe keys} that must all exist in the same {@link HMap} to be collectively extracted. Note + * that if any of the keys is absent in the map, the result will be {@link Maybe#nothing()}. + * + * @param the {@link HList} of values to focus on + * @see TypeSafeKey + */ public interface Schema> extends Lens.Simple> { @SuppressWarnings("unchecked") @@ -28,6 +36,7 @@ default > Schema add(TypeSafeKe ::apply; } + @SuppressWarnings("unchecked") static Schema> schema(TypeSafeKey key) { return valueAt(key) .mapA(ma -> ma.fmap(HList::singletonHList)) From 1348fc7a68ffb504c76ecb4d40a534df919c125b Mon Sep 17 00:00:00 2001 From: jnape Date: Thu, 29 Nov 2018 00:43:41 -0600 Subject: [PATCH 27/31] IO monad arrives --- CHANGELOG.md | 5 +- .../palatable/lambda/functions/Effect.java | 10 +- .../jnape/palatable/lambda/functions/Fn0.java | 8 +- .../jnape/palatable/lambda/functions/IO.java | 118 ++++++++++++++++++ .../lambda/functions/builtin/fn2/Alter.java | 15 +-- .../palatable/lambda/functions/IOTest.java | 32 +++++ .../functions/builtin/fn2/AlterTest.java | 2 +- .../java/testsupport/EqualityAwareIO.java | 64 ++++++++++ 8 files changed, 236 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/jnape/palatable/lambda/functions/IO.java create mode 100644 src/test/java/com/jnape/palatable/lambda/functions/IOTest.java create mode 100644 src/test/java/testsupport/EqualityAwareIO.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 47f9bc3d0..079c6b54f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - ***Breaking Change***: `Effect#accept()` is now the required method to implement in the functional interface - ***Breaking Change***: `Fn0#apply()` is now the required method to implement in the functional interface - ***Breaking Change***: `GTBy`, `GT`, `LTBy`, `LT`, `GTEBy`, `GTE`, `LTEBy`, and `LTE` take the right-hand side first for more intuitive partial application +- ***Breaking Change***: `Effect` now returns an `IO` +- ***Breaking Change***: `Alter` now returns an `IO` - `RightAny` overload returns `Monoid` - monoids now all fold with respect to `foldMap` - monoid folding now implicitly starts with the identity, regardless of iterable population @@ -29,7 +31,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Alter`, for applying an `Effect` to an input and returning it, presumably altered - `Clamp`, for clamping a value between two bounds - `Between`, for determining if a value is in a closed interval -- `Strong`, profunctor strength +- `Strong`, profunctor strength +- `IO` monad ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Effect.java b/src/main/java/com/jnape/palatable/lambda/functions/Effect.java index f9adebe97..8a341d9a3 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Effect.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Effect.java @@ -6,7 +6,8 @@ import java.util.function.Consumer; import java.util.function.Function; -import static com.jnape.palatable.lambda.adt.Unit.UNIT; +import static com.jnape.palatable.lambda.functions.Fn0.fn0; +import static com.jnape.palatable.lambda.functions.IO.io; /** * A function returning "no result", and therefore only useful as a side-effect. @@ -16,12 +17,11 @@ * @see Consumer */ @FunctionalInterface -public interface Effect extends Fn1, Consumer { +public interface Effect extends Fn1>, Consumer { @Override - default Unit apply(A a) { - accept(a); - return UNIT; + default IO apply(A a) { + return io(fn0(() -> accept(a))); } @Override diff --git a/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java b/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java index 023f531c3..84eb3e4a8 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/Fn0.java @@ -9,7 +9,7 @@ import java.util.function.Supplier; import static com.jnape.palatable.lambda.adt.Unit.UNIT; -import static com.jnape.palatable.lambda.functions.Effect.effect; +import static com.jnape.palatable.lambda.functions.IO.io; /** * A function taking "no arguments", implemented as an {@link Fn1}<{@link Unit}, A>. @@ -120,11 +120,11 @@ static Fn0 fn0(Fn0 fn) { /** * Static factory method for adapting a {@link Runnable} to an {@link Fn0}<{@link Unit}>. * - * @param fn the {@link Runnable} + * @param runnable the {@link Runnable} * @return the {@link Fn0} */ - static Fn0 fn0(Runnable fn) { - return effect(fn).thunk(UNIT); + static Fn0 fn0(Runnable runnable) { + return io(runnable)::unsafePerformIO; } /** diff --git a/src/main/java/com/jnape/palatable/lambda/functions/IO.java b/src/main/java/com/jnape/palatable/lambda/functions/IO.java new file mode 100644 index 000000000..8e05dfcaf --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/functions/IO.java @@ -0,0 +1,118 @@ +package com.jnape.palatable.lambda.functions; + +import com.jnape.palatable.lambda.adt.Unit; +import com.jnape.palatable.lambda.functor.Applicative; +import com.jnape.palatable.lambda.monad.Monad; + +import java.util.function.Function; + +import static com.jnape.palatable.lambda.adt.Unit.UNIT; + +/** + * A {@link Monad} representing some effectful computation to be performed. + * + * @param the result type + */ +public interface IO extends Monad> { + + /** + * Run the effect represented by this {@link IO} instance + * + * @return the result of the effect + */ + A unsafePerformIO(); + + /** + * {@inheritDoc} + */ + @Override + default IO flatMap(Function>> f) { + return () -> f.apply(unsafePerformIO()).>coerce().unsafePerformIO(); + } + + /** + * {@inheritDoc} + */ + @Override + default IO pure(B b) { + return () -> b; + } + + /** + * {@inheritDoc} + */ + @Override + default IO fmap(Function fn) { + return Monad.super.fmap(fn).coerce(); + } + + /** + * {@inheritDoc} + */ + @Override + default IO zip(Applicative, IO> appFn) { + return Monad.super.zip(appFn).coerce(); + } + + /** + * {@inheritDoc} + */ + @Override + default IO discardL(Applicative> appB) { + return Monad.super.discardL(appB).coerce(); + } + + /** + * {@inheritDoc} + */ + @Override + default IO discardR(Applicative> appB) { + return Monad.super.discardR(appB).coerce(); + } + + /** + * Static factory method for coercing a lambda to an {@link IO}. + * + * @param io the lambda to coerce + * @param the result type + * @return the {@link IO} + */ + static IO io(IO io) { + return io; + } + + /** + * Static factory method for creating an {@link IO} that just returns a when performed. + * + * @param a the result + * @param the result type + * @return the {@link IO} + */ + static IO io(A a) { + return io(() -> a); + } + + /** + * Static factory method for creating an {@link IO} that runs runnable and returns {@link Unit}. + * + * @param runnable the {@link Runnable} + * @return the {@link IO} + */ + static IO io(Runnable runnable) { + return io(() -> { + runnable.run(); + return UNIT; + }); + } + + /** + * Static factory method for creating an {@link IO} from an {@link Fn1}<{@link Unit}, A>. + * + * @param fn1 the {@link Fn1} + * @param the result type + * @return the {@link IO} + */ + static IO io(Fn1 fn1) { + return io(() -> fn1.apply(UNIT)); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java index 5b122c5ff..f51050eae 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/builtin/fn2/Alter.java @@ -3,16 +3,17 @@ import com.jnape.palatable.lambda.functions.Effect; import com.jnape.palatable.lambda.functions.Fn1; import com.jnape.palatable.lambda.functions.Fn2; +import com.jnape.palatable.lambda.functions.IO; import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly; /** - * Given an {@link Effect}<A> and some A, perform the effect on the A and - * return it. + * Given an {@link Effect}<A> and some A, produce an {@link IO} that, when run, performs + * the effect on A and returns it. * * @param the input and output */ -public final class Alter implements Fn2, A, A> { +public final class Alter implements Fn2, A, IO> { private static final Alter INSTANCE = new Alter(); @@ -20,8 +21,8 @@ private Alter() { } @Override - public A apply(Effect effect, A a) { - return effect.fmap(constantly(a)).apply(a); + public IO apply(Effect effect, A a) { + return effect.fmap(io -> io.fmap(constantly(a))).apply(a); } @SuppressWarnings("unchecked") @@ -29,11 +30,11 @@ public static Alter alter() { return INSTANCE; } - public static Fn1 alter(Effect effect) { + public static Fn1> alter(Effect effect) { return Alter.alter().apply(effect); } - public static A alter(Effect effect, A a) { + public static IO alter(Effect effect, A a) { return Alter.alter(effect).apply(a); } } diff --git a/src/test/java/com/jnape/palatable/lambda/functions/IOTest.java b/src/test/java/com/jnape/palatable/lambda/functions/IOTest.java new file mode 100644 index 000000000..e9038fa6f --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/functions/IOTest.java @@ -0,0 +1,32 @@ +package com.jnape.palatable.lambda.functions; + +import com.jnape.palatable.traitor.annotations.TestTraits; +import com.jnape.palatable.traitor.runners.Traits; +import org.junit.Test; +import org.junit.runner.RunWith; +import testsupport.EqualityAwareIO; +import testsupport.traits.ApplicativeLaws; +import testsupport.traits.FunctorLaws; +import testsupport.traits.MonadLaws; + +import static com.jnape.palatable.lambda.adt.Unit.UNIT; +import static com.jnape.palatable.lambda.functions.Fn0.fn0; +import static com.jnape.palatable.lambda.functions.IO.io; +import static org.junit.Assert.assertEquals; + +@RunWith(Traits.class) +public class IOTest { + + @TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class}) + public IO testSubject() { + return new EqualityAwareIO<>(io(1)); + } + + @Test + public void staticFactoryMethods() { + assertEquals((Integer) 1, io(1).unsafePerformIO()); + assertEquals((Integer) 1, io(() -> 1).unsafePerformIO()); + assertEquals((Integer) 1, io(fn0(() -> 1)).unsafePerformIO()); + assertEquals(UNIT, io(() -> {}).unsafePerformIO()); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java index 8a8031f61..73e11e800 100644 --- a/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java +++ b/src/test/java/com/jnape/palatable/lambda/functions/builtin/fn2/AlterTest.java @@ -14,7 +14,7 @@ public class AlterTest { @Test public void altersInput() { ArrayList input = new ArrayList<>(); - assertSame(input, alter(xs -> xs.add("foo"), input)); + assertSame(input, alter(xs -> xs.add("foo"), input).unsafePerformIO()); assertEquals(singletonList("foo"), input); } } \ No newline at end of file diff --git a/src/test/java/testsupport/EqualityAwareIO.java b/src/test/java/testsupport/EqualityAwareIO.java new file mode 100644 index 000000000..822cfebf7 --- /dev/null +++ b/src/test/java/testsupport/EqualityAwareIO.java @@ -0,0 +1,64 @@ +package testsupport; + +import com.jnape.palatable.lambda.functions.IO; +import com.jnape.palatable.lambda.functor.Applicative; +import com.jnape.palatable.lambda.monad.Monad; + +import java.util.function.Function; + +import static java.util.Objects.hash; + +public final class EqualityAwareIO implements IO { + private final IO io; + + public EqualityAwareIO(IO io) { + this.io = io; + } + + @Override + public A unsafePerformIO() { + return io.unsafePerformIO(); + } + + @Override + public EqualityAwareIO flatMap(Function>> f) { + return new EqualityAwareIO<>(io.flatMap(f)); + } + + @Override + public EqualityAwareIO fmap(Function f) { + return new EqualityAwareIO<>(io.fmap(f)); + } + + @Override + public EqualityAwareIO zip(Applicative, IO> appFn) { + return new EqualityAwareIO<>(io.zip(appFn)); + } + + @Override + public EqualityAwareIO pure(B b) { + return new EqualityAwareIO<>(io.pure(b)); + } + + + @Override + public EqualityAwareIO discardL(Applicative> appB) { + return new EqualityAwareIO<>(io.discardL(appB)); + } + + @Override + public EqualityAwareIO discardR(Applicative> appB) { + return new EqualityAwareIO<>(io.discardR(appB)); + } + + @Override + @SuppressWarnings("unchecked") + public boolean equals(Object other) { + return other instanceof IO && ((IO) other).unsafePerformIO().equals(unsafePerformIO()); + } + + @Override + public int hashCode() { + return hash(io); + } +} From 14cb27f248282ec7cfc0dc92a504fc775ee4fd0d Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 2 Dec 2018 17:04:34 -0600 Subject: [PATCH 28/31] CheckedRunnable is an IO --- CHANGELOG.md | 1 + .../specialized/checked/CheckedRunnable.java | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 079c6b54f..86026c917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Either#diverge` returns a `Choice3` - `Maybe` is now a `CoProduct2` of `Unit` and `A` - `Fn0` now additionally implements `Callable` +- `CheckedRunnable` is an `IO` ### Added - `Predicate#predicate` static factory method diff --git a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedRunnable.java b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedRunnable.java index 2552c746e..7eb794917 100644 --- a/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedRunnable.java +++ b/src/main/java/com/jnape/palatable/lambda/functions/specialized/checked/CheckedRunnable.java @@ -1,6 +1,7 @@ package com.jnape.palatable.lambda.functions.specialized.checked; import com.jnape.palatable.lambda.adt.Unit; +import com.jnape.palatable.lambda.functions.IO; import static com.jnape.palatable.lambda.adt.Unit.UNIT; import static com.jnape.palatable.lambda.functions.specialized.checked.Runtime.throwChecked; @@ -13,7 +14,14 @@ * @see CheckedFn1 */ @FunctionalInterface -public interface CheckedRunnable extends Runnable { +public interface CheckedRunnable extends Runnable, IO { + + /** + * A version of {@link Runnable#run()} that can throw checked exceptions. + * + * @throws T any exception that can be thrown by this method + */ + void checkedRun() throws T; @Override default void run() { @@ -24,12 +32,11 @@ default void run() { } } - /** - * A version of {@link Runnable#run()} that can throw checked exceptions. - * - * @throws T any exception that can be thrown by this method - */ - void checkedRun() throws T; + @Override + default Unit unsafePerformIO() { + run(); + return UNIT; + } /** * Convert this {@link CheckedRunnable} to a {@link CheckedSupplier} that returns {@link Unit}. From efefe5aca45c8befa026561439ecd7402e416d23 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 2 Dec 2018 17:09:59 -0600 Subject: [PATCH 29/31] RunAll semigroup and monoid for IO --- CHANGELOG.md | 1 + .../lambda/monoid/builtin/RunAll.java | 47 +++++++++++++++++++ .../lambda/semigroup/builtin/RunAll.java | 42 +++++++++++++++++ .../lambda/monoid/builtin/RunAllTest.java | 18 +++++++ .../lambda/semigroup/builtin/RunAllTest.java | 17 +++++++ 5 files changed, 125 insertions(+) create mode 100644 src/main/java/com/jnape/palatable/lambda/monoid/builtin/RunAll.java create mode 100644 src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RunAll.java create mode 100644 src/test/java/com/jnape/palatable/lambda/monoid/builtin/RunAllTest.java create mode 100644 src/test/java/com/jnape/palatable/lambda/semigroup/builtin/RunAllTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 86026c917..d02db6c43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `Between`, for determining if a value is in a closed interval - `Strong`, profunctor strength - `IO` monad +- `RunAll` semigroup and monoid instance for `IO` ### Deprecated - `AddAll` semigroup, in favor of the monoid that no longer mutates any argument diff --git a/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RunAll.java b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RunAll.java new file mode 100644 index 000000000..8e3c0d869 --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/monoid/builtin/RunAll.java @@ -0,0 +1,47 @@ +package com.jnape.palatable.lambda.monoid.builtin; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.IO; +import com.jnape.palatable.lambda.functions.specialized.MonoidFactory; +import com.jnape.palatable.lambda.monoid.Monoid; +import com.jnape.palatable.lambda.semigroup.Semigroup; + +import static com.jnape.palatable.lambda.functions.IO.io; +import static com.jnape.palatable.lambda.monoid.Monoid.monoid; + +/** + * Run {@link IO} operations, aggregating their results in terms of the provided {@link Monoid}. + * + * @param the {@link IO} result + * @see com.jnape.palatable.lambda.semigroup.builtin.RunAll + */ +public final class RunAll implements MonoidFactory, IO> { + + private static final RunAll INSTANCE = new RunAll(); + + private RunAll() { + } + + @Override + public Monoid> apply(Monoid monoid) { + Semigroup> semigroup = com.jnape.palatable.lambda.semigroup.builtin.RunAll.runAll(monoid); + return monoid(semigroup, io(monoid.identity())); + } + + @SuppressWarnings("unchecked") + public static RunAll runAll() { + return INSTANCE; + } + + public static Monoid> runAll(Monoid monoid) { + return RunAll.runAll().apply(monoid); + } + + public static Fn1, IO> runAll(Monoid monoid, IO x) { + return runAll(monoid).apply(x); + } + + public static IO runAll(Monoid monoid, IO x, IO y) { + return runAll(monoid, x).apply(y); + } +} diff --git a/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RunAll.java b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RunAll.java new file mode 100644 index 000000000..5ae09b8ac --- /dev/null +++ b/src/main/java/com/jnape/palatable/lambda/semigroup/builtin/RunAll.java @@ -0,0 +1,42 @@ +package com.jnape.palatable.lambda.semigroup.builtin; + +import com.jnape.palatable.lambda.functions.Fn1; +import com.jnape.palatable.lambda.functions.IO; +import com.jnape.palatable.lambda.functions.specialized.SemigroupFactory; +import com.jnape.palatable.lambda.semigroup.Semigroup; + +/** + * Run {@link IO} operations, aggregating their results in terms of the provided {@link Semigroup}. + * + * @param the {@link IO} result + * @see com.jnape.palatable.lambda.monoid.builtin.RunAll + */ +public final class RunAll implements SemigroupFactory, IO> { + + private static final RunAll INSTANCE = new RunAll(); + + private RunAll() { + } + + @Override + public Semigroup> apply(Semigroup semigroup) { + return (ioX, ioY) -> ioY.zip(ioX.fmap(semigroup)); + } + + @SuppressWarnings("unchecked") + public static RunAll runAll() { + return INSTANCE; + } + + public static Semigroup> runAll(Semigroup semigroup) { + return RunAll.runAll().apply(semigroup); + } + + public static Fn1, IO> runAll(Semigroup semigroup, IO ioX) { + return runAll(semigroup).apply(ioX); + } + + public static IO runAll(Semigroup semigroup, IO ioX, IO ioY) { + return runAll(semigroup, ioX).apply(ioY); + } +} diff --git a/src/test/java/com/jnape/palatable/lambda/monoid/builtin/RunAllTest.java b/src/test/java/com/jnape/palatable/lambda/monoid/builtin/RunAllTest.java new file mode 100644 index 000000000..782ee334f --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/monoid/builtin/RunAllTest.java @@ -0,0 +1,18 @@ +package com.jnape.palatable.lambda.monoid.builtin; + +import com.jnape.palatable.lambda.monoid.Monoid; +import org.junit.Test; + +import static com.jnape.palatable.lambda.functions.IO.io; +import static com.jnape.palatable.lambda.monoid.builtin.RunAll.runAll; +import static org.junit.Assert.assertEquals; + +public class RunAllTest { + + @Test + public void monoid() { + Monoid add = Monoid.monoid((x, y) -> x + y, 0); + assertEquals((Integer) 3, runAll(add).apply(io(1), io(2)).unsafePerformIO()); + assertEquals((Integer) 0, runAll(add).identity().unsafePerformIO()); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/RunAllTest.java b/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/RunAllTest.java new file mode 100644 index 000000000..c8840da69 --- /dev/null +++ b/src/test/java/com/jnape/palatable/lambda/semigroup/builtin/RunAllTest.java @@ -0,0 +1,17 @@ +package com.jnape.palatable.lambda.semigroup.builtin; + +import com.jnape.palatable.lambda.semigroup.Semigroup; +import org.junit.Test; + +import static com.jnape.palatable.lambda.functions.IO.io; +import static com.jnape.palatable.lambda.semigroup.builtin.RunAll.runAll; +import static org.junit.Assert.assertEquals; + +public class RunAllTest { + + @Test + public void semigroup() { + Semigroup add = (x, y) -> x + y; + assertEquals((Integer) 3, runAll(add).apply(io(1), io(2)).unsafePerformIO()); + } +} \ No newline at end of file From 08cc0f2dca91addc6f6fd03e23255070bde0aa68 Mon Sep 17 00:00:00 2001 From: jnape Date: Sun, 2 Dec 2018 18:08:56 -0600 Subject: [PATCH 30/31] Ritual sacrifice to the javadoc gods --- CHANGELOG.md | 1 - src/main/java/com/jnape/palatable/lambda/functor/Strong.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d02db6c43..e04438485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - ***Breaking Change***: `Fn0#apply()` is now the required method to implement in the functional interface - ***Breaking Change***: `GTBy`, `GT`, `LTBy`, `LT`, `GTEBy`, `GTE`, `LTEBy`, and `LTE` take the right-hand side first for more intuitive partial application - ***Breaking Change***: `Effect` now returns an `IO` -- ***Breaking Change***: `Alter` now returns an `IO` - `RightAny` overload returns `Monoid` - monoids now all fold with respect to `foldMap` - monoid folding now implicitly starts with the identity, regardless of iterable population diff --git a/src/main/java/com/jnape/palatable/lambda/functor/Strong.java b/src/main/java/com/jnape/palatable/lambda/functor/Strong.java index c31a605b4..c6b4929c2 100644 --- a/src/main/java/com/jnape/palatable/lambda/functor/Strong.java +++ b/src/main/java/com/jnape/palatable/lambda/functor/Strong.java @@ -6,7 +6,7 @@ /** * "Strong" {@link Profunctor profunctors} are profunctors that can be "strengthened" to preserve the pairing of an - * arbitrary type under dimap (p a b -> p (c, a) (c, b) for any type c). + * arbitrary type under dimap (p a b -> p (c, a) (c, b) for any type c). * * @param the type of the left parameter * @param the type of the left parameter From 68029d2cabb46db831d1a53e27c125bf6ab5de44 Mon Sep 17 00:00:00 2001 From: jnape Date: Sat, 8 Dec 2018 17:19:06 -0600 Subject: [PATCH 31/31] [maven-release-plugin] prepare release lambda-3.2.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 94275b818..a117dcaf0 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ lambda - 3.1.1-SNAPSHOT + 3.2.0 jar Lambda