以下案例
let a = [1]
let f x = x
let b = a |> List.map f
a是一个int列表。我们调用List.map以确保f必须是int->?功能。为什么f仍然键入'a - >'a而不是int-> int? 如果这就是F#中类型推断(不)的工作方式,我认为它没什么好处。
是否有解决方法而未明确指定f中的x类型? 让我们想象一下x有类型(A * B * C列表(D选项,E列表)))
另一个有趣的事情:
open System.Collections.Generic
let d = new Dictionary()
d.[1] ="a"
除非删除“new”关键字,否则无效。
答案 0 :(得分:4)
类型推理在这里工作得很好。 f
被推断为具有类型'a -> 'a
,这意味着它将获取泛型类型'a
的值并返回相同泛型类型'a
的值。
在这种情况下,当您使用时,类型推理会启动。由于a
的类型为int list
,并且因为List.map
具有签名('T -> 'U) -> 'T list -> 'U list
,因此它可以从表达式中推断类型
let b = a |> List.map f
在这种情况下,'T list
参数为a
,因此它的类型为int list
。这意味着它现在知道'T
是int
。
传递给List.map
的函数的格式为'T -> 'U
,但在这种情况下,我们传递的f
格式为'a -> 'a
,相当于{{ 1}}。因此,编译器理解在这种情况下,'T -> 'T
和'T
是相同的类型。
这意味着它可以推断返回类型'U
也必须是'U list
。
答案 1 :(得分:3)
函数f
的类型为'a -> 'a
,因为它适用于所有类型,而不仅仅是int
:
> f "foo";;
val it = "foo" : string
> f 0.8;;
val it = 0.8 : float
这样做有一个优势:通用类型'a -> 'a
可以让您在安全的情况下自由使用f
,而不是只在int -> int
类型。
答案 2 :(得分:0)
为此处列出的优秀答案添加一些内容。
有一种情况是您不想使用通用推断类型。 f的通用版本将比特定于版本的版本慢。但是F#有一个关键字可以帮助你解决这个问题:
let inline f x = x
它告诉编译器使用您应用于x的任何操作的类型特定版本。推断类型将保持通用。您只需要在时间关键的代码段中使用它。
如其他地方所述,通用推理是一个有用的东西,你可能会喜欢它。