com.jnape.palatable.lambda.functor.builtin.Writer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lambda Show documentation
Show all versions of lambda Show documentation
Functional patterns for Java
package com.jnape.palatable.lambda.functor.builtin;
import com.jnape.palatable.lambda.adt.Unit;
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
import com.jnape.palatable.lambda.functions.Fn1;
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult;
import com.jnape.palatable.lambda.functions.specialized.Pure;
import com.jnape.palatable.lambda.functor.Applicative;
import com.jnape.palatable.lambda.monad.Monad;
import com.jnape.palatable.lambda.monad.MonadRec;
import com.jnape.palatable.lambda.monad.MonadWriter;
import com.jnape.palatable.lambda.monad.transformer.builtin.WriterT;
import com.jnape.palatable.lambda.monoid.Monoid;
import static com.jnape.palatable.lambda.adt.Unit.UNIT;
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly;
import static com.jnape.palatable.lambda.functions.builtin.fn2.Both.both;
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
import static com.jnape.palatable.lambda.functions.recursion.Trampoline.trampoline;
/**
* The lazy writer monad, a monad capturing some accumulation (eventually to be folded in terms of a given monoid) and
* a value. Note that unlike the {@link State} monad, the {@link Writer} monad does not allow the value to be fully
* derived from the accumulation.
*
* @param the accumulation type
* @param the value type
*/
public final class Writer implements
MonadWriter>,
MonadRec> {
private final Fn1 super Monoid, ? extends Tuple2> writerFn;
private Writer(Fn1 super Monoid, ? extends Tuple2> writerFn) {
this.writerFn = writerFn;
}
/**
* Given a {@link Monoid} for the accumulation, run the computation represented by this {@link Writer}, accumulate
* the written output in terms of the {@link Monoid}, and produce the accumulation and the value.
*
* @param monoid the accumulation {@link Monoid}
* @return the accumulation with the value
*/
public Tuple2 runWriter(Monoid monoid) {
return writerFn.apply(monoid);
}
/**
* {@inheritDoc}
*/
@Override
public Writer> listens(Fn1 super W, ? extends B> fn) {
return new Writer<>(monoid -> runWriter(monoid).into((a, w) -> tuple(both(constantly(a), fn, w), w)));
}
/**
* {@inheritDoc}
*/
@Override
public Writer censor(Fn1 super W, ? extends W> fn) {
return new Writer<>(monoid -> runWriter(monoid).fmap(fn));
}
/**
* {@inheritDoc}
*/
@Override
public Writer trampolineM(Fn1 super A, ? extends MonadRec, Writer>> fn) {
return new Writer<>(monoid -> trampoline(into((a, w) -> fn.apply(a).>>coerce()
.runWriter(monoid)
.fmap(monoid.apply(w))
.into((aOrB, w_) -> aOrB.biMap(a_ -> tuple(a_, w_), b -> tuple(b, w_)))), runWriter(monoid)));
}
/**
* {@inheritDoc}
*/
@Override
public Writer flatMap(Fn1 super A, ? extends Monad>> f) {
return new Writer<>(monoid -> writerFn.apply(monoid)
.into((a, w) -> f.apply(a).>coerce().runWriter(monoid).fmap(monoid.apply(w))));
}
/**
* {@inheritDoc}
*/
@Override
public Writer pure(B b) {
return listen(b);
}
/**
* {@inheritDoc}
*/
@Override
public Writer fmap(Fn1 super A, ? extends B> fn) {
return MonadRec.super.fmap(fn).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public Writer zip(Applicative, Writer> appFn) {
return MonadRec.super.zip(appFn).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public Lazy> lazyZip(
Lazy extends Applicative, Writer>> lazyAppFn) {
return MonadRec.super.lazyZip(lazyAppFn).fmap(MonadRec>::coerce);
}
/**
* {@inheritDoc}
*/
@Override
public Writer discardL(Applicative> appB) {
return MonadRec.super.discardL(appB).coerce();
}
/**
* {@inheritDoc}
*/
@Override
public Writer discardR(Applicative> appB) {
return MonadRec.super.discardR(appB).coerce();
}
/**
* Construct a {@link Writer} from an accumulation.
*
* @param w the accumulation
* @param the accumulation type
* @return the {@link Writer}
*/
public static Writer tell(W w) {
return writer(tuple(UNIT, w));
}
/**
* Construct a {@link Writer} from a value.
*
* @param a the output value
* @param the accumulation type
* @param the value type
* @return the {@link Writer}
*/
public static Writer listen(A a) {
return Writer.pureWriter().apply(a);
}
/**
* Construct a {@link Writer} from an accumulation and a value.
*
* @param aw the output value and accumulation
* @param the accumulation type
* @param the value type
* @return the {@link WriterT}
*/
public static Writer writer(Tuple2 aw) {
return new Writer<>(constantly(aw));
}
/**
* The canonical {@link Pure} instance for {@link Writer}.
*
* @param the accumulation type
* @return the {@link Pure} instance
*/
public static Pure> pureWriter() {
return new Pure>() {
@Override
public Writer checkedApply(A a) {
return new Writer<>(monoid -> tuple(a, monoid.identity()));
}
};
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy