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

com.jnape.palatable.lambda.functions.builtin.fn2.LazyRec Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
package com.jnape.palatable.lambda.functions.builtin.fn2;

import com.jnape.palatable.lambda.functions.Fn2;
import com.jnape.palatable.lambda.functions.specialized.Kleisli;
import com.jnape.palatable.lambda.functor.builtin.Lazy;

import static com.jnape.palatable.lambda.functions.specialized.Kleisli.kleisli;
import static com.jnape.palatable.lambda.functor.builtin.Lazy.lazy;

/**
 * Given a {@link Fn2} that receives a recursive function and an input and yields a {@link Lazy lazy} result, and an
 * input, produce a {@link Lazy lazy} result that, when forced, will recursively invoke the function until it terminates
 * in a stack-safe way.
 * 

* Example: *

 * {@code
 * Lazy lazyFactorial = lazyRec((fact, x) -> x.equals(ONE)
 *                                                       ? lazy(x)
 *                                                       : fact.apply(x.subtract(ONE)).fmap(y -> y.multiply(x)),
 *                                                  BigInteger.valueOf(50_000));
 * BigInteger value = lazyFactorial.value(); // 3.34732050959714483691547609407148647791277322381045 x 10^213236
 * }
 * 
* * @param the input type * @param the output type */ public final class LazyRec implements Fn2, Lazy>, A, Lazy>, A, Lazy> { private static final LazyRec INSTANCE = new LazyRec<>(); private LazyRec() { } @Override public Lazy checkedApply(Fn2, Lazy>, A, Lazy> fn, A a) { return lazy(a).flatMap(fn.apply(lazyRec(fn))); } @SuppressWarnings("unchecked") public static LazyRec lazyRec() { return (LazyRec) INSTANCE; } public static Kleisli, Lazy> lazyRec( Fn2, Lazy>, A, Lazy> fn) { return kleisli(LazyRec.lazyRec().apply(fn)); } public static Lazy lazyRec(Fn2, Lazy>, A, Lazy> fn, A a) { return lazyRec(fn).apply(a); } }