Skip to content

Instantly share code, notes, and snippets.

@allquantor
Created May 28, 2017 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save allquantor/cc20bcb7753827447036ffa85927e579 to your computer and use it in GitHub Desktop.
Save allquantor/cc20bcb7753827447036ffa85927e579 to your computer and use it in GitHub Desktop.
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