com.jnape.palatable.lambda.adt.coproduct

## Interface CoProduct2<A,B,CP2 extends CoProduct2<A,B,?>>

- Type Parameters:
    `A` - the first possible type
    `B` - the second possible type
    `CP2` - the recursive type of this coproduct (used for embedding)
  All Known Implementing Classes:
    Choice2, Either, Maybe, RecursiveResult, Try
  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 CoProduct2<A,B,CP2 extends CoProduct2<A,B,?>>

  A generalization of the coproduct of two types. Coproducts represent the disjoint union of two or more distinct types, and provides an interface for specifying morphisms from those types to a common result type.

  Learn more about Coproducts.

  See Also:
    `Choice2`, `Either`

- - ### Method Summary

    All Methods Instance Methods Abstract Methods Default Methods
    Modifier and Type | Method and Description
    --- | ---
    `default <C> CoProduct3<A,B,C,? extends CoProduct3<A,B,C,?>>` | `diverge()` Diverge this coproduct by introducing another possible type that it could represent.
    `default <R> R` | `embed(Fn1<? super CP2,? extends R> aFn, Fn1<? super CP2,? extends R> bFn)` Embed this coproduct inside another value; that is, given morphisms from this coproduct to `R`, apply the appropriate morphism to this coproduct as a whole.
    `default CoProduct2<B,A,? extends CoProduct2<B,A,?>>` | `invert()` Swap the type parameters.
    `<R> R` | `match(Fn1<? super A,? extends R> aFn, Fn1<? super B,? extends R> bFn)` Type-safe convergence requiring a match against all potential types.
    `default Product2<Maybe<A>,Maybe<B>>` | `project()` Project this coproduct onto a product, such that the index in the product that corresponds to this coproduct's value is present, while the other indices are absent.
    `default Maybe<A>` | `projectA()` Convenience method for projecting this coproduct onto a product and then extracting the first slot value.
    `default Maybe<B>` | `projectB()` Convenience method for projecting this coproduct onto a product and then extracting the second slot value.

- - ### Method Detail

    - #### match

          <R> R match(Fn1<? super A,? extends R> aFn,
                      Fn1<? super B,? extends R> bFn)

      Type-safe convergence requiring a match against all potential types.
      Type Parameters:
        `R` - result type
      Parameters:
        `aFn` - morphism `A -> R`
        `bFn` - morphism `B -> R`
      Returns:
        the result of applying the appropriate morphism to this coproduct's unwrapped value

    - #### diverge

          default <C> CoProduct3<A,B,C,? extends CoProduct3<A,B,C,?>> diverge()

      Diverge this coproduct by introducing another possible type that it could represent. As no morphisms can be provided mapping current types to the new type, this operation merely acts as a convenience method to allow the use of a more convergent coproduct with a more divergent one; that is, if a `CoProduct3<String, Integer, Boolean>` is expected, a `CoProduct2<String, Integer>` should suffice.

      Generally, we use inheritance to make this a non-issue; however, with coproducts of differing magnitudes, we cannot guarantee variance compatibility in one direction conveniently at construction time, and in the other direction, at all. A `CoProduct2` could not be a `CoProduct3` without specifying all type parameters that are possible for a `CoProduct3` - more specifically, the third possible type - which is not necessarily known at construction time, or even useful if never used in the context of a `CoProduct3`. The inverse inheritance relationship - `CoProduct3` < `CoProduct2` - is inherently unsound, as a `CoProduct3` cannot correctly implement `match(com.jnape.palatable.lambda.functions.Fn1<? super A, ? extends R>, com.jnape.palatable.lambda.functions.Fn1<? super B, ? extends R>)`, given that the third type `C` is always possible.

      For this reason, there is a `diverge` method supported between all `CoProduct` types of single magnitude difference.

      Type Parameters:
        `C` - the additional possible type of this coproduct
      Returns:
        a `CoProduct3`<A, B, C>

    - #### project

          default Product2<Maybe<A>,Maybe<B>> project()

      Project this coproduct onto a product, such that the index in the product that corresponds to this coproduct's value is present, while the other indices are absent.
      Returns:
        a product of the coproduct projection

    - #### projectA

          default Maybe<A> projectA()

      Convenience method for projecting this coproduct onto a product and then extracting the first slot value.
      Returns:
        an optional value representing the projection of the "a" type index

    - #### projectB

          default Maybe<B> projectB()

      Convenience method for projecting this coproduct onto a product and then extracting the second slot value.
      Returns:
        an optional value representing the projection of the "b" type index

    - #### invert

          default CoProduct2<B,A,? extends CoProduct2<B,A,?>> invert()

      Swap the type parameters.
      Returns:
        The inverted coproduct

    - #### embed

          default <R> R embed(Fn1<? super CP2,? extends R> aFn,
                              Fn1<? super CP2,? extends R> bFn)

      Embed this coproduct inside another value; that is, given morphisms from this coproduct to `R`, apply the appropriate morphism to this coproduct as a whole. Like `match(com.jnape.palatable.lambda.functions.Fn1<? super A, ? extends R>, com.jnape.palatable.lambda.functions.Fn1<? super B, ? extends R>)`, but without unwrapping the value.
      Type Parameters:
        `R` - result type
      Parameters:
        `aFn` - morphism `A v B -> R`, applied in the `A` case
        `bFn` - morphism `A v B -> R`, applied in the `B` case
      Returns:
        the result of applying the appropriate morphism to this coproduct