I am working on a small functional library written in Java, which mimics the a functional style of programming. I am stuck with a undesirable type cast in one of my method definitions and would love some help.
Ok, so we do not have first class functions in Java, so I define them as objects, with one method 'apply()' like so:
public abstract class Function2<R,T1,T2> {
public abstract R apply(final T1 paramOne, final T2 paramTwo);
}
I then define my cons method as a Function2 object, which I can pass around like I would a function in another language that supports it:
public static <T> Function2<List<T>, T, List<T>> cons(){
return new Function2<List<T>, T, List<T>>(){
@Override
public List<T> apply(T x, List<T> xs) {
return new NonEmptyList<T>(x, xs);
}
};
}
I have omitted my list structure for brevity; assume it is a functional style list data structure with all the usual head/tail/etc. operations.
I then want to implement a function like 'reverse', which returns a list of items in reverse order. I use foldl1 (fold a non empty list from the left) to achieve this, and pass the cons function as a parameter to foldl1 like so:
public static <T> List<T> foldl( Function2<List<T>, T, List<T>> f,
List<T> acc,
List<T> xs ){
if(xs.isEmpty()){ return acc; }
return foldl(f, (f.apply(xs.head(), acc)), xs.tail());
}
public static <T> List<T> reverse(List<T> xs){
// how do I avoid this cast??
return foldl( (Function2) cons(), new EmptyList(), xs);
}
But when I pass my 'cons()' object in 'reverse', I need to cast it as a Function2, and I have no idea how to avoid doing this. I have tried all manner of messing around with types...I feel this is simply a lack of experience on my part with the Java type system...anyone?
PS. I am aware of other functional libraries in Java, I just wanted to do my own small one as a learning experience.
EDIT - OK, so I am using a regular 'foldl' now to get back a List, but I still have to perform the cast? The return type of 'cons' align with 'foldl'...
foldl1
as takingFunction2<T, T, T>
, andcons()
returns aFunction2<List<T>, T, List<T>>
; so it shouldn't type check. It only type checks if you ignore the generics which is what you're doing by casting to the raw type.