You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2020/06/14 23:27:28 UTC

[commons-lang] branch master updated: [LANG-1568] More failable functional interfaces to match JRE functional interfaces.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new 7f90306  [LANG-1568] More failable functional interfaces to match JRE functional interfaces.
7f90306 is described below

commit 7f90306f909e6dba46be275c0f492c8de353b492
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Jun 14 19:27:23 2020 -0400

    [LANG-1568] More failable functional interfaces to match JRE functional
    interfaces.
---
 .../java/org/apache/commons/lang3/Functions.java   |  476 +++++-
 .../org/apache/commons/lang3/FunctionsTest.java    | 1562 +++++++++++++++++---
 2 files changed, 1798 insertions(+), 240 deletions(-)

diff --git a/src/main/java/org/apache/commons/lang3/Functions.java b/src/main/java/org/apache/commons/lang3/Functions.java
index 0f701f4..0eeef44 100644
--- a/src/main/java/org/apache/commons/lang3/Functions.java
+++ b/src/main/java/org/apache/commons/lang3/Functions.java
@@ -27,18 +27,36 @@ import java.util.function.BiFunction;
 import java.util.function.BiPredicate;
 import java.util.function.BooleanSupplier;
 import java.util.function.Consumer;
+import java.util.function.DoubleBinaryOperator;
 import java.util.function.DoubleConsumer;
+import java.util.function.DoubleFunction;
 import java.util.function.DoubleSupplier;
+import java.util.function.DoubleToIntFunction;
+import java.util.function.DoubleToLongFunction;
 import java.util.function.Function;
+import java.util.function.IntBinaryOperator;
 import java.util.function.IntConsumer;
+import java.util.function.IntFunction;
 import java.util.function.IntSupplier;
+import java.util.function.IntToDoubleFunction;
+import java.util.function.IntToLongFunction;
+import java.util.function.LongBinaryOperator;
 import java.util.function.LongConsumer;
+import java.util.function.LongFunction;
 import java.util.function.LongSupplier;
+import java.util.function.LongToDoubleFunction;
+import java.util.function.LongToIntFunction;
 import java.util.function.ObjDoubleConsumer;
 import java.util.function.ObjIntConsumer;
 import java.util.function.ObjLongConsumer;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
+import java.util.function.ToDoubleBiFunction;
+import java.util.function.ToDoubleFunction;
+import java.util.function.ToIntBiFunction;
+import java.util.function.ToIntFunction;
+import java.util.function.ToLongBiFunction;
+import java.util.function.ToLongFunction;
 import java.util.stream.Stream;
 
 import org.apache.commons.lang3.Streams.FailableStream;
@@ -79,7 +97,7 @@ import org.apache.commons.lang3.Streams.FailableStream;
 public class Functions {
 
     /**
-     * A functional interface like {@link BiConsumer} that declares a Throwable.
+     * A functional interface like {@link BiConsumer} that declares a {@code Throwable}.
      *
      * @param <O1> Consumed type 1.
      * @param <O2> Consumed type 2.
@@ -99,15 +117,15 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link BiFunction} that declares a Throwable.
+     * A functional interface like {@link BiFunction} that declares a {@code Throwable}.
      *
-     * @param <I1> Input type 1.
-     * @param <I2> Input type 2.
+     * @param <O1> Input type 1.
+     * @param <O2> Input type 2.
      * @param <R> Return type.
      * @param <T> Thrown exception.
      */
     @FunctionalInterface
-    public interface FailableBiFunction<I1, I2, R, T extends Throwable> {
+    public interface FailableBiFunction<O1, O2, R, T extends Throwable> {
 
         /**
          * Applies this function.
@@ -115,20 +133,20 @@ public class Functions {
          * @param input1 the first input for the function
          * @param input2 the second input for the function
          * @return the result of the function
-         * @throws T if the function fails
+         * @throws T Thrown when the function fails.
          */
-        R apply(I1 input1, I2 input2) throws T;
+        R apply(O1 input1, O2 input2) throws T;
     }
 
     /**
-     * A functional interface like {@link BiPredicate} that declares a Throwable.
+     * A functional interface like {@link BiPredicate} that declares a {@code Throwable}.
      *
-     * @param <I1> Predicate type 1.
-     * @param <I2> Predicate type 2.
+     * @param <O1> Predicate type 1.
+     * @param <O2> Predicate type 2.
      * @param <T> Thrown exception.
      */
     @FunctionalInterface
-    public interface FailableBiPredicate<I1, I2, T extends Throwable> {
+    public interface FailableBiPredicate<O1, O2, T extends Throwable> {
 
         /**
          * Tests the predicate.
@@ -138,11 +156,11 @@ public class Functions {
          * @return the predicate's evaluation
          * @throws T if the predicate fails
          */
-        boolean test(I1 object1, I2 object2) throws T;
+        boolean test(O1 object1, O2 object2) throws T;
     }
 
     /**
-     * A functional interface like {@link BooleanSupplier} that declares a Throwable.
+     * A functional interface like {@link BooleanSupplier} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -160,7 +178,7 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link java.util.concurrent.Callable} that declares a Throwable.
+     * A functional interface like {@link java.util.concurrent.Callable} that declares a {@code Throwable}.
      *
      * @param <R> Return type.
      * @param <T> Thrown exception.
@@ -178,7 +196,7 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link Consumer} that declares a Throwable.
+     * A functional interface like {@link Consumer} that declares a {@code Throwable}.
      *
      * @param <O> Consumed type 1.
      * @param <T> Thrown exception.
@@ -196,7 +214,27 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link DoubleConsumer} that declares a Throwable.
+     * A functional interface like {@link DoubleBinaryOperator} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableDoubleBinaryOperator<T extends Throwable> {
+
+        /**
+         * Applies this operator to the given operands.
+         *
+         * @param left the first operand
+         * @param right the second operand
+         * @return the operator result
+         * @throws T if the operation fails
+         */
+        double applyAsDouble(double left, double right) throws T;
+    }
+
+    /**
+     * A functional interface like {@link DoubleConsumer} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -214,7 +252,26 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link DoubleSupplier} that declares a Throwable.
+     * A functional interface like {@link DoubleFunction} that declares a {@code Throwable}.
+     *
+     * @param <R> Return type.
+     * @param <T> Thrown exception.
+     */
+    @FunctionalInterface
+    public interface FailableDoubleFunction<R, T extends Throwable> {
+
+        /**
+         * Applies this function.
+         *
+         * @param input the input for the function
+         * @return the result of the function
+         * @throws T Thrown when the function fails.
+         */
+        R apply(double input) throws T;
+    }
+
+    /**
+     * A functional interface like {@link DoubleSupplier} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -232,7 +289,45 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link Function} that declares a Throwable.
+     * A functional interface like {@link DoubleToIntFunction} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableDoubleToIntFunction<T extends Throwable> {
+
+        /**
+         * Applies this function to the given argument.
+         *
+         * @param value the function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        int applyAsInt(double value) throws T;
+    }
+
+    /**
+     * A functional interface like {@link DoubleToLongFunction} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableDoubleToLongFunction<T extends Throwable> {
+
+        /**
+         * Applies this function to the given argument.
+         *
+         * @param value the function argument
+         * @return the function result
+         * @throws T if the operation fails
+         */
+        int applyAsLong(double value) throws T;
+    }
+
+    /**
+     * A functional interface like {@link Function} that declares a {@code Throwable}.
      *
      * @param <I> Input type 1.
      * @param <R> Return type.
@@ -246,13 +341,33 @@ public class Functions {
          *
          * @param input the input for the function
          * @return the result of the function
-         * @throws T if the function fails
+         * @throws T Thrown when the function fails.
          */
         R apply(I input) throws T;
     }
 
     /**
-     * A functional interface like {@link IntConsumer} that declares a Throwable.
+     * A functional interface like {@link IntBinaryOperator} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableIntBinaryOperator<T extends Throwable> {
+
+        /**
+         * Applies this operator to the given operands.
+         *
+         * @param left the first operand
+         * @param right the second operand
+         * @return the operator result
+         * @throws T if the operation fails
+         */
+        int applyAsInt(int left, int right) throws T;
+    }
+
+    /**
+     * A functional interface like {@link IntConsumer} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -270,7 +385,26 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link IntSupplier} that declares a Throwable.
+     * A functional interface like {@link IntFunction} that declares a {@code Throwable}.
+     *
+     * @param <R> Return type.
+     * @param <T> Thrown exception.
+     */
+    @FunctionalInterface
+    public interface FailableIntFunction<R, T extends Throwable> {
+
+        /**
+         * Applies this function.
+         *
+         * @param input the input for the function
+         * @return the result of the function
+         * @throws T Thrown when the function fails.
+         */
+        R apply(int input) throws T;
+    }
+
+    /**
+     * A functional interface like {@link IntSupplier} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -288,7 +422,65 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link LongConsumer} that declares a Throwable.
+     * A functional interface like {@link IntToDoubleFunction} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableIntToDoubleFunction<T extends Throwable> {
+
+        /**
+         * Applies this function to the given argument.
+         *
+         * @param value the function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        double applyAsDouble(int value) throws T;
+    }
+
+    /**
+     * A functional interface like {@link IntToLongFunction} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableIntToLongFunction<T extends Throwable> {
+
+        /**
+         * Applies this function to the given argument.
+         *
+         * @param value the function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        long applyAsLong(int value) throws T;
+    }
+
+    /**
+     * A functional interface like {@link LongBinaryOperator} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableLongBinaryOperator<T extends Throwable> {
+
+        /**
+         * Applies this operator to the given operands.
+         *
+         * @param left the first operand
+         * @param right the second operand
+         * @return the operator result
+         * @throws T if the operation fails
+         */
+        long applyAsLong(long left, long right) throws T;
+    }
+
+    /**
+     * A functional interface like {@link LongConsumer} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -306,7 +498,26 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link LongSupplier} that declares a Throwable.
+     * A functional interface like {@link LongFunction} that declares a {@code Throwable}.
+     *
+     * @param <R> Return type.
+     * @param <T> Thrown exception.
+     */
+    @FunctionalInterface
+    public interface FailableLongFunction<R, T extends Throwable> {
+
+        /**
+         * Applies this function.
+         *
+         * @param input the input for the function
+         * @return the result of the function
+         * @throws T Thrown when the function fails.
+         */
+        R apply(long input) throws T;
+    }
+
+    /**
+     * A functional interface like {@link LongSupplier} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      * @since 3.11
@@ -324,7 +535,45 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link ObjDoubleConsumer} that declares a Throwable.
+     * A functional interface like {@link LongToDoubleFunction} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableLongToDoubleFunction<T extends Throwable> {
+
+        /**
+         * Applies this function to the given argument.
+         *
+         * @param value the function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        double applyAsDouble(long value) throws T;
+    }
+
+    /**
+     * A functional interface like {@link LongToIntFunction} that declares a {@code Throwable}.
+     *
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableLongToIntFunction<T extends Throwable> {
+
+        /**
+         * Applies this function to the given argument.
+         *
+         * @param value the function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        int applyAsInt(long value) throws T;
+    }
+
+    /**
+     * A functional interface like {@link ObjDoubleConsumer} that declares a {@code Throwable}.
      *
      * @param <O> the type of the object argument to the operation.
      * @param <T> Thrown exception.
@@ -344,7 +593,7 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link ObjIntConsumer} that declares a Throwable.
+     * A functional interface like {@link ObjIntConsumer} that declares a {@code Throwable}.
      *
      * @param <O> the type of the object argument to the operation.
      * @param <T> Thrown exception.
@@ -364,7 +613,7 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link ObjLongConsumer} that declares a Throwable.
+     * A functional interface like {@link ObjLongConsumer} that declares a {@code Throwable}.
      *
      * @param <O> the type of the object argument to the operation.
      * @param <T> Thrown exception.
@@ -384,7 +633,7 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link Predicate} that declares a Throwable.
+     * A functional interface like {@link Predicate} that declares a {@code Throwable}.
      *
      * @param <I> Predicate type 1.
      * @param <T> Thrown exception.
@@ -403,7 +652,7 @@ public class Functions {
     }
 
     /**
-     * A functional interface like {@link Runnable} that declares a Throwable.
+     * A functional interface like {@link Runnable} that declares a {@code Throwable}.
      *
      * @param <T> Thrown exception.
      */
@@ -413,13 +662,13 @@ public class Functions {
         /**
          * Runs the function.
          *
-         * @throws T if the function fails
+         * @throws T Thrown when the function fails.
          */
         void run() throws T;
     }
 
     /**
-     * A functional interface like {@link Supplier} that declares a Throwable.
+     * A functional interface like {@link Supplier} that declares a {@code Throwable}.
      *
      * @param <R> Return type.
      * @param <T> Thrown exception.
@@ -437,6 +686,132 @@ public class Functions {
     }
 
     /**
+     * A functional interface like {@link ToDoubleBiFunction} that declares a {@code Throwable}.
+     *
+     * @param <O1> the type of the first argument to the function
+     * @param <O2> the type of the second argument to the function
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableToDoubleBiFunction<O1, O2, T extends Throwable> {
+
+        /**
+         * Applies this function to the given arguments.
+         *
+         * @param t the first function argument
+         * @param u the second function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        double applyAsDouble(O1 t, O2 u) throws T;
+    }
+
+    /**
+     * A functional interface like {@link ToDoubleFunction} that declares a {@code Throwable}.
+     *
+     * @param <I> the type of the first argument to the function
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableToDoubleFunction<I, T extends Throwable> {
+
+        /**
+         * Applies this function to the given arguments.
+         *
+         * @param t the first function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        double applyAsDouble(I t) throws T;
+    }
+
+    /**
+     * A functional interface like {@link ToIntBiFunction} that declares a {@code Throwable}.
+     *
+     * @param <O1> the type of the first argument to the function
+     * @param <O2> the type of the second argument to the function
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableToIntBiFunction<O1, O2, T extends Throwable> {
+
+        /**
+         * Applies this function to the given arguments.
+         *
+         * @param t the first function argument
+         * @param u the second function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        int applyAsInt(O1 t, O2 u) throws T;
+    }
+
+    /**
+     * A functional interface like {@link ToIntFunction} that declares a {@code Throwable}.
+     *
+     * @param <I> the type of the first argument to the function
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableToIntFunction<I, T extends Throwable> {
+
+        /**
+         * Applies this function to the given arguments.
+         *
+         * @param t the first function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        int applyAsInt(I t) throws T;
+    }
+
+    /**
+     * A functional interface like {@link ToLongBiFunction} that declares a {@code Throwable}.
+     *
+     * @param <O1> the type of the first argument to the function
+     * @param <O2> the type of the second argument to the function
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableToLongBiFunction<O1, O2, T extends Throwable> {
+
+        /**
+         * Applies this function to the given arguments.
+         *
+         * @param t the first function argument
+         * @param u the second function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        long applyAsLong(O1 t, O2 u) throws T;
+    }
+
+    /**
+     * A functional interface like {@link ToLongFunction} that declares a {@code Throwable}.
+     *
+     * @param <I> the type of the first argument to the function
+     * @param <T> Thrown exception.
+     * @since 3.11
+     */
+    @FunctionalInterface
+    public interface FailableToLongFunction<I, T extends Throwable> {
+
+        /**
+         * Applies this function to the given arguments.
+         *
+         * @param t the first function argument
+         * @return the function result
+         * @throws T Thrown when the function fails.
+         */
+        long applyAsLong(I t) throws T;
+    }
+
+    /**
      * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
      *
      * @param consumer the consumer to consume
@@ -505,14 +880,14 @@ public class Functions {
      * @param function the function to apply
      * @param input1 the first input to apply {@code function} on
      * @param input2 the second input to apply {@code function} on
-     * @param <I1> the type of the first argument the function accepts
-     * @param <I2> the type of the second argument the function accepts
+     * @param <O1> the type of the first argument the function accepts
+     * @param <O2> the type of the second argument the function accepts
      * @param <O> the return type of the function
      * @param <T> the type of checked exception the function may throw
      * @return the value returned from the function
      */
-    public static <I1, I2, O, T extends Throwable> O apply(final FailableBiFunction<I1, I2, O, T> function,
-        final I1 input1, final I2 input2) {
+    public static <O1, O2, O, T extends Throwable> O apply(final FailableBiFunction<O1, O2, O, T> function,
+        final O1 input1, final O2 input2) {
         return get(() -> function.apply(input1, input2));
     }
 
@@ -531,42 +906,57 @@ public class Functions {
     }
 
     /**
+     * Applies a function and rethrows any exception as a {@link RuntimeException}.
+     *
+     * @param function the function to apply
+     * @param left the first input to apply {@code function} on
+     * @param right the second input to apply {@code function} on
+     * @param <T> the type of checked exception the function may throw
+     * @return the value returned from the function
+     * @since 3.11
+     */
+    public static <T extends Throwable> double applyAsDouble(final FailableDoubleBinaryOperator<T> function,
+        final double left, final double right) {
+        return getAsDouble(() -> function.applyAsDouble(left, right));
+    }
+
+    /**
      * Converts the given {@link FailableBiConsumer} into a standard {@link BiConsumer}.
      *
-     * @param <I1> the type of the first argument of the consumers
-     * @param <I2> the type of the second argument of the consumers
+     * @param <O1> the type of the first argument of the consumers
+     * @param <O2> the type of the second argument of the consumers
      * @param consumer a failable {@code BiConsumer}
      * @return a standard {@code BiConsumer}
      * @since 3.10
      */
-    public static <I1, I2> BiConsumer<I1, I2> asBiConsumer(final FailableBiConsumer<I1, I2, ?> consumer) {
+    public static <O1, O2> BiConsumer<O1, O2> asBiConsumer(final FailableBiConsumer<O1, O2, ?> consumer) {
         return (input1, input2) -> accept(consumer, input1, input2);
     }
 
     /**
      * Converts the given {@link FailableBiFunction} into a standard {@link BiFunction}.
      *
-     * @param <I1> the type of the first argument of the input of the functions
-     * @param <I2> the type of the second argument of the input of the functions
+     * @param <O1> the type of the first argument of the input of the functions
+     * @param <O2> the type of the second argument of the input of the functions
      * @param <O> the type of the output of the functions
      * @param function a {@code FailableBiFunction}
      * @return a standard {@code BiFunction}
      * @since 3.10
      */
-    public static <I1, I2, O> BiFunction<I1, I2, O> asBiFunction(final FailableBiFunction<I1, I2, O, ?> function) {
+    public static <O1, O2, O> BiFunction<O1, O2, O> asBiFunction(final FailableBiFunction<O1, O2, O, ?> function) {
         return (input1, input2) -> apply(function, input1, input2);
     }
 
     /**
      * Converts the given {@link FailableBiPredicate} into a standard {@link BiPredicate}.
      *
-     * @param <I1> the type of the first argument used by the predicates
-     * @param <I2> the type of the second argument used by the predicates
+     * @param <O1> the type of the first argument used by the predicates
+     * @param <O2> the type of the second argument used by the predicates
      * @param predicate a {@code FailableBiPredicate}
      * @return a standard {@code BiPredicate}
      * @since 3.10
      */
-    public static <I1, I2> BiPredicate<I1, I2> asBiPredicate(final FailableBiPredicate<I1, I2, ?> predicate) {
+    public static <O1, O2> BiPredicate<O1, O2> asBiPredicate(final FailableBiPredicate<O1, O2, ?> predicate) {
         return (input1, input2) -> test(predicate, input1, input2);
     }
 
diff --git a/src/test/java/org/apache/commons/lang3/FunctionsTest.java b/src/test/java/org/apache/commons/lang3/FunctionsTest.java
index 043f135..d114224 100644
--- a/src/test/java/org/apache/commons/lang3/FunctionsTest.java
+++ b/src/test/java/org/apache/commons/lang3/FunctionsTest.java
@@ -117,7 +117,8 @@ class FunctionsTest {
 
     public static class Testable<T, P> {
         private T acceptedObject;
-        private P acceptedPrimitiveObject;
+        private P acceptedPrimitiveObject1;
+        private P acceptedPrimitiveObject2;
         private Throwable throwable;
 
         Testable(final Throwable throwable) {
@@ -128,8 +129,12 @@ class FunctionsTest {
             return acceptedObject;
         }
 
-        public P getAcceptedPrimitiveObject() {
-            return acceptedPrimitiveObject;
+        public P getAcceptedPrimitiveObject1() {
+            return acceptedPrimitiveObject1;
+        }
+
+        public P getAcceptedPrimitiveObject2() {
+            return acceptedPrimitiveObject2;
         }
 
         public void setThrowable(final Throwable throwable) {
@@ -140,105 +145,117 @@ class FunctionsTest {
             test(throwable);
         }
 
+        public Object test(Object input1, Object input2) throws Throwable {
+            test(throwable);
+            return acceptedObject;
+        }
+
         public void test(final Throwable throwable) throws Throwable {
             if (throwable != null) {
                 throw throwable;
             }
         }
 
-        public boolean testBooleanPrimitive() throws Throwable {
-            return testBooleanPrimitive(throwable);
+        public boolean testAsBooleanPrimitive() throws Throwable {
+            return testAsBooleanPrimitive(throwable);
         }
 
-        public boolean testBooleanPrimitive(final Throwable throwable) throws Throwable {
+        public boolean testAsBooleanPrimitive(final Throwable throwable) throws Throwable {
             if (throwable != null) {
                 throw throwable;
             }
             return false;
         }
 
-        public void testDouble(double i) throws Throwable {
-            test(throwable);
-            acceptedPrimitiveObject = (P) ((Double) i);
-        }
-
-        public double testDoublePrimitive() throws Throwable {
-            return testDoublePrimitive(throwable);
+        public double testAsDoublePrimitive() throws Throwable {
+            return testAsDoublePrimitive(throwable);
         }
 
-        public double testDoublePrimitive(final Throwable throwable) throws Throwable {
+        public double testAsDoublePrimitive(final Throwable throwable) throws Throwable {
             if (throwable != null) {
                 throw throwable;
             }
             return 0;
         }
 
-        public void testInt(int i) throws Throwable {
-            test(throwable);
-            acceptedPrimitiveObject = (P) ((Integer) i);
+        public Integer testAsInteger() throws Throwable {
+            return testAsInteger(throwable);
+        }
+
+        public Integer testAsInteger(final Throwable throwable) throws Throwable {
+            if (throwable != null) {
+                throw throwable;
+            }
+            return 0;
         }
 
-        public Integer testInteger() throws Throwable {
-            return testInteger(throwable);
+        public int testAsIntPrimitive() throws Throwable {
+            return testAsIntPrimitive(throwable);
         }
 
-        public Integer testInteger(final Throwable throwable) throws Throwable {
+        public int testAsIntPrimitive(final Throwable throwable) throws Throwable {
             if (throwable != null) {
                 throw throwable;
             }
             return 0;
         }
 
-        public int testIntPrimitive() throws Throwable {
-            return testIntPrimitive(throwable);
+        public long testAsLongPrimitive() throws Throwable {
+            return testAsLongPrimitive(throwable);
         }
 
-        public int testIntPrimitive(final Throwable throwable) throws Throwable {
+        public long testAsLongPrimitive(final Throwable throwable) throws Throwable {
             if (throwable != null) {
                 throw throwable;
             }
             return 0;
         }
 
-        public void testLong(long i) throws Throwable {
+        public void testDouble(double i) throws Throwable {
             test(throwable);
-            acceptedPrimitiveObject = (P) ((Long) i);
+            acceptedPrimitiveObject1 = (P) ((Double) i);
         }
 
-        public long testLongPrimitive() throws Throwable {
-            return testLongPrimitive(throwable);
+        public double testDoubleDouble(double i, double j) throws Throwable {
+            test(throwable);
+            acceptedPrimitiveObject1 = (P) ((Double) i);
+            acceptedPrimitiveObject2 = (P) ((Double) j);
+            return 3d;
         }
 
-        public long testLongPrimitive(final Throwable throwable) throws Throwable {
-            if (throwable != null) {
-                throw throwable;
-            }
-            return 0;
+        public void testInt(int i) throws Throwable {
+            test(throwable);
+            acceptedPrimitiveObject1 = (P) ((Integer) i);
+        }
+
+        public void testLong(long i) throws Throwable {
+            test(throwable);
+            acceptedPrimitiveObject1 = (P) ((Long) i);
         }
 
         public void testObjDouble(T object, double i) throws Throwable {
             test(throwable);
             acceptedObject = object;
-            acceptedPrimitiveObject = (P) ((Double) i);
+            acceptedPrimitiveObject1 = (P) ((Double) i);
         }
 
         public void testObjInt(T object, int i) throws Throwable {
             test(throwable);
             acceptedObject = object;
-            acceptedPrimitiveObject = (P) ((Integer) i);
+            acceptedPrimitiveObject1 = (P) ((Integer) i);
         }
 
         public void testObjLong(T object, long i) throws Throwable {
             test(throwable);
             acceptedObject = object;
-            acceptedPrimitiveObject = (P) ((Long) i);
+            acceptedPrimitiveObject1 = (P) ((Long) i);
         }
     }
 
     @Test
     void testAcceptBiConsumer() {
         final IllegalStateException ise = new IllegalStateException();
-        final Testable<?, ?> testable = new Testable(null);
+        final Testable<?, ?> testable = new Testable<>(null);
         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(Testable::test, testable, ise));
         assertSame(ise, e);
 
@@ -286,13 +303,13 @@ class FunctionsTest {
         final Testable<?, Double> testable = new Testable<>(ise);
         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testDouble, 1d));
         assertSame(ise, e);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testDouble, 1d));
         assertSame(error, e);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
@@ -300,11 +317,11 @@ class FunctionsTest {
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         testable.setThrowable(null);
         Functions.accept(testable::testDouble, 1d);
-        assertEquals(1, testable.getAcceptedPrimitiveObject());
+        assertEquals(1, testable.getAcceptedPrimitiveObject1());
     }
 
     @Test
@@ -313,13 +330,13 @@ class FunctionsTest {
         final Testable<?, Integer> testable = new Testable<>(ise);
         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testInt, 1));
         assertSame(ise, e);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testInt, 1));
         assertSame(error, e);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
@@ -327,11 +344,11 @@ class FunctionsTest {
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         testable.setThrowable(null);
         Functions.accept(testable::testInt, 1);
-        assertEquals(1, testable.getAcceptedPrimitiveObject());
+        assertEquals(1, testable.getAcceptedPrimitiveObject1());
     }
 
     @Test
@@ -340,13 +357,13 @@ class FunctionsTest {
         final Testable<?, Long> testable = new Testable<>(ise);
         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testLong, 1L));
         assertSame(ise, e);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testLong, 1L));
         assertSame(error, e);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
@@ -354,28 +371,29 @@ class FunctionsTest {
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         testable.setThrowable(null);
         Functions.accept(testable::testLong, 1L);
-        assertEquals(1, testable.getAcceptedPrimitiveObject());
+        assertEquals(1, testable.getAcceptedPrimitiveObject1());
     }
 
     @Test
     void testAcceptObjDoubleConsumer() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<String, Double> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjDouble, "X", 1d));
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.accept(testable::testObjDouble, "X", 1d));
         assertSame(ise, e);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjDouble, "X", 1d));
         assertSame(error, e);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
@@ -384,12 +402,12 @@ class FunctionsTest {
         assertNotNull(t);
         assertSame(ioe, t);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         testable.setThrowable(null);
         Functions.accept(testable::testObjDouble, "X", 1d);
         assertEquals("X", testable.getAcceptedObject());
-        assertEquals(1d, testable.getAcceptedPrimitiveObject());
+        assertEquals(1d, testable.getAcceptedPrimitiveObject1());
     }
 
     @Test
@@ -399,14 +417,14 @@ class FunctionsTest {
         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjInt, "X", 1));
         assertSame(ise, e);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjInt, "X", 1));
         assertSame(error, e);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
@@ -415,12 +433,12 @@ class FunctionsTest {
         assertNotNull(t);
         assertSame(ioe, t);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         testable.setThrowable(null);
         Functions.accept(testable::testObjInt, "X", 1);
         assertEquals("X", testable.getAcceptedObject());
-        assertEquals(1, testable.getAcceptedPrimitiveObject());
+        assertEquals(1, testable.getAcceptedPrimitiveObject1());
     }
 
     @Test
@@ -430,14 +448,14 @@ class FunctionsTest {
         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjLong, "X", 1L));
         assertSame(ise, e);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjLong, "X", 1L));
         assertSame(error, e);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
@@ -446,244 +464,221 @@ class FunctionsTest {
         assertNotNull(t);
         assertSame(ioe, t);
         assertNull(testable.getAcceptedObject());
-        assertNull(testable.getAcceptedPrimitiveObject());
+        assertNull(testable.getAcceptedPrimitiveObject1());
 
         testable.setThrowable(null);
         Functions.accept(testable::testObjLong, "X", 1L);
         assertEquals("X", testable.getAcceptedObject());
-        assertEquals(1L, testable.getAcceptedPrimitiveObject());
+        assertEquals(1L, testable.getAcceptedPrimitiveObject1());
     }
 
     @Test
     public void testApplyBiFunction() {
         final IllegalStateException ise = new IllegalStateException();
-        final Testable<?, ?> testable = new Testable(null);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.apply(Testable::testInteger, testable, ise));
+        final Testable<?, ?> testable = new Testable<>(null);
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.apply(Testable::testAsInteger, testable, ise));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testInteger, testable, error));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testAsInteger, testable, error));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
-        e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testInteger, testable, ioe));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testAsInteger, testable, ioe));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
-        final Integer i = Functions.apply(Testable::testInteger, testable, (Throwable) null);
+        final Integer i = Functions.apply(Testable::testAsInteger, testable, (Throwable) null);
         assertNotNull(i);
         assertEquals(0, i.intValue());
     }
 
     @Test
+    public void testApplyDoubleBinaryOperator() {
+        final IllegalStateException ise = new IllegalStateException();
+        final Testable<?, Double> testable = new Testable<>(ise);
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.applyAsDouble(testable::testDoubleDouble, 1d, 2d));
+        assertSame(ise, e);
+
+        final Testable<?, Double> testable2 = new Testable<>(null);
+        final double i = Functions.applyAsDouble(testable2::testDoubleDouble, 1d, 2d);
+        assertEquals(3d, i);
+    }
+
+    @Test
     public void testApplyFunction() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.apply(Testable::testInteger, testable));
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.apply(Testable::testAsInteger, testable));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testInteger, testable));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testAsInteger, testable));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testInteger, testable));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testAsInteger, testable));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
         testable.setThrowable(null);
-        final Integer i = Functions.apply(Testable::testInteger, testable);
+        final Integer i = Functions.apply(Testable::testAsInteger, testable);
         assertNotNull(i);
         assertEquals(0, i.intValue());
     }
 
     @Test
-    void testAsBiConsumer() {
-        final IllegalStateException ise = new IllegalStateException();
-        final Testable<?, ?> testable = new Testable(null);
-        final FailableBiConsumer<Testable, Throwable, Throwable> failableBiConsumer = (t, th) -> {
-            t.setThrowable(th); t.test();
-        };
-        final BiConsumer<Testable, Throwable> consumer = Functions.asBiConsumer(failableBiConsumer);
-        Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable, ise));
-        assertSame(ise, e);
-
-        final Error error = new OutOfMemoryError();
-        e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, error));
-        assertSame(error, e);
-
-        final IOException ioe = new IOException("Unknown I/O error");
-        testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable,  ioe));
-        final Throwable t = e.getCause();
-        assertNotNull(t);
-        assertSame(ioe, t);
-
-        consumer.accept(testable, null);
+    void testAsCallable() {
+        FailureOnOddInvocations.invocations = 0;
+        final FailableCallable<FailureOnOddInvocations, SomeException> failableCallable = FailureOnOddInvocations::new;
+        final Callable<FailureOnOddInvocations> callable = Functions.asCallable(failableCallable);
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, callable::call);
+        final Throwable cause = e.getCause();
+        assertNotNull(cause);
+        assertTrue(cause instanceof SomeException);
+        assertEquals("Odd Invocation: 1", cause.getMessage());
+        final FailureOnOddInvocations instance;
+        try {
+            instance = callable.call();
+        } catch (final Exception ex) {
+            throw Functions.rethrow(ex);
+        }
+        assertNotNull(instance);
     }
 
     @Test
-    public void testAsBiFunction() {
+    void testAsConsumer() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        final FailableBiFunction<Testable, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> {
-            t.setThrowable(th);
-            return Integer.valueOf(t.testInteger());
-        };
-        final BiFunction<Testable, Throwable, Integer> biFunction = Functions.asBiFunction(failableBiFunction);
-        Throwable e = assertThrows(IllegalStateException.class, () -> biFunction.apply(testable, ise));
+        final Consumer<Testable<?, ?>> consumer = Functions.asConsumer(Testable::test);
+        Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, error));
+        e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> biFunction.apply(testable, ioe));
+        e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
-        assertEquals(0, biFunction.apply(testable, null).intValue());
+        testable.setThrowable(null);
+        Functions.accept(Testable::test, testable);
     }
 
     @Test
-    @DisplayName("Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate ")
-    public void testAsBiPredicate() {
+    void testAsRunnable() {
         FailureOnOddInvocations.invocations = 0;
-        final Functions.FailableBiPredicate<Object, Object, Throwable> failableBiPredicate = (t1, t2) -> FailureOnOddInvocations.failingBool();
-        final BiPredicate<?, ?> predicate = Functions.asBiPredicate(failableBiPredicate);
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () -> predicate.test(null, null));
+        final Runnable runnable = Functions.asRunnable(FailureOnOddInvocations::new);
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, runnable::run);
         final Throwable cause = e.getCause();
         assertNotNull(cause);
         assertTrue(cause instanceof SomeException);
         assertEquals("Odd Invocation: 1", cause.getMessage());
-        final boolean instance = predicate.test(null, null);
-        assertNotNull(instance);
+
+        // Even invocations, should not throw an exception
+        runnable.run();
     }
 
     @Test
-    void testAsCallable() {
+    public void testAsSupplier() {
         FailureOnOddInvocations.invocations = 0;
-        final FailableCallable<FailureOnOddInvocations, SomeException> failableCallable = FailureOnOddInvocations::new;
-        final Callable<FailureOnOddInvocations> callable = Functions.asCallable(failableCallable);
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, callable::call);
+        final FailableSupplier<FailureOnOddInvocations, Throwable> failableSupplier = FailureOnOddInvocations::new;
+        final Supplier<FailureOnOddInvocations> supplier = Functions.asSupplier(failableSupplier);
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, supplier::get);
         final Throwable cause = e.getCause();
         assertNotNull(cause);
         assertTrue(cause instanceof SomeException);
         assertEquals("Odd Invocation: 1", cause.getMessage());
-        final FailureOnOddInvocations instance;
-        try {
-            instance = callable.call();
-        } catch (final Exception ex) {
-            throw Functions.rethrow(ex);
-        }
-        assertNotNull(instance);
+        assertNotNull(supplier.get());
     }
 
     @Test
-    void testAsConsumer() {
+    void testBiConsumer() {
         final IllegalStateException ise = new IllegalStateException();
-        final Testable<?, ?> testable = new Testable<>(ise);
-        final Consumer<Testable> consumer = Functions.asConsumer(Testable::test);
-        Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable));
+        final Testable<?, ?> testable = new Testable<>(null);
+        final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failableBiConsumer = (t, th) -> {
+            t.setThrowable(th);
+            t.test();
+        };
+        final BiConsumer<Testable<?, ?>, Throwable> consumer = Functions.asBiConsumer(failableBiConsumer);
+        Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable, ise));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
-        testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable));
+        e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, error));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable));
+        e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable, ioe));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
-        testable.setThrowable(null);
-        Functions.accept(Testable::test, testable);
+        consumer.accept(testable, null);
     }
 
     @Test
-    public void testAsFunction() {
+    public void testBiFunction() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        final FailableFunction<Throwable, Integer, Throwable> failableFunction = th -> {
-            testable.setThrowable(th);
-            return Integer.valueOf(testable.testInteger());
+        final FailableBiFunction<Testable<?, ?>, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> {
+            t.setThrowable(th);
+            return Integer.valueOf(t.testAsInteger());
         };
-        final Function<Throwable, Integer> function = Functions.asFunction(failableFunction);
-        Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ise));
+        final BiFunction<Testable<?, ?>, Throwable, Integer> biFunction = Functions.asBiFunction(failableBiFunction);
+        Throwable e = assertThrows(IllegalStateException.class, () -> biFunction.apply(testable, ise));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> function.apply(error));
+        e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, error));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> function.apply(ioe));
+        e = assertThrows(UncheckedIOException.class, () -> biFunction.apply(testable, ioe));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
-        assertEquals(0, function.apply(null).intValue());
+        assertEquals(0, biFunction.apply(testable, null).intValue());
     }
 
     @Test
-    @DisplayName("Test that asPredicate(FailablePredicate) is converted to -> Predicate ")
-    public void testAsPredicate() {
+    @DisplayName("Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate ")
+    public void testBiPredicate() {
         FailureOnOddInvocations.invocations = 0;
-        final Functions.FailablePredicate<Object, Throwable> failablePredicate = t -> FailureOnOddInvocations.failingBool();
-        final Predicate<?> predicate = Functions.asPredicate(failablePredicate);
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () -> predicate.test(null));
+        final Functions.FailableBiPredicate<Object, Object, Throwable> failableBiPredicate = (t1,
+            t2) -> FailureOnOddInvocations.failingBool();
+        final BiPredicate<?, ?> predicate = Functions.asBiPredicate(failableBiPredicate);
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
+            () -> predicate.test(null, null));
         final Throwable cause = e.getCause();
         assertNotNull(cause);
         assertTrue(cause instanceof SomeException);
         assertEquals("Odd Invocation: 1", cause.getMessage());
-        final boolean instance = predicate.test(null);
+        final boolean instance = predicate.test(null, null);
         assertNotNull(instance);
     }
 
     @Test
-    void testAsRunnable() {
-        FailureOnOddInvocations.invocations = 0;
-        final Runnable runnable = Functions.asRunnable(FailureOnOddInvocations::new);
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, runnable::run);
-        final Throwable cause = e.getCause();
-        assertNotNull(cause);
-        assertTrue(cause instanceof SomeException);
-        assertEquals("Odd Invocation: 1", cause.getMessage());
-
-        // Even invocations, should not throw an exception
-        runnable.run();
-    }
-
-    @Test
-    public void testAsSupplier() {
-        FailureOnOddInvocations.invocations = 0;
-        final FailableSupplier<FailureOnOddInvocations, Throwable> failableSupplier = FailureOnOddInvocations::new;
-        final Supplier<FailureOnOddInvocations> supplier = Functions.asSupplier(failableSupplier);
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, supplier::get);
-        final Throwable cause = e.getCause();
-        assertNotNull(cause);
-        assertTrue(cause instanceof SomeException);
-        assertEquals("Odd Invocation: 1", cause.getMessage());
-        assertNotNull(supplier.get());
-    }
-
-    @Test
     void testCallable() {
         FailureOnOddInvocations.invocations = 0;
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () ->  Functions.run(FailureOnOddInvocations::new));
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
+            () -> Functions.run(FailureOnOddInvocations::new));
         final Throwable cause = e.getCause();
         assertNotNull(cause);
         assertTrue(cause instanceof SomeException);
@@ -699,72 +694,101 @@ class FunctionsTest {
     }
 
     @Test
+    public void testFunction() {
+        final IllegalStateException ise = new IllegalStateException();
+        final Testable<?, ?> testable = new Testable<>(ise);
+        final FailableFunction<Throwable, Integer, Throwable> failableFunction = th -> {
+            testable.setThrowable(th);
+            return Integer.valueOf(testable.testAsInteger());
+        };
+        final Function<Throwable, Integer> function = Functions.asFunction(failableFunction);
+        Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ise));
+        assertSame(ise, e);
+
+        final Error error = new OutOfMemoryError();
+        testable.setThrowable(error);
+        e = assertThrows(OutOfMemoryError.class, () -> function.apply(error));
+        assertSame(error, e);
+
+        final IOException ioe = new IOException("Unknown I/O error");
+        testable.setThrowable(ioe);
+        e = assertThrows(UncheckedIOException.class, () -> function.apply(ioe));
+        final Throwable t = e.getCause();
+        assertNotNull(t);
+        assertSame(ioe, t);
+
+        assertEquals(0, function.apply(null).intValue());
+    }
+
+    @Test
     public void testGetAsBooleanSupplier() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.getAsBoolean(testable::testBooleanPrimitive));
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.getAsBoolean(testable::testAsBooleanPrimitive));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsBoolean(testable::testBooleanPrimitive));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsBoolean(testable::testAsBooleanPrimitive));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsBoolean(testable::testBooleanPrimitive));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsBoolean(testable::testAsBooleanPrimitive));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
         testable.setThrowable(null);
-        assertFalse(Functions.getAsBoolean(testable::testBooleanPrimitive));
+        assertFalse(Functions.getAsBoolean(testable::testAsBooleanPrimitive));
     }
 
     @Test
     public void testGetAsDoubleSupplier() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.getAsDouble(testable::testDoublePrimitive));
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.getAsDouble(testable::testAsDoublePrimitive));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsDouble(testable::testDoublePrimitive));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsDouble(testable::testAsDoublePrimitive));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsDouble(testable::testDoublePrimitive));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsDouble(testable::testAsDoublePrimitive));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
         testable.setThrowable(null);
-        assertEquals(0, Functions.getAsDouble(testable::testDoublePrimitive));
+        assertEquals(0, Functions.getAsDouble(testable::testAsDoublePrimitive));
     }
 
     @Test
     public void testGetAsIntSupplier() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.getAsInt(testable::testIntPrimitive));
+        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.getAsInt(testable::testAsIntPrimitive));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsInt(testable::testIntPrimitive));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsInt(testable::testAsIntPrimitive));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsInt(testable::testIntPrimitive));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsInt(testable::testAsIntPrimitive));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
         testable.setThrowable(null);
-        final int i = Functions.getAsInt(testable::testInteger);
+        final int i = Functions.getAsInt(testable::testAsInteger);
         assertEquals(0, i);
     }
 
@@ -772,30 +796,32 @@ class FunctionsTest {
     public void testGetAsLongSupplier() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.getAsLong(testable::testLongPrimitive));
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.getAsLong(testable::testAsLongPrimitive));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsLong(testable::testLongPrimitive));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.getAsLong(testable::testAsLongPrimitive));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsLong(testable::testLongPrimitive));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.getAsLong(testable::testAsLongPrimitive));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
         testable.setThrowable(null);
-        final long i = Functions.getAsLong(testable::testLongPrimitive);
+        final long i = Functions.getAsLong(testable::testAsLongPrimitive);
         assertEquals(0, i);
     }
 
     @Test
     public void testGetFromSupplier() {
         FailureOnOddInvocations.invocations = 0;
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () ->  Functions.run(FailureOnOddInvocations::new));
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
+            () -> Functions.run(FailureOnOddInvocations::new));
         final Throwable cause = e.getCause();
         assertNotNull(cause);
         assertTrue(cause instanceof SomeException);
@@ -808,31 +834,49 @@ class FunctionsTest {
     public void testGetSupplier() {
         final IllegalStateException ise = new IllegalStateException();
         final Testable<?, ?> testable = new Testable<>(ise);
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.get(testable::testInteger));
+        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.get(testable::testAsInteger));
         assertSame(ise, e);
 
         final Error error = new OutOfMemoryError();
         testable.setThrowable(error);
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.get(testable::testInteger));
+        e = assertThrows(OutOfMemoryError.class, () -> Functions.get(testable::testAsInteger));
         assertSame(error, e);
 
         final IOException ioe = new IOException("Unknown I/O error");
         testable.setThrowable(ioe);
-        e = assertThrows(UncheckedIOException.class, () -> Functions.get(testable::testInteger));
+        e = assertThrows(UncheckedIOException.class, () -> Functions.get(testable::testAsInteger));
         final Throwable t = e.getCause();
         assertNotNull(t);
         assertSame(ioe, t);
 
         testable.setThrowable(null);
-        final Integer i = Functions.apply(Testable::testInteger, testable);
+        final Integer i = Functions.apply(Testable::testAsInteger, testable);
         assertNotNull(i);
         assertEquals(0, i.intValue());
     }
 
     @Test
+    @DisplayName("Test that asPredicate(FailablePredicate) is converted to -> Predicate ")
+    public void testPredicate() {
+        FailureOnOddInvocations.invocations = 0;
+        final Functions.FailablePredicate<Object, Throwable> failablePredicate = t -> FailureOnOddInvocations
+            .failingBool();
+        final Predicate<?> predicate = Functions.asPredicate(failablePredicate);
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
+            () -> predicate.test(null));
+        final Throwable cause = e.getCause();
+        assertNotNull(cause);
+        assertTrue(cause instanceof SomeException);
+        assertEquals("Odd Invocation: 1", cause.getMessage());
+        final boolean instance = predicate.test(null);
+        assertNotNull(instance);
+    }
+
+    @Test
     void testRunnable() {
         FailureOnOddInvocations.invocations = 0;
-        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, () ->  Functions.run(FailureOnOddInvocations::new));
+        final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
+            () -> Functions.run(FailureOnOddInvocations::new));
         final Throwable cause = e.getCause();
         assertNotNull(cause);
         assertTrue(cause instanceof SomeException);
@@ -842,24 +886,1148 @@ class FunctionsTest {
         Functions.run(FailureOnOddInvocations::new);
     }
 
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableBiConsumer_Object_Throwable() {
+        new Functions.FailableBiConsumer<Object, Object, Throwable>() {
+
+            @Override
+            public void accept(Object object1, Object object2) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableBiConsumer_String_IOException() {
+        new Functions.FailableBiConsumer<String, String, IOException>() {
+
+            @Override
+            public void accept(String object1, String object2) throws IOException {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableBiFunction_Object_Throwable() {
+        new Functions.FailableBiFunction<Object, Object, Object, Throwable>() {
+
+            @Override
+            public Object apply(Object input1, Object input2) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableBiFunction_String_IOException() {
+        new Functions.FailableBiFunction<String, String, String, IOException>() {
+
+            @Override
+            public String apply(String input1, String input2) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableBiPredicate_Object_Throwable() {
+        new Functions.FailableBiPredicate<Object, Object, Throwable>() {
+
+            @Override
+            public boolean test(Object object1, Object object2) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableBiPredicate_String_IOException() {
+        new Functions.FailableBiPredicate<String, String, IOException>() {
+
+            @Override
+            public boolean test(String object1, String object2) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableBooleanSupplier_Object_Throwable() {
+        new Functions.FailableBooleanSupplier<Throwable>() {
+
+            @Override
+            public boolean getAsBoolean() throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableBooleanSupplier_String_IOException() {
+        new Functions.FailableBooleanSupplier<IOException>() {
+
+            @Override
+            public boolean getAsBoolean() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableCallable_Object_Throwable() {
+        new Functions.FailableCallable<Object, Throwable>() {
+
+            @Override
+            public Object call() throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableCallable_String_IOException() {
+        new Functions.FailableCallable<String, IOException>() {
+
+            @Override
+            public String call() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableConsumer_Object_Throwable() {
+        new Functions.FailableConsumer<Object, Throwable>() {
+
+            @Override
+            public void accept(Object object) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableConsumer_String_IOException() {
+        new Functions.FailableConsumer<String, IOException>() {
+
+            @Override
+            public void accept(String object) throws IOException {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableDoubleBinaryOperator_Object_Throwable() {
+        new Functions.FailableDoubleBinaryOperator<Throwable>() {
+
+            @Override
+            public double applyAsDouble(double left, double right) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableDoubleBinaryOperator_String_IOException() {
+        new Functions.FailableDoubleBinaryOperator<IOException>() {
+
+            @Override
+            public double applyAsDouble(double left, double right) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableDoubleConsumer_Object_Throwable() {
+        new Functions.FailableDoubleConsumer<Throwable>() {
+
+            @Override
+            public void accept(double value) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableDoubleConsumer_String_IOException() {
+        new Functions.FailableDoubleConsumer<IOException>() {
+
+            @Override
+            public void accept(double value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableDoubleFunction_Object_Throwable() {
+        new Functions.FailableDoubleFunction<Object, Throwable>() {
+
+            @Override
+            public Object apply(double input) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableDoubleFunction_String_IOException() {
+        new Functions.FailableDoubleFunction<String, IOException>() {
+
+            @Override
+            public String apply(double input) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableDoubleSupplier_Object_Throwable() {
+        new Functions.FailableDoubleSupplier<Throwable>() {
+
+            @Override
+            public double getAsDouble() throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableDoubleSupplier_String_IOException() {
+        new Functions.FailableDoubleSupplier<IOException>() {
+
+            @Override
+            public double getAsDouble() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableDoubleToIntFunction_Object_Throwable() {
+        new Functions.FailableDoubleToIntFunction<Throwable>() {
+
+            @Override
+            public int applyAsInt(double value) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableDoubleToIntFunction_String_IOException() {
+        new Functions.FailableDoubleToIntFunction<IOException>() {
+
+            @Override
+            public int applyAsInt(double value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableDoubleToLongFunction_Object_Throwable() {
+        new Functions.FailableDoubleToLongFunction<Throwable>() {
+
+            @Override
+            public int applyAsLong(double value) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableDoubleToLongFunction_String_IOException() {
+        new Functions.FailableDoubleToLongFunction<IOException>() {
+
+            @Override
+            public int applyAsLong(double value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableFunction_Object_Throwable() {
+        new Functions.FailableFunction<Object, Object, Throwable>() {
+
+            @Override
+            public Object apply(Object input) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableFunction_String_IOException() {
+        new Functions.FailableFunction<String, String, IOException>() {
+
+            @Override
+            public String apply(String input) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableIntBinaryOperator_Object_Throwable() {
+        new Functions.FailableIntBinaryOperator<Throwable>() {
+
+            @Override
+            public int applyAsInt(int left, int right) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableIntBinaryOperator_String_IOException() {
+        new Functions.FailableIntBinaryOperator<IOException>() {
+
+            @Override
+            public int applyAsInt(int left, int right) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableIntConsumer_Object_Throwable() {
+        new Functions.FailableIntConsumer<Throwable>() {
+
+            @Override
+            public void accept(int value) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableIntConsumer_String_IOException() {
+        new Functions.FailableIntConsumer<IOException>() {
+
+            @Override
+            public void accept(int value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableIntFunction_Object_Throwable() {
+        new Functions.FailableIntFunction<Object, Throwable>() {
+
+            @Override
+            public Object apply(int input) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableIntFunction_String_IOException() {
+        new Functions.FailableIntFunction<String, IOException>() {
+
+            @Override
+            public String apply(int input) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableIntSupplier_Object_Throwable() {
+        new Functions.FailableIntSupplier<Throwable>() {
+
+            @Override
+            public int getAsInt() throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableIntSupplier_String_IOException() {
+        new Functions.FailableIntSupplier<IOException>() {
+
+            @Override
+            public int getAsInt() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableIntToDoubleFunction_Object_Throwable() {
+        new Functions.FailableIntToDoubleFunction<Throwable>() {
+
+            @Override
+            public double applyAsDouble(int value) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableIntToDoubleFunction_String_IOException() {
+        new Functions.FailableIntToDoubleFunction<IOException>() {
+
+            @Override
+            public double applyAsDouble(int value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableIntToLongFunction_Object_Throwable() {
+        new Functions.FailableIntToLongFunction<Throwable>() {
+
+            @Override
+            public long applyAsLong(int value) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableIntToLongFunction_String_IOException() {
+        new Functions.FailableIntToLongFunction<IOException>() {
+
+            @Override
+            public long applyAsLong(int value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableLongBinaryOperator_Object_Throwable() {
+        new Functions.FailableLongBinaryOperator<Throwable>() {
+
+            @Override
+            public long applyAsLong(long left, long right) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableLongBinaryOperator_String_IOException() {
+        new Functions.FailableLongBinaryOperator<IOException>() {
+
+            @Override
+            public long applyAsLong(long left, long right) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableLongConsumer_Object_Throwable() {
+        new Functions.FailableLongConsumer<Throwable>() {
+
+            @Override
+            public void accept(long object) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableLongConsumer_String_IOException() {
+        new Functions.FailableLongConsumer<IOException>() {
+
+            @Override
+            public void accept(long object) throws IOException {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableLongFunction_Object_Throwable() {
+        new Functions.FailableLongFunction<Object, Throwable>() {
+
+            @Override
+            public Object apply(long input) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableLongFunction_String_IOException() {
+        new Functions.FailableLongFunction<String, IOException>() {
+
+            @Override
+            public String apply(long input) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableLongSupplier_Object_Throwable() {
+        new Functions.FailableLongSupplier<Throwable>() {
+
+            @Override
+            public long getAsLong() throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableLongSupplier_String_IOException() {
+        new Functions.FailableLongSupplier<IOException>() {
+
+            @Override
+            public long getAsLong() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableLongToDoubleFunction_Object_Throwable() {
+        new Functions.FailableLongToDoubleFunction<Throwable>() {
+
+            @Override
+            public double applyAsDouble(long value) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableLongToDoubleFunction_String_IOException() {
+        new Functions.FailableLongToDoubleFunction<IOException>() {
+
+            @Override
+            public double applyAsDouble(long value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableLongToIntFunction_Object_Throwable() {
+        new Functions.FailableLongToIntFunction<Throwable>() {
+
+            @Override
+            public int applyAsInt(long value) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableLongToIntFunction_String_IOException() {
+        new Functions.FailableLongToIntFunction<IOException>() {
+
+            @Override
+            public int applyAsInt(long value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableObjDoubleConsumer_Object_Throwable() {
+        new Functions.FailableObjDoubleConsumer<Object, Throwable>() {
+
+            @Override
+            public void accept(Object object, double value) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableObjDoubleConsumer_String_IOException() {
+        new Functions.FailableObjDoubleConsumer<String, IOException>() {
+
+            @Override
+            public void accept(String object, double value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableObjIntConsumer_Object_Throwable() {
+        new Functions.FailableObjIntConsumer<Object, Throwable>() {
+
+            @Override
+            public void accept(Object object, int value) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableObjIntConsumer_String_IOException() {
+        new Functions.FailableObjIntConsumer<String, IOException>() {
+
+            @Override
+            public void accept(String object, int value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableObjLongConsumer_Object_Throwable() {
+        new Functions.FailableObjLongConsumer<Object, Throwable>() {
+
+            @Override
+            public void accept(Object object, long value) throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableObjLongConsumer_String_IOException() {
+        new Functions.FailableObjLongConsumer<String, IOException>() {
+
+            @Override
+            public void accept(String object, long value) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailablePredicate_Object_Throwable() {
+        new Functions.FailablePredicate<Object, Throwable>() {
+
+            @Override
+            public boolean test(Object object) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailablePredicate_String_IOException() {
+        new Functions.FailablePredicate<String, IOException>() {
+
+            @Override
+            public boolean test(String object) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableRunnable_Object_Throwable() {
+        new Functions.FailableRunnable<Throwable>() {
+
+            @Override
+            public void run() throws Throwable {
+                throw new IOException("test");
+
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableRunnable_String_IOException() {
+        new Functions.FailableRunnable<IOException>() {
+
+            @Override
+            public void run() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableSupplier_Object_Throwable() {
+        new Functions.FailableSupplier<Object, Throwable>() {
+
+            @Override
+            public Object get() throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableSupplier_String_IOException() {
+        new Functions.FailableSupplier<String, IOException>() {
+
+            @Override
+            public String get() throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableToDoubleBiFunction_Object_Throwable() {
+        new Functions.FailableToDoubleBiFunction<Object, Object, Throwable>() {
+
+            @Override
+            public double applyAsDouble(Object t, Object u) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableToDoubleBiFunction_String_IOException() {
+        new Functions.FailableToDoubleBiFunction<String, String, IOException>() {
+
+            @Override
+            public double applyAsDouble(String t, String u) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableToDoubleFunction_Object_Throwable() {
+        new Functions.FailableToDoubleFunction<Object, Throwable>() {
+
+            @Override
+            public double applyAsDouble(Object t) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableToDoubleFunction_String_IOException() {
+        new Functions.FailableToDoubleFunction<String, IOException>() {
+
+            @Override
+            public double applyAsDouble(String t) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableToIntBiFunction_Object_Throwable() {
+        new Functions.FailableToIntBiFunction<Object, Object, Throwable>() {
+
+            @Override
+            public int applyAsInt(Object t, Object u) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableToIntBiFunction_String_IOException() {
+        new Functions.FailableToIntBiFunction<String, String, IOException>() {
+
+            @Override
+            public int applyAsInt(String t, String u) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableToIntFunction_Object_Throwable() {
+        new Functions.FailableToIntFunction<Object, Throwable>() {
+
+            @Override
+            public int applyAsInt(Object t) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableToIntFunction_String_IOException() {
+        new Functions.FailableToIntFunction<String, IOException>() {
+
+            @Override
+            public int applyAsInt(String t) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableToLongBiFunction_Object_Throwable() {
+        new Functions.FailableToLongBiFunction<Object, Object, Throwable>() {
+
+            @Override
+            public long applyAsLong(Object t, Object u) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableToLongBiFunction_String_IOException() {
+        new Functions.FailableToLongBiFunction<String, String, IOException>() {
+
+            @Override
+            public long applyAsLong(String t, String u) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
+     * Object and Throwable.
+     */
+    @Test
+    void testThrows_FailableToLongFunction_Object_Throwable() {
+        new Functions.FailableToLongFunction<Object, Throwable>() {
+
+            @Override
+            public long applyAsLong(Object t) throws Throwable {
+                throw new IOException("test");
+            }
+        };
+    }
+
+    /**
+     * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
+     * generic test types.
+     */
+    @Test
+    void testThrows_FailableToLongFunction_String_IOException() {
+        new Functions.FailableToLongFunction<String, IOException>() {
+
+            @Override
+            public long applyAsLong(String t) throws IOException {
+                throw new IOException("test");
+            }
+        };
+    }
+
     @Test
     public void testTryWithResources() {
         final CloseableObject co = new CloseableObject();
         final FailableConsumer<Throwable, ? extends Throwable> consumer = co::run;
         final IllegalStateException ise = new IllegalStateException();
-        Throwable e = assertThrows(IllegalStateException.class, () -> Functions.tryWithResources(() -> consumer.accept(ise), co::close));
+        Throwable e = assertThrows(IllegalStateException.class,
+            () -> Functions.tryWithResources(() -> consumer.accept(ise), co::close));
         assertSame(ise, e);
 
         assertTrue(co.isClosed());
         co.reset();
         final Error error = new OutOfMemoryError();
-        e = assertThrows(OutOfMemoryError.class, () -> Functions.tryWithResources(() -> consumer.accept(error), co::close));
+        e = assertThrows(OutOfMemoryError.class,
+            () -> Functions.tryWithResources(() -> consumer.accept(error), co::close));
         assertSame(error, e);
 
         assertTrue(co.isClosed());
         co.reset();
         final IOException ioe = new IOException("Unknown I/O error");
-        final UncheckedIOException uioe = assertThrows(UncheckedIOException.class, () ->  Functions.tryWithResources(() -> consumer.accept(ioe), co::close));
+        final UncheckedIOException uioe = assertThrows(UncheckedIOException.class,
+            () -> Functions.tryWithResources(() -> consumer.accept(ioe), co::close));
         final IOException cause = uioe.getCause();
         assertSame(ioe, cause);