git.fiddlerwoaroof.com
Raw Blame History
package com.company.main;

import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;

public interface Lens<S, T, A, B> extends java.util.function.BiFunction<A, Function<T,S>, B> {
    B over(A rec, Function<T, S> fun);

    @Override
    default B apply(A a, Function<T, S> tsFunction) {
        return over(a, tsFunction);
    }

    default B set(A rec, S value) {
        return over(rec, Constant.ly(value));
    }

    default T get(A rec) {
        final AtomicReference<T> store = new AtomicReference<>();
        over(rec, (T v) -> {
            store.set(v);
            return null;
        });
        return store.get();
    }

    default <W, X> Lens<W, X, A, B> compose(Lens<W, X, T, S> b) {
        return Lens.staticCompose(this, b);
    }

    static <S, T, A, B, U, V> Lens<S, T, A, B> staticCompose(Lens<V, U, A, B> a, Lens<S, T, U, V> b) {
        return (rec, fun) -> a.set(rec, b.set(a.get(rec), fun.apply(b.get(a.get(rec)))));
    }
}


class Constant<T, R> implements Function<T, R> {
    private R v;

    private Constant(R v) {
        this.v = v;
    }

    @Override
    public R apply(T o) {
        return v;
    }

    static <T, R> Constant<T, R> ly(R v) {
        return new Constant<>(v);
    }
}