從不同的角度來看,似乎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