Created
May 28, 2017 15:08
-
-
Save allquantor/cc20bcb7753827447036ffa85927e579 to your computer and use it in GitHub Desktop.
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
import java.util.function.Function; | |
public interface Functor<T, F extends Functor<?,?>> { | |
<R> F map(Function<T,R> f); | |
} | |
import java.util.function.Function; | |
public abstract class Monad<F, M extends Monad<?, ?>> implements Functor<F, M> { | |
F value; | |
abstract <T> M unit(T value); | |
abstract M flatMap(Function<F, M> f); | |
@Override | |
public <T> M map(Function<F, T> f) { | |
return flatMap(e -> | |
unit(f.apply(e)) | |
); | |
} | |
@Override | |
public boolean equals(Object o) { | |
if (this == o) return true; | |
if (!(o instanceof Monad)) return false; | |
Monad<?, ?> monad = (Monad<?, ?>) o; | |
return value.equals(monad.value); | |
} | |
@Override | |
public int hashCode() { | |
return value.hashCode(); | |
} | |
} | |
/////// Tests | |
import org.junit.Test; | |
import java.util.function.Function; | |
import static org.junit.Assert.assertEquals; | |
public class MonadTest { | |
class IdentityMonad<T> extends Monad<T, IdentityMonad<?>> { | |
public IdentityMonad(T v) { | |
super.value = v; | |
} | |
@Override | |
public <T1> IdentityMonad<T1> unit(T1 value) { | |
return new IdentityMonad<>(value); | |
} | |
@Override | |
IdentityMonad<?> flatMap(Function<T, IdentityMonad<?>> f) { | |
return f.apply(value); | |
} | |
} | |
final IdentityMonad<String> imS = new IdentityMonad<>("Goedel"); | |
final IdentityMonad<Integer> imI = new IdentityMonad<>("Goedel".length()); | |
final Function<Integer, IdentityMonad<Integer>> f = i -> new IdentityMonad<Integer>(i * 100); | |
final Function<Integer, IdentityMonad<Integer>> g = i -> new IdentityMonad<>(-1); | |
@Test | |
public void testUnit() throws Exception { | |
assertEquals(imS.unit("Leibnitz"), new IdentityMonad<>("Leibnitz")); | |
} | |
@Test | |
public void testMonadIdentity() { | |
assertEquals(imS.map(x -> x), imS); | |
} | |
@Test | |
public void testFlatMapEquality() throws Exception { | |
final Monad im1 = imS.flatMap(x -> new IdentityMonad<>(x.length())); | |
final Monad<Integer, IdentityMonad<?>> im2 = imS.unit(imS.value.length()); | |
assertEquals(im1, im2); | |
final Monad im3 = new IdentityMonad<>(new IdentityMonad<>("Neuman")).flatMap(x -> | |
x.map(String::length) | |
); | |
final Monad<Integer, IdentityMonad<?>> im4 = new IdentityMonad<>("Neuman".length()); | |
assertEquals(im4, im3); | |
} | |
// now try a double flat map here | |
@Test | |
public void testLeftIdentityLaw() { | |
assertEquals(imI.unit(imI.value).flatMap(f::apply).flatMap(im2.unit), f.apply(imI.value)); | |
} | |
// now try a double flat map here | |
@Test | |
public void testRightIdentityLaw() { | |
assertEquals(imI.flatMap(imI::unit), imI); | |
} | |
@Test | |
public void testMap() throws Exception { | |
assertEquals(imS.map(String::length).value, imS.value.length()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment