[英]Functors in Java
我正在嘗試在Java中定義類似於Haskell的仿函數的類。 因此,仿函數定義為:
/**
* Programming languages allow only (just simply enough) endofunctor, that are functors from and to the same category.
* In this case, the category is the one of the datatypes (in here Type, in order to make it more clear)
*/
public interface EndoFunctor<X extends Type> extends Type {
/**
* The basic implementation for any element fx
* @param map Transformation function for the type parameter
* @param fx Element of the current class
* @param <Y> Target type
* @return transformed element through map
*/
<Y extends Type> EndoFunctor<Y> fmap(Function<X,Y> map, EndoFunctor<X> fx);
}
public class Id<X extends Type> implements EndoFunctor<X> {
protected X witness;
Id(X witness) { this.witness = witness; }
@Override
public <Y extends Type> Id<Y> fmap(Function<X, Y> map, Id<X> fx) {
return new Id<>(map.apply(fx.witness));
}
}
此代碼的問題是Id<X>
與EndoFunctor<X>
類型不匹配。 我如何在EndoFunctor
接口中確定fmap
,以便如果任何類型K<T>
實現EndoFunctor<T>
並且給出了映射函數T->U
,那么K<U>
將作為值返回,而不進行任何類型轉換(即是的,因為我知道我的對象是Id<T>
,那么fmap
的結果“必須是” Id<U>
,因此我將EndoFunctor<U>
類型的結果向下轉換為這種類型)?
你可以使用CRTP :
interface EndoFunctor<X extends Type, T extends EndoFunctor<X, T>> extends Type {
<Y extends Type> EndoFunctor<Y, ?> fmap(Function<X,Y> map, T fx);
}
class Id<X extends Type> implements EndoFunctor<X, Id<X>> {
protected X witness;
Id(X witness) { this.witness = witness; }
@Override
public <Y extends Type> Id<Y> fmap(Function<X, Y> map, Id<X> fx) {
return new Id<>(map.apply(fx.witness));
}
}
如何在EndoFunctor接口中確定fmap,以便如果任何類型K實現EndoFunctor並且給出了映射函數T-> U,那么K將作為值返回,而不進行任何類型轉換(也就是說,因為我知道我的對象是一個Id,那么fmap的結果“必須是”一個Id,因此我將EndoFunctor類型的結果向下轉換為這種類型)?
你不能; 這被稱為高級多態,Java不支持它(很少有語言)。 Jorn Vernee的答案可以讓您在Java中獲得最接近的答案,但該界面允許您編寫
class NotId<X extends Type> implements EndoFunctor<X, Id<X>> {
@Override
public <Y extends Type> ADifferentEndoFunctorAgain<Y> fmap(Function<X, Y> map, Id<X> fx) { ... }
}
如果你想在EndoFunctor
上編寫通用代碼而不是像Id
一樣使用特定的 EndoFunctor
,那么EndoFunctor
。
問題不在於Id<X>
與EndoFunctor<X>
不匹配,但是當您嘗試覆蓋fmap
您已使參數類型更具體,因此方法簽名不再與fmap
中EndoFunctor
的方法簽名匹配
這意味着它當前形式的Id<X>
不能完全實現EndoFunctor<X>
接口。 實現接口時,必須能夠與您的類進行交互,而無需知道它是不同的接口。
請遵循有關刪除此方法參數和使用實例變量的注釋中的建議,或將Id<X>
的簽名修改為public <Y extends Type> Id<Y> fmap(Function<X, Y> map, EndoFunctor<X> fx)
使其與界面兼容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.