Last active
January 6, 2017 14:58
-
-
Save manuel-mauky/e28fb8a340737ffd9623 to your computer and use it in GitHub Desktop.
Does JDK8's CompletableFuture class satisfy the Monad laws? Yes, it does.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* ``` | |
* Does JDK8's CompletableFuture class satisfy the Monad laws? | |
* ================================================= | |
* 1. Left identity: true | |
* 2. Right identity: true | |
* 3. Associativity: true | |
* | |
* Yes, it does. | |
* ``` | |
* | |
* For more info on the monad laws, see: | |
* [1] http://learnyouahaskell.com/a-fistful-of-monads#monad-laws | |
* [2] http://eed3si9n.com/learning-scalaz/Monad+laws.html | |
* [3] http://en.wikipedia.org/wiki/Monad_(functional_programming)#Monad_laws | |
* | |
* Note: The original code for this tests monad laws of Optional class. | |
* See: https://gist.github.com/ms-tg/7420496 | |
* | |
* @author Marc Siegel <[email protected]>, Manuel Mauky <[email protected]> | |
*/ | |
import java.util.concurrent.CompletableFuture; | |
import java.util.function.Function; | |
class jdk8_completablefuture_monad_laws { | |
public static void main (String[] args) throws java.lang.Exception | |
{ | |
System.out.println(""); | |
System.out.println("Does JDK8's CompletableFuture class satisfy the Monad laws?"); | |
System.out.println("================================================="); | |
System.out.println(" 1. Left identity: " + satisfiesLaw1LeftIdentity()); | |
System.out.println(" 2. Right identity: " + satisfiesLaw2RightIdentity()); | |
System.out.println(" 3. Associativity: " + satisfiesLaw3Associativity()); | |
System.out.println(""); | |
System.out.println(satisfiesLaw1LeftIdentity() | |
&& satisfiesLaw2RightIdentity() | |
&& satisfiesLaw3Associativity() | |
? "Yes, it does." | |
: "No, it doesn't."); | |
} | |
// Input values for the monad law tests below | |
static int value = 42; | |
static CompletableFuture<Integer> monadicValue = CompletableFuture.completedFuture(value); | |
static Function<Integer, CompletableFuture<Integer>> f = n -> CompletableFuture.completedFuture(n * 2); | |
static Function<Integer, CompletableFuture<Integer>> g = n -> CompletableFuture.completedFuture(n * 5); | |
static Function<Integer, CompletableFuture<Integer>> f_flatMap_g = n -> f.apply(n).thenCompose(g); | |
/** | |
* Monad law 1, Left Identity | |
* | |
* From LYAHFGG [1] above: | |
* The first monad law states that if we take a value, put it in a default context | |
* with return and then feed it to a function by using >>=, it’s the same as just | |
* taking the value and applying the function to it | |
*/ | |
public static boolean satisfiesLaw1LeftIdentity() throws Exception { | |
return CompletableFuture.completedFuture(value).thenCompose(f).get().equals(f.apply(value).get()); | |
} | |
/** | |
* Monad law 2, Right Identity | |
* | |
* From LYAHFGG [1] above: | |
* The second law states that if we have a monadic value and we use >>= to feed | |
* it to return, the result is our original monadic value. | |
*/ | |
public static boolean satisfiesLaw2RightIdentity() throws Exception { | |
return monadicValue.thenCompose(CompletableFuture::completedFuture).get().equals(monadicValue.get()); | |
} | |
/** | |
* Monad law 3, Associativity | |
* | |
* From LYAHFGG [1] above: | |
* The final monad law says that when we have a chain of monadic function | |
* applications with >>=, it shouldn’t matter how they’re nested. | |
*/ | |
public static boolean satisfiesLaw3Associativity() throws Exception { | |
return monadicValue.thenCompose(f).thenCompose(g).get().equals(monadicValue.thenCompose(f_flatMap_g).get()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment