import edu.neu.ccs.demeterf.*;

abstract class TUCombiner<T> extends IDfb{
        // Type Unifying combiner (TU)
        // Identity... allows apply(...) to transform into a "T"
        Object combine(Object o1){ return o1; }

        //** A Bunch of simple Object* methods to catch all the rest
        T combine(Object o1, Object o2)
          { 
	    System.out.println("in combine 1 Object; " + o1);
	    return simplify(new Object[]{o2}); }
        T combine(Object o1, Object o2, Object o3)
          { return simplify(new Object[]{o2,o3}); }
        T combine(Object o1, Object o2, Object o3, Object o4)
          { return simplify(new Object[]{o2,o3,o4}); }
        T combine(Object o1, Object o2, Object o3, Object o4, Object o5)
          { return simplify(new Object[]{o2,o3,o4,o5}); }
        T combine(Object o1, Object o2, Object o3, Object o4,
                             Object o5, Object o6)
          { return simplify( new Object[]{o2,o3,o4,o5,o6}); }

        //** More if needed...

        // The simplify for an array... called from above
        T simplify(Object o[]){ return simplify(o, (T)o[0], 1); }

        // Recursive fold over the array
        T simplify(Object o[], T t, int i){
            if(i >= o.length)return t;
            return simplify(o, fold(t, (T)o[i]), i+1);
        }

        // * * * * Actual Stuff... * * * *
        // Clients extend TUCombiner and implement the methods below.

        // Perform one step of the combination
        abstract T fold(T accum, T one);

        // Default apply (must be overridden for safety)
        abstract T apply(Object o);

        //** Other apply methods can be written in a subc
}

abstract class FloatTUCombiner extends TUCombiner<Float> {}