这是从别人一个复杂的,但希望有趣的问题是谁在做太多Haskell和C++模板元编程。请跟我使Java功能的正确方法对象来封装通用功能
我写一些通用的Java代码来检查的功能的某些代数性质,以及我在未来与适当的类型有些人有些难度承担。
作为该工作的例子,这里是检查的功能是交换的功能:
<E, R>
boolean checkCommutative(Binary<E,E,R> f
, Binary<R,R,Boolean> eq
, E a, E b)
{
return eq.ap(f.ap(a,b), f.ap(b, a));
}
这个功能应该阅读:“一个二元函数f
带有两个E
的并产生R
是交换(与由函数eq
比较两个R
的定义的相等),如果对于任何a
和E
类型的b
,施加到(a,b)
f
等于f
施加到(b,a)
“。
然后我就可以测试一个给定函数C.plus(Integer,Integer)
是通过执行以下交换:
class Plus implements Binary<Integer, Integer, Integer> {
Integer ap(Integer a, Integer b) { return C.plus(a,b); }
}
class Eq implements Binary<Integer, Integer, Boolean> {
Boolean ap(Integer a, Integer b) { return a.equals(b); }
}
checkCommutative(new Plus(), new Eq(), rand(), rand());
,所有都很好。
现在我想实现一些更复杂的东西。比方说,我有一个通用的接口Group<E>
有加方法:
interface Group<E> {
E plus(E,E);
}
比方说,我有两种实现方式:TheIntegers
和TheRationals
:
class TheIntegers implements Group<Integer> { ... }
class TheRationals implements Group<Fraction> { ... }
现在,我希望能够捕捉到的想法,从整数到有理数的通用函数F
通过与Group.plus
类似的函数g
来通勤。作为第一个切,我想写的东西是这样的:
<E, R>
booleanCheckCommutesWith(Unary<E,R> f
, ?? g
, Binary<R,R,Boolean> eq
, E a, E b)
{
return eq.ap(f.ap(g.ap(a,b)), g.ap(f.ap(a), f.ap(b));
}
class F implements Unary<TheIntegers, TheRationals> {
Fraction ap (Integer x) { ... }
}
checkCommutesWith(new F(), new Plus(), new Eq(), rand(), rand());
这里的问题是应该怎样为g
类型是什么?问题是g
应用于两种不同类型:E
和R
。在具体的例子中,我们希望g
代表Group<Integer>.plus(Integer,Integer)
和Group<Fraction>.plus(Fraction,Fraction)
。现在
的checkCommutesWith
实施上述不可能工作,因为到g.ap
两个电话之间的唯一区别是通用型,其将被清除。
boolean checkCommutesWith(Unary<DE,RE> f
, ?? g
, Binary<RE,RE,Boolean> eq
, S domain, S range
, E x, E y)
{
return eq.ap(f.ap(g.ap(domain, x, y)),
, g.ap(range, f.ap(x), f.ap(y))
);
}
class Plus implements ??
{
<E, G extends Group<E>>
E ap (G gp, E x, E y) { return gp.plus(x,y); }
}
那么应该怎么接口(??
)的样子:因此,我将通过添加域和值域为对象稍作修改?如果这是C++我会写的
interface ?? <T> {
<E, S extends T<E>>
E ap(S, E, E);
}
等效但AFAICT Java没有模板,模板参数相当。这就是我卡住的地方。
请注意,我不希望将组作为checkCommutesWith
签名的一部分,因为我希望能够将此代码与其他结构一起使用。我认为一个通用的定义应该是可能的(对“应该”:)的一些定义)。这里
更新/澄清的问题的关键是,集之间的映射的定义特性是它们与通勤EQ()。群同态的定义属性是他们通过plus()。环同态的定义属性是他们通过times()。我试图定义一个通用的commutesWith函数来捕获这个想法,并且我正在寻找正确的抽象来封装eq,plus和times(以及其他结构)。
策略模式 – rees
“的问题是,克施加到两种不同类型: E和R“。如果是这样,问题在于你的设计,而不是java。 Java在不允许的情况下是正确的。你能举出更具体的例子吗? –
@AlexeiKaigorodov:考虑函数plus()。如果我给它一个小组,以及来自该小组的两个元素,那么它应该给我一个该小组的一个元素。我应该能够将它应用到TheRationals中,以从一对理性到理性获得一个函数,并且让TheIntegers从一个整数到一个整数。 类似地,times(),当提供一个环时,以及该环的两个元素,应该为我提供该环的一个元素。因此,我试图封装的常见结构是一个函数形式> E ap(S,E,E),对于任意的T. –
mdgeorge