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

发布于 2024-09-14 20:48:30 字数 860 浏览 5 评论 0原文

给出以下代码:

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 成员函数具有不同的参数签名,而无需我显式地为它们提供参数类型

Given the following code:

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

The last two lines will not work. I have to do this:

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

Even if I do this, the second line fails:

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

Since F# is all fancy-pants with the type inference, why can't it figure out that the two processItems member functions have different parameter signatures without my having to explicitly provide parameter types for both of them??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

极致的悲 2024-09-21 20:48:30

我认为这个问题的出现是由于 .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

I believe the issue arises because of the difference between methods and properties at the .NET representation level. Your original code would result in two different static properties with the same name (which is not supported). Your intermediate example defines two methods with the same name but different argument types (which is supported). I'm not sure why the final example doesn't work. Note that I don't think that this has anything to do with inference. This works:

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
只涨不跌 2024-09-21 20:48:30

对 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++,请考虑如何创建与这些语言中的原始代码类似的内容。也会出现同样的问题。

Somebody who knows more about F# can probably do a better job with this that I can, but I think it has to do with the fact that the signatures of the arguments (i.e. no arguments) of the members (as values) are the same. It's by the return types that they differ, which is not enough to distinguish them. Providing explicit arguments makes it possible to create different input signatures:

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 

If you know C# or C++, think about how you would create something similar to the original code in those languages. The same problem would obtain.

む无字情书 2024-09-21 20:48:30

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

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 规范并不禁止它)

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

The cause of issue here lies not in type inference. In your first sample use define two properties that has the same names but different return types.

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

second sample is correct because you explicitly declare two methods

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

you can modify it by removing type annotations:

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

in the third sample you are trying to define property and method with the same names (C# prohibits this too, through IIRC it is not forbidden by CLI spec)

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文