从不同的角度来看,似乎Functor不应该被建模为“包装“的数据,但实际上更像是一个类型,它的工作原理上的的数据。透视这一转变允许没有一个单一的投编码的一切,绝对类型安全的(但仍然有很多的样板):
public interface Functor<A, B, FromInstance, ToInstance> {
public ToInstance fmap(FromInstance instance, F<A,B> f);
}
public class ListFunctor<A,B> implements Functor<A, B, List<A>, List<B>> {
@Override
public List<B> fmap(List<A> instance, F<A, B> f) {
List<B> result = new ArrayList<B>();
for(A a: instance) result.add(f.apply(a));
return result;
}
}
List<String> stringList = Arrays.asList("one","two","three");
ListFunctor<String,Integer> functor = new ListFunctor<String,Integer>();
List<Integer> intList = functor.fmap(stringList, stringLengthF);
System.out.println(intList);
//--> [3, 3, 5]
看来我太专注于一种类型的包装都FromInstance和ToInstance参数(例如ListFunctor中的List),这不是严格必要的。然而,现在不仅有A而且还有B作为类型参数是一个沉重的负担,这可能使这种方法实际上无法使用。
[研究]
我找到了一种方法,使该版本至少一点点有用:这仿函数可用于解除功能。例如。如果你有F<String, Integer>
,你可以从它构建一个F<Foo<String>, Foo<Integer>>
当你定义了一个FooFunctor
如上图所示:
public interface F<A,B> {
public B apply(A a);
public <FromInstance, ToInstance> F<FromInstance, ToInstance> lift(
Functor<A,B,FromInstance, ToInstance> functor);
}
public abstract class AbstractF<A,B> implements F<A,B> {
@Override
public abstract B apply(A a);
@Override
public <FromInstance, ToInstance> F<FromInstance, ToInstance> lift(
final Functor<A, B, FromInstance, ToInstance> functor) {
return new AbstractF<FromInstance, ToInstance>() {
@Override
public ToInstance apply(FromInstance fromInstance) {
return functor.fmap(fromInstance, AbstractF.this);
}
};
}
}
public interface Functor<A, B, FromInstance, ToInstance> {
public ToInstance fmap(FromInstance instance, F<A,B> f);
}
public class ListFunctor<A, B> implements Functor<A, B, List<A>, List<B>> {
@Override
public List<B> fmap(List<A> instance, F<A, B> f) {
List<B> result = new ArrayList<B>();
for (A a : instance) {
result.add(f.apply(a));
}
return result;
}
}
//Usage:
F<String, Integer> strLenF = new AbstractF<String, Integer>() {
public Integer apply(String a) {
return a.length();
}
};
//Whoa, magick!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
F<List<String>,List<Integer>> liftedF = strLenF.lift(new ListFunctor<String, Integer>());
List<String> stringList = Arrays.asList("one", "two", "three");
List<Integer> intList = liftedF.apply(stringList);
System.out.println(intList);
//--> [3, 3, 5]
我认为它仍然不是很有用,但至少冷却器的方式比其他的尝试:-P
可能有错误的形式有超过3个类型参数,尤其是包含其他类型的参数,因为声明变得很混乱,没有人知道发生了什么。 – 2011-02-01 12:23:11
关于“库作家”和使用方面有所不同。即使使用了Java的有限类型推断(例如通过使用静态方法),您也可以经常“隐藏”泛型。 – Landei 2011-02-01 12:36:47