cyclops.companion.vavr.Queues 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.tryType;
import io.vavr.Lazy;
import io.vavr.collection.*;
import io.vavr.concurrent.Future;
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 com.aol.cyclops2.types.anyM.AnyMSeq;
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.ListKind;
import cyclops.monads.VavrWitness;
import cyclops.monads.VavrWitness.queue;
import com.aol.cyclops.vavr.hkt.QueueKind;
import cyclops.monads.AnyM;
import cyclops.monads.WitnessType;
import cyclops.monads.XorM;
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.List;
import io.vavr.collection.Queue;
import lombok.experimental.UtilityClass;
import org.jooq.lambda.tuple.Tuple2;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import static com.aol.cyclops.vavr.hkt.QueueKind.widen;
public class Queues {
public static Coproduct coproduct(Queue type, InstanceDefinitions def1){
return Coproduct.of(Xor.primary(widen(type)),def1, Instances.definitions());
}
public static Coproduct coproduct(InstanceDefinitions def1,T... values){
return coproduct(Queue.of(values),def1);
}
public static ,T> XorM xorM(Queue type){
return XorM.right(anyM(type));
}
public static ,T> XorM xorM(T... values){
return xorM(Queue.of(values));
}
public static AnyMSeq anyM(Queue option) {
return AnyM.ofSeq(option, queue.INSTANCE);
}
/**
* Perform a For Comprehension over a Queue, accepting 3 generating functions.
* This results in a four level nested internal iteration over the provided Publishers.
*
*
* {@code
*
* import static cyclops.Queues.forEach4;
*
forEach4(IntQueue.range(1,10).boxed(),
a-> Queue.iterate(a,i->i+1).limit(10),
(a,b) -> Queue.of(a+b),
(a,b,c) -> Queue.just(a+b+c),
Tuple::tuple)
*
* }
*
*
* @param value1 top level Queue
* @param value2 Nested Queue
* @param value3 Nested Queue
* @param value4 Nested Queue
* @param yieldingFunction Generates a result per combination
* @return Queue with an element per combination of nested publishers generated by the yielding function
*/
public static Queue forEach4(Queue extends T1> value1,
Function super T1, ? extends Queue> value2,
BiFunction super T1, ? super R1, ? extends Queue> value3,
Fn3 super T1, ? super R1, ? super R2, ? extends Queue> value4,
Fn4 super T1, ? super R1, ? super R2, ? super R3, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Queue a = value2.apply(in);
return a.flatMap(ina -> {
Queue b = value3.apply(in,ina);
return b.flatMap(inb -> {
Queue c = value4.apply(in,ina,inb);
return c.map(in2 -> yieldingFunction.apply(in, ina, inb, in2));
});
});
});
}
/**
* Perform a For Comprehension over a Queue, accepting 3 generating function.
* This results in a four level nested internal iteration over the provided Publishers.
*
* {@code
*
* import static com.aol.cyclops2.reactor.Queuees.forEach4;
*
* forEach4(IntQueue.range(1,10).boxed(),
a-> Queue.iterate(a,i->i+1).limit(10),
(a,b) -> Queue.just(a+b),
(a,b,c) -> Queue.just(a+b+c),
(a,b,c,d) -> a+b+c+d <100,
Tuple::tuple);
*
* }
*
*
* @param value1 top level Queue
* @param value2 Nested Queue
* @param value3 Nested Queue
* @param value4 Nested Queue
* @param filterFunction A filtering function, keeps values where the predicate holds
* @param yieldingFunction Generates a result per combination
* @return Queue with an element per combination of nested publishers generated by the yielding function
*/
public static Queue forEach4(Queue extends T1> value1,
Function super T1, ? extends Queue> value2,
BiFunction super T1, ? super R1, ? extends Queue> value3,
Fn3 super T1, ? super R1, ? super R2, ? extends Queue> 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 -> {
Queue a = value2.apply(in);
return a.flatMap(ina -> {
Queue b = value3.apply(in,ina);
return b.flatMap(inb -> {
Queue 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 Queue, accepting 2 generating function.
* This results in a three level nested internal iteration over the provided Publishers.
*
*
* {@code
*
* import static Queues.forEach3;
*
* forEach(IntQueue.range(1,10).boxed(),
a-> Queue.iterate(a,i->i+1).limit(10),
(a,b) -> Queue.of(a+b),
Tuple::tuple);
*
* }
*
*
*
* @param value1 top level Queue
* @param value2 Nested Queue
* @param value3 Nested Queue
* @param yieldingFunction Generates a result per combination
* @return Queue with an element per combination of nested publishers generated by the yielding function
*/
public static Queue forEach3(Queue extends T1> value1,
Function super T1, ? extends Queue> value2,
BiFunction super T1, ? super R1, ? extends Queue> value3,
Fn3 super T1, ? super R1, ? super R2, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Queue a = value2.apply(in);
return a.flatMap(ina -> {
Queue b = value3.apply(in,ina);
return b.map(in2 -> yieldingFunction.apply(in, ina, in2));
});
});
}
/**
* Perform a For Comprehension over a Queue, accepting 2 generating function.
* This results in a three level nested internal iteration over the provided Publishers.
*
* {@code
*
* import static Queues.forEach;
*
* forEach(IntQueue.range(1,10).boxed(),
a-> Queue.iterate(a,i->i+1).limit(10),
(a,b) -> Queue.of(a+b),
(a,b,c) ->a+b+c<10,
Tuple::tuple)
.toQueueX();
* }
*
*
* @param value1 top level Queue
* @param value2 Nested publisher
* @param value3 Nested publisher
* @param filterFunction A filtering function, keeps values where the predicate holds
* @param yieldingFunction Generates a result per combination
* @return
*/
public static Queue forEach3(Queue extends T1> value1,
Function super T1, ? extends Queue> value2,
BiFunction super T1, ? super R1, ? extends Queue> value3,
Fn3 super T1, ? super R1, ? super R2, Boolean> filterFunction,
Fn3 super T1, ? super R1, ? super R2, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Queue a = value2.apply(in);
return a.flatMap(ina -> {
Queue 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 Queue, accepting an additonal generating function.
* This results in a two level nested internal iteration over the provided Publishers.
*
*
* {@code
*
* import static Queues.forEach2;
* forEach(IntQueue.range(1, 10).boxed(),
* i -> Queue.range(i, 10), Tuple::tuple)
.forEach(System.out::println);
//(1, 1)
(1, 2)
(1, 3)
(1, 4)
...
*
* }
*
* @param value1 top level Queue
* @param value2 Nested publisher
* @param yieldingFunction Generates a result per combination
* @return
*/
public static Queue forEach2(Queue extends T> value1,
Function super T, Queue> value2,
BiFunction super T, ? super R1, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Queue a = value2.apply(in);
return a.map(in2 -> yieldingFunction.apply(in, in2));
});
}
/**
*
*
* {@code
*
* import static Queues.forEach2;
*
* forEach(IntQueue.range(1, 10).boxed(),
* i -> Queue.range(i, 10),
* (a,b) -> a>2 && b<10,
* Tuple::tuple)
.forEach(System.out::println);
//(3, 3)
(3, 4)
(3, 5)
(3, 6)
(3, 7)
(3, 8)
(3, 9)
...
*
* }
*
*
* @param value1 top level Queue
* @param value2 Nested publisher
* @param filterFunction A filtering function, keeps values where the predicate holds
* @param yieldingFunction Generates a result per combination
* @return
*/
public static Queue forEach2(Queue extends T> value1,
Function super T, ? extends Queue> value2,
BiFunction super T, ? super R1, Boolean> filterFunction,
BiFunction super T, ? super R1, ? extends R> yieldingFunction) {
return value1.flatMap(in -> {
Queue a = value2.apply(in);
return a.filter(in2->filterFunction.apply(in,in2))
.map(in2 -> yieldingFunction.apply(in, in2));
});
}
public static Active allTypeclasses(Queue array){
return Active.of(widen(array), Queues.Instances.definitions());
}
public static Nested mapM(Queue array, Function super T,? extends Higher> fn, InstanceDefinitions defs){
Queue> e = array.map(fn);
QueueKind> lk = widen(e);
return Nested.of(lk, Queues.Instances.definitions(), defs);
}
/**
* Companion class for creating Type Class instances for working with Queues
*
*/
@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.zippingApplicative();
}
@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.none();
}
@Override
public Maybe> unfoldable() {
return Maybe.just(Instances.unfoldable());
}
};
}
/**
*
* Transform a list, mulitplying every element by 2
*
*
* {@code
* QueueKind list = Queues.functor().map(i->i*2, QueueKind.widen(Arrays.asQueue(1,2,3));
*
* //[2,4,6]
*
*
* }
*
*
* An example fluent api working with Queues
*
* {@code
* QueueKind list = Queues.unit()
.unit("hello")
.then(h->Queues.functor().map((String v) ->v.length(), h))
.convert(QueueKind::narrowK);
*
* }
*
*
*
* @return A functor for Queues
*/
public static Functor functor(){
BiFunction,Function super T, ? extends R>,QueueKind> map = Instances::map;
return General.functor(map);
}
/**
*
* {@code
* QueueKind list = Queues.unit()
.unit("hello")
.convert(QueueKind::narrowK);
//Arrays.asQueue("hello"))
*
* }
*
*
*
* @return A factory for Queues
*/
public static Pure unit(){
return General.unit(QueueKind::of);
}
/**
*
*
* {@code
* import static com.aol.cyclops.hkt.jdk.QueueKind.widen;
* import static com.aol.cyclops.util.function.Lambda.l1;
* import static java.util.Arrays.asQueue;
*
Queues.zippingApplicative()
.ap(widen(asQueue(l1(this::multiplyByTwo))),widen(asQueue(1,2,3)));
*
* //[2,4,6]
* }
*
*
*
* Example fluent API
*
* {@code
* QueueKind> listFn =Queues.unit()
* .unit(Lambda.l1((Integer i) ->i*2))
* .convert(QueueKind::narrowK);
QueueKind list = Queues.unit()
.unit("hello")
.then(h->Queues.functor().map((String v) ->v.length(), h))
.then(h->Queues.zippingApplicative().ap(listFn, h))
.convert(QueueKind::narrowK);
//Arrays.asQueue("hello".length()*2))
*
* }
*
*
*
* @return A zipper for Queues
*/
public static Applicative zippingApplicative(){
BiFunction>,QueueKind,QueueKind> ap = Instances::ap;
return General.applicative(functor(), unit(), ap);
}
/**
*
*
* {@code
* import static com.aol.cyclops.hkt.jdk.QueueKind.widen;
* QueueKind list = Queues.monad()
.flatMap(i->widen(QueueX.range(0,i)), widen(Arrays.asQueue(1,2,3)))
.convert(QueueKind::narrowK);
* }
*
*
* Example fluent API
*
* {@code
* QueueKind list = Queues.unit()
.unit("hello")
.then(h->Queues.monad().flatMap((String v) ->Queues.unit().unit(v.length()), h))
.convert(QueueKind::narrowK);
//Arrays.asQueue("hello".length())
*
* }
*
*
* @return Type class with monad functions for Queues
*/
public static Monad monad(){
BiFunction,Function super T, ? extends Higher>,Higher> flatMap = Instances::flatMap;
return General.monad(zippingApplicative(), flatMap);
}
/**
*
*
* {@code
* QueueKind list = Queues.unit()
.unit("hello")
.then(h->Queues.monadZero().filter((String t)->t.startsWith("he"), h))
.convert(QueueKind::narrowK);
//Arrays.asQueue("hello"));
*
* }
*
*
*
* @return A filterable monad (with default value)
*/
public static MonadZero monadZero(){
return General.monadZero(monad(), widen(Queue.empty()));
}
/**
*
* {@code
* QueueKind list = Queues.monadPlus()
.plus(QueueKind.widen(Arrays.asQueue()), QueueKind.widen(Arrays.asQueue(10)))
.convert(QueueKind::narrowK);
//Arrays.asQueue(10))
*
* }
*
* @return Type class for combining Queues by concatenation
*/
public static MonadPlus monadPlus(){
Monoid> m = Monoid.of(widen(Queue.empty()), Instances::concat);
Monoid> m2= (Monoid)m;
return General.monadPlus(monadZero(),m2);
}
/**
*
*
* {@code
* Monoid> m = Monoid.of(QueueKind.widen(Arrays.asQueue()), (a,b)->a.isEmpty() ? b : a);
QueueKind list = Queues.monadPlus(m)
.plus(QueueKind.widen(Arrays.asQueue(5)), QueueKind.widen(Arrays.asQueue(10)))
.convert(QueueKind::narrowK);
//Arrays.asQueue(5))
*
* }
*
*
* @param m Monoid to use for combining Queues
* @return Type class for combining Queues
*/
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(){
BiFunction,QueueKind>,Higher>> sequenceFn = (ap, list) -> {
Higher> identity = ap.unit(widen(Queue.empty()));
BiFunction>,Higher,Higher>> combineToQueue = (acc, next) -> ap.apBiFn(ap.unit((a, b) -> widen(QueueKind.narrow(a).append(b))),
acc,next);
BinaryOperator>> combineQueues = (a, b)-> ap.apBiFn(ap.unit((l1, l2)-> widen(QueueKind.narrow(l1).appendAll(l2.narrow()))),a,b); ;
return ReactiveSeq.fromIterable(QueueKind.narrow(list))
.reduce(identity,
combineToQueue,
combineQueues);
};
BiFunction,Higher>,Higher>> sequenceNarrow =
(a,b) -> QueueKind.widen2(sequenceFn.apply(a, QueueKind.narrowK(b)));
return General.traverse(zippingApplicative(), sequenceNarrow);
}
/**
*
*
* {@code
* int sum = Queues.foldable()
.foldLeft(0, (a,b)->a+b, QueueKind.widen(Arrays.asQueue(1,2,3,4)));
//10
*
* }
*
*
*
* @return Type class for folding / reduction operations
*/
public static Foldable foldable(){
BiFunction,Higher,T> foldRightFn = (m, l)-> ReactiveSeq.fromIterable(QueueKind.narrow(l)).foldRight(m);
BiFunction,Higher,T> foldLeftFn = (m, l)-> ReactiveSeq.fromIterable(QueueKind.narrow(l)).reduce(m);
return General.foldable(foldRightFn, foldLeftFn);
}
private static QueueKind concat(QueueKind l1, QueueKind l2){
return widen(l1.appendAll(QueueKind.narrow(l2)));
}
private static QueueKind ap(QueueKind> lt, QueueKind list){
return widen(FromCyclopsReact.fromStream(ReactiveSeq.fromIterable(lt.narrow()).zip(list.narrow(), (a, b)->a.apply(b))).toQueue());
}
private static Higher flatMap(Higher lt, Function super T, ? extends Higher> fn){
return widen(QueueKind.narrow(lt).flatMap(fn.andThen(QueueKind::narrow)));
}
private static QueueKind map(QueueKind lt, Function super T, ? extends R> fn){
return widen(QueueKind.narrow(lt).map(in->fn.apply(in)));
}
public static Unfoldable unfoldable(){
return new Unfoldable() {
@Override
public Higher unfold(T b, Function super T, Optional>> fn) {
return widen(ReactiveSeq.unfold(b,fn).collect(Queue.collector()));
}
};
}
}
public static interface QueueNested{
public static Nested lazy(Queue> type){
return Nested.of(widen(type.map(LazyKind::widen)),Instances.definitions(),Lazys.Instances.definitions());
}
public static Nested queueTry(Queue> type){
return Nested.of(widen(type.map(TryKind::widen)),Instances.definitions(),Trys.Instances.definitions());
}
public static Nested future(Queue> type){
return Nested.of(widen(type.map(FutureKind::widen)),Instances.definitions(),Futures.Instances.definitions());
}
public static Nested queue(Queue> nested){
return Nested.of(widen(nested.map(QueueKind::widen)),Instances.definitions(),Queues.Instances.definitions());
}
public static Nested, R> either(Queue> nested){
return Nested.of(widen(nested.map(EitherKind::widen)),Instances.definitions(),Eithers.Instances.definitions());
}
public static Nested stream(Queue> nested){
return Nested.of(widen(nested.map(StreamKind::widen)),Instances.definitions(),Streams.Instances.definitions());
}
public static Nested list(Queue> nested){
return Nested.of(widen(nested.map(ListKind::widen)), Instances.definitions(),Lists.Instances.definitions());
}
public static Nested array(Queue> nested){
return Nested.of(widen(nested.map(ArrayKind::widen)),Instances.definitions(),Arrays.Instances.definitions());
}
public static Nested vector(Queue> nested){
return Nested.of(widen(nested.map(VectorKind::widen)),Instances.definitions(),Vectors.Instances.definitions());
}
public static Nested set(Queue> nested){
return Nested.of(widen(nested.map(HashSetKind::widen)),Instances.definitions(), HashSets.Instances.definitions());
}
public static Nested reactiveSeq(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),ReactiveSeq.Instances.definitions());
}
public static Nested maybe(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),Maybe.Instances.definitions());
}
public static Nested eval(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),Eval.Instances.definitions());
}
public static Nested cyclopsFuture(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),cyclops.async.Future.Instances.definitions());
}
public static Nested, P> xor(Queue> nested){
QueueKind> x = widen(nested);
QueueKind, P>> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),Xor.Instances.definitions());
}
public static Nested, T> reader(Queue> nested){
QueueKind> x = widen(nested);
QueueKind, T>> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),Reader.Instances.definitions());
}
public static Nested, P> cyclopsTry(Queue> nested){
QueueKind> x = widen(nested);
QueueKind, P>> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(),cyclops.control.Try.Instances.definitions());
}
public static Nested queueal(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(), Optionals.Instances.definitions());
}
public static Nested completableQueue(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(), CompletableFutures.Instances.definitions());
}
public static Nested javaStream(Queue> nested){
QueueKind> x = widen(nested);
QueueKind> y = (QueueKind)x;
return Nested.of(y,Instances.definitions(), cyclops.companion.Streams.Instances.definitions());
}
}
public static interface NestedQueue{
public static Nested reactiveSeq(ReactiveSeq> nested){
ReactiveSeq> x = nested.map(QueueKind::widenK);
return Nested.of(x,ReactiveSeq.Instances.definitions(),Instances.definitions());
}
public static Nested maybe(Maybe> nested){
Maybe> x = nested.map(QueueKind::widenK);
return Nested.of(x,Maybe.Instances.definitions(),Instances.definitions());
}
public static Nested eval(Eval> nested){
Eval> x = nested.map(QueueKind::widenK);
return Nested.of(x,Eval.Instances.definitions(),Instances.definitions());
}
public static Nested cyclopsFuture(cyclops.async.Future> nested){
cyclops.async.Future