com.jnape.palatable.lambda.optics

## Interface Lens<S,T,A,B>

- Type Parameters:
    `S` - the type of the "larger" value for reading
    `T` - the type of the "larger" value for putting
    `A` - the type of the "smaller" value that is read
    `B` - the type of the "smaller" update value
  All Superinterfaces:
    Applicative<T,Lens<S,?,A,B>>, Contravariant<S,Profunctor<?,T,Lens<?,?,A,B>>>, Functor<T,Lens<S,?,A,B>>, Monad<T,Lens<S,?,A,B>>, MonadRec<T,Lens<S,?,A,B>>, Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>, Profunctor<S,T,Lens<?,?,A,B>>
  All Known Subinterfaces:
    Lens.Simple<S,A>, Schema<Values>
  Functional Interface:
    This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

      @FunctionalInterface
      public interface Lens<S,T,A,B>
      extends Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>, MonadRec<T,Lens<S,?,A,B>>, Profunctor<S,T,Lens<?,?,A,B>>

  An approximation of van Laarhoven lenses.

  A "lens" can be considered in its simplest form as the conjugation of a "getter" and a "setter"; that is, a unification type representing the way to retrieve a "smaller" value `A` from a "larger" value `S`, as well as a way to update a "smaller" value `B` of a "larger" value `S`, producing another "larger" value `T`.

  Consider the following example:

       public final class Person {
           private final int age;

           public Person(int age) {
               this.age = age;
           }

           public int getAge() {
               return age;
           }

           public Person setAge(int age) {
               return new Person(age);
           }
       }

  A lens that focused on the `age` field of an instance of `Person` might look like this:

       Lens<Person, Person, Integer, Integer> ageLens = Lens.lens(Person::getAge, Person::setAge);

       Person adult = new Person(18);
       Integer age = view(ageLens, adult); // 18

       Person olderAdult = set(ageLens, 19, adult);
       Integer olderAge = view(ageLens, olderAdult); // 19

  The pattern of a getter and setter that mutually agree on both `A` and `B` as well as on both `S` and `T` is so common that this can be given a simplified type signature:

       Lens.Simple<Person, Integer> ageLens = Lens.simpleLens(Person::getAge, Person::setAge);

       Person adult = new Person(18);
       Integer age = view(ageLens, adult); // 18

       Person olderAdult = set(ageLens, 19, adult);
       Integer olderAge = view(ageLens, olderAdult); // 19

  However, consider if `age` could be updated on a `Person` by being provided a date of birth, in the form of a `LocalDate`:

       public final class Person {
           private final int age;

           public Person(int age) {
               this.age = age;
           }

           public int getAge() {
               return age;
           }

           public Person setAge(int age) {
               return new Person(age);
           }

           public Person setAge(LocalDate dob) {
               return setAge((int) YEARS.between(dob, LocalDate.now()));
           }
       }

  This is why Lens has both an `A` and a `B`: `A` is the value for "getting", and `B` is the potentially different value for "setting". This distinction makes lenses powerful enough to express the more complicated `setAge` case naturally:

       Lens<Person, Person, Integer, LocalDate> ageDobLens = Lens.lens(Person::getAge, Person::setAge);

       Person adult = new Person(18);
       Integer age = view(ageDobLens, adult); // 18

       Person olderAdult = set(ageDobLens, LocalDate.of(1997, 1, 1), adult);
       Integer olderAge = view(ageDobLens, olderAdult); // 19 at the time of this writing...anyone else feel old?

  Additionally, we might imagine a lens that produces a different "larger" value on updating than what was given. Consider a lens that reads the first string from a list, but produces a Set of strings on update:

       Lens<List<String>, Set<String>, String, String> lens = Lens.lens(
               l -> l.get(0),
               (l, s) -> {
                   List<String> copy = new ArrayList<>(l);
                   copy.set(0, s);
                   return new HashSet<>(copy);
               });

       String firstElement = view(lens, asList("foo", "bar")); // "foo
       System.out.println(firstElement);

       set(lens, "oof", asList("foo", "bar")); // ["bar", "oof"]
       set(lens, "bar", asList("foo", "bar")); // ["bar"]

  For more information, learn about lenses.
  See Also:
    `Optic`, `Iso`

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Interface and Description
    --- | ---
    `static interface` | `Lens.Simple<S,A>` A convenience type with a simplified type signature for common lenses with both unified "larger" values and unified "smaller" values.

  - ### Method Summary

    All Methods Static Methods Instance Methods Default Methods
    Modifier and Type | Method and Description
    --- | ---
    `default <C,D> Lens<S,T,C,D>` | `andThen(Optic<? super Cartesian<?,?,?>,? super Functor<?,?>,A,B,C,D> f)` Left-to-right composition of optics.
    `static <S,A,B> Lens.Simple<S,Tuple2<A,B>>` | `both(Lens.Simple<S,A> f, Lens.Simple<S,B> g)` Dually focus on two simple lenses at the same time.
    `static <S,A,B,C,D> Lens<S,S,Tuple2<A,B>,Tuple2<C,D>>` | `both(Lens<S,S,A,C> f, Lens<S,S,B,D> g)` Dually focus on two lenses at the same time.
    `default <R,U> Lens<R,U,A,B>` | `compose(Optic<? super Cartesian<?,?,?>,? super Functor<?,?>,R,U,S,T> g)` Right-to-Left composition of optics.
    `default <R> Lens<R,T,A,B>` | `contraMap(Fn1<? super R,? extends S> fn)` Contravariantly map `A <- B`.
    `default <R,U> Lens<R,U,A,B>` | `diMap(Fn1<? super R,? extends S> lFn, Fn1<? super T,? extends U> rFn)` Dually map contravariantly over the left parameter and covariantly over the right parameter.
    `default <R> Lens<R,T,A,B>` | `diMapL(Fn1<? super R,? extends S> fn)` Contravariantly map over the left parameter.
    `default <U> Lens<S,U,A,B>` | `diMapR(Fn1<? super T,? extends U> fn)` Covariantly map over the right parameter.
    `default <U> Lens<S,U,A,B>` | `discardL(Applicative<U,Lens<S,?,A,B>> appB)` Sequence both this `Applicative` and `appB`, discarding this `Applicative's` result and returning `appB`.
    `default <U> Lens<S,T,A,B>` | `discardR(Applicative<U,Lens<S,?,A,B>> appB)` Sequence both this `Applicative` and `appB`, discarding `appB's` result and returning this `Applicative`.
    `default <U> Lens<S,U,A,B>` | `flatMap(Fn1<? super T,? extends Monad<U,Lens<S,?,A,B>>> f)` Chain dependent computations that may continue or short-circuit based on previous results.
    `default <U> Lens<S,U,A,B>` | `fmap(Fn1<? super T,? extends U> fn)` Covariantly transmute this functor's parameter using the given mapping function.
    `static <S,T,A,B> Lens<S,T,A,B>` | `lens(Fn1<? super S,? extends A> getter, Fn2<? super S,? super B,? extends T> setter)` Static factory method for creating a lens from a getter function and a setter function.
    `static <S,T,A,B> Lens<S,T,A,B>` | `lens(Optic<? super Cartesian<?,?,?>,? super Functor<?,?>,S,T,A,B> optic)` Promote an optic with compatible bounds to a `Lens`.
    `default <C> Lens<S,T,C,B>` | `mapA(Fn1<? super A,? extends C> fn)` Covariantly map `A` to `C`, yielding a new optic.
    `default <Z> Lens<S,T,A,Z>` | `mapB(Fn1<? super Z,? extends B> fn)` Contravariantly map `B` to `Z`, yielding a new optic.
    `default <R> Lens<R,T,A,B>` | `mapS(Fn1<? super R,? extends S> fn)` Contravariantly map `S` to `R`, yielding a new optic.
    `default <U> Lens<S,U,A,B>` | `mapT(Fn1<? super T,? extends U> fn)` Covariantly map `T` to `U`, yielding a new optic.
    `default <U> Lens<S,U,A,B>` | `pure(U u)` Lift the value `b` into this applicative functor.
    `static <S,A,B> Pure<Lens<S,?,A,B>>` | `pureLens(Fn1<? super S,? extends A> sa)` The canonical `Pure` instance for `Lens`.
    `static <S,A> Lens.Simple<S,A>` | `simpleLens(Fn1<? super S,? extends A> getter, Fn2<? super S,? super A,? extends S> setter)` Static factory method for creating a simple lens from a getter function and a setter function.
    `default Iso<S,T,A,B>` | `toIso(S s)` Produce an `Iso` from this `Lens` by providing a default `S` value.
    `default <U> Lens<S,U,A,B>` | `trampolineM(Fn1<? super T,? extends MonadRec<RecursiveResult<T,U>,Lens<S,?,A,B>>> fn)` Given some operation yielding a `RecursiveResult` inside this `MonadRec`, internally trampoline the operation until it yields a `termination` instruction.
    `default <U> Lens<S,U,A,B>` | `zip(Applicative<Fn1<? super T,? extends U>,Lens<S,?,A,B>> appFn)` Given another instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.

    - ### Methods inherited from interface com.jnape.palatable.lambda.optics.Optic

      `apply, monomorphize, optic, reframe`

    - ### Methods inherited from interface com.jnape.palatable.lambda.monad.MonadRec

      `lazyZip`

    - ### Methods inherited from interface com.jnape.palatable.lambda.monad.Monad

      `join`

    - ### Methods inherited from interface com.jnape.palatable.lambda.functor.Functor

      `coerce`

- - ### Method Detail

    - #### fmap

          default <U> Lens<S,U,A,B> fmap(Fn1<? super T,? extends U> fn)

      Covariantly transmute this functor's parameter using the given mapping function. Generally this method is specialized to return an instance of the class implementing Functor.
      Specified by:
        `fmap` in interface `Applicative<T,Lens<S,?,A,B>>`
      Specified by:
        `fmap` in interface `Functor<T,Lens<S,?,A,B>>`
      Specified by:
        `fmap` in interface `Monad<T,Lens<S,?,A,B>>`
      Specified by:
        `fmap` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the new parameter type
      Parameters:
        `fn` - the mapping function
      Returns:
        a functor over B (the new parameter type)

    - #### pure

          default <U> Lens<S,U,A,B> pure(U u)

      Lift the value `b` into this applicative functor.
      Specified by:
        `pure` in interface `Applicative<T,Lens<S,?,A,B>>`
      Specified by:
        `pure` in interface `Monad<T,Lens<S,?,A,B>>`
      Specified by:
        `pure` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the type of the returned applicative's parameter
      Parameters:
        `u` - the value
      Returns:
        an instance of this applicative over b

    - #### zip

          default <U> Lens<S,U,A,B> zip(Applicative<Fn1<? super T,? extends U>,Lens<S,?,A,B>> appFn)

      Given another instance of this applicative over a mapping function, "zip" the two instances together using whatever application semantics the current applicative supports.
      Specified by:
        `zip` in interface `Applicative<T,Lens<S,?,A,B>>`
      Specified by:
        `zip` in interface `Monad<T,Lens<S,?,A,B>>`
      Specified by:
        `zip` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the resulting applicative parameter type
      Parameters:
        `appFn` - the other applicative instance
      Returns:
        the mapped applicative

    - #### discardL

          default <U> Lens<S,U,A,B> discardL(Applicative<U,Lens<S,?,A,B>> appB)

      Sequence both this `Applicative` and `appB`, discarding this `Applicative's` result and returning `appB`. This is generally useful for sequentially performing side-effects.
      Specified by:
        `discardL` in interface `Applicative<T,Lens<S,?,A,B>>`
      Specified by:
        `discardL` in interface `Monad<T,Lens<S,?,A,B>>`
      Specified by:
        `discardL` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the type of the returned Applicative's parameter
      Parameters:
        `appB` - the other Applicative
      Returns:
        appB

    - #### discardR

          default <U> Lens<S,T,A,B> discardR(Applicative<U,Lens<S,?,A,B>> appB)

      Sequence both this `Applicative` and `appB`, discarding `appB's` result and returning this `Applicative`. This is generally useful for sequentially performing side-effects.
      Specified by:
        `discardR` in interface `Applicative<T,Lens<S,?,A,B>>`
      Specified by:
        `discardR` in interface `Monad<T,Lens<S,?,A,B>>`
      Specified by:
        `discardR` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the type of appB's parameter
      Parameters:
        `appB` - the other Applicative
      Returns:
        this Applicative

    - #### flatMap

          default <U> Lens<S,U,A,B> flatMap(Fn1<? super T,? extends Monad<U,Lens<S,?,A,B>>> f)

      Chain dependent computations that may continue or short-circuit based on previous results.
      Specified by:
        `flatMap` in interface `Monad<T,Lens<S,?,A,B>>`
      Specified by:
        `flatMap` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the resulting monad parameter type
      Parameters:
        `f` - the dependent computation over A
      Returns:
        the new monad instance

    - #### trampolineM

          default <U> Lens<S,U,A,B> trampolineM(Fn1<? super T,? extends MonadRec<RecursiveResult<T,U>,Lens<S,?,A,B>>> fn)

      Given some operation yielding a `RecursiveResult` inside this `MonadRec`, internally trampoline the operation until it yields a `termination` instruction.

      Stack-safety depends on implementations guaranteeing that the growth of the call stack is a constant factor independent of the number of invocations of the operation. For various examples of how this can be achieved in stereotypical circumstances, see the referenced types.

      Specified by:
        `trampolineM` in interface `MonadRec<T,Lens<S,?,A,B>>`
      Type Parameters:
        `U` - the ultimate resulting carrier type
      Parameters:
        `fn` - the function to internally trampoline
      Returns:
        the trampolined `MonadRec`
      See Also:
        `for a basic implementation`, `for a {@link CoProduct2 coproduct} implementation`, `for an implementation leveraging an already stack-safe {@link Monad#flatMap(Fn1)}`, `for a {@link MonadT monad transformer} implementation`

    - #### diMapL

          default <R> Lens<R,T,A,B> diMapL(Fn1<? super R,? extends S> fn)

      Contravariantly map over the left parameter.
      Specified by:
        `diMapL` in interface `Profunctor<S,T,Lens<?,?,A,B>>`
      Type Parameters:
        `R` - the new left parameter type
      Parameters:
        `fn` - the mapping function
      Returns:
        a profunctor over Z (the new left parameter type) and C (the same right parameter type)

    - #### diMapR

          default <U> Lens<S,U,A,B> diMapR(Fn1<? super T,? extends U> fn)

      Covariantly map over the right parameter. For all profunctors that are also functors, it should hold that `diMapR(f) == fmap(f)`.
      Specified by:
        `diMapR` in interface `Profunctor<S,T,Lens<?,?,A,B>>`
      Type Parameters:
        `U` - the new right parameter type
      Parameters:
        `fn` - the mapping function
      Returns:
        a profunctor over A (the same left parameter type) and C (the new right parameter type)

    - #### diMap

          default <R,U> Lens<R,U,A,B> diMap(Fn1<? super R,? extends S> lFn,
                                            Fn1<? super T,? extends U> rFn)

      Dually map contravariantly over the left parameter and covariantly over the right parameter. This is isomorphic to `diMapL(lFn).diMapR(rFn)`.
      Specified by:
        `diMap` in interface `Profunctor<S,T,Lens<?,?,A,B>>`
      Type Parameters:
        `R` - the new left parameter type
        `U` - the new right parameter type
      Parameters:
        `lFn` - the left parameter mapping function
        `rFn` - the right parameter mapping function
      Returns:
        a profunctor over Z (the new left parameter type) and C (the new right parameter type)

    - #### contraMap

          default <R> Lens<R,T,A,B> contraMap(Fn1<? super R,? extends S> fn)

      Contravariantly map `A <- B`.
      Specified by:
        `contraMap` in interface `Contravariant<S,Profunctor<?,T,Lens<?,?,A,B>>>`
      Specified by:
        `contraMap` in interface `Profunctor<S,T,Lens<?,?,A,B>>`
      Type Parameters:
        `R` - the new parameter type
      Parameters:
        `fn` - the mapping function
      Returns:
        the mapped Contravariant functor instance

    - #### mapS

          default <R> Lens<R,T,A,B> mapS(Fn1<? super R,? extends S> fn)

      Contravariantly map `S` to `R`, yielding a new optic.
      Specified by:
        `mapS` in interface `Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>`
      Type Parameters:
        `R` - the new left side of the output profunctor
      Parameters:
        `fn` - the mapping function
      Returns:
        the new optic

    - #### mapT

          default <U> Lens<S,U,A,B> mapT(Fn1<? super T,? extends U> fn)

      Covariantly map `T` to `U`, yielding a new optic.
      Specified by:
        `mapT` in interface `Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>`
      Type Parameters:
        `U` - the new right side's functor embedding of the output profunctor
      Parameters:
        `fn` - the mapping function
      Returns:
        the new optic

    - #### mapA

          default <C> Lens<S,T,C,B> mapA(Fn1<? super A,? extends C> fn)

      Covariantly map `A` to `C`, yielding a new optic.
      Specified by:
        `mapA` in interface `Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>`
      Type Parameters:
        `C` - the new left side of the input profunctor
      Parameters:
        `fn` - the mapping function
      Returns:
        the new optic

    - #### mapB

          default <Z> Lens<S,T,A,Z> mapB(Fn1<? super Z,? extends B> fn)

      Contravariantly map `B` to `Z`, yielding a new optic.
      Specified by:
        `mapB` in interface `Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>`
      Type Parameters:
        `Z` - the new right side's functor embedding of the input profunctor
      Parameters:
        `fn` - the mapping function
      Returns:
        the new optic

    - #### toIso

          default Iso<S,T,A,B> toIso(S s)

      Produce an `Iso` from this `Lens` by providing a default `S` value.
      Parameters:
        `s` - the default `S`
      Returns:
        an `Iso`

    - #### andThen

          default <C,D> Lens<S,T,C,D> andThen(Optic<? super Cartesian<?,?,?>,? super Functor<?,?>,A,B,C,D> f)

      Left-to-right composition of optics. Requires compatibility between `S` and `T`.
      Specified by:
        `andThen` in interface `Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>`
      Type Parameters:
        `C` - the new left side of the input profunctor
        `D` - the new right side's functor embedding of the input profunctor
      Parameters:
        `f` - the other optic
      Returns:
        the composed optic

    - #### compose

          default <R,U> Lens<R,U,A,B> compose(Optic<? super Cartesian<?,?,?>,? super Functor<?,?>,R,U,S,T> g)

      Right-to-Left composition of optics. Requires compatibility between `A` and `B`.
      Specified by:
        `compose` in interface `Optic<Cartesian<?,?,?>,Functor<?,?>,S,T,A,B>`
      Type Parameters:
        `R` - the new left side of the output profunctor
        `U` - the new right side's functor embedding of the output profunctor
      Parameters:
        `g` - the other optic
      Returns:
        the composed optic

    - #### lens

          static <S,T,A,B> Lens<S,T,A,B> lens(Fn1<? super S,? extends A> getter,
                                              Fn2<? super S,? super B,? extends T> setter)

      Static factory method for creating a lens from a getter function and a setter function.
      Type Parameters:
        `S` - the type of the "larger" value for reading
        `T` - the type of the "larger" value for putting
        `A` - the type of the "smaller" value that is read
        `B` - the type of the "smaller" update value
      Parameters:
        `getter` - the getter function
        `setter` - the setter function
      Returns:
        the lens

    - #### lens

          static <S,T,A,B> Lens<S,T,A,B> lens(Optic<? super Cartesian<?,?,?>,? super Functor<?,?>,S,T,A,B> optic)

      Promote an optic with compatible bounds to a `Lens`.
      Type Parameters:
        `S` - the type of the "larger" value for reading
        `T` - the type of the "larger" value for putting
        `A` - the type of the "smaller" value that is read
        `B` - the type of the "smaller" update value
      Parameters:
        `optic` - the `Optic`
      Returns:
        the `Lens`

    - #### simpleLens

          static <S,A> Lens.Simple<S,A> simpleLens(Fn1<? super S,? extends A> getter,
                                                   Fn2<? super S,? super A,? extends S> setter)

      Static factory method for creating a simple lens from a getter function and a setter function.
      Type Parameters:
        `S` - the type of both "larger" values
        `A` - the type of both "smaller" values
      Parameters:
        `getter` - the getter function
        `setter` - the setter function
      Returns:
        the lens

    - #### both

          static <S,A,B,C,D> Lens<S,S,Tuple2<A,B>,Tuple2<C,D>> both(Lens<S,S,A,C> f,
                                                                    Lens<S,S,B,D> g)

      Dually focus on two lenses at the same time. Requires `S` and `T` to be invariant between lenses.
      Type Parameters:
        `S` - both larger values
        `A` - f's smaller viewing value
        `B` - g's smaller viewing value
        `C` - f's smaller setting value
        `D` - g's smaller setting value
      Parameters:
        `f` - the first lens
        `g` - the second lens
      Returns:
        the dual-focus lens

    - #### both

          static <S,A,B> Lens.Simple<S,Tuple2<A,B>> both(Lens.Simple<S,A> f,
                                                         Lens.Simple<S,B> g)

      Dually focus on two simple lenses at the same time.
      Type Parameters:
        `S` - both larger values
        `A` - both smaller viewing values
        `B` - both smaller setting values
      Parameters:
        `f` - the first lens
        `g` - the second lens
      Returns:
        the dual-focus simple lens

    - #### pureLens

          static <S,A,B> Pure<Lens<S,?,A,B>> pureLens(Fn1<? super S,? extends A> sa)

      The canonical `Pure` instance for `Lens`.
      Type Parameters:
        `S` - the type of the "larger" value for reading
        `A` - the type of the "smaller" value that is read
        `B` - the type of the "smaller" update value
      Parameters:
        `sa` - the getting function
      Returns:
        the `Pure` instance