F# '+' 运算符重载和 List.fold

标签 f# overloading record operator-keyword fold

我正在尝试在为 + 定义运算符重载的记录类型上使用 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/

相关文章:

recursion - 具有递归的 F# 求和类型?

f# - 为自定义集合定义 cons (::) 运算符

ios - 使用ffmpeg,函数 av_find_input_format ("avfoundation")返回 null

java - 将 java 转换为 scala - 重载静态方法

javascript - 录制语音JS并发送到服务器

ruby-on-rails-3 - 在 Rails 中结合 API 数据和本地数据

.net - 如何在 F# 中模拟鼠标点击和按键

.net - 在 System.Numerics.Vector<T> 中使用 F# 度量单位

java - 在 Java 中使用派生类型作为参数的方法重载

基于参数计数的Python方法重载?