1

这是我的代码:

open System

let places = [ ("Grandchester", 552);
               ("Cambridge", 117900);
               ("Prague", 1188126); ]

let statusByPopulation = function
                            | n when n > 1000000 -> "City"
                            | n when n > 50000   -> "Town"
                            | _                  -> "Village"

System.Console.WriteLine ( places |> List.map (fun (_, population) -> statusByPopulation population)) 

let print x = 
    Console.WriteLine (List.map (fun (_, population) -> statusByPopulation population) x) // what I'm trying to do

let something (x:(string * int) list) = 
    List.map (fun (_, population) -> statusByPopulation population) x; // checking what kinf of type it returns

let print: (string * int) list -> unit = 
    Console.WriteLine << List.map (fun (_, population) -> statusByPopulation population) // what I'm not allowed to do

System.Console.ReadKey () |> ignore

我想熟悉函数组合运算符的工作方式,但由于某种原因,F# 找不到函数的最佳重载...

在我明确声明参数的示例中,它将类型设置为val print : x:('a * int) list -> unit,因此我使用组合运算符明确设置函数中的类型,<<希望我能得到正确的结果......我没有......

然后我something使用显式声明的参数类型创建函数,只是为了看看它会返回什么......它返回这个:val something : x:(string * int) list -> string list

所以它肯定会返回一个类型......一个字符串列表,我知道 Console.WriteLine 能够打印......那么为什么它告诉我它无法确定重载?

4

1 回答 1

4

F# 中的类型推断从左到右进行 - 这意味着编译器使用程序早期可用的信息来确定程序稍后的表达式类型(这是一个轻微的简化,但它是一般的想法)。

因此,在您的代码中,当您编写时:

Console.WriteLine << List.map (fun (_, population) -> statusByPopulation population)

.. 编译器不会通过List.map调用将有关函数输入类型的信息传播回WriteLine调用。这也解释了为什么前向链接和组合通常在 F# 中更有用。以下作品:

List.map (fun (_, population) -> statusByPopulation population) >> Console.WriteLine

为了使您的原始代码正常工作,您可以提供一些确定正确WriteLine过载所需的最少信息object。如果你告诉编译器它需要一个列表,那么它可以选择正确的重载:

(Console.WriteLine:list<_> -> unit) << List.map (fun (_, population) -> 
    statusByPopulation population) 
于 2013-10-07T03:11:51.513 回答