F#: Why am I required to supply parameter types when overloading member functions?
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 My开发者_StackOverflow中文版Type.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??
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
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.
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
精彩评论