All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cyclops.companion.vavr.Futures Maven / Gradle / Ivy

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 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 value1, Function> value2, BiFunction> value3, Fn3> value4, Fn4 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 value1, Function> value2, BiFunction> value3, Fn3> value4, Fn4 filterFunction, Fn4 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 value1, Function> value2, BiFunction> value3, Fn3 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 value1, Function> value2, BiFunction> value3, Fn3 filterFunction, Fn3 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 value1, Function> value2, BiFunction 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 value1, Function> value2, BiFunction filterFunction, BiFunction 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 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 f, final Value v, final BiFunction 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 f, final Future v, final BiFunction 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 f, final Iterable v, final BiFunction 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 p, final Future f, final BiFunction 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 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> 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,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>,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, ? 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> fn){ return widen(FutureKind.narrow(lt).flatMap(fn.andThen(FutureKind::narrowK))); } private static FutureKind map(FutureKind lt, Function fn){ return widen(lt.map(fn)); } private static Higher> traverseA(Applicative applicative, Function> 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> type){ return Nested.of(widen(type.map(OptionKind::widen)),Instances.definitions(),Options.Instances.definitions()); } public static Nested futureTry(Future> type){ return Nested.of(widen(type.map(TryKind::widen)),Instances.definitions(),Trys.Instances.definitions()); } public static Nested future(Future> type){ return Nested.of(widen(type.map(FutureKind::widen)),Instances.definitions(),Futures.Instances.definitions()); } public static Nested lazy(Future> nested){ return Nested.of(widen(nested.map(LazyKind::widen)),Instances.definitions(),Lazys.Instances.definitions()); } public static Nested, R> either(Future> nested){ return Nested.of(widen(nested.map(EitherKind::widen)),Instances.definitions(),Eithers.Instances.definitions()); } public static Nested queue(Future> nested){ return Nested.of(widen(nested.map(QueueKind::widen)), Instances.definitions(),Queues.Instances.definitions()); } public static Nested stream(Future> nested){ return Nested.of(widen(nested.map(StreamKind::widen)),Instances.definitions(),Streams.Instances.definitions()); } public static Nested list(Future> nested){ return Nested.of(widen(nested.map(ListKind::widen)), Instances.definitions(),Lists.Instances.definitions()); } public static Nested array(Future> nested){ return Nested.of(widen(nested.map(ArrayKind::widen)),Instances.definitions(),Arrays.Instances.definitions()); } public static Nested vector(Future> nested){ return Nested.of(widen(nested.map(VectorKind::widen)),Instances.definitions(),Vectors.Instances.definitions()); } public static Nested set(Future> nested){ return Nested.of(widen(nested.map(HashSetKind::widen)),Instances.definitions(), HashSets.Instances.definitions()); } public static Nested reactiveSeq(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),ReactiveSeq.Instances.definitions()); } public static Nested maybe(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),Maybe.Instances.definitions()); } public static Nested eval(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),Eval.Instances.definitions()); } public static Nested cyclopsFuture(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),cyclops.async.Future.Instances.definitions()); } public static Nested, P> xor(Future> nested){ FutureKind> x = widen(nested); FutureKind, P>> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),Xor.Instances.definitions()); } public static Nested, T> reader(Future> nested){ FutureKind> x = widen(nested); FutureKind, T>> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),Reader.Instances.definitions()); } public static Nested, P> cyclopsTry(Future> nested){ FutureKind> x = widen(nested); FutureKind, P>> y = (FutureKind)x; return Nested.of(y,Instances.definitions(),cyclops.control.Try.Instances.definitions()); } public static Nested optional(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(), Optionals.Instances.definitions()); } public static Nested completableFuture(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(), CompletableFutures.Instances.definitions()); } public static Nested javaStream(Future> nested){ FutureKind> x = widen(nested); FutureKind> y = (FutureKind)x; return Nested.of(y,Instances.definitions(), cyclops.companion.Streams.Instances.definitions()); } } public static interface NestedFuture{ public static Nested reactiveSeq(ReactiveSeq> nested){ ReactiveSeq> x = nested.map(FutureKind::widenK); return Nested.of(x,ReactiveSeq.Instances.definitions(),Instances.definitions()); } public static Nested maybe(Maybe> nested){ Maybe> x = nested.map(FutureKind::widenK); return Nested.of(x,Maybe.Instances.definitions(),Instances.definitions()); } public static Nested eval(Eval> nested){ Eval> x = nested.map(FutureKind::widenK); return Nested.of(x,Eval.Instances.definitions(),Instances.definitions()); } public static Nested cyclopsFuture(cyclops.async.Future> nested){ cyclops.async.Future> x = nested.map(FutureKind::widenK); return Nested.of(x,cyclops.async.Future.Instances.definitions(),Instances.definitions()); } public static Nested,future, P> xor(Xor> nested){ Xor> x = nested.map(FutureKind::widenK); return Nested.of(x,Xor.Instances.definitions(),Instances.definitions()); } public static Nested,future, T> reader(Reader> nested){ Reader> x = nested.map(FutureKind::widenK); return Nested.of(x,Reader.Instances.definitions(),Instances.definitions()); } public static Nested,future, P> cyclopsTry(cyclops.control.Try, S> nested){ cyclops.control.Try, S> x = nested.map(FutureKind::widenK); return Nested.of(x,cyclops.control.Try.Instances.definitions(),Instances.definitions()); } public static Nested optional(Optional> nested){ Optional> x = nested.map(FutureKind::widenK); return Nested.of(Optionals.OptionalKind.widen(x), Optionals.Instances.definitions(), Instances.definitions()); } public static Nested completableFuture(CompletableFuture> nested){ CompletableFuture> x = nested.thenApply(FutureKind::widenK); return Nested.of(CompletableFutures.CompletableFutureKind.widen(x), CompletableFutures.Instances.definitions(),Instances.definitions()); } public static Nested javaStream(java.util.stream.Stream> nested){ java.util.stream.Stream> x = nested.map(FutureKind::widenK); return Nested.of(cyclops.companion.Streams.StreamKind.widen(x), cyclops.companion.Streams.Instances.definitions(),Instances.definitions()); } } }