cyclops.free.Cofree 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.free;
import com.oath.cyclops.hkt.Higher;
import com.oath.cyclops.hkt.Higher2;
import com.oath.cyclops.hkt.DataWitness.cofree;
import com.oath.cyclops.hkt.DataWitness.eval;
import cyclops.control.Eval;
import cyclops.function.NaturalTransformation;
import cyclops.instances.control.EvalInstances;
import cyclops.typeclasses.comonad.Comonad;
import cyclops.typeclasses.functor.Functor;
import cyclops.typeclasses.monad.Monad;
import cyclops.typeclasses.monad.Traverse;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/*
* Cofree refs & guides : https://github.com/typelevel/cats/blob/master/free/src/main/scala/cats/free/Cofree.scala
* https://github.com/kategory/kategory/blob/master/kategory/src/main/kotlin/kategory/free/Cofree.kt
*
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Cofree implements Supplier, Higher2 {
private final Functor functor;
private final T head;
private final Eval>> tail;
public static Cofree of(Functor functor, T head, Eval>> tail) {
return new Cofree(functor,head,tail);
}
public Higher> tailForced() {
return tail.get();
}
public Cofree map(Function f){
return transform(f,c->c.map(f));
}
public Cofree coflatMap(Function,? extends R> f){
return of(functor, f.apply(this), tail.map(h-> functor.map_(h, __->coflatMap(f))));
}
public Cofree> nest() {
return of(functor, this, tail.map(h-> functor.map_(h, __-> nest())));
}
public Cofree transform(Function f, Function,Cofree> g) {
return of(functor,f.apply(head),tail.map(i-> functor.map_(i,g)));
}
public Cofree mapBranchingRoot(NaturalTransformation nat) {
return of(functor, head, tail.map(h->nat.apply(h)));
}
public Cofree mapBranchingS(Functor functor,NaturalTransformation nat) {
return of(functor, head, tail.map(ce -> nat.apply(this.functor.map_(ce, cofree -> cofree.mapBranchingS( functor,nat)))));
}
public Cofree mapBranchingT(Functor functor,NaturalTransformation nat) {
return of(functor, head, tail.map(ce -> functor.map_(nat.apply(ce), cofree -> cofree.mapBranchingT(functor,nat))));
}
public Cofree forceTail() {
return of(functor, head, Eval.now(tail.get()));
}
public Cofree forceAll(){
return of(functor, head, Eval.now(tail.map(h-> functor.map_(h, c->c.forceAll())).get()));
}
public T extract(){
return head;
}
public T get(){
return extract();
}
public Eval fold(Traverse traverse, BiFunction,Eval> fn) {
Eval> eval = traverse.traverseA(EvalInstances.applicative(), it -> it.fold( traverse,fn), tailForced())
.convert(Eval::narrowK);
return eval.flatMap(i->fn.apply(extract(), i));
}
public Higher visitM(Traverse traverse, Monad monad,BiFunction,Higher> fn,
NaturalTransformation inclusion) {
class inner {
public Eval> loop(Cofree eval) {
Higher> looped = traverse.traverseA(monad, (Cofree fr) -> monad.flatten(inclusion.apply(Eval.defer(()->loop(fr)))), eval.tailForced());
Higher folded = monad.flatMap_(looped, fb -> fn.apply(eval.head, fb));
return Eval.now(folded);
}
}
return monad.flatten(inclusion.apply(new inner().loop(this)));
}
public static Cofree unfold(Functor functor,T b, Function> fn) {
return of(functor, b, Eval.later(() -> functor.map_(fn.apply(b), t -> unfold(functor, t, fn))));
}
public static Cofree narrowK2(final Higher2 cof) {
return (Cofree)cof;
}
public static Cofree narrowK(final Higher,T> cof) {
return (Cofree)cof;
}
public static class Instances{
public Comonad> comonad(){
return new Comonad>() {
@Override
public T extract(Higher, T> ds) {
return narrowK(ds).extract();
}
@Override
public Higher, Higher, T>> nest(Higher, T> ds) {
return (Higher)narrowK(ds).nest();
}
@Override
public Higher, R> coflatMap(Function, T>, R> mapper, Higher, T> ds) {
return narrowK(ds).coflatMap(mapper);
}
};
}
}
}