簡體   English   中英

Java中的函數

[英]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);

}

如果我想實現一個 身份類型的Identity Functor 仿函數,我必須寫一些類似的東西

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您已使參數類型更具體,因此方法簽名不再與fmapEndoFunctor的方法簽名匹配

這意味着它當前形式的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM