Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save manuel-mauky/aaca0415aa3a22a692cd to your computer and use it in GitHub Desktop.
Save manuel-mauky/aaca0415aa3a22a692cd to your computer and use it in GitHub Desktop.
/**
* ```
* Does JDK8's Optional class satisfy the Monad laws?
* =================================================
* 1. Left identity: true
* 2. Right identity: true
* 3. Associativity: true
*
* Yes, it does.
* ```
*
* To install the JDK8 Early Access release via Ubuntu PPA, see:
* http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html
*
* 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
*
* @author Marc Siegel <[email protected]>
*/
import java.util.function.Function;
import java.util.Optional;
class jdk8_optional_monad_laws {
public static void main (String[] args) throws java.lang.Exception
{
System.out.println("");
System.out.println("Does JDK8's Optional 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 Optional<Integer> monadicValue = Optional.of(value);
static Function<Integer, Optional<Integer>> f = n -> Optional.of(n * 2);
static Function<Integer, Optional<Integer>> g = n -> Optional.of(n * 5);
static Function<Integer, Optional<Integer>> f_flatMap_g = n -> f.apply(n).flatMap(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() {
return Optional.of(value).flatMap(f)
.equals(f.apply(value));
}
/**
* 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() {
return monadicValue.flatMap(Optional::of)
.equals(monadicValue);
}
/**
* 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() {
return monadicValue.flatMap(f).flatMap(g)
.equals(monadicValue.flatMap(f_flatMap_g));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment