我正在尝试在为 +
定义运算符重载的记录类型上使用 List.fold,但在尝试使用 (+ )
运算符作为传递给 fold 的 lambda。这是一个简化的片段,它举例说明了我的问题:
// 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”作为累加器。我不确定是否有可能让我的自定义运算符重载正常工作,如果可能的话,我缺少什么来实现它。 (我假设有可能完成这项工作,因为您可以在 float 上使用 +
)。
编辑
我知道问题是类型不匹配。正如 JaredPar 所写,我知道我可以编写一个 lambda 来获取两个人的记录并添加年龄。那不是我的意思。问题是,在我看来,应该有一种方法可以使我已经编写的 +
运算符重载被 fold 确认为有效重载。
另一个编辑
感谢大家的参与。一件越来越清楚的事情是,它不可能做我想做的事,但这没关系。我学到了一些东西!我所看到的是运算符重载的解决方案使得它们无法在所有上下文中工作——因此使用 fold
没有无缝方法来制作 +
作为 lambda 传递,就像用作中缀 ala jen + kevin
时一样。为什么这不起作用是完全有道理的。人们建议解决这个问题的解决方案基本上是一次性的,以处理 fold
的特定问题——我真正想要的是如何获得正确的运算符重载来为 every 情况(即 foldback
等)——我不想编写一堆特殊情况代码来处理列表。很明显,F# 的运算符重载解决方案没有一些限制,使其只能在表面上工作,这很好。
最佳答案
List.fold
函数采用 State -> T -> State
类型的 lambda/函数。本例中的 +
运算符具有与签名不兼容的类型 Person -> Person -> int
。这就是您收到错误的原因。
要折叠年龄,请尝试以下操作
people |> List.fold (fun sum p -> sum + p.Age) 0
在此处使用 +
运算符作为折叠的一部分的一种方法是将 Person
映射到 Age 属性,然后对 int + 使用折叠
运算符。
people
|> Seq.ofList
|> Seq.map (fun p -> p.Age)
|> Seq.fold (+) 0
关于F# '+' 运算符重载和 List.fold,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8797562/