cyclops.companion.vavr.Futures Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cyclops-vavr Show documentation
Show all versions of cyclops-vavr Show documentation
Converters and Comprehenders for Javaslang
The newest version!
package cyclops.companion.vavr;
import cyclops.monads.VavrWitness.list;
import cyclops.monads.VavrWitness.stream;
import cyclops.monads.VavrWitness.tryType;
import io.vavr.Lazy;
import io.vavr.collection.*;
import io.vavr.control.*;
import com.aol.cyclops.vavr.hkt.*;
import cyclops.companion.CompletableFutures;
import cyclops.companion.Optionals;
import cyclops.control.Eval;
import cyclops.control.Maybe;
import cyclops.control.Reader;
import cyclops.control.Xor;
import cyclops.conversion.vavr.FromCyclopsReact;
import cyclops.monads.*;
import cyclops.monads.VavrWitness.*;
import com.aol.cyclops2.hkt.Higher;
import cyclops.function.Fn3;
import cyclops.function.Fn4;
import cyclops.function.Monoid;
import cyclops.monads.Witness.*;
import cyclops.stream.ReactiveSeq;
import cyclops.typeclasses.*;
import com.aol.cyclops.vavr.hkt.ArrayKind;
import com.aol.cyclops.vavr.hkt.ListKind;
import com.aol.cyclops2.react.Status;
import cyclops.conversion.vavr.ToCyclopsReact;
import cyclops.monads.VavrWitness.future;
import com.aol.cyclops.vavr.hkt.FutureKind;
import com.aol.cyclops2.data.collections.extensions.CollectionX;
import com.aol.cyclops2.types.Value;
import com.aol.cyclops2.types.anyM.AnyMValue;
import cyclops.collections.mutable.ListX;
import cyclops.companion.Monoids;
import cyclops.function.Reducer;
import cyclops.monads.transformers.FutureT;
import cyclops.typeclasses.comonad.Comonad;
import cyclops.typeclasses.foldable.Foldable;
import cyclops.typeclasses.foldable.Unfoldable;
import cyclops.typeclasses.functor.Functor;
import cyclops.typeclasses.instances.General;
import cyclops.typeclasses.monad.*;
import io.vavr.collection.Array;
import io.vavr.concurrent.Future;
import lombok.experimental.UtilityClass;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import static com.aol.cyclops.vavr.hkt.FutureKind.widen;
/**
* Utilty methods for working with JDK CompletableFutures
*
* @author johnmcclean
*
*/
@UtilityClass
public class Futures {
public static Coproduct coproduct(Future type, InstanceDefinitions def1){
return Coproduct.of(Xor.primary(widen(type)),def1, Instances.definitions());
}
public static ,T> XorM xorM(Future type){
return XorM.right(anyM(type));
}
public static void subscribe(final Subscriber super T> sub, Future f){
asPublisher(f).subscribe(sub);
}
public static Publisher asPublisher(Future f){
return ToCyclopsReact.future(f);
}
public static AnyMValue anyM(Future future) {
return AnyM.ofValue(future, VavrWitness.future.INSTANCE);
}
/**
* Lifts a vavr Future into a cyclops FutureT monad transformer (involves an observables conversion to
* cyclops Future types)
*
*/
public static > FutureT liftM(Future opt, W witness) {
return FutureT.of(witness.adapter().unit(ToCyclopsReact.future(opt)));
}
/**
* Select the first Future to complete
*
* @see CompletableFuture#anyOf(CompletableFuture...)
* @param fts FutureWs to race
* @return First Future to complete
*/
public static Future anyOf(Future... fts) {
return FromCyclopsReact.future(cyclops.async.Future.anyOf(ToCyclopsReact.futures(fts)));
}
/**
* Wait until all the provided Future's to complete
*
* @see CompletableFuture#allOf(CompletableFuture...)
*
* @param fts FutureWs to wait on
* @return Future that completes when all the provided Futures Complete. Empty Future result, or holds an Exception
* from a provided Future that failed.
*/
public static Future allOf(Future... fts) {
return FromCyclopsReact.future(cyclops.async.Future.allOf(ToCyclopsReact.futures(fts)));
}
/**
* Block until a Quorum of results have returned as determined by the provided Predicate
*
*
* {@code
*
* Future> strings = Future.quorum(status -> status.getCompleted() >0, Future.ofSupplier(()->1),Future.future(),Future.future());
strings.get().size()
//1
*
* }
*
*
*
* @param breakout Predicate that determines whether the block should be
* continued or removed
* @param fts FutureWs to wait on results from
* @param errorHandler Consumer to handle any exceptions thrown
* @return Future which will be populated with a Quorum of results
*/
@SafeVarargs
public static Future> quorum(Predicate> breakout, Consumer errorHandler, Future... fts) {
return FromCyclopsReact.future(cyclops.async.Future.quorum(breakout,errorHandler,ToCyclopsReact.futures(fts)));
}
/**
* Block until a Quorum of results have returned as determined by the provided Predicate
*
*
* {@code
*
* Future> strings = Future.quorum(status -> status.getCompleted() >0, Future.ofSupplier(()->1),Future.future(),Future.future());
strings.get().size()
//1
*
* }
*
*
*
* @param breakout Predicate that determines whether the block should be
* continued or removed
* @param fts FutureWs to wait on results from
* @return Future which will be populated with a Quorum of results
*/
@SafeVarargs
public static Future> quorum(Predicate> breakout, Future... fts) {
return FromCyclopsReact.future(cyclops.async.Future.quorum(breakout,ToCyclopsReact.futures(fts)));
}
/**
* Select the first Future to return with a successful result
*
*
* {@code
* Future ft = Future.future();
Future result = Future.firstSuccess(Future.ofSupplier(()->1),ft);
ft.complete(10);
result.get() //1
* }
*
*
* @param fts Futures to race
* @return First Future to return with a result
*/
@SafeVarargs
public static Future firstSuccess(Future... fts) {
return FromCyclopsReact.future(cyclops.async.Future.firstSuccess(ToCyclopsReact.futures(fts)));
}
/**
* Perform a For Comprehension over a Future, accepting 3 generating function.
* This results in a four level nested internal iteration over the provided Futures.
*
*
* {@code
*
* import static com.aol.cyclops2.reactor.Futures.forEach4;
*
forEach4(Future.just(1),
a-> Future.just(a+1),
(a,b) -> Future.just(a+b),
a (a,b,c) -> Future.just(a+b+c),
Tuple::tuple)
*
* }
*
*
* @param value1 top level Future
* @param value2 Nested Future
* @param value3 Nested Future
* @param value4 Nested Future
* @param yieldingFunction Generates a result per combination
* @return Future with a combined value generated by the yielding function
*/
public static Future forEach4(Future extends T1> value1,
Function super T1, ? extends Future> value2,
BiFunction super T1, ? super R1, ? extends Future> value3,
Fn3 super T1, ? super R1, ? super R2, ? extends Future> value4,
Fn4 super T1, ? super R1, ? super R2, ? super R3, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Future a = value2.apply(in);
return a.flatMap(ina -> {
Future b = value3.apply(in,ina);
return b.flatMap(inb -> {
Future c = value4.apply(in,ina,inb);
return c.map(in2 -> yieldingFunction.apply(in, ina, inb, in2));
});
});
});
}
/**
*
* Perform a For Comprehension over a Future, accepting 3 generating function.
* This results in a four level nested internal iteration over the provided Futures.
*
*
* {@code
*
* import static com.aol.cyclops2.reactor.Futures.forEach4;
*
* forEach4(Future.just(1),
a-> Future.just(a+1),
(a,b) -> Future.just(a+b),
(a,b,c) -> Future.just(a+b+c),
(a,b,c,d) -> a+b+c+d <100,
Tuple::tuple);
*
* }
*
*
* @param value1 top level Future
* @param value2 Nested Future
* @param value3 Nested Future
* @param value4 Nested Future
* @param filterFunction A filtering function, keeps values where the predicate holds
* @param yieldingFunction Generates a result per combination
* @return Future with a combined value generated by the yielding function
*/
public static Future forEach4(Future extends T1> value1,
Function super T1, ? extends Future> value2,
BiFunction super T1, ? super R1, ? extends Future> value3,
Fn3 super T1, ? super R1, ? super R2, ? extends Future> value4,
Fn4 super T1, ? super R1, ? super R2, ? super R3, Boolean> filterFunction,
Fn4 super T1, ? super R1, ? super R2, ? super R3, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Future a = value2.apply(in);
return a.flatMap(ina -> {
Future b = value3.apply(in,ina);
return b.flatMap(inb -> {
Future c = value4.apply(in,ina,inb);
return c.filter(in2->filterFunction.apply(in,ina,inb,in2))
.map(in2 -> yieldingFunction.apply(in, ina, inb, in2));
});
});
});
}
/**
* Perform a For Comprehension over a Future, accepting 2 generating function.
* This results in a three level nested internal iteration over the provided Futures.
*
*
* {@code
*
* import static com.aol.cyclops2.reactor.Futures.forEach3;
*
forEach3(Future.just(1),
a-> Future.just(a+1),
(a,b) -> Future.just(a+b),
Tuple::tuple)
*
* }
*
*
* @param value1 top level Future
* @param value2 Nested Future
* @param value3 Nested Future
* @param yieldingFunction Generates a result per combination
* @return Future with a combined value generated by the yielding function
*/
public static Future forEach3(Future extends T1> value1,
Function super T1, ? extends Future> value2,
BiFunction super T1, ? super R1, ? extends Future> value3,
Fn3 super T1, ? super R1, ? super R2, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Future a = value2.apply(in);
return a.flatMap(ina -> {
Future b = value3.apply(in,ina);
return b.map(in2 -> yieldingFunction.apply(in, ina, in2));
});
});
}
/**
*
* Perform a For Comprehension over a Future, accepting 2 generating function.
* This results in a three level nested internal iteration over the provided Futures.
*
*
* {@code
*
* import static com.aol.cyclops2.reactor.Futures.forEach3;
*
* forEach3(Future.just(1),
a-> Future.just(a+1),
(a,b) -> Future.just(a+b),
(a,b,c) -> a+b+c <100,
Tuple::tuple);
*
* }
*
*
* @param value1 top level Future
* @param value2 Nested Future
* @param value3 Nested Future
* @param filterFunction A filtering function, keeps values where the predicate holds
* @param yieldingFunction Generates a result per combination
* @return Future with a combined value generated by the yielding function
*/
public static Future forEach3(Future extends T1> value1,
Function super T1, ? extends Future> value2,
BiFunction super T1, ? super R1, ? extends Future> value3,
Fn3 super T1, ? super R1, ? super R2, Boolean> filterFunction,
Fn3 super T1, ? super R1, ? super R2, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Future a = value2.apply(in);
return a.flatMap(ina -> {
Future b = value3.apply(in,ina);
return b.filter(in2->filterFunction.apply(in,ina,in2))
.map(in2 -> yieldingFunction.apply(in, ina, in2));
});
});
}
/**
* Perform a For Comprehension over a Future, accepting a generating function.
* This results in a two level nested internal iteration over the provided Futures.
*
*
* {@code
*
* import static com.aol.cyclops2.reactor.Futures.forEach;
*
forEach(Future.just(1),
a-> Future.just(a+1),
Tuple::tuple)
*
* }
*
*
* @param value1 top level Future
* @param value2 Nested Future
* @param yieldingFunction Generates a result per combination
* @return Future with a combined value generated by the yielding function
*/
public static Future forEach2(Future extends T> value1, Function super T, Future> value2,
BiFunction super T, ? super R1, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Future a = value2.apply(in);
return a.map(in2 -> yieldingFunction.apply(in, in2));
});
}
/**
*
* Perform a For Comprehension over a Future, accepting a generating function.
* This results in a two level nested internal iteration over the provided Futures.
*
*
* {@code
*
* import static com.aol.cyclops2.reactor.Futures.forEach;
*
* forEach(Future.just(1),
a-> Future.just(a+1),
(a,b) -> Future.just(a+b),
(a,b,c) -> a+b+c <100,
Tuple::tuple);
*
* }
*
*
* @param value1 top level Future
* @param value2 Nested Future
* @param filterFunction A filtering function, keeps values where the predicate holds
* @param yieldingFunction Generates a result per combination
* @return Future with a combined value generated by the yielding function
*/
public static Future forEach2(Future extends T> value1, Function super T, ? extends Future> value2,
BiFunction super T, ? super R1, Boolean> filterFunction,
BiFunction super T, ? super R1, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Future a = value2.apply(in);
return a.filter(in2->filterFunction.apply(in,in2))
.map(in2 -> yieldingFunction.apply(in, in2));
});
}
/**
* Sequence operation, take a Collection of Futures and turn it into a Future with a Collection
* By constrast with {@link Futures#sequencePresent(CollectionX)}, if any Futures are empty the result
* is an empty Future
*
*
* {@code
*
* Future just = Future.of(10);
Future none = Future.empty();
*
* Future> opts = Futures.sequence(ListX.of(just, none, Future.of(1)));
//Future.empty();
*
* }
*
*
*
* @param opts Maybes to Sequence
* @return Maybe with a List of values
*/
public static Future> sequence(final CollectionX> opts) {
return sequence(opts.stream()).map(s -> s.toListX());
}
/**
* Sequence operation, take a Collection of Futures and turn it into a Future with a Collection
* Only successes are retained. By constrast with {@link Futures#sequence(CollectionX)} Future#empty types are
* tolerated and ignored.
*
*
* {@code
* Future just = Future.of(10);
Future none = Future.empty();
*
* Future> maybes = Futures.sequencePresent(ListX.of(just, none, Future.of(1)));
//Future.of(ListX.of(10, 1));
* }
*
*
* @param opts Futures to Sequence
* @return Future with a List of values
*/
public static Future> sequencePresent(final CollectionX> opts) {
return sequence(opts.stream().filter(Future::isCompleted)).map(s->s.toListX());
}
/**
* Sequence operation, take a Collection of Futures and turn it into a Future with a Collection
* By constrast with {@link Futures#sequencePresent(CollectionX)} if any Future types are empty
* the return type will be an empty Future
*
*
* {@code
*
* Future just = Future.of(10);
Future none = Future.empty();
*
* Future> maybes = Futures.sequence(ListX.of(just, none, Future.of(1)));
//Future.empty();
*
* }
*
*
*
* @param opts Maybes to Sequence
* @return Future with a List of values
*/
public static Future> sequence(final java.util.stream.Stream> opts) {
return AnyM.sequence(opts.map(Futures::anyM), future.INSTANCE)
.map(ReactiveSeq::fromStream)
.to(VavrWitness::future);
}
/**
* Accummulating operation using the supplied Reducer (@see cyclops2.Reducers). A typical use case is to accumulate into a Persistent Collection type.
* Accumulates the present results, ignores empty Futures.
*
*
* {@code
* Future just = Future.of(10);
Future none = Future.empty();
* Future> opts = Future.accumulateJust(ListX.of(just, none, Future.of(1)), Reducers.toPersistentSetX());
//Future.of(PersistentSetX.of(10, 1)));
*
* }
*
*
* @param futureals Futures to accumulate
* @param reducer Reducer to accumulate values with
* @return Future with reduced value
*/
public static Future accumulatePresent(final CollectionX> futureals, final Reducer reducer) {
return sequencePresent(futureals).map(s -> s.mapReduce(reducer));
}
/**
* Accumulate the results only from those Futures which have a value present, using the supplied mapping function to
* convert the data from each Future before reducing them using the supplied Monoid (a combining BiFunction/BinaryOperator and identity element that takes two
* input values of the same type and returns the combined result) {@see cyclops2.Monoids }.
*
*
* {@code
* Future just = Future.of(10);
Future none = Future.empty();
* Future opts = Future.accumulateJust(ListX.of(just, none, Future.of(1)), i -> "" + i,
Monoids.stringConcat);
//Future.of("101")
*
* }
*
*
* @param futureals Futures to accumulate
* @param mapper Mapping function to be applied to the result of each Future
* @param reducer Monoid to combine values from each Future
* @return Future with reduced value
*/
public static Future accumulatePresent(final CollectionX> futureals, final Function super T, R> mapper,
final Monoid reducer) {
return sequencePresent(futureals).map(s -> s.map(mapper)
.reduce(reducer));
}
/**
* Accumulate the results only from those Futures which have a value present, using the
* supplied Monoid (a combining BiFunction/BinaryOperator and identity element that takes two
* input values of the same type and returns the combined result) {@see cyclops2.Monoids }.
*
*
* {@code
* Future just = Future.of(10);
Future none = Future.empty();
* Future opts = Future.accumulateJust(Monoids.stringConcat,ListX.of(just, none, Future.of(1)),
);
//Future.of("101")
*
* }
*
*
* @param futureals Futures to accumulate
* @param reducer Monoid to combine values from each Future
* @return Future with reduced value
*/
public static Future accumulatePresent(final Monoid reducer, final CollectionX> futureals) {
return sequencePresent(futureals).map(s -> s
.reduce(reducer));
}
/**
* Combine an Future with the provided value using the supplied BiFunction
*
*
* {@code
* Futures.combine(Future.of(10),Maybe.just(20), this::add)
* //Future[30]
*
* private int add(int a, int b) {
return a + b;
}
*
* }
*
* @param f Future to combine with a value
* @param v Value to combine
* @param fn Combining function
* @return Future combined with supplied value
*/
public static Future combine(final Future extends T1> f, final Value extends T2> v,
final BiFunction super T1, ? super T2, ? extends R> fn) {
return narrow(FromCyclopsReact.future(ToCyclopsReact.future(f)
.combine(v, fn)));
}
/**
* Combine an Future with the provided Future using the supplied BiFunction
*
*
* {@code
* Futures.combine(Future.of(10),Future.of(20), this::add)
* //Future[30]
*
* private int add(int a, int b) {
return a + b;
}
*
* }
*
*
* @param f Future to combine with a value
* @param v Future to combine
* @param fn Combining function
* @return Future combined with supplied value, or empty Future if no value present
*/
public static Future combine(final Future extends T1> f, final Future extends T2> v,
final BiFunction super T1, ? super T2, ? extends R> fn) {
return combine(f,ToCyclopsReact.future(v),fn);
}
/**
* Combine an Future with the provided Iterable (selecting one element if present) using the supplied BiFunction
*
* {@code
* Futures.zip(Future.of(10),Arrays.asList(20), this::add)
* //Future[30]
*
* private int add(int a, int b) {
return a + b;
}
*
* }
*
* @param f Future to combine with first element in Iterable (if present)
* @param v Iterable to combine
* @param fn Combining function
* @return Future combined with supplied Iterable, or empty Future if no value present
*/
public static Future zip(final Future extends T1> f, final Iterable extends T2> v,
final BiFunction super T1, ? super T2, ? extends R> fn) {
return narrow(FromCyclopsReact.future(ToCyclopsReact.future(f)
.zip(v, fn)));
}
/**
* Combine an Future with the provided Publisher (selecting one element if present) using the supplied BiFunction
*
* {@code
* Futures.zip(Flux.just(10),Future.of(10), this::add)
* //Future[30]
*
* private int add(int a, int b) {
return a + b;
}
*
* }
*
*
* @param p Publisher to combine
* @param f Future to combine with
* @param fn Combining function
* @return Future combined with supplied Publisher, or empty Future if no value present
*/
public static Future zip(final Publisher extends T2> p, final Future extends T1> f,
final BiFunction super T1, ? super T2, ? extends R> fn) {
return narrow(FromCyclopsReact.future(ToCyclopsReact.future(f)
.zipP(p, fn)));
}
/**
* Narrow covariant type parameter
*
* @param futureal Future with covariant type parameter
* @return Narrowed Future
*/
public static Future narrow(final Future extends T> futureal) {
return (Future) futureal;
}
public static Active allTypeclasses(Future future){
return Active.of(widen(future), Futures.Instances.definitions());
}
public static Nested mapM(Future future, Function super T,? extends Higher> fn, InstanceDefinitions defs){
Future> e = future.map(fn);
FutureKind> lk = widen(e);
return Nested.of(lk, Futures.Instances.definitions(), defs);
}
/**
* Companion class for creating Type Class instances for working with Futures
* @author johnmcclean
*
*/
@UtilityClass
public static class Instances {
public static InstanceDefinitions definitions() {
return new InstanceDefinitions() {
@Override
public Functor functor() {
return Instances.functor();
}
@Override
public Pure unit() {
return Instances.unit();
}
@Override
public Applicative applicative() {
return Instances.applicative();
}
@Override
public Monad monad() {
return Instances.monad();
}
@Override
public Maybe> monadZero() {
return Maybe.just(Instances.monadZero());
}
@Override
public Maybe> monadPlus() {
return Maybe.just(Instances.monadPlus());
}
@Override
public Maybe> monadPlus(Monoid> m) {
return Maybe.just(Instances.monadPlus(m));
}
@Override
public Maybe> traverse() {
return Maybe.just(Instances.traverse());
}
@Override
public Maybe> foldable() {
return Maybe.just(Instances.foldable());
}
@Override
public Maybe> comonad() {
return Maybe.just(Instances.comonad());
}
@Override
public Maybe> unfoldable() {
return Maybe.none();
}
};
}
/**
*
* Transform a Future, mulitplying every element by 2
*
*
* {@code
* FutureKind future = Futures.functor().map(i->i*2, FutureKind.widen(Future.successful(1));
*
* //[2]
*
*
* }
*
*
* An example fluent api working with Futures
*
* {@code
* FutureKind ft = Futures.unit()
.unit("hello")
.then(h->Futures.functor().map((String v) ->v.length(), h))
.convert(FutureKind::narrowK);
*
* }
*
*
*
* @return A functor for Futures
*/
public static Functor functor(){
BiFunction,Function super T, ? extends R>,FutureKind> map = Instances::map;
return General.functor(map);
}
/**
*
* {@code
* FutureKind ft = Futures.unit()
.unit("hello")
.convert(FutureKind::narrowK);
//Arrays.asFuture("hello"))
*
* }
*
*
*
* @return A factory for Futures
*/
public static Pure unit(){
return General.unit(Instances::of);
}
/**
*
*
* {@code
* import static com.aol.cyclops.hkt.jdk.FutureKind.widen;
* import static com.aol.cyclops.util.function.Lambda.l1;
*
Futures.applicative()
.ap(widen(Future.successful(l1(this::multiplyByTwo))),widen(asFuture(1,2,3)));
*
* //[2,4,6]
* }
*
*
*
* Example fluent API
*
* {@code
* FutureKind> ftFn =Futures.unit()
* .unit(Lambda.l1((Integer i) ->i*2))
* .convert(FutureKind::narrowK);
FutureKind ft = Futures.unit()
.unit("hello")
.then(h->Futures.functor().map((String v) ->v.length(), h))
.then(h->Futures.applicative().ap(ftFn, h))
.convert(FutureKind::narrowK);
//Arrays.asFuture("hello".length()*2))
*
* }
*
*
*
* @return A zipper for Futures
*/
public static Applicative applicative(){
BiFunction>,FutureKind,FutureKind> ap = Instances::ap;
return General.applicative(functor(), unit(), ap);
}
/**
*
*
* {@code
* import static com.aol.cyclops.hkt.jdk.FutureKind.widen;
* FutureKind ft = Futures.monad()
.flatMap(i->widen(Future.successful(i), widen(Future.successful(3))
.convert(FutureKind::narrowK);
* }
*
*
* Example fluent API
*
* {@code
* FutureKind ft = Futures.unit()
.unit("hello")
.then(h->Futures.monad().flatMap((String v) ->Futures.unit().unit(v.length()), h))
.convert(FutureKind::narrowK);
//Arrays.asFuture("hello".length())
*
* }
*
*
* @return Type class with monad functions for Futures
*/
public static Monad monad(){
BiFunction,Function super T, ? extends Higher>,Higher> flatMap = Instances::flatMap;
return General.monad(applicative(), flatMap);
}
/**
*
*
* {@code
* FutureKind ft = Futures.unit()
.unit("hello")
.then(h->Futures.monadZero().filter((String t)->t.startsWith("he"), h))
.convert(FutureKind::narrowK);
//Arrays.asFuture("hello"));
*
* }
*
*
*
* @return A filterable monad (with default value)
*/
public static MonadZero monadZero(){
return General.monadZero(monad(), FutureKind.promise());
}
/**
*
* {@code
* FutureKind ft = Futures.monadPlus()
.plus(FutureKind.widen(Arrays.asFuture()), FutureKind.widen(Future.successful((10)))
.convert(FutureKind::narrowK);
//Future(10)
*
* }
*
* @return Type class for combining Futures by concatenation
*/
public static MonadPlus monadPlus(){
Monoid> mn = Monoids.firstSuccessfulFuture();
Monoid> m = Monoid.of(widen(mn.zero()), (f, g)-> widen(
mn.apply(ToCyclopsReact.future(f), ToCyclopsReact.future(g))));
Monoid> m2= (Monoid)m;
return General.monadPlus(monadZero(),m2);
}
/**
*
*
* {@code
* Monoid> m = Monoid.of(FutureKind.widen(Future.failed(e), (a,b)->a.isEmpty() ? b : a);
FutureKind ft = Futures.monadPlus(m)
.plus(FutureKind.widen(Future.successful(5), FutureKind.widen(Future.successful(10))
.convert(FutureKind::narrowK);
//Future(5)
*
* }
*
*
* @param m Monoid to use for combining Futures
* @return Type class for combining Futures
*/
public static MonadPlus monadPlus(Monoid> m){
Monoid> m2= (Monoid)m;
return General.monadPlus(monadZero(),m2);
}
public static MonadPlus monadPlusK(Monoid> m){
Monoid> m2= (Monoid)m;
return General.monadPlus(monadZero(),m2);
}
/**
* @return Type class for traversables with traverse / sequence operations
*/
public static Traverse traverse(){
return General.traverseByTraverse(applicative(), Instances::traverseA);
}
/**
*
*
* {@code
* int sum = Futures.foldable()
.foldLeft(0, (a,b)->a+b, FutureKind.widen(Future.successful(4));
//4
*
* }
*
*
*
* @return Type class for folding / reduction operations
*/
public static Foldable foldable(){
BiFunction,Higher,T> foldRightFn = (m, l)-> m.apply(m.zero(), FutureKind.narrow(l).get());
BiFunction,Higher,T> foldLeftFn = (m, l)-> m.apply(m.zero(), FutureKind.narrow(l).get());
return General.foldable(foldRightFn, foldLeftFn);
}
public static Comonad comonad(){
Function super Higher, ? extends T> extractFn = maybe -> maybe.convert(FutureKind::narrow).get();
return General.comonad(functor(), unit(), extractFn);
}
private FutureKind of(T value){
return widen(Future.successful(value));
}
private static FutureKind ap(FutureKind> lt, FutureKind list){
return widen(ToCyclopsReact.future(lt).combine(ToCyclopsReact.future(list), (a, b)->a.apply(b)));
}
private static Higher flatMap(Higher lt, Function super T, ? extends Higher> fn){
return widen(FutureKind.narrow(lt).flatMap(fn.andThen(FutureKind::narrowK)));
}
private static FutureKind map(FutureKind lt, Function super T, ? extends R> fn){
return widen(lt.map(fn));
}
private static Higher> traverseA(Applicative applicative, Function super T, ? extends Higher> fn,
Higher ds){
Future future = FutureKind.narrow(ds);
return applicative.map(FutureKind::successful, fn.apply(future.get()));
}
}
public static interface FutureNested{
public static Nested option(Future