-
Notifications
You must be signed in to change notification settings - Fork 253
Description
This is more a discussion than an issue which should be fixed immediately. There are a lot of missing methods in collections like contains(Equal<A>), partition(int), filter(Equal<A>) etc. In Haskell this is solved with type classes like Traversable and Foldable. However these classes are based on higher kinded types, but Java does not support higher kinded types. So if we want to add these methods to all collections without code repetition, we should come up with some solution.
One way is to add a base class Traversable<A> to all collections, e.g.:
public abstract class Traversable<A> implements Iterable<A> {
public boolean contains(Equal<A> eq, A element) { ... }
}
public abstract class List<A> extends Traversable<A> { ... }There is an issue with such approach: how should methods that return collections of the same type should look like? Example:
public abstract class Traversable<A> implements Iterable<A> {
public P2<???, ???> partition(int index) { ... }
public ??? take(int n) { ... }
public ??? drop(int n) { ... }
}What should we put instead of ???? Traversable<A> is not good, because it is abstract.
So, there is a second way (Scala way):
public abstract class Traversable<A, F> {
public P2<F, F> partition(int i) { ... }
public F take(int i) { ... }
public F drop(int i) { ... }
}
public abstract class List<A> extends Traversable<A, List<A>> { ... }This works, but the class definition looks a bit cumbersome.
The third way is to provide only part of methods that do not return collections of the same type and implement the remaining methods via code repetition.
The fourh way: try to overcome Java's lack of higher kinded types (partially) and implement the type class Traversable<A, F>:
public abstract class Traversable<A, F> {
public P2<F, F> partition(F collection, int i) { ... }
public F take(F collection, int i) { ... }
public F drop(F collection, int i) { ... }
public static <A> Traversable<A, List<A>> listTraversable() {
return new Traversable<A, List<A>>() {
@Override List<A> take(List<A> collection, int i) { ... }
@Override List<A> drop(List<A> collection, int i) { ... }
};
}
}This is not type safe, unfortunately, however this is the way which is closest to Haskell. A similar approach was proposed by @jbgi in #126 (though, with some differences).