de.caff.generics.function

## Interface Predicate2<P1,P2>

- Type Parameters:
    `P1` - parameter type 1
    `P2` - parameter type 2
  All Superinterfaces:
    java.util.function.BiPredicate<P1,P2>, java.util.function.Predicate<ITuple2<? extends P1,? extends P2>>, Predicate1<ITuple2<? extends P1,? extends P2>>
  All Known Subinterfaces:
    BooleanPredicate2, BytePredicate2, CharPredicate2, DoublePredicate2, FloatPredicate2, IntPredicate2, LongPredicate2, ShortPredicate2
  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 Predicate2<P1,P2>
      extends java.util.function.BiPredicate<P1,P2>, Predicate1<ITuple2<? extends P1,? extends P2>>

  A function with two arguments which returns a boolean value.

  Predicates can be chained to simulate boolean logic by `and(BiPredicate)`, `or(BiPredicate)`, `xor(BiPredicate)`, and `negate()`.

  There is a general problem with combining types which don't allow to use the above combination methods in all cases similar to standard Java's logical expressions. The following static methods of this interface may be used in all cases: `and(BiPredicate, BiPredicate)`, `or(BiPredicate, BiPredicate)`, and `xor(BiPredicate, BiPredicate)`.

  Useful for start values in algorithms or as default values are the two values returned by `alwaysTrue()` (a predicate which always returns `true` regardless the argument applied to the `BiPredicate.test(Object, Object)` method) and `alwaysFalse()` (same for `false`).

  Partial evaluation is possible via `partialLeft(Object)` which allows to provide a fix first argument and `partialLeft(Object)` which provides a fix second argument. Both return a `Predicate1` with the type of the other argument.

  If a predicate with arguments in reverse order is required `reverseOrder()` comes to help.

  Compared to the standard Java `BiPredicate` this implementation has an improved `negate()` and provides optimized `alwaysTrue()` and `alwaysFalse()` implementations plus an additional `xor(BiPredicate)`. It also allows to use a predicate where the arguments are expected in `reverse order` or to use this 2 argument predicate where only 1 argument is expected by providing a fix value for either `first` or the `second` argument.

  Author:
    Rammi
  See Also:
    `Predicate1`, `Predicate3`, `Predicate4`, `Predicate5`, `Predicate6`, `Predicate7`, `Predicate8`, `Predicate9`

- - ### Field Summary

    - ### Fields inherited from interface de.caff.generics.function.Predicate1

      `ALWAYS_FALSE, ALWAYS_TRUE`

  - ### Method Summary

    All Methods Static Methods Instance Methods Default Methods Deprecated Methods
    Modifier and Type | Method and Description
    --- | ---
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP> Predicate1<FP>` | `after1(java.util.function.Function<FP,FR> before)` Get a chained predicate which first applies the given function, then this predicate.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2> Predicate2<FP1,FP2>` | `after2(java.util.function.BiFunction<FP1,FP2,FR> before)` Get a chained predicate which first applies the given 2-parameter function, then this predicate.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3> Predicate3<FP1,FP2,FP3>` | `after3(Function3<FR,FP1,FP2,FP3> before)` Get a chained predicate which first applies the given 3-parameter function, then this predicate.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5> Predicate5<FP1,FP2,FP3,FP4,FP5>` | `after5(Function5<FR,FP1,FP2,FP3,FP4,FP5> before)` Get a chained predicate which first applies the given 5-parameter function, then this predicate.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6> Predicate6<FP1,FP2,FP3,FP4,FP5,FP6>` | `after6(Function6<FR,FP1,FP2,FP3,FP4,FP5,FP6> before)` Get a chained predicate which first applies the given 6-parameter function, then this predicate.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6,FP7> Predicate7<FP1,FP2,FP3,FP4,FP5,FP6,FP7>` | `after7(Function7<FR,FP1,FP2,FP3,FP4,FP5,FP6,FP7> before)` Get a chained predicate which first applies the given 7-parameter function, then this one.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8> Predicate8<FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8>` | `after8(Function8<FR,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8> before)` Get a chained predicate which first applies the given 8-parameter function, then this one.
    `default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8,FP9> Predicate9<FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8,FP9>` | `after9(Function9<FR,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8,FP9> before)` Get a chained predicate which first applies the given 9-parameter function, then this one.
    `static <T1,T2> Predicate2<T1,T2>` | `alwaysFalse()` Get a predicate which always evaluates to `false`.
    `static <T1,T2> Predicate2<T1,T2>` | `alwaysTrue()` Get a predicate which always evaluates to `true`.
    `default Predicate2<P1,P2>` | `and(java.util.function.BiPredicate<? super P1,? super P2> other)` Combine this and another predicate with logical and.
    `static <T1,T2> Predicate2<T1,T2>` | `and(java.util.function.BiPredicate<? super T1,? super T2> pred1, java.util.function.BiPredicate<? super T1,? super T2> pred2)` Get a predicate which is the combination of two predicates with a logical and.
    `default boolean` | `apply(P1 arg1, P2 arg2)` Deprecated. This has been renamed to `BiPredicate.test(Object, Object)` to be more in sync with standard Java
    `static <T> Predicate2<T,T>` | `areIdentical()` Get a predicate which checks whether 2 objects represent the same object.
    `static <T1,T2> Predicate2<T1,T2>` | `from(java.util.function.BiPredicate<T1,T2> bipred)` Make a standard `BiPredicate` usable as a `Predicate2`.
    `static <T> Predicate2<T,T>` | `isEqual()` Get a predicate which compares 2 objects for deep equality.
    `default Predicate2<P1,P2>` | `negate()` Get the negation of this predicate.
    `default Predicate2<P1,P2>` | `or(java.util.function.BiPredicate<? super P1,? super P2> other)` Combine this and another predicate with logical or.
    `static <T1,T2> Predicate2<T1,T2>` | `or(java.util.function.BiPredicate<? super T1,? super T2> pred1, java.util.function.BiPredicate<? super T1,? super T2> pred2)` Get a predicate which is the combination of two predicates with a logical or.
    `default Predicate1<P2>` | `partial1(P1 argument)` Get a partially applied predicate using a fix first argument.
    `default Predicate1<P1>` | `partial2(P2 argument)` Get a partially applied predicate using a fix second argument.
    `default Predicate1<P2>` | `partialLeft(P1 argument)` Get a partially applied predicate.
    `default Predicate1<P1>` | `partialRight(P2 argument)` Get a partially applied predicate.
    `default Predicate2<P2,P1>` | `reverseOrder()` Get a two argument predicate which expects the arguments in reverse order.
    `default boolean` | `test(ITuple2<? extends P1,? extends P2> tuple2)` Expand a tuple into the arguments of this predicate.
    `default Predicate2<P1,P2>` | `xor(java.util.function.BiPredicate<? super P1,? super P2> other)` Combine this and another predicate with logical exclusive or.
    `static <T1,T2> Predicate2<T1,T2>` | `xor(java.util.function.BiPredicate<? super T1,? super T2> pred1, java.util.function.BiPredicate<? super T1,? super T2> pred2)` Get a predicate which is the combination of two predicates with a logical exclusive or.

    - ### Methods inherited from interface java.util.function.BiPredicate

      `test`

    - ### Methods inherited from interface de.caff.generics.function.Predicate1

      `adapted, and_, and, and, from, isEqual, isNull, notNull, or_, or, or, testNonNull, xor_, xor, xor`

- - ### Method Detail

    - #### test

          default boolean test(@NotNull
                               ITuple2<? extends P1,? extends P2> tuple2)

      Expand a tuple into the arguments of this predicate.
      Specified by:
        `test` in interface `java.util.function.Predicate<ITuple2<? extends P1,? extends P2>>`
      Parameters:
        `tuple2` - tuple to expand
      Returns:
        the result of testing the expended eleeents of the tuple

    - #### apply

          @Deprecated
          default boolean apply(P1 arg1,
                                            P2 arg2)

      Deprecated. This has been renamed to `BiPredicate.test(Object, Object)` to be more in sync with standard Java
      Test the given. This is outdated.
      Parameters:
        `arg1` - function argument 1
        `arg2` - function argument 2
      Returns:
        `true` or `false`

    - #### and

          @NotNull
          default Predicate2<P1,P2> and(@NotNull
                                                 java.util.function.BiPredicate<? super P1,? super P2> other)

      Combine this and another predicate with logical and. The result will use shortcut evaluation, so if this predicate already returns `false` the other one is not evaluated.

      This method has a problem if either one of the argument types pf the parameter is not a super class of this predicate's parameter types. See `and(BiPredicate, BiPredicate)` for such cases.

      Specified by:
        `and` in interface `java.util.function.BiPredicate<P1,P2>`
      Parameters:
        `other` - other predicate to be chained with logical and
      Returns:
        predicates combined with logical and

    - #### or

          @NotNull
          default Predicate2<P1,P2> or(@NotNull
                                                java.util.function.BiPredicate<? super P1,? super P2> other)

      Combine this and another predicate with logical or. The result will use shortcut evaluation, so if this predicate already returns `true` the other one is not evaluated.

      This method has a problem if either one of the argument types pf the parameter is not a super class of this predicate's parameter types. See `or(BiPredicate, BiPredicate)` for such cases.

      Specified by:
        `or` in interface `java.util.function.BiPredicate<P1,P2>`
      Parameters:
        `other` - other predicate to be chained with logical or
      Returns:
        predicates combined with logical or

    - #### xor

          @NotNull
          default Predicate2<P1,P2> xor(@NotNull
                                                 java.util.function.BiPredicate<? super P1,? super P2> other)

      Combine this and another predicate with logical exclusive or.

      This method has a problem if either one of the argument types pf the parameter is not a super class of this predicate's parameter types. See `xor(BiPredicate, BiPredicate)` for such cases.

      Parameters:
        `other` - other predicate to be chained with logical exclusive or
      Returns:
        predicates combined with logical exclusive or

    - #### negate

          @NotNull
          default Predicate2<P1,P2> negate()

      Get the negation of this predicate.
      Specified by:
        `negate` in interface `java.util.function.BiPredicate<P1,P2>`
      Specified by:
        `negate` in interface `java.util.function.Predicate<ITuple2<? extends P1,? extends P2>>`
      Specified by:
        `negate` in interface `Predicate1<ITuple2<? extends P1,? extends P2>>`
      Returns:
        negation of this predicate

    - #### partialLeft

          @NotNull
          default Predicate1<P2> partialLeft(P1 argument)

      Get a partially applied predicate.
      Parameters:
        `argument` - value applied for first argument
      Returns:
        partially evaluated predicate

    - #### partial1

          @NotNull
          default Predicate1<P2> partial1(P1 argument)

      Get a partially applied predicate using a fix first argument. This is the same as `partialLeft(Object)` but more consistently named.
      Parameters:
        `argument` - value applied for first argument
      Returns:
        partially evaluated predicate

    - #### partialRight

          @NotNull
          default Predicate1<P1> partialRight(P2 argument)

      Get a partially applied predicate.
      Parameters:
        `argument` - value applied for second argument
      Returns:
        partially evaluated predicate

    - #### partial2

          @NotNull
          default Predicate1<P1> partial2(P2 argument)

      Get a partially applied predicate using a fix second argument. This is the same as `partialRight(Object)` but more consistently named.
      Parameters:
        `argument` - value applied for second argument
      Returns:
        partially evaluated predicate

    - #### reverseOrder

          @NotNull
          default Predicate2<P2,P1> reverseOrder()

      Get a two argument predicate which expects the arguments in reverse order.
      Returns:
        predicate with reversed order of arguments

    - #### from

          @NotNull
          static <T1,T2> Predicate2<T1,T2> from(@NotNull
                                                         java.util.function.BiPredicate<T1,T2> bipred)

      Make a standard `BiPredicate` usable as a `Predicate2`.
      Type Parameters:
        `T1` - type of first argument
        `T2` - type of second argument
      Parameters:
        `bipred` - bipredicate
      Returns:
        `Predicate2` view of the given bipredicatge

    - #### alwaysTrue

          @NotNull
          static <T1,T2> Predicate2<T1,T2> alwaysTrue()

      Get a predicate which always evaluates to `true`.
      Specified by:
        `alwaysTrue` in interface `Predicate1<ITuple2<? extends P1,? extends P2>>`
      Type Parameters:
        `T1` - type of first predicate parameter
        `T2` - type of second predicate parameter
      Returns:
        predicate always returning `true`

    - #### alwaysFalse

          @NotNull
          static <T1,T2> Predicate2<T1,T2> alwaysFalse()

      Get a predicate which always evaluates to `false`.
      Specified by:
        `alwaysFalse` in interface `Predicate1<ITuple2<? extends P1,? extends P2>>`
      Type Parameters:
        `T1` - type of first predicate parameter
        `T2` - type of second predicate parameter
      Returns:
        predicate always returning `false`

    - #### isEqual

          @NotNull
          static <T> Predicate2<T,T> isEqual()

      Get a predicate which compares 2 objects for deep equality.

      This internally uses `Objects.deepEquals(Object, Object)` for the equality test.

      Type Parameters:
        `T` - object type
      Returns:
        predicate for deep equality

    - #### areIdentical

          @NotNull
          static <T> Predicate2<T,T> areIdentical()

      Get a predicate which checks whether 2 objects represent the same object.
      Type Parameters:
        `T` - object type
      Returns:
        predicate for checking whether 2 objects represent the same object

    - #### and

          @NotNull
          static <T1,T2> Predicate2<T1,T2> and(@NotNull
                                                        java.util.function.BiPredicate<? super T1,? super T2> pred1,
                                                        @NotNull
                                                        java.util.function.BiPredicate<? super T1,? super T2> pred2)

      Get a predicate which is the combination of two predicates with a logical and.

      The result will use shortcut evaluation, so if this predicate already returns `false` the other one is not evaluated.

      Type Parameters:
        `T1` - resulting type of first argument, which is the most extending type of both `pred1`'s first argument type and `pred2`'s first argument type, so if neither type is extending the other this method will not compile
        `T2` - resulting type of second argument, see `<T1>` for the fine print
      Parameters:
        `pred1` - first predicate
        `pred2` - second predicate
      Returns:
        combination of both predicates with logical and
      See Also:
        `and(BiPredicate)`

    - #### or

          @NotNull
          static <T1,T2> Predicate2<T1,T2> or(@NotNull
                                                       java.util.function.BiPredicate<? super T1,? super T2> pred1,
                                                       @NotNull
                                                       java.util.function.BiPredicate<? super T1,? super T2> pred2)

      Get a predicate which is the combination of two predicates with a logical or.

      The result will use shortcut evaluation, so if this predicate already returns `true` the other one is not evaluated.

      Type Parameters:
        `T1` - resulting type of first argument, which is the most extending type of both `pred1`'s first argument type and `pred2`'s first argument type, so if neither type is extending the other this method will not compile
        `T2` - resulting type of second argument, see `<T1>` for the fine print
      Parameters:
        `pred1` - first predicate
        `pred2` - second predicate
      Returns:
        combination of both predicates with logical or
      See Also:
        `or(BiPredicate)`

    - #### xor

          @NotNull
          static <T1,T2> Predicate2<T1,T2> xor(@NotNull
                                                        java.util.function.BiPredicate<? super T1,? super T2> pred1,
                                                        @NotNull
                                                        java.util.function.BiPredicate<? super T1,? super T2> pred2)

      Get a predicate which is the combination of two predicates with a logical exclusive or.

      The result will use shortcut evaluation, so if this predicate already returns `true` the other one is not evaluated.

      Type Parameters:
        `T1` - resulting type of first argument, which is the most extending type of both `pred1`'s first argument type and `pred2`'s first argument type, so if neither type is extending the other this method will not compile
        `T2` - resulting type of second argument, see `<T1>` for the fine print
      Parameters:
        `pred1` - first predicate
        `pred2` - second predicate
      Returns:
        combination of both predicates with logical exclusive or
      See Also:
        `xor(BiPredicate)`

    - #### after1

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP> Predicate1<FP> after1(@NotNull
                                                                                                    java.util.function.Function<FP,FR> before)

      Get a chained predicate which first applies the given function, then this predicate. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this predicate.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP` - function `before`'s parameter type, same for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of function and this predicate

    - #### after2

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2> Predicate2<FP1,FP2> after2(@NotNull
                                                                                                              java.util.function.BiFunction<FP1,FP2,FR> before)

      Get a chained predicate which first applies the given 2-parameter function, then this predicate. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this predicate.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, same for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate

    - #### after3

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3> Predicate3<FP1,FP2,FP3> after3(@NotNull
                                                                                                                      Function3<FR,FP1,FP2,FP3> before)

      Get a chained predicate which first applies the given 3-parameter function, then this predicate. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this predicate.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, sane for returned predicate
        `FP3` - function `before`'s third parameter type, sane for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate

    - #### after5

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5> Predicate5<FP1,FP2,FP3,FP4,FP5> after5(@NotNull
                                                                                                                                      Function5<FR,FP1,FP2,FP3,FP4,FP5> before)

      Get a chained predicate which first applies the given 5-parameter function, then this predicate. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this function.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, sane for returned predicate
        `FP3` - function `before`'s third parameter type, sane for returned predicate
        `FP4` - function `before`'s fourth parameter type, sane for returned predicate
        `FP5` - function `before`'s fifth parameter type, sane for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate

    - #### after6

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6> Predicate6<FP1,FP2,FP3,FP4,FP5,FP6> after6(@NotNull
                                                                                                                                              Function6<FR,FP1,FP2,FP3,FP4,FP5,FP6> before)

      Get a chained predicate which first applies the given 6-parameter function, then this predicate. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this function.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, sane for returned predicate
        `FP3` - function `before`'s third parameter type, sane for returned predicate
        `FP4` - function `before`'s fourth parameter type, sane for returned predicate
        `FP5` - function `before`'s fifth parameter type, sane for returned predicate
        `FP6` - function `before`'s sixth parameter type, sane for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate

    - #### after7

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6,FP7> Predicate7<FP1,FP2,FP3,FP4,FP5,FP6,FP7> after7(@NotNull
                                                                                                                                                      Function7<FR,FP1,FP2,FP3,FP4,FP5,FP6,FP7> before)

      Get a chained predicate which first applies the given 7-parameter function, then this one. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this predicate.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, sane for returned predicate
        `FP3` - function `before`'s third parameter type, sane for returned predicate
        `FP4` - function `before`'s fourth parameter type, sane for returned predicate
        `FP5` - function `before`'s fifth parameter type, sane for returned predicate
        `FP6` - function `before`'s sixth parameter type, sane for returned predicate
        `FP7` - function `before`'s seventh parameter type, sane for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate

    - #### after8

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8> Predicate8<FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8> after8(@NotNull
                                                                                                                                                              Function8<FR,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8> before)

      Get a chained predicate which first applies the given 8-parameter function, then this one. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this predicate.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, sane for returned predicate
        `FP3` - function `before`'s third parameter type, sane for returned predicate
        `FP4` - function `before`'s fourth parameter type, sane for returned predicate
        `FP5` - function `before`'s fifth parameter type, sane for returned predicate
        `FP6` - function `before`'s sixth parameter type, sane for returned predicate
        `FP7` - function `before`'s seventh parameter type, sane for returned predicate
        `FP8` - function `before`'s seventh parameter type, sane for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate

    - #### after9

          @NotNull
          default <FR extends ITuple2<? extends P1,? extends P2>,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8,FP9> Predicate9<FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8,FP9> after9(@NotNull
                                                                                                                                                                      Function9<FR,FP1,FP2,FP3,FP4,FP5,FP6,FP7,FP8,FP9> before)

      Get a chained predicate which first applies the given 9-parameter function, then this one. The given function has to return a `ITuple2` with matching parametric types which are applied in their order to this predicate.
      Type Parameters:
        `FR` - function `before`'s return type, has to be a 2-tuple with matching types
        `FP1` - function `before`'s first parameter type, sane for returned predicate
        `FP2` - function `before`'s second parameter type, sane for returned predicate
        `FP3` - function `before`'s third parameter type, sane for returned predicate
        `FP4` - function `before`'s fourth parameter type, sane for returned predicate
        `FP5` - function `before`'s fifth parameter type, sane for returned predicate
        `FP6` - function `before`'s sixth parameter type, sane for returned predicate
        `FP7` - function `before`'s seventh parameter type, sane for returned predicate
        `FP8` - function `before`'s seventh parameter type, sane for returned predicate
        `FP9` - function `before`'s ninth parameter type, sane for returned predicate
      Parameters:
        `before` - function to apply first, has to return a non-`null` result so unpacking the parameters from the tuple is possible
      Returns:
        chain of the given function and this predicate