我有Set<String*String>
,我正在尝试编写一个函数,该函数接受该Set的所有元素并返回Set<String>
。我的想法是使用Set.fold,并有一个空集累加器并采用两个集合的并集,但我遇到了问题。这是代码:
type Chart = Set<Country*Country>;;
let countriesInChart (chart : Chart) =
Set.fold(fun (x,y) set -> Set.union [x;y] set ) chart []
但是我收到了这个错误
Set.fold(fun (x,y) set -> Set.union [x;y] set ) chart [];;
--------------------------------^^^^^^^^^^^^^^^^^^^
error FS0001: This expression was expected to have type
'a * 'b
but here has type
Set<'c>
答案 0 :(得分:4)
查看您的类型和功能签名。
Set.fold
将'State -> 'T -> 'State
作为folder
函数。 'State
是您要折叠的类型,它将是最终的返回值,因此在这种情况下,您希望它的类型为Set<Country>
。
这意味着你的lambda不能正确,因为第一个参数是一个元组。所以我们应该切换那个lambda的参数:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> Set.union [x;y] set ) chart []
编译给我们
(96,39): error FS0001: This expression was expected to have type
Set<'a>
but here has type
'b list
在这种情况下,(96,39)是Set.union
函数,当然没有正确使用,因为它需要两个集合,但我们传递一个集合和一个列表。我们可以使用Set.ofList
:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart []
同样,我们得到了一个不同的错误,所以我们可能正在取得进展:
(96,80): error FS0001: This expression was expected to have type
Set<(Country * Country) * (Country * Country)>
but here has type
'a list
(96,80)是该行末尾的空列表 - 当然,这是错误的,因为Set.fold
的第三个参数需要是Set<'T>
。空列表的集合替换为Set.empty
,所以让我们继续:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart Set.empty
它汇编!但正如您所发现的那样,它会返回Set<Country * Country>
而不只是Set<Country>
。
这样的情况是,当类型推断使得查看正在发生的事情变得有点困难时,我们应该继续添加类型注释,我们确切地知道类型需要什么。最明显的地方是函数的返回类型:
let countriesInChart (chart : Chart) : Set<Country> =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart Set.empty
现在错误是:
(96,74): error FS0001: Type mismatch. Expecting a
Set<Country>
but given a
Chart
The type 'Country' does not match the type 'Country * Country'
该错误是针对Set.fold
的第二个参数,原因是再一次,参数的顺序错误。 Set.fold
的签名是('State -> 'T -> 'State) -> 'State -> Set<'T> -> 'State
。如果我们查看已有的内容,则'State
在这种情况下为Set<Country>
,'T
为Country * Country
。这意味着Set.empty
需要成为第二个chart
最后一个参数,所以我们到达
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) Set.empty chart
函数式编程最重要的规则是:让类型引导你! ; - )
答案 1 :(得分:0)
试试这个:
let f (chart: Chart) =
Set.fold (fun (x:Set<string>) (a,b) -> x |> Set.add a |> Set.add b) Set.empty chart
我不确定类型注释是否必要,但它确实强制输出为Set<string>
。