java - Constrained interface implementation -


in haskell (and rust, , others) can have instances constrained other instances:

data pair b = pair b  instance (eq a, eq b) => eq (pair b)      pair b == pair a' b' = == a' && b == b' 

with java interfaces can't. must require type parameters of pair implement eq, or can't implement eq<pair<a, b>> @ all:

interface eq<a> {     public boolean eq(a other); }  class pair<a extends eq<a>, b extends eq<b>> implements eq<pair<a, b>> {     a;     b b;     public boolean eq(pair<a, b> other){         return a.eq(other.a) && b.eq(other.b);     } } 

i'd have like:

class pair<a, b> implements eq<pair<a, b>> if (a implements eq<a> && b implements eq<b>) {...} 

so far internet has told me desired functionality isn't directly supported in java. nevertheless find rather critical factor in (re)usability of interfaces. i'd know if there workarounds or solutions approximately cover same ground.

one canonical solution comes mind make comparator external class. approach scala takes, while making easier digestible of implicits. , you'd have methods constructing comparators, such as

public <a, b> comparator<pair<a,b>> paircmp(comparator<a> ca, comparator<b> cb) { ... 

this quite cumbersome work with. haskell same thing internally, passing dictionaries of type-classes implementitions under hood, type-class interface type inference makes more pleasant.

as far know, in java there no way how declare conditional instances. more oo approach have sub-class pairs allow equality:

class paireq<a extends eq<a>, b extends eq<b>>   extends pair<a,b>   implements eq<pair<a, b>> {  ... 

there again manual process involved, need decide when use pair , when paireq. method overloading, make easier use declaring smart constructors. java picks specific one, whenever need create pair, use mkpair , java pick 1 returning paireq, if arguments implement eq appropriately:

public static <a,b> pair<a,b> mkpair(a a, b b) {     return new pair<a,b>(a, b); }  public static <a extends eq<a>, b extends eq<b>> paireq<a,b> mkpair(a a, b b) {     return new paireq<a,b>(a, b); } 

complete sample code:

interface eq<a> {     public boolean eq(a other); }  public class pair<a,b> {     public final a;     public final b b;      public pair(a a, b b) {         this.a = a;         this.b = b;     }      public static <a,b> pair<a,b> mkpair(a a, b b) {         return new pair<a,b>(a, b);     }      public static <a extends eq<a>, b extends eq<b>> paireq<a,b> mkpair(a a, b b) {         return new paireq<a,b>(a, b);     } }  class paireq<a extends eq<a>, b extends eq<b>>     extends pair<a,b>     implements eq<pair<a,b>> {     public paireq(a a, b b) {         super(a, b);     }      @override     public boolean eq(pair<a,b> that) {         return a.eq(that.a) && b.eq(that.b);     } } 

Comments