我想用Java定义一个Functor类.这有效:
//a Function
public interface F<A,R> {
public R apply(A a);
}
public interface Functor<A> {
public <B> Functor<B> fmap(F<A,B> f);
}
Run Code Online (Sandbox Code Playgroud)
但是fmap的返回值不应该是Functor
,而是适当的子类.通常这可以使用CRTP进行编码,但是由于附加参数,我似乎在这里遇到了问题A
.例如,以下和类似的编码不起作用("类型参数FInst不在其范围内"):
public interface Functor<A, FInst extends Functor<A,FInst>> {
public <B, I extends Functor<B,FInst>> I fmap(F<A,B> f);
}
Run Code Online (Sandbox Code Playgroud)
[澄清]
对于"适当的子类",我指的是被称为自身的类的类型.例如列表是算子,所以我想写类似的东西
public class ListFunctor<A> implements ??? {
final private List<A> list;
public ListFunctor(List<A> list) {
this.list = list;
}
@Override
<B> ListFunctor<B> fmap(F<A,B> f) {
List<B> result = new ArrayList<B>();
for(A a: list) result.add(f.apply(a));
return new ListFunctor<B>(result);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道即使使用我给出的第一个定义也可以写这个(因为允许使用协变返回类型),但是我希望返回类型"ListFunctor" 由类型系统强制执行(这样我就不能返回相反,FooFunctor),这意味着Functor接口需要返回"自我类型"(至少在其他语言中被称为).
[结果]
所以看起来我想要的是不可能的.这是一篇相关的博客文章:http://blog.tmorris.net/higher-order-polymorphism-for-pseudo-java/
[后果]
我偶然发现了这个古老的问题,并意识到这是我的图书馆highJ的惊人旅程的起点,不仅仅是一个简单的Functor
.我永远不会想象人们会把这些疯狂的东西用于任何严肃的事情,但事情发生了,这让我很开心.
public interface Functor<A, FInst extends Functor<A,FInst>> {
public <B, I extends Functor<B,FInst>> I fmap(F<A,B> f);
}
Run Code Online (Sandbox Code Playgroud)
此代码生成错误,因为在定义时I
,将其定义为子类Functor<B,FInst>
,但Functor<B,FInst>
在这种情况下,FInst参数必须是子类,而上面定义为它的子类Functor<A,FInst>
.由于Functor<A,FInst>
和Functor<B,FInst>
不兼容,您会收到此错误.
我完全无法解决这个问题,但我至少可以完成一半的工作:
import java.util.ArrayList;
import java.util.List;
interface F<A,R> {
public R apply(A a);
}
interface Functor<A, FClass extends Functor<?, FClass>> {
public <B> FClass fmap(F<A,B> f);
}
public class ListFunctor<A> implements Functor<A, ListFunctor<?>> {
final private List<A> list;
public ListFunctor(List<A> list) {
this.list = list;
}
@Override
public <B> ListFunctor<B> fmap(F<A,B> f) {
List<B> result = new ArrayList<B>();
for(A a: list) result.add(f.apply(a));
return new ListFunctor<B>(result);
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,并且它正确地将允许的返回类型集限制为ListFunctor,但它并不仅限于它的子类ListFunctor<B>
.您可以将其声明为返回ListFunctor<A>
或任何其他ListFunctor,它仍然可以编译.但是您不能将其声明为返回FooFunctor或任何其他Functor.
解决其余问题的主要问题是你不能只将FClass限制为子类ListFunctor<B>
,因为B参数是在方法级别声明的,而不是在类级别,所以你不能写
public class ListFunctor<A> implements Functor<A, ListFunctor<B>> {
Run Code Online (Sandbox Code Playgroud)
因为B在那一点上没有任何意义.我无法使用fmap()的第二个参数,但即使我可以,它只会强制您指定两次返回类型 - 一次在type参数中,再一次作为返回类型本身.
归档时间: |
|
查看次数: |
5039 次 |
最近记录: |