--- jsr166/src/test/tck/CompletableFutureTest.java 2015/11/15 00:37:50 1.128 +++ jsr166/src/test/tck/CompletableFutureTest.java 2015/11/15 01:33:02 1.129 @@ -3772,7 +3772,7 @@ public class CompletableFutureTest exten return completedFuture(value); } // monadic zero ? - static CompletableFuture zero(T value) { + static CompletableFuture zero() { return failedFuture(new MonadError()); } // >=> @@ -3818,17 +3818,17 @@ public class CompletableFutureTest exten static CompletableFuture plus(CompletableFuture f, CompletableFuture g) { PlusFuture plus = new PlusFuture(); - BiConsumer action = (T result, Throwable fail) -> { + BiConsumer action = (T result, Throwable ex) -> { if (result != null) { if (plus.complete(result)) if (plus.firstFailure.get() != null) plus.firstFailure.set(null); } - else if (plus.firstFailure.compareAndSet(null, fail)) { + else if (plus.firstFailure.compareAndSet(null, ex)) { if (plus.isDone()) plus.firstFailure.set(null); } else { - if (plus.completeExceptionally(fail)) + if (plus.completeExceptionally(ex)) plus.firstFailure.set(null); } }; @@ -3843,59 +3843,59 @@ public class CompletableFutureTest exten * https://en.wikipedia.org/wiki/Monad_(functional_programming)#Additive_monads */ public void testAdditiveMonad() throws Throwable { + Function> unit = Monad::unit; + CompletableFuture zero = Monad.zero(); + // Some mutually non-commutative functions Function> triple - = (x) -> completedFuture(3 * x); + = (x) -> Monad.unit(3 * x); Function> inc - = (x) -> completedFuture(x + 1); - - Function> unit = Monad::unit; - Function> zero = Monad::zero; + = (x) -> Monad.unit(x + 1); // unit is a right identity: m >>= unit === m - Monad.assertFutureEquals( - inc.apply(5L).thenCompose(unit), - inc.apply(5L)); + Monad.assertFutureEquals(inc.apply(5L).thenCompose(unit), + inc.apply(5L)); // unit is a left identity: (unit x) >>= f === f x - Monad.assertFutureEquals( - unit.apply(5L).thenCompose(inc), - inc.apply(5L)); + Monad.assertFutureEquals(unit.apply(5L).thenCompose(inc), + inc.apply(5L)); + // associativity: (m >>= f) >>= g === m >>= ( \x -> (f x >>= g) ) Monad.assertFutureEquals( unit.apply(5L).thenCompose(inc).thenCompose(triple), unit.apply(5L).thenCompose((x) -> inc.apply(x).thenCompose(triple))); + // The case for CompletableFuture as an additive monad is weaker... + // zero is a monadic zero - Monad.assertZero(zero.apply(5L)); - // left zero: zero >>= f === zero - Monad.assertZero(zero.apply(5L).thenCompose(inc)); - // right zero: f >>= zero === zero - Monad.assertZero(inc.apply(5L).thenCompose(zero)); + Monad.assertZero(zero); - // inc plus zero === inc - Monad.assertFutureEquals( - inc.apply(5L), - Monad.plus(inc.apply(5L), zero.apply(5L))); - // zero plus inc === inc - Monad.assertFutureEquals( - inc.apply(5L), - Monad.plus(zero.apply(5L), inc.apply(5L))); + // left zero: zero >>= f === zero + Monad.assertZero(zero.thenCompose(inc)); + // right zero: f >>= (\x -> zero) === zero + Monad.assertZero(inc.apply(5L).thenCompose((x) -> zero)); + + // f plus zero === f + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(Monad.unit(5L), zero)); + // zero plus f === f + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(zero, Monad.unit(5L))); // zero plus zero === zero - Monad.assertZero(Monad.plus(zero.apply(5L), zero.apply(5L))); + Monad.assertZero(Monad.plus(zero, zero)); { - CompletableFuture f = Monad.plus(inc.apply(5L), inc.apply(8L)); - assertTrue(f.get() == 6L || f.get() == 9L); + CompletableFuture f = Monad.plus(Monad.unit(5L), + Monad.unit(8L)); + // non-determinism + assertTrue(f.get() == 5L || f.get() == 8L); } CompletableFuture godot = new CompletableFuture<>(); - // inc plus godot === inc (doesn't wait for godot) - Monad.assertFutureEquals( - inc.apply(5L), - Monad.plus(inc.apply(5L), godot)); - // godot plus inc === inc (doesn't wait for godot) - Monad.assertFutureEquals( - inc.apply(5L), - Monad.plus(godot, inc.apply(5L))); + // f plus godot === f (doesn't wait for godot) + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(Monad.unit(5L), godot)); + // godot plus f === f (doesn't wait for godot) + Monad.assertFutureEquals(Monad.unit(5L), + Monad.plus(godot, Monad.unit(5L))); } // static U join(CompletionStage stage) {