我无法理解F#类型推理器的行为。运算符string
在编译时依赖于静态类型调度,而不是运行时,这就是为什么let lowerstring = string >> (fun s -> s.ToLowerInvariant())
之类的东西不是通用的 - 编译器需要知道参数的类型。但是,我看到了一些奇怪的行为。
具有以下定义:
let inline lower (s: string) = s.ToLowerInvariant()
// 'T -> string, constrained to the type of its first use
let lowerstring1 = string >> lower
// Same as above
let lowerstring2 value = value |> string |> lower
// Same as above
let lowerstring3 = box >> string >> lower
// 'a -> string, fully generalized
let lowerstring4 value = value |> box |> string |> lower
我观察到这种行为:
// val token: JToken
// val num: int
let tokstr1 = lowerstring1 token // lowerstring1 now has type JToken -> string
let numstr1 = lowerstring1 num // Error, doesn't compile
(* As above with lowerstring2 and lowerstring3 *)
let tokstr4 = lowerstring4 token // lowerstring4 now has type 'a -> string
let numstr4 = lowerstring4 num // no error, works as 'expected'
我不清楚为什么lowerstring3
和lowerstring4
的格式不同。静态约束似乎很可能,但如果是这种情况,那么lowerstring4
是否应该不能概括?为什么函数参数的显式存在会产生差异呢?
答案 0 :(得分:1)
F#必须将代码转换为IL,并且由于.NET中没有通用的“值”,因此只有当它们是真正的合成函数(生成为可以是通用的.NET方法)时才会生成函数。 / p>
(一个例外是[<GeneralizableValueAttribute>]
,请参阅例如here。)