From 7ebc811d0e6cd189e7386091e43aa3624b1abbdc Mon Sep 17 00:00:00 2001 From: Marco Cetica Date: Tue, 17 Sep 2024 16:23:43 +0200 Subject: [PATCH] Added functor map method and unit tests --- .../com/ceticamarco/lambdatonic/Either.java | 27 ++++++++++++++++--- .../com/ceticamarco/lambdatonic/Left.java | 5 ++++ .../com/ceticamarco/lambdatonic/Right.java | 5 ++++ .../ceticamarco/lambdatonic/LeftTests.java | 12 +++++++++ .../ceticamarco/lambdatonic/RightTests.java | 16 +++++++++-- 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/ceticamarco/lambdatonic/Either.java b/src/main/java/com/ceticamarco/lambdatonic/Either.java index dc76ec8..f6d1b6d 100644 --- a/src/main/java/com/ceticamarco/lambdatonic/Either.java +++ b/src/main/java/com/ceticamarco/lambdatonic/Either.java @@ -15,7 +15,8 @@ import java.util.function.Function; public sealed interface Either permits Left, Right { /** *

- * Executing an anonymous function by discriminating the Either data type value + * Executing an anonymous function by discriminating against + * the Either data type value *

* * @param onLeft The function to execute on the Left case @@ -27,7 +28,7 @@ public sealed interface Either permits Left, Right { /** *

- * Returns true if the Either type is instantiated with the Left subtype, + * Returns true if the Either type is instantiated with the Left subtype, * false otherwise *

* @return Boolean value @@ -36,10 +37,30 @@ public sealed interface Either permits Left, Right { /** *

- * Returns true if the Either type is instantiated with the Right subtype, + * Returns true if the Either type is instantiated with the Right subtype, * false otherwise *

* @return Boolean value */ boolean isRight(); + + /** + *

+ * Defines a functor. That is, a data type that supports + * a mapping operation defined by the map method. + *

+ * This method + * applies a function(fn) to the values inside the data type, + * returning a new data type(i.e., a new functor) if and only if the the Either + * type is instantiated with the Right subtype. Otherwise it leaves the functor + * unchanged. + *

+ * The type of the resulting functor is the return type specified on the fn + * function + *

+ * @param fn The function to applies to the Either data type + * @return An Either functor + * @param The return type of the fn function + */ + Either map(Function fn); } \ 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 255430c..8ee74a5 100644 --- a/src/main/java/com/ceticamarco/lambdatonic/Left.java +++ b/src/main/java/com/ceticamarco/lambdatonic/Left.java @@ -26,4 +26,9 @@ public record Left(L value) implements Either { public boolean isRight() { return false; } + + @Override + public Either map(Function fn) { + return new Left<>(this.value); + } } \ No newline at end of file diff --git a/src/main/java/com/ceticamarco/lambdatonic/Right.java b/src/main/java/com/ceticamarco/lambdatonic/Right.java index dd4c0cc..4bce7e3 100644 --- a/src/main/java/com/ceticamarco/lambdatonic/Right.java +++ b/src/main/java/com/ceticamarco/lambdatonic/Right.java @@ -26,4 +26,9 @@ public record Right(R value) implements Either { public boolean isRight() { return true; } + + @Override + public Either map(Function fn) { + return new Right<>(fn.apply(this.value)); + } } \ No newline at end of file diff --git a/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java b/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java index e98ab04..dd9e21c 100644 --- a/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java +++ b/src/test/java/com/ceticamarco/lambdatonic/LeftTests.java @@ -9,10 +9,12 @@ import static org.junit.jupiter.api.Assertions.assertFalse; public class LeftTests { private Either resEither; + private Either numEither; @BeforeEach public void tearUp() { this.resEither = new Left<>(19); + this.numEither = new Left<>(new Error("Undefined variable")); } @Test @@ -36,4 +38,14 @@ public class LeftTests { public void testIsRight() { assertFalse(this.resEither.isRight()); } + + @Test + public void testFunctorMapLeft() { + Either res = this.numEither.map(x -> x * x); + + assertEquals(res.match( + Throwable::getMessage, + _ -> "Undefined variable" + ), "Undefined variable"); + } } diff --git a/src/test/java/com/ceticamarco/lambdatonic/RightTests.java b/src/test/java/com/ceticamarco/lambdatonic/RightTests.java index ad16f48..140e6f9 100644 --- a/src/test/java/com/ceticamarco/lambdatonic/RightTests.java +++ b/src/test/java/com/ceticamarco/lambdatonic/RightTests.java @@ -9,17 +9,19 @@ import static org.junit.jupiter.api.Assertions.assertFalse; public class RightTests { private Either resEither; + private Either numEither; @BeforeEach public void tearUp() { this.resEither = new Right<>("Query executed successfully"); + this.numEither = new Right<>(4); } @Test public void testMatchRight() { var actual = this.resEither.match( - errorCode -> "Error code: " + errorCode.toString(), - successMsg -> successMsg + errorCode -> "Error code: " + errorCode.toString(), + successMsg -> successMsg ); var expected = "Query executed successfully"; @@ -36,4 +38,14 @@ public class RightTests { public void testIsRight() { assertTrue(this.resEither.isRight()); } + + @Test + public void testFunctorMapRight() { + Either res = this.numEither.map(x -> x * x); + + assertEquals((int)res.match( + _ -> 0, + x -> x + ), 16); + } }