diff --git a/src/main/java/com/ceticamarco/lambdatonic/Either.java b/src/main/java/com/ceticamarco/lambdatonic/Either.java index 4004613..1ca7363 100644 --- a/src/main/java/com/ceticamarco/lambdatonic/Either.java +++ b/src/main/java/com/ceticamarco/lambdatonic/Either.java @@ -64,6 +64,19 @@ public sealed interface Either permits Left, Right { */ Either map(Function fn); + /** + *

+ * Applies onLeft function to the Left subtype or the + * onRight function to the Right subtype. + *

+ * @param onLeft The function to apply to the Left subtyp + * @param onRight The function to apply to the Right subtype + * @return An Either functor + * @param The return type of the onLeft function + * @param The return type of the onRight function + */ + Either bimap(Function onLeft, Function onRight); + /** *

* Returns the content of Right or a default value @@ -85,4 +98,5 @@ public sealed interface Either permits Left, Right { * @return The left value of Either or the default value */ L fromLeft(L defaultValue); + } \ No newline at end of file diff --git a/src/main/java/com/ceticamarco/lambdatonic/Left.java b/src/main/java/com/ceticamarco/lambdatonic/Left.java index 5d70761..076fcca 100644 --- a/src/main/java/com/ceticamarco/lambdatonic/Left.java +++ b/src/main/java/com/ceticamarco/lambdatonic/Left.java @@ -32,6 +32,11 @@ public record Left(L value) implements Either { return new Left<>(this.value); } + @Override + public Either bimap(Function onLeft, Function onRight) { + return new Left<>(onLeft.apply(this.value)); + } + @Override public R fromRight(R defaultValue) { return defaultValue; diff --git a/src/main/java/com/ceticamarco/lambdatonic/Right.java b/src/main/java/com/ceticamarco/lambdatonic/Right.java index d154c28..1a95c2c 100644 --- a/src/main/java/com/ceticamarco/lambdatonic/Right.java +++ b/src/main/java/com/ceticamarco/lambdatonic/Right.java @@ -32,6 +32,11 @@ public record Right(R value) implements Either { return new Right<>(fn.apply(this.value)); } + @Override + public Either bimap(Function onLeft, Function onRight) { + return new Right<>(onRight.apply(this.value)); + } + @Override public R fromRight(R defaultValue) { return this.value; diff --git a/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java b/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java index 3610933..cc0acce 100644 --- a/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java +++ b/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java @@ -51,6 +51,16 @@ public class LeftTests { ), "Undefined variable"); } + @Test + public void testFunctorBiMapLeft() { + Function f = x -> x + 1; + Function g = String::toUpperCase; + + Either actual = this.resEither.bimap(f, g); + + assertEquals(actual.fromLeft(-1), 20); + } + @Test public void testLeftFunctorIdentityMorphism() { // Applying the map function with the identity function, diff --git a/src/test/java/com/ceticamarco/lambdatonic/RightTests.java b/src/test/java/com/ceticamarco/lambdatonic/RightTests.java index 78abf89..dcde712 100644 --- a/src/test/java/com/ceticamarco/lambdatonic/RightTests.java +++ b/src/test/java/com/ceticamarco/lambdatonic/RightTests.java @@ -51,6 +51,16 @@ public class RightTests { ), 16); } + @Test + public void testFunctorBiMapRight() { + Function f = x -> x + 1; + Function g = String::toUpperCase; + + Either actual = this.resEither.bimap(f, g); + + assertEquals(actual.fromRight("-1"), "QUERY EXECUTED SUCCESSFULLY"); + } + @Test public void testRightFunctorIdentityMorphism() { // Applying the map function with the identity function,