为什么在这种情况下F#类型推断不起作用

时间:2014-03-22 12:57:27

标签: f#

以下案例

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”关键字,否则无效。

3 个答案:

答案 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。这意味着它现在知道'Tint

传递给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的任何操作的类型特定版本。推断类型将保持通用。您只需要在时间关键的代码段中使用它。

如其他地方所述,通用推理是一个有用的东西,你可能会喜欢它。