// Path: src/main/java/co/unruly/control/result/Match.java
// @SafeVarargs
// public static <I, O> MatchAttempt<I, O> match(Function<I, Result<O, I>>... potentialMatchers) {
//     return f -> attemptMatch(potentialMatchers).andThen(ifFailed(f));
// }
// 
// Path: src/main/java/co/unruly/control/result/Match.java
// @SafeVarargs
// public static <I, O> BoundMatchAttempt<I, O> matchValue(I inputValue, Function<I, Result<O, I>>... potentialMatchers) {
//     return f -> pipe(inputValue)
//             .then(attemptMatch(potentialMatchers))
//             .then(ifFailed(f))
//             .resolve();
// }
// 
// Path: src/main/java/co/unruly/control/result/Recover.java
// public interface Recover {
// 
//     /**
//      * Returns a function which takes an Optional value, and returns a failure of the
//      * wrapped value if it was present, otherwise returns a success using the provided Supplier
//      */
//     static <S, F> Function<Optional<F>, Result<S, F>> whenAbsent(Supplier<S> onEmpty) {
//         return maybe -> maybe.map(Result::<S, F>failure).orElseGet(() -> Result.success(onEmpty.get()));
//     }
// 
//     /**
//      * Takes a class and a mapping function and returns a function which takes a value and, if it's of the
//      * provided class, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F, TF extends F> Function<F, Result<S, F>> ifType(Class<TF> targetClass, Function<TF, S> mapper) {
//         return Introducers.<F, TF>castTo(targetClass).andThen(Transformers.onSuccess(mapper));
//     }
// 
//     /**
//      * Takes a predicate and a mapping function and returns a function which takes a value and, if it satisfies
//      * the predicate, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F> Function<F, Result<S, F>> ifIs(Predicate<F> test, Function<F, S> mapper) {
//         return input -> test.test(input)
//             ? Result.success(mapper.apply(input))
//             : Result.failure(input);
//     }
// 
//     /**
//      * Takes a predicate and a mapping function and returns a function which takes a value and, if it doesn't
//      * satisfy the predicate, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F> Function<F, Result<S, F>> ifNot(Predicate<F> test, Function<F, S> mapper) {
//         return ifIs(test.negate(), mapper);
//     }
// 
//     /**
//      * Takes a value and a mapping function and returns a function which takes a value and, if it is equal to
//      * the provided value, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F> Function<F, Result<S, F>> ifEquals(F expectedValue, Function<F, S> mapper) {
//         return input -> expectedValue.equals(input)
//             ? Result.success(mapper.apply(input))
//             : Result.failure(input);
//     }
// 
//     /**
//      * Matches the value if the provided function yields an Optional whose value is
//      * present, returning the value in that Optional.
//      */
//     static <S, F> Function<F, Result<S, F>> ifPresent(Function<F, Optional<S>> successProvider) {
//         return value -> successProvider
//                 .apply(value)
//                 .map(Result::<S, F>success)
//                 .orElseGet(() -> Result.failure(value));
//     }
// }


import org.junit.Test;
import java.util.Optional;
import java.util.function.Function;
import static co.unruly.control.result.Match.match;
import static co.unruly.control.result.Match.matchValue;
import static co.unruly.control.result.Recover.*;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
    }

    @Test
    public void canMatchOnValue() {
        Function<Integer, String> matchByType = match(
                ifEquals(4, x -> x + " sure looks like a 4 to me!"),
                ifEquals(7, x -> x + " looks like one of them gosh-darned 7s?")
        ).otherwise(x -> "I have no idea what a " + x + " is though...");

        assertThat(matchByType.apply(3), is("I have no idea what a 3 is though..."));
        assertThat(matchByType.apply(4), is("4 sure looks like a 4 to me!"));
        assertThat(matchByType.apply(6), is("I have no idea what a 6 is though..."));
        assertThat(matchByType.apply(7), is("7 looks like one of them gosh-darned 7s?"));
    }

    @Test
    public void canMatchOnTest() {
        Function<Integer, String> matchByType = match(
                ifIs((Integer x) -> x % 2 == 0, x -> x + ", well, that's one of those even numbers"),
                ifIs(x -> x < 0, x -> x + " is one of those banker's negative number thingies")
        ).otherwise(x -> x + " is a regular, god-fearing number for god-fearing folks");

        assertThat(matchByType.apply(2), is("2, well, that's one of those even numbers"));
        assertThat(matchByType.apply(-6), is("-6, well, that's one of those even numbers"));
        assertThat(matchByType.apply(3), is("3 is a regular, god-fearing number for god-fearing folks"));
        assertThat(matchByType.apply(-9), is("-9 is one of those banker's negative number thingies"));
    }

    @Test
    public void canMatchOnTestPassingArgument() {
// Path: src/main/java/co/unruly/control/result/Match.java
// @SafeVarargs
// public static <I, O> MatchAttempt<I, O> match(Function<I, Result<O, I>>... potentialMatchers) {
//     return f -> attemptMatch(potentialMatchers).andThen(ifFailed(f));
// }
// 
// Path: src/main/java/co/unruly/control/result/Match.java
// @SafeVarargs
// public static <I, O> BoundMatchAttempt<I, O> matchValue(I inputValue, Function<I, Result<O, I>>... potentialMatchers) {
//     return f -> pipe(inputValue)
//             .then(attemptMatch(potentialMatchers))
//             .then(ifFailed(f))
//             .resolve();
// }
// 
// Path: src/main/java/co/unruly/control/result/Recover.java
// public interface Recover {
// 
//     /**
//      * Returns a function which takes an Optional value, and returns a failure of the
//      * wrapped value if it was present, otherwise returns a success using the provided Supplier
//      */
//     static <S, F> Function<Optional<F>, Result<S, F>> whenAbsent(Supplier<S> onEmpty) {
//         return maybe -> maybe.map(Result::<S, F>failure).orElseGet(() -> Result.success(onEmpty.get()));
//     }
// 
//     /**
//      * Takes a class and a mapping function and returns a function which takes a value and, if it's of the
//      * provided class, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F, TF extends F> Function<F, Result<S, F>> ifType(Class<TF> targetClass, Function<TF, S> mapper) {
//         return Introducers.<F, TF>castTo(targetClass).andThen(Transformers.onSuccess(mapper));
//     }
// 
//     /**
//      * Takes a predicate and a mapping function and returns a function which takes a value and, if it satisfies
//      * the predicate, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F> Function<F, Result<S, F>> ifIs(Predicate<F> test, Function<F, S> mapper) {
//         return input -> test.test(input)
//             ? Result.success(mapper.apply(input))
//             : Result.failure(input);
//     }
// 
//     /**
//      * Takes a predicate and a mapping function and returns a function which takes a value and, if it doesn't
//      * satisfy the predicate, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F> Function<F, Result<S, F>> ifNot(Predicate<F> test, Function<F, S> mapper) {
//         return ifIs(test.negate(), mapper);
//     }
// 
//     /**
//      * Takes a value and a mapping function and returns a function which takes a value and, if it is equal to
//      * the provided value, applies the mapping function to it and returns it as a Success, otherwise returning
//      * the input value as a Failure.
//      */
//     static <S, F> Function<F, Result<S, F>> ifEquals(F expectedValue, Function<F, S> mapper) {
//         return input -> expectedValue.equals(input)
//             ? Result.success(mapper.apply(input))
//             : Result.failure(input);
//     }
// 
//     /**
//      * Matches the value if the provided function yields an Optional whose value is
//      * present, returning the value in that Optional.
//      */
//     static <S, F> Function<F, Result<S, F>> ifPresent(Function<F, Optional<S>> successProvider) {
//         return value -> successProvider
//                 .apply(value)
//                 .map(Result::<S, F>success)
//                 .orElseGet(() -> Result.failure(value));
//     }
// }


// Path: src/test/java/co/unruly/control/result/MatchTest.java
import org.junit.Test;
import java.util.Optional;
import java.util.function.Function;
import static co.unruly.control.result.Match.match;
import static co.unruly.control.result.Match.matchValue;
import static co.unruly.control.result.Recover.*;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

    }

    @Test
    public void canMatchOnValue() {
        Function<Integer, String> matchByType = match(
                ifEquals(4, x -> x + " sure looks like a 4 to me!"),
                ifEquals(7, x -> x + " looks like one of them gosh-darned 7s?")
        ).otherwise(x -> "I have no idea what a " + x + " is though...");

        assertThat(matchByType.apply(3), is("I have no idea what a 3 is though..."));
        assertThat(matchByType.apply(4), is("4 sure looks like a 4 to me!"));
        assertThat(matchByType.apply(6), is("I have no idea what a 6 is though..."));
        assertThat(matchByType.apply(7), is("7 looks like one of them gosh-darned 7s?"));
    }

    @Test
    public void canMatchOnTest() {
        Function<Integer, String> matchByType = match(
                ifIs((Integer x) -> x % 2 == 0, x -> x + ", well, that's one of those even numbers"),
                ifIs(x -> x < 0, x -> x + " is one of those banker's negative number thingies")
        ).otherwise(x -> x + " is a regular, god-fearing number for god-fearing folks");

        assertThat(matchByType.apply(2), is("2, well, that's one of those even numbers"));
        assertThat(matchByType.apply(-6), is("-6, well, that's one of those even numbers"));
        assertThat(matchByType.apply(3), is("3 is a regular, god-fearing number for god-fearing folks"));
        assertThat(matchByType.apply(-9), is("-9 is one of those banker's negative number thingies"));
    }

    @Test
    public void canMatchOnTestPassingArgument() {
        String matchByResult = matchValue(4,