Java中的函数

jac*_*ckb 6 java haskell category-theory

我正在尝试在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);

}
Run Code Online (Sandbox Code Playgroud)

如果我想实现一个 身份类型的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));
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码的问题是Id<X>与类型不匹配EndoFunctor<X>.我怎么能确定fmapEndoFunctor接口,如果任何类型的K<T>工具EndoFunctor<T>和地图功能T->U给出,然后K<U>返回一个值,没有任何类型转换(也就是,因为我知道,我的目标是一个Id<T>,那么结果fmap"有是"a Id<U>,因此我将类型的结果向下倾斜EndoFunctor<U>到这种类型)?

Jor*_*nee 8

你可以使用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));
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*nov 8

如何在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) { ... }
}
Run Code Online (Sandbox Code Playgroud)

如果你想编写的代码一般过去,将无法正常工作EndoFunctors,而不是与工作具体 EndoFunctorId.