你得到的类型是不是一个“多晶型”类型,它是一个函数类型。您得到类型'a -> int * int
而不是您期望的int * int
结果的原因是您没有将所有参数传递给您的函数,因此F#返回了一个函数,该函数需要其余参数。这就是所谓的“部分应用程序”,你可以在这里阅读更多关于它:
https://fsharpforfunandprofit.com/posts/currying/
和
https://fsharpforfunandprofit.com/posts/partial-application/
两篇文章的简要总结:在F#中,所有功能都视为取一个参数并返回一个结果。是的,所有功能。当您创建一个看起来需要两个参数的函数时,F#会在内部重写它。它变成一个函数,它接受一个参数并返回第二个函数;这第二个函数接受一个参数并返回结果。在这一点上,一个具体的例子可能会有用。考虑一下这个功能:
let doubleAndSubtract a b = (a * 2) - b
(显然,围绕a * 2
括号并不真正需要,但我离开了他们,使功能明确的阅读)。
内部,F#实际上重写此功能为以下:
let doubleAndSubtract a =
let subtract b = (a * 2) - b
subtract
换句话说,它构建一个功能“关闭了”(捕获),您传入的a
值。所以,下面的两个功能是完全等价的:
let explicitSubtract b = (5 * 2) - b
let implicitSubtract = doubleAndSubtract 5
如果您在到F#交互提示符下键入这些功能,并期待在其声明每个函数有类型,explicitSubtract
的类型为b:int -> int
,并implicitSubtract
的类型是int -> int
。这两者之间的唯一区别是explicitSubtract
的类型命名参数,而implicitSubtract
不会“知道”其参数的名称。但是两者都会接受一个int,并返回一个int(具体来说,是减去参数)。
现在,让我们来看看doubleAndSubtract
的类型签名。如果您将其输入到F#交互式提示符中,则会看到它的类型签名为int -> int -> int
。在类型签名中,->
是右关联的,所以签名实际上是int -> (int -> int)
- 换句话说,函数接受一个int并返回一个接受int并返回int的函数。 但是你也可以把它看作一个函数,它需要两个int并返回一个int,并且你可以这样定义它。
那么,发生了什么与您的代码这里是你定义这样的功能:
let get_mouse_position (relative_to : IInputElement) (args : Input.MouseEventArgs) : (int*int) = ...
这是一个有两个参数(类型IInputElement
和Input.MouseEventArgs
),并返回整数的元组的功能。 ... 但这相当于一个函数,该函数接受IInputElement
类型的一个参数,并返回一个函数,该函数需要一个Input.MouseEventArgs
并返回一个包含两个整数的元组。换句话说,你的函数签名是:
IInputElement -> Input.MouseEventArgs -> (int * int)
当你叫它为get_mouse_position element
你通过它只有一个参数,你有这么什么Input.MouseEventArgs -> (int * int)
类型的函数。类型检查器将此类型报告为类型'a -> int * int
(将Input.MouseEventArgs
更改为泛型类型名称'a
),原因我不想进入此处(这已经很长),但这就是为什么您得到了结果。
我希望这可以帮助您更好地理解F#函数。并阅读我链接的两篇文章;他们会进一步理解你的理解。
您忘了在'get_mouse_position元素'中添加参数。习惯这个错误信息;它会发生很多:) – Ray