Kev*_*Won 2 f# overloading record fold operator-keyword
我正在尝试在定义运算符重载的记录类型上使用List.fold +,但是当尝试使用(+)运算符作为lambda传递给fold 时,我遇到类型不匹配错误.这是一个简化的代码片段,它举例说明了我的问题:
// 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
Run Code Online (Sandbox Code Playgroud)
在+超负荷的工作就好了
> jen + kevin;;
val it : int = 87
Run Code Online (Sandbox Code Playgroud)
但是说我有个人名单:
> let people = [kevin;jen];;
Run Code Online (Sandbox Code Playgroud)
我不能使用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'
Run Code Online (Sandbox Code Playgroud)
我猜测问题是F#无法识别+以这种方式传递时的重载,因为fold隐式输入列表,int因为我使用'0'作为累加器.我不确定是否有可能让我的自定义操作符重载正常工作,如果可能的话,我错过了让它发生的事情.(我假设它可以使这项工作,因为你可以使用+浮动).
我知道问题是类型不匹配.正如JaredPar所写,我知道我可以写一个lambda来获取两个人的记录并添加年龄.那不是我的观点.问题是在我看来应该有一种方法可以让+我已经编写的操作符重载被fold确认为有效的重载.
谢谢大家的意见.有一件事情变得清晰,那就是不可能做我想做的事,但那没关系.我学到了什么!我所看到的是,运算符重载的解决方案使得它们不能在每个上下文中工作 - 因此fold没有无缝的方式可以+作为lambda工作传递,就像用作中缀ala时那样jen + kevin.总而言之,为什么这不起作用.人们建议解决这个问题的解决方案基本上是一次性处理特定问题 - fold我真正想到的是如何获得正确的运算符重载以获取每种情况(即foldback等等) - 我不想写一堆特殊的案例代码来处理列表.很明显不是F#的操作符重载分辨率有一些限制,使它适用于皮肤深层次,这很好.
该List.fold函数采用lambda /函数类型State -> T -> State.+在这种情况下,操作员的类型Person -> Person -> int与签名不兼容.这就是你收到错误的原因.
要折叠年龄,请尝试以下方法
people |> List.fold (fun sum p -> sum + p.Age) 0
Run Code Online (Sandbox Code Playgroud)
在+此处使用运算符作为折叠的一部分的一种方法是Person将Age 映射到Age属性,然后对int +运算符使用fold .
people
|> Seq.ofList
|> Seq.map (fun p -> p.Age)
|> Seq.fold (+) 0
Run Code Online (Sandbox Code Playgroud)
这是一个合理的解决方案,可能对您有用。
type Person = {
Name : string
Age: int
} with
static member (+) (x: Person, y: Person) =
{ Set = Set.ofList [x; y]; SumOfAges = x.Age + y.Age }
and People = {
Set:Person Set
SumOfAges:int
} with
static member (+) (x:People, y:Person) =
{ x with Set = x.Set.Add y; SumOfAges = x.SumOfAges + y.Age }
static member Empty =
{ Set = Set.empty; SumOfAges = 0 }
let p = [ { Name = "Matt"; Age = 32; }; { Name = "Dan"; Age = 26; } ]
let r = p |> List.fold (+) People.Empty
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
578 次 |
| 最近记录: |