cyclops.hkt.Product Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cyclops-pure Show documentation
Show all versions of cyclops-pure Show documentation
Platform for Functional Reactive Programming with Java 8
The newest version!
package cyclops.hkt;
import com.oath.cyclops.hkt.Higher;
import com.oath.cyclops.hkt.Higher3;
import com.oath.cyclops.types.Filters;
import com.oath.cyclops.types.foldable.To;
import com.oath.cyclops.types.functor.Transformable;
import cyclops.control.*;
import cyclops.control.Maybe;
import cyclops.data.ImmutableList;
import cyclops.data.LazySeq;
import cyclops.data.Seq;
import cyclops.function.Function3;
import cyclops.function.Function4;
import cyclops.function.Monoid;
import com.oath.cyclops.hkt.DataWitness.*;
import cyclops.reactive.ReactiveSeq;
import cyclops.typeclasses.InstanceDefinitions;
import cyclops.typeclasses.Pure;
import cyclops.typeclasses.comonad.Comonad;
import cyclops.typeclasses.foldable.Foldable;
import cyclops.typeclasses.foldable.Unfoldable;
import cyclops.arrow.MonoidK;
import cyclops.arrow.SemigroupK;
import cyclops.typeclasses.functor.Functor;
import cyclops.typeclasses.monad.*;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import cyclops.data.tuple.Tuple;
import cyclops.data.tuple.Tuple2;
import cyclops.data.tuple.Tuple3;
import java.util.Arrays;
import java.util.function.*;
import static cyclops.data.tuple.Tuple.tuple;
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@EqualsAndHashCode(of="run")
@Getter
public class Product implements Filters,
Higher3,
Transformable,
To> {
private final Tuple2,Higher> run;
private final InstanceDefinitions def1;
private final InstanceDefinitions def2;
public Tuple2,Higher> asTuple(){
return run;
}
public Tuple2,Active> asActiveTuple(){
return run.transform((a, b)->Tuple.tuple(Active.of(a,def1),Active.of(b,def2)));
}
public Active _1(){
return Active.of(run._1(),def1);
}
public Active _2(){
return Active.of(run._2(),def2);
}
public static Product of(Tuple2,
Higher> run, InstanceDefinitions def1, InstanceDefinitions def2){
return new Product<>(run,def1,def2);
}
public static Product of(Active a1, Active a2){
return of(Tuple.tuple(a1.getSingle(),a2.getSingle()),a1.getDef1(),a2.getDef1());
}
public Coproduct coproduct(BiPredicate,Higher> test){
return test.test(run._1(),run._2()) ?Coproduct.left(run._1(),def1,def2) : Coproduct.right(run._2(),def1,def2);
}
public Product filter(Predicate test) {
return of(run.transform((m1, m2)->{
Higher x2 = def2.monadZero().fold(p->p.filter(test,m2),()->m2);
Higher x1 = def1.monadZero().fold(p->p.filter(test,m1),()->m1);
return Tuple.tuple(x1, x2);
}),def1,def2);
}
@Override
public Product ofType(Class type) {
return (Product)Filters.super.ofType(type);
}
@Override
public Product filterNot(Predicate predicate) {
return filter(predicate.negate());
}
@Override
public Product notNull() {
return (Product)Filters.super.notNull();
}
public Active zipWithSecond(BiFunction,? extends R> f) {
return Active.of(def1.traverse().zipWith(def2.foldable(),f,run._1(),run._2()),def1);
}
public Product> zip(Product p2){
return zip(p2,Tuple::tuple);
}
public Product> zip(Product p2, Product p3){
return zip(p2,p3);
}
public Product zip(Product p2, BiFunction zipper){
Active a1 = Active.of(run._1(),def1);
Active a2 = Active.of(p2.run._1(),def1);
Active a3 = a1.zip(a2,zipper);
Active b1 = Active.of(run._2(),def2);
Active b2 = Active.of(p2.run._2(),def2);
Active b3 = b1.zip(b2,zipper);
return of(a3,b3);
}
public Product zip(Product p2, Product p3, Function3 zipper){
Active a1 = Active.of(run._1(),def1);
Active a2 = Active.of(p2.run._1(),def1);
Active a3 = Active.of(p3.run._1(),def1);
Active a4 = a1.zip(a2,a3,zipper);
Active b1 = Active.of(run._2(),def2);
Active b2 = Active.of(p2.run._2(),def2);
Active b3 = Active.of(p3.run._2(),def2);
Active b4 = b1.zip(b2,b3,zipper);
return of(a4,b4);
}
public Product mapWithIndex(BiFunction f) {
return of(Tuple.tuple(def1.traverse().mapWithIndex(f,run._1()),def2.traverse().mapWithIndex(f,run._2())),def1,def2);
}
public Product> zipWithIndex() {
return mapWithIndex(Tuple::tuple);
}
@Override
public Product map(Function fn) {
return of(run.transform((m1, m2)->{
Higher x2 = def2.functor().map(fn, m2);
Higher x1 = def1.functor().map(fn, m1);
return Tuple.tuple(x1, x2);
}),def1,def2);
}
public Product flatMap(Function> fn) {
return of(map(fn).run.transform((m1, m2)->Tuple.tuple(def1.monad().flatMap(p->p.asTuple()._1(),m1),def2.monad().flatMap(p->p.asTuple()._2(),m2))),def1,def2);
}
@Override
public Product peek(Consumer c) {
return map(a->{
c.accept(a);
return a;
});
}
@Override
public String toString() {
return "Product["+ run.toString()+"]";
}
public Active tailRec1(T initial,Function>> fn){
return asActiveTuple()._1().tailRec(initial, fn);
}
public Active tailRec2(T initial,Function>> fn){
return asActiveTuple()._2().tailRec(initial, fn);
}
public Active activeFirst(SemigroupK sg, Higher concat){
return Active.of(sg.apply(run._1(),concat),def1);
}
public Active activeSecond(SemigroupK sg, Higher concat){
return Active.of(sg.apply(run._2(),concat),def2);
}
public R fold(BiFunction,? super Higher, ? extends R> visitor){
return run.transform(visitor);
}
public R visitA(BiFunction,? super Active, ? extends R> visitor){
return run.transform((a, b)->visitor.apply(Active.of(a,def1),Active.of(b,def2)));
}
public Product plusFirst(SemigroupK semigroupK, Higher add){
return of(Tuple.tuple(semigroupK.apply(run._1(),add),run._2()),def1,def2);
}
public Product plusSecond(SemigroupK semigroupK, Higher add){
return of(Tuple.tuple(run._1(),semigroupK.apply(run._2(),add)),def1,def2);
}
public Product swap(){
return of(run.swap(),def2,def1);
}
public Unfolds unfoldsDefault(){
return new Unfolds(def1.unfoldable().fold(p->p,()->new Unfoldable.UnsafeValueUnfoldable<>()),
def2.unfoldable().fold(p->p,()->new Unfoldable.UnsafeValueUnfoldable<>()));
}
public Maybe unfolds(){
if(def1.unfoldable().isPresent() && def2.unfoldable().isPresent())
return Maybe.just(new Unfolds(def1.unfoldable().orElse(null),def2.unfoldable().orElse(null)));
return Maybe.nothing();
}
public Plus plusUnsafe(){
return new Plus(def1.monadPlus().orElse(null),def2.monadPlus().orElse(null));
}
public Maybe plus(){
if(def1.monadPlus().isPresent() && def2.monadPlus().isPresent())
return Maybe.just(new Plus(def1.monadPlus().orElse(null),def2.monadPlus().orElse(null)));
return Maybe.nothing();
}
@AllArgsConstructor
public class Unfolds {
private final Unfoldable unf1;
private final Unfoldable unf2;
public Product unfold(T b, Function>> fn){
Tuple2, Higher> res = run.transform((left, right) -> Tuple.tuple(unf1.unfold(b, fn), unf2.unfold(b, fn)));
return Product.of(res, def1, def2);
}
public Product replicate(int n, T value) {
return unfold(n,i -> Option.some(tuple(value, i-1)));
}
public Product none() {
return unfold((T) null, t -> Option.>none());
}
public Product one(T a) {
return replicate(1, a);
}
}
@AllArgsConstructor
public class Plus{
private final MonadPlus plus1;
private final MonadPlus plus2;
public Product plus(Product a){
Active r1 = Active.of(run._1(), def1).plus(plus1).plusA(a._1());
Active r2 = Active.of(run._2(), def2).plus(plus2).plusA(a._2());
return of(r1,r2);
}
public Product sum(ImmutableList> list){
Active r1 = Active.of(run._1(), def1).plus(plus1).sumA(list.map(p->p.asActiveTuple()._1()));
Active r2 = Active.of(run._2(), def2).plus(plus2).sumA(list.map(p->p.asActiveTuple()._2()));
return of(r1,r2);
}
}
public R foldMap(final Monoid mb, final Function fn) {
return run.transform((a, b) -> {
R r1 = def1.foldable().foldMap(mb, fn, a);
R r2 = def2.foldable().foldMap(mb, fn, b);
return mb.foldRight(Arrays.asList(r2, r1));
});
}
public T foldRight(Monoid monoid) {
return run.transform((a, b) -> {
T r1 = def1.foldable().foldRight(monoid, a);
T r2 = def2.foldable().foldRight(monoid, b);
return monoid.foldRight(Arrays.asList(r2, r1));
});
}
public T foldRight(T identity, BinaryOperator semigroup) {
return foldRight(Monoid.fromBiFunction(identity, semigroup));
}
public Tuple2,LazySeq> toLazySeq(){
return run.transform((a, b)->Tuple.tuple(def1.foldable().lazySeq(a),
def2.foldable().lazySeq(b)));
}
public Tuple2,Seq> toSeq(){
return run.transform((a, b)->Tuple.tuple(def1.foldable().seq(a),
def2.foldable().seq(b)));
}
public Seq toSeqBoth(){
return toSeq().transform((a, b)->a.plusAll(b));
}
public Tuple2,ReactiveSeq> stream(){
return toLazySeq().transform((a, b)->Tuple.tuple(a.stream(),b.stream()));
}
public ReactiveSeq streamBoth(){
return stream().transform((a, b)->a.appendStream(b));
}
public Product reverse(){
return Product.of(run.transform((a, b)->Tuple.tuple(def1.traverse().reverse(a),def2.traverse().reverse(b))),def1,def2);
}
public Tuple2 size() {
return run.transform((a, b)->Tuple.tuple(def1.foldable().size(a),
def2.foldable().size(b)));
}
public long totalSize() {
return size().transform((a, b)->a+b);
}
public T foldLeft(Monoid monoid) {
return run.transform((a, b) -> {
T r1 = def1.foldable().foldRight(monoid, a);
T r2 = def2.foldable().foldRight(monoid, b);
return monoid.foldLeft(Arrays.asList(r1, r2));
});
}
public T foldLeft(T identity, BinaryOperator semigroup) {
return foldLeft(Monoid.fromBiFunction(identity, semigroup));
}
public Tuple2 foldMapTuple(final Monoid mb, final Function fn) {
return run.transform((a, b) -> {
R r1 = def1.foldable().foldMap(mb, fn, a);
R r2 = def2.foldable().foldMap(mb, fn, b);
return Tuple.tuple(r2, r1);
});
}
public Tuple2 foldRightTuple(Monoid monoid) {
return run.transform((a, b) -> {
T r1 = def1.foldable().foldRight(monoid, a);
T r2 = def2.foldable().foldRight(monoid, b);
return Tuple.tuple(r2, r1);
});
}
public Tuple2 foldRightTuple(T identity, BinaryOperator semigroup) {
return foldRightTuple(Monoid.fromBiFunction(identity, semigroup));
}
public Tuple2 foldLeftTuple(Monoid monoid) {
return run.transform((a, b) -> {
T r1 = def1.foldable().foldRight(monoid, a);
T r2 = def2.foldable().foldRight(monoid, b);
return Tuple.tuple(r1, r2);
});
}
public Tuple2 foldLeftTuple(T identity, BinaryOperator semigroup) {
return foldLeftTuple(Monoid.fromBiFunction(identity, semigroup));
}
public Product forEach2(Function> value1, final BiFunction yieldingFunction) {
return flatMap(a->{
return value1.apply(a).map(b->yieldingFunction.apply(a,b));
});
}
public Product forEach3(final Function> value1, final BiFunction> value2,
final Function3 yieldingFunction) {
return flatMap(a->{
return value1.apply(a).flatMap(b->value2.apply(a,b).map(c->yieldingFunction.apply(a,b,c)));
});
}
public Product forEach4(final Function> value1, final BiFunction> value2, final Function3> value3,
final Function4 yieldingFunction) {
return flatMap(a->{
return value1.apply(a).flatMap(b->value2.apply(a,b).flatMap(c->value3.apply(a,b,c).map(d->yieldingFunction.apply(a,b,c,d))));
});
}
public static Product narrowK(Higher, W2>, T> ds){
return (Product)ds;
}
public Active,W2>,T> allTypeClasses(){
return Active.of(this, Instances.definitions(def1, def2));
}
public Higher> traverseA(Applicative applicative, Function> fn){
return traverseA(applicative,fn,this);
}
public static Higher> traverseA(Applicative applicative, Function> fn,Product n){
Higher> v1 = n._1().traverseA(applicative, fn);
Higher> v2 = n._2().traverseA(applicative, fn);
return applicative.zip(v1,v2,(a,b)->a.concat(b));
}
public Higher> sequenceA(Applicative applicative,
Product> ds){
return traverseA(applicative, i -> i, ds);
}
public Higher> flatTraverseA(Applicative applicative,
Function>> f) {
return applicative.map_(traverseA(applicative, f), it-> it.flatMap(a->a));
}
public Higher> flatSequenceA(Applicative applicative, Product>> fgfa) {
return applicative.map(i -> i.flatMap(Function.identity()),sequenceA(applicative, fgfa) );
}
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public static class Instances implements InstanceDefinitions, W2>>{
private final InstanceDefinitions def1;
private final InstanceDefinitions def2;
public static InstanceDefinitions, W2>> definitions(InstanceDefinitions def1,InstanceDefinitions def2){
return new Instances<>(def1,def2);
}
public Functor, W2>> functor(){
return new Functor, W2>>(){
@Override
public Higher, W2>, R> map(Function fn, Higher, W2>, T> ds) {
return narrowK(ds).map(fn);
}
};
}
public Pure, W2>> unit(){
return new Pure, W2>>(){
@Override
public Higher, W2>, T> unit(T value) {
return Product.of(Active.of(def1,value), Active.of(def2, value));
}
};
}
public Applicative, W2>> applicative(){
return new Applicative, W2>>(){
@Override
public Higher, W2>, R> ap(Higher, W2>, ? extends Function> fn, Higher, W2>, T> apply) {
return narrowK(fn).flatMap(x -> narrowK(apply).map(x));
}
@Override
public Higher, W2>, R> map(Function fn, Higher, W2>, T> ds) {
return functor().map(fn,ds);
}
@Override
public Higher, W2>, T> unit(T value) {
return Instances.this.unit().unit(value);
}
};
}
public Monad, W2>> monad(){
return new Monad, W2>>(){
@Override
public Higher, W2>, R> ap(Higher, W2>, ? extends Function> fn, Higher, W2>, T> apply) {
return applicative().ap(fn,apply);
}
@Override
public Higher, W2>, R> map(Function fn, Higher, W2>, T> ds) {
return functor().map(fn,ds);
}
@Override
public Higher, W2>, T> unit(T value) {
return Instances.this.unit().unit(value);
}
@Override
public Higher, W2>, R> flatMap(Function, W2>, R>> fn, Higher, W2>, T> ds) {
return narrowK(ds).flatMap(fn.andThen(Product::narrowK));
}
};
}
@Override
public Option, W2>>> monadZero() {
return def1.monadZero().flatMap(x->{
return def2.monadZero().map(y->{
return new MonadZero, W2>>() {
@Override
public Higher, W2>, R> ap(Higher, W2>, ? extends Function> fn, Higher, W2>, T> apply) {
return applicative().ap(fn,apply);
}
@Override
public Higher, W2>, R> map(Function fn, Higher, W2>, T> ds) {
return functor().map(fn,ds);
}
@Override
public Higher, W2>, T> filter(Predicate predicate, Higher, W2>, T> ds) {
return narrowK(ds).filter(predicate);
}
@Override
public Higher, W2>, ?> zero() {
Active ac1 = Active.of( def1.monadZero().orElse(null).zero(), def1);
Active ac2 = Active.of(def2.monadZero().orElse(null).zero(), def2);
return Product.of(ac1, ac2);
}
@Override
public Higher, W2>, T> unit(T value) {
return Instances.this.unit().unit(value);
}
@Override
public Higher, W2>, R> flatMap(Function, W2>, R>> fn, Higher, W2>, T> ds) {
return monad().flatMap(fn,ds);
}
};});
});
}
public MonadRec, W2>> monadRec() {
return new MonadRec