package com.googlecode.totallylazy;
import com.googlecode.totallylazy.functions.Curried2;
import com.googlecode.totallylazy.functions.Function1;
public class Lense<A, B> {
private final Function1<A, B> get;
private final Curried2<B, A, A> set;
private Lense(Function1<A, B> get, Curried2<B, A, A> set) {
this.get = get;
this.set = set;
}
public static <A, B> Lense<A, B> lense(Function1<A, B> get, Curried2<B, A, A> set) {
return new Lense<>(get, set);
}
public B get(A a) {
return get.apply(a);
}
public A set(B b, A a) {
return set.apply(b, a);
}
public A modify(A a, Function1<B, B> updateFunction) throws Exception {
return set(updateFunction.call(get(a)), a);
}
public <C> Lense<A, C> then(final Lense<B, C> other) {
return lense(get.then(other.get), setter(other));
}
private <C> Curried2<C, A, A> setter(final Lense<B, C> other) {
return (c, a) -> set(other.set(c, get(a)), a);
}
}