package com.sageserpent.americium;

import scala.NotImplementedError;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class Trials {
    public interface Trial<Case> {
        <TransformedCase> Trial<TransformedCase> map(Function<Case, TransformedCase> transform);

        <TransformedCase> Trial<TransformedCase> flatMap(Function<Case, Trial<TransformedCase>> step);

        Trial<Case> filter(Predicate<Case> predicate);

        class TrialException extends RuntimeException{

        }

        /**
         * Consume trial cases until either there are no more or an exception is thrown by {@code consumer}.
         * If an exception is thrown, attempts will be made to shrink the trial case that caused the
         * exception to a simpler case that throws an exception - the specific kind of exception isn't
         * necessarily the same between the first exceptional case and the final simplified one. The exception
         * from the simplified case (or the original exceptional case if it could not be simplified) is wrapped
         * in an instance of {@link TrialException} which also contains the corresponding exceptional trial.
         *
         * @param consumer An operation that consumes a 'Case', and may throw an exception.
         */
        void yieldOrSimplifyExceptionalCase(Consumer<Case> consumer);
    }

    public static <Case> Trial<Case> constant(Case value) {
        throw new NotImplementedError();
    }

    public static <Case> Trial<Case> choose(Case... choices) {
        throw new NotImplementedError();
    }

    public static <Case> Trial<Case> choose(Iterable<Case> choices) {
        throw new NotImplementedError();
    }

    public static <Case> Trial<Case> alternate(Trial<Case>... alternatives) {
        throw new NotImplementedError();
    }

    public static <Case> Trial<Case> alternate(Iterable<Trial<Case>> alternatives) {
        throw new NotImplementedError();
    }
}
@@ -185,49 +185,29 @@
 lic 
-class Trials %7B%0A    public interface
+abstract class
  Trial
+s
 %3CCas
@@ -211,27 +211,32 @@
 Case%3E %7B%0A    
-   
+abstract
  %3CTransforme
@@ -239,32 +239,33 @@
 ormedCase%3E Trial
+s
 %3CTransformedCase
@@ -319,19 +319,24 @@
 );%0A%0A    
-   
+abstract
  %3CTransf
@@ -347,24 +347,25 @@
 dCase%3E Trial
+s
 %3CTransformed
@@ -398,16 +398,17 @@
 e, Trial
+s
 %3CTransfo
@@ -434,17 +434,23 @@
     
-   
+abstract
  Trial
+s
 %3CCas
@@ -492,19 +492,31 @@
 );%0A%0A    
-   
+abstract static
  class T
@@ -557,22 +557,11 @@
 tion
+ 
 %7B%0A
-%0A        %7D%0A%0A
     
@@ -568,24 +568,345 @@
     /**%0A    
+     * @return The case that provoked the exception.%0A         */%0A        abstract Object provokingCase();%0A%0A%0A        /**%0A         * @return A recipe that can be used to reproduce the provoking case%0A         * when supplied to the corresponding trials instance.%0A         */%0A        abstract String recipe();%0A    %7D%0A%0A    /**%0A
      * Consu
@@ -1003,20 +1003,16 @@
 %7D.%0A     
-    
 * If an 
@@ -1095,20 +1095,16 @@
 sed the%0A
-    
      * e
@@ -1199,20 +1199,16 @@
 't%0A     
-    
 * necess
@@ -1301,20 +1301,16 @@
 ception%0A
-    
      * f
@@ -1414,20 +1414,16 @@
 ed%0A     
-    
 * in an 
@@ -1486,55 +1486,48 @@
 he c
-orresponding exceptional trial.%0A   
+ase that provoked the exception.%0A
      
- 
 *%0A
-    
     
@@ -1619,58 +1619,37 @@
     
-    
 */%0A    
-    void yieldOrSimplifyExceptionalCase
+abstract void supplyTo
 (Con
@@ -1671,23 +1671,63 @@
 sumer);%0A
+%0A
     
-%7D
+abstract Case reproduce(String recipe);
 %0A%0A
+%0A
     publ
@@ -1740,32 +1740,33 @@
 tic %3CCase%3E Trial
+s
 %3CCase%3E constant(
@@ -1849,32 +1849,33 @@
 tic %3CCase%3E Trial
+s
 %3CCase%3E choose(Ca
@@ -1965,24 +1965,25 @@
 %3CCase%3E Trial
+s
 %3CCase%3E choos
@@ -2080,32 +2080,33 @@
 tic %3CCase%3E Trial
+s
 %3CCase%3E alternate
@@ -2107,24 +2107,25 @@
 ernate(Trial
+s
 %3CCase%3E... al
@@ -2212,24 +2212,25 @@
 %3CCase%3E Trial
+s
 %3CCase%3E alter
@@ -2248,16 +2248,17 @@
 le%3CTrial
+s
 %3CCase%3E%3E 

Add some more detail to the API and use just a single abstract class rather than a combination of interface and module class.