在这个片段中,当前(4.1)编译器抱怨它无法确定转换为使用哪个重载(可能需要类型注释),但它将s识别为字符串。为什么呢?
let wtf (list:string List) =
List.map (fun s -> System.Convert.ToInt32(s)) list
答案 0 :(得分:8)
如评论中所述,编译器对代码使用单次传递来确定类型。这意味着当它通过有问题的代码时,它将报告错误(例如,当它无法确定使用哪个重载时)。如果以后找到更多信息,则不使用其他信息。
这正是这里发生的事情。考虑:
let wtf (list:string List) =
List.map (fun s -> s) list
此处,s
的类型为string
,一切正常。但是,在检查fun s -> s
时,编译器还不知道s
的类型是string
,并且它将其视为类型变量'a
的值 - 它会检查函数类型为'a -> 'a
,稍后会将'a
与string
统一起来。回到你的案子:
let wtf (list:string List) =
List.map (fun s -> System.Convert.ToInt32(s)) list
检查lambda时,编译器知道s
类型为'a
,但无法解决ToInt32
的重载问题。它报告错误,跳过子表达式并继续(尽可能获得有用的IntelliSense),后来发现s
实际上是string
。这出现在IntelliSense中,但它不会撤消错误。
仅为了记录,避免这种情况的最佳方法是使用|>
并首先输入list
输入:
let awesome (list:string List) =
list |> List.map (fun s -> System.Convert.ToInt32(s))