F# 解决类方法调用的奇怪差异

标签 f#

给定以下 F# 代码

type MyClass = class end

type MyWorker1() = 
    (*1*)member this.DoWork(myObject: MyClass) = ()
    (*2*)member this.DoWork(myObjects: MyClass seq) = myObjects |> Seq.iter this.DoWork //Resolves to (*1*)

type MyWorker2() = 
    (*3*)member this.DoWork(myObject: #MyClass) = ()
    (*4*)member this.DoWork(myObjects: #MyClass seq) = myObjects |> Seq.iter this.DoWork //Resolves to (*4*)

在 MyWorker2 中,调用 this.DoWork 被解析为递归调用。我希望表现得像在 MyWorker1 中那样,即调用 (*3*)。

有人可以解释造成这种差异的原因吗?

最佳答案

正如 @Gus on Slack 所报道的那样,这可能是一个错误,很好,你报告了它!请注意,它似乎只发生在 seq 上。 ,而不是其他集合类型,如 arraylist .当您使用 let 时也不会发生这种情况绑定(bind)而不是 memberstatic member .

这可能是因为let除非添加 rec,否则绑定(bind)不能自引用.通过添加 rec ,您实际上再次看到相同的行为,但这次是预期的。

我很惊讶 F# 添加了一个额外的约束 'a :> seq<'a> ,我觉得这真的很奇怪。

因为这是 SO,而且我假设这会阻止某种编码模式,所以这里有一个解决方法。这是一个额外的间接寻址,但如果您在现实世界的代码中需要上述模式,可以按照以下方法进行操作:

type MyWorker2() = 
    let doWork1(myObject: #MyClass) = ()
    let doWork2(myObjects: seq<#MyClass>) = myObjects |> Seq.iter (fun x -> doWork1 x) //Resolves to (*4*)

    member this.DoWork(myObject: #MyClass) = doWork1 myObject
    member this.DoWork(myObjects: seq<#MyClass>) = doWork2 myObjects

一个观察,如果你使私有(private)let -绑定(bind)相同的名称(即只是 doWork 而不是 doWork1|2 ),额外类型限制的问题出现在第一个 DoWork 上.但这一次是有道理的,因为 let 绑定(bind)相互影响。

关于F# 解决类方法调用的奇怪差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73467027/

相关文章:

.net - F# 电子邮件监听器

f# - 伪造的 dotCover

visual-studio - 为什么 F# Interactive 不标记此错误?

F# 图形库(类似 ocamlgraph)

.net - 带有嵌套聚合的Elasticsearch NEST客户端

.net - 如何在 F# 中打印格式化日期

dynamic - 使用 F# 在类/接口(interface)中动态定义多个成员

generics - F# - 类型参数在 'k : comparison 时缺少约束

c# - F# 伤了我的脑子……谁能帮忙把 C# 翻译成 F#?

f# - 让 FParsec 拒绝不匹配的开始结束标签?