package fj.data;
import fj.*;
/**
* Created by MarkPerry on 7/07/2014.
*/
public final class Writer<W, A> {
private final A val;
private final W logValue;
private final Monoid<W> monoid;
private Writer(A a, W w, Monoid<W> m) {
val = a;
logValue = w;
monoid = m;
}
public P2<W, A> run() {
return P.p(logValue, val);
}
public A value() {
return val;
}
public W log() {
return logValue;
}
public Monoid<W> monoid() {
return monoid;
}
public static <W, A> Writer<W, A> unit(A a, W w, Monoid<W> m) {
return new Writer<>(a, w, m);
}
public static <W, A> Writer<W, A> unit(A a, Monoid<W> m) {
return new Writer<>(a, m.zero(), m);
}
public Writer<W, A> tell(W w) {
return unit(val, monoid.sum(logValue, w), monoid);
}
public <B> Writer<W, B> map(F<A, B> f) {
return unit(f.f(val), logValue, monoid);
}
public <B> Writer<W, B> flatMap(F<A, Writer<W, B>> f) {
Writer<W, B> writer = f.f(val);
return unit(writer.val, writer.monoid.sum(logValue, writer.logValue), writer.monoid);
}
public static <B> Writer<String, B> unit(B b) {
return unit(b, Monoid.stringMonoid);
}
public static <A> F<A, Writer<String, A>> stringLogger() {
return a -> unit(a, Monoid.stringMonoid);
}
}