【发布时间】:2012-01-10 01:36:04
【问题描述】:
我正在尝试在为 + 定义运算符重载的记录类型上使用 List.fold,但在尝试使用 (+) 运算符作为传递给 fold 的 lambda 时出现类型不匹配错误.这是一个简化的 sn-p 示例,可以说明我的问题:
// a record type that also includes an overload for '+'
type Person =
{ Name : string; Age: int }
static member ( + ) (x: Person, y: Person) = x.Age + y.Age
+ 重载工作正常
> jen + kevin;;
val it : int = 87
但是说我有一个人的名单:
> let people = [kevin;jen];;
我不能使用 List.fold 来总结所有年龄:
> List.fold (+) 0 people;;
List.fold (+) 0 people;;
----------------^^^^^^
error FS0001: Type constraint mismatch. The type
int
is not compatible with type
Person
The type 'int' is not compatible with the type 'Person'
我猜问题是 F# 在以这种方式传递时无法识别 + 的重载,因为 fold 隐含地将列表键入到 int,因为我使用 '0' 作为累加器.我不确定是否有可能让我的自定义运算符重载正常工作,如果可能的话,我缺少什么来实现它。 (我假设可以使这项工作成为可能,因为您可以在浮点数上使用+)。
编辑
我知道问题是类型不匹配。正如 JaredPar 所写,我知道我可以编写一个 lambda 来获取两个人的记录并添加年龄。那不是我的意思。问题是,在我看来,应该有一种方法可以让我已经写过的 + 运算符重载被折叠确认为有效重载。
另一个编辑
感谢大家的意见。越来越清楚的一件事是,不可能做我想做的事,但这没关系。我学到了一些东西!我所看到的是,运算符重载的解决方法使得它们不能在每种情况下都起作用——所以对于 fold,没有 无缝 方法可以使 + 作为传递lambda 就像用作中缀ala jen + kevin 时一样工作。为什么这不起作用是完全有道理的。人们建议解决此问题的解决方案基本上是一次性处理fold 的特定问题--我真正追求的是如何获得正确的运算符重载以便为每个挑选> 情况(即foldback 等)——我不想编写一堆特殊情况代码来处理列表。很明显,F# 的运算符重载解决方案有一些限制,使其工作到肤浅的水平,这很好。
【问题讨论】:
-
您的
+成员毫无意义。为什么将两个人相加会返回他们的年龄总和? -
你在下面得到了很多很好的解释。我建议您自己尝试编写 fold 函数,看看为什么您不应该期望它的行为方式与您想象的一样。
-
@ChaosPandion:这个例子是一个展示原理的愚蠢设置——这不是我真正想要做的——我做了一个愚蠢的例子来清楚地展示这个问题。
-
@Kevin Won - 你能在你认为这样的操作有意义的地方展示代码吗?
-
@Kevin - 我不同意你在“另一个编辑”部分的结论。您可以像使用内置运算符一样使用
(+)运算符,只要它有意义,F# 就会识别和使用它而不会出现任何问题(例如List.map2 (+) [jen] [kevin])。在这种情况下,问题是您尝试使用int种子、person -> person -> int累加器和person list,这与fold的工作方式不兼容。
标签: f# overloading record operator-keyword fold