F#:重载成员函数时为什么要求我提供参数类型?

F#:重载成员函数时为什么要求我提供参数类型?,f#,operator-overloading,type-inference,F#,Operator Overloading,Type Inference,给定以下代码: type MyType() = static member processString (_string:string) = _string.Substring(0, 1) static member processInt (_int:int) = _int.ToString() static member processItems = List.map MyType.processString static member processItems

给定以下代码:

type MyType() =
    static member processString (_string:string) = _string.Substring(0, 1)
    static member processInt (_int:int) = _int.ToString()
    static member processItems = List.map MyType.processString
    static member processItems = List.map MyType.processInt
最后两行行不通。我必须这样做:

    static member processItems (_strings:string list) = _strings |> List.map MyType.processString
    static member processItems (_ints:int list) = _ints |> List.map MyType.processInt
即使我这样做,第二行也会失败:

    static member processItems (_strings:string list) = _strings |> List.map MyType.processString
    static member processItems = List.map MyType.processInt

既然F#是一个具有类型推断功能的高级函数,为什么我不必显式地为这两个processItems成员函数提供参数类型,它就不能发现这两个processItems成员函数具有不同的参数签名呢?

了解F#更多的人可能会比我做得更好,但我认为这与成员(作为值)的参数(即无参数)的签名是相同的这一事实有关。它们的区别在于返回类型,这还不足以区分它们。提供显式参数可以创建不同的输入签名:

type MyType() = 
    static member processString (_string:string) = _string.Substring(0, 1) 
    static member processInt (_int:int) = _int.ToString() 
    static member processFloat (_float:float) = _float.ToString() 
    static member processItems a = a |> List.map MyType.processString  
    static member processItems a = a |> List.map MyType.processInt 
    static member processItems a = a |> List.map MyType.processFloat 

<>如果你知道C或C++,想想你如何创建类似于那些语言中的原始代码的东西。同样的问题也会出现。

我认为问题的出现是因为.NET表示级别的方法和属性之间存在差异。您的原始代码将导致两个具有相同名称的不同静态属性(不受支持)。中间示例定义了两个名称相同但参数类型不同(受支持)的方法。我不确定最后一个例子为什么不起作用。注意,我不认为这与推理有任何关系。这项工作:

type MyType() = 
    static member processString (_string:string) = _string.Substring(0, 1) 
    static member processInt (_int:int) = _int.ToString() 
    static member processItems l = l |> List.map MyType.processString 
    static member processItems l = l |> List.map MyType.processInt

这里的问题不在于类型推断。在第一个示例中,使用定义两个名称相同但返回类型不同的属性

type MyType() =
    static member processString (_string:string) = _string.Substring(0, 1)
    static member processInt (_int:int) = _int.ToString()
    static member processItems = List.map MyType.processString
    static member processItems = List.map MyType.processInt
第二个示例是正确的,因为您显式声明了两个方法

type MyType() =
    static member processString (_string:string) = _string.Substring(0, 1)
    static member processInt (_int:int) = _int.ToString()
    static member processItems (_strings:string list) = _strings |> List.map MyType.processString
    static member processItems (_ints:int list) = _ints |> List.map MyType.processInt
您可以通过删除类型批注来修改它:

type MyType() =
    static member processString (_string:string) = _string.Substring(0, 1)
    static member processInt (_int:int) = _int.ToString()
    static member processItems s = s |> List.map MyType.processString
    static member processItems i = i |> List.map MyType.processInt
在第三个示例中,您试图使用相同的名称定义属性和方法(C#也禁止这样做,通过IIRC,CLI规范并不禁止这样做)


我给出的第二个例子确实有效(正如我所写的)。有趣的是,你的例子是有效的!你关于这是一个.NET问题的解释听起来很有道理。谢谢你的回复,让我大开眼界@哎呀,我在回答中调高了“中间”和“最终”。我已经编辑了答案。明白了,我以为我是在使用部分应用程序来定义方法,但实际上我只是在定义属性。明白了,这就清楚了!谢谢
type MyType() =
    static member processString (_string:string) = _string.Substring(0, 1)
    static member processInt (_int:int) = _int.ToString()
    static member processItems (_strings:string list) = _strings |> List.map MyType.processString
    static member processItems = List.map MyType.processInt