Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 受限接口实现_Java_Haskell_Interface - Fatal编程技术网

Java 受限接口实现

Java 受限接口实现,java,haskell,interface,Java,Haskell,Interface,在Haskell(和Rust等)中,我可以拥有受其他实例约束的实例: data Pair a b = Pair a b instance (Eq a, Eq b) => Eq (Pair a b) where Pair a b == Pair a' b' = a == a' && b == b' 对于Java接口,我不能。我必须要求Pair的类型参数始终实现Eq,否则我根本无法实现Eq: interface Eq<A> { public b

在Haskell(和Rust等)中,我可以拥有受其他实例约束的实例:

data Pair a b = Pair a b

instance (Eq a, Eq b) => Eq (Pair a b) where 
    Pair a b == Pair a' b' = a == a' && b == b'
对于Java接口,我不能。我必须要求
Pair
的类型参数始终实现
Eq
,否则我根本无法实现
Eq

interface Eq<A> {
    public boolean eq(A other);
}

class Pair<A extends Eq<A>, B extends Eq<B>> implements Eq<Pair<A, B>> {
    A a;
    B b;
    public boolean eq(Pair<A, B> other){
        return a.eq(other.a) && b.eq(other.b);
    }
}
接口均衡{
公共布尔eq(其他);
}
类对实现Eq{
A A;
B B;
公共布尔等式(对其他){
返回a.eq(其他a)和b.eq(其他b);
}
}
我想要一些像:

class Pair<A, B> implements Eq<Pair<A, B>> if (A implements Eq<A> && B implements Eq<B>) {...}
类对实现Eq如果(A实现Eq&&B实现Eq){…}
到目前为止,互联网告诉我,Java并不直接支持我想要的功能。然而,我发现这是接口(重新)可用性的一个相当关键的因素。我想知道是否有一些变通方法或解决方案大致涵盖了相同的领域。

嗯。。。没有

但是我们可以有一种方便的方法,即如果
a、B
都是
Eq
,则将
转换为
Eq
。这需要在使用站点上执行额外的步骤,程序员必须在需要时执行显式类型转换;但这可能并不太糟糕

class Pair<A, B>
{
    A a;
    B b;
}

static
<A extends Eq<A>, B extends Eq<B>>
Eq<Pair<A,B>> cast(Pair<A,B> p1)
{
    return p2->( p1.a.eq(p2.a) && p1.b.eq(p2.b) );
}

--

    Pair<X,Y> pair = ...;

    Eq<Pair<X,Y>> eq = cast(pair);

我想到的一个规范解决方案是将比较器置于类外部。这是Scala所采用的方法,同时通过帮助使其更易于消化。你可以用一些方法来构造比较器,比如

public <A, B> Comparator<Pair<A,B>> pairCmp(Comparator<A> ca, Comparator<B> cb) { ...
完整的示例代码:

interface Eq<A> {
    public boolean eq(A other);
}

public class Pair<A,B> {
    public final A 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);
    }
}
接口均衡{
公共布尔eq(其他);
}
公共类对{
公开决赛A;
公开决赛B;
公共对(A、B){
这个a=a;
这个.b=b;
}
公共静态对mkPair(A、B){
返回新的一对(a,b);
}
公共静态PairEq mkPair(A、B){
返回新的PairEq(a,b);
}
}
类PairEq
延伸对
实现Eq
{
公共PairEq(A、B){
超级(a,b);
}
@凌驾
公共布尔eq(配对){
返回a.eq(that.a)和&b.eq(that.b);
}
}

您将TypeClass翻译错了

类型类与继承无关。它们实现了特设多态性,即用于扩展已定义类型的功能

这个东西可以作为模式转换为Java,但您必须注意,在Haskell中,实例是隐式提供的,而在Java中,您必须显式地将它们作为参数传递:

interface Eq<A> {
  public boolean eq(A left, A right);
}

class EqInstances {
  public static Eq<Pair<A, B>> pair (final Eq<A> aInstance, final Eq<B> bInstance) {
    return new Eq<Pair<A, B>> {
      public boolean eq(Pair<A, B> left, Pair<A, B> right) {
        return aInstance.eq(left.a, right.a) && bInstance.eq(left.b, right.b);
      }
    };
  }
}
接口均衡{
公共布尔等式(左、右);
}
阶级立场{
公共静态均衡器对(最终均衡器状态、最终均衡器状态){
返回新的Eq{
公共布尔均衡器(左对、右对){
返回aInstance.eq(左a、右a)和&bInstance.eq(左b、右b);
}
};
}
}
下面是如何使用此模式编写多态函数:

boolean someMethodThatUsesAnEqInstance<A>(final Eq<A> aEqInstance, A a1, A a2) {
  return aEqInstance.eq(a1, a2);
}
boolean somemethod使用一个新的站姿(最终的Eq AEQ站姿,A a1,A a2){
返回AEQinstation.eq(a1,a2);
}

看起来还不错,但这不需要为每个实例组合使用一个子类吗?(例如
PairEq
PairShow
PairEqShow
对于
Eq
Show
)您一定会从一些API获得
类型,而不是
PairEq
,即使
a、B
满足约束条件。现在您仍然需要将
Pair
转换为
PairEq
@AndrásKovács Yest,这是一个不幸的结果,因为在Java中,类的超类列表总是固定的。我看不出有什么办法可以绕过它。这在一定程度上可以通过,
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);
}
interface Eq<A> {
    public boolean eq(A other);
}

public class Pair<A,B> {
    public final A 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);
    }
}
interface Eq<A> {
  public boolean eq(A left, A right);
}

class EqInstances {
  public static Eq<Pair<A, B>> pair (final Eq<A> aInstance, final Eq<B> bInstance) {
    return new Eq<Pair<A, B>> {
      public boolean eq(Pair<A, B> left, Pair<A, B> right) {
        return aInstance.eq(left.a, right.a) && bInstance.eq(left.b, right.b);
      }
    };
  }
}
boolean someMethodThatUsesAnEqInstance<A>(final Eq<A> aEqInstance, A a1, A a2) {
  return aEqInstance.eq(a1, a2);
}