如何建模多变量函数?

时间:2009-07-12 00:56:30

标签: java collections

我们知道Map接口模型在数学中具有抽象功能。我该如何建模多变量函数?例如,为了模拟f(x,y,z),我有两个选择:

Map<List<Integer>, Integer> f1;

Map<Integer, Map<Integer, Map<Integer, Integer>>> f2;

您认为哪一个更好?

谢谢,

3 个答案:

答案 0 :(得分:4)

都不是。

您正在寻找的teqnique称为uncurrying。我们知道函数代表了逻辑含义:

∀ a b. a -> b

我们也知道如果A和B暗示C,则A暗示B暗示C:

∀ a b c. ((a, b) => c) <=> (a => b => c)

Here's proof.查看一个关于逻辑含义的真值表,你会发现它们是等价的。那么如何在类型级别表示A and B?您使用的是产品类型。两种类型的乘积是一对,即其值具有两种类型的类型:

interface P2<A, B> { public A _1(); public B _2(); }

你可以用三元组或任何arity的元组做同样的事情。但请注意,因为这种推理会引导您进入异构列表,aren't pretty in Java

此外,您的Map表示仅适用于部分功能。更重要的是,JDK的Map接口设计为可变,谁听说过可变功能?这是一个更好的代表:

interface F<A, B> { public B apply(A a); }

答案 1 :(得分:3)

我希望第三个选项是定义一个包含三个Integer字段xyz的简单类(称之为Triple例如,并使用Map<Triple, Integer>

如果你经常需要这种东西,你可以使Triple本身通用,并使用Map<Triple<Integer>, Integer>(或者如果你的某些“函数”需要有不同类型的参数,它甚至可以一个Map<Triple<Integer, Integer, Integer>, Integer>,但这开始失去可读性恕我直言。

答案 2 :(得分:0)

您的第一选择通常更好,因为它需要更少的内存并且需要更少的代码来访问:

Map<List<Integer>, Integer> f1 = ... 
f1.put(Arrays.asList(1, 2, 3), 7);
Integer v = f1.get(Arrays.asList(1, 2, 3));

仅在访问模式需要时使用地图地图,例如

Map<Integer, Map<Integer, Map<Integer, Integer>>> f2 = ...
Set<Integer> keys = f2.keySet();