cyclops.free.FreeAp Maven / Gradle / Ivy
Show all versions of cyclops-pure Show documentation
package cyclops.free;
import com.oath.cyclops.hkt.Higher;
import com.oath.cyclops.hkt.Higher2;
import cyclops.companion.Functions;
import cyclops.function.Lambda;
import com.oath.cyclops.hkt.DataWitness.free;
import com.oath.cyclops.hkt.DataWitness.freeAp;
import cyclops.instances.free.FreeApInstances;
import cyclops.instances.free.FreeInstances;
import cyclops.function.NaturalTransformation;
import cyclops.typeclasses.monad.Applicative;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import java.util.function.BiFunction;
import java.util.function.Function;
//FreeAp refs : = https://github.com/typelevel/cats/blob/master/free/src/main/scala/cats/free/FreeApplicative.scala
public interface FreeAp extends Higher2 {
static FreeAp pure(T value) {
return new Pure(value);
}
static FreeAp ap(Higher fp, FreeAp> fn){
return new Ap(fp,fn);
}
default FreeAp ap(FreeAp> b){
return b.>fold(f->this.map(f),
(pivot,fn)->ap(pivot,ap(fn.map(fx->a->p->fx.apply(p).apply(a)))));
}
default
FreeAp map(Function f){
return this.>fold(a->pure(f.apply(a)),
(pivot,fn)-> ap(pivot, fn.map(it -> {
Function
x = f.compose(it);
return Functions.narrow(x);
})));
}
default
Higher foldMap(NaturalTransformation f, Applicative applicative){
return this.>fold(a->applicative.unit(a),
(pivot,fn)->applicative.zip(f.apply(pivot),fn.foldMap(f,applicative),(a, g)->g.apply(a)));
}
default
Higher fold(Applicative applicative){
return this.foldMap(NaturalTransformation.identity(), applicative);
}
default Free monad(Applicative applicative){
return Free.narrowK(foldMap(new NaturalTransformation>() {
@Override
public Higher, T> apply(Higher a) {
Free res = Free.liftF(a, applicative);
return res;
}
}, FreeInstances.applicative(applicative, applicative)));
}
default FreeAp compile(NaturalTransformation f, Applicative applicative){
return FreeAp.narrowK(foldMap(new NaturalTransformation>() {
@Override
public Higher, T> apply(Higher a) {
return FreeAp.lift(f.apply(a),applicative);
}
}, FreeApInstances.applicative(applicative, applicative)));
}
static FreeAp lift(Higher fa, Applicative applicative) {
return ap(fa,pure(Lambda.l1(a -> a)));
}
R fold(Function pure, BiFunction,FreeAp>,? extends R> ap);
@AllArgsConstructor(access = AccessLevel.PRIVATE)
static class Pure implements FreeAp {
private final A a;
@Override
public R fold(Function pure, BiFunction, FreeAp>, ? extends R> ap) {
return pure.apply(a);
}
}
@AllArgsConstructor(access = AccessLevel.PRIVATE)
static class Ap implements FreeAp {
private final Higher pivot;
private final FreeAp> fn;
@Override
public R fold(Function pure, BiFunction, FreeAp>, ? extends R> ap) {
Higher p = (Higher)pivot;
return (R)ap.apply((Higher)pivot, (FreeAp) fn);
}
}
static FreeAp narrowK(Higher, T> ds){
return (FreeAp)ds;
}
}