Set.union F#麻烦 [英] Set.union F# trouble
问题描述
我有一个Set<String*String>
,并且我正在尝试编写一个函数,该函数接受该Set的所有元素并返回一个Set<String>
.我的想法是使用Set.fold,并有一个空的set累加器并采用这两个set的并集,但是我遇到了问题.这是代码:
I have a Set<String*String>
, and I'm trying to write a function that takes all the elements of that Set and return a Set<String>
. My idea is to use Set.fold, and have an empty set accumulator and take the union of the two sets, but I'm running into problems. Here is the code:
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>
推荐答案
查看您的类型和函数签名.
Look at your types and function signatures.
Set.fold
将'State -> 'T -> 'State
作为folder
功能. 'State
是您要折叠的类型,它将是最终的返回值,因此在这种情况下,您希望它的类型为Set<Country>
.
Set.fold
takes a 'State -> 'T -> 'State
as the folder
function. 'State
is the type that you're folding into and that will be the eventual return value, so in this case, you want it to be of type Set<Country>
.
这意味着您的lambda不正确,因为第一个参数是元组.因此,我们可能应该切换该lambda的参数:
That means your lambda can't be right, because the first argument is a tuple. So we should probably switch the arguments of that lambda:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> Set.union [x;y] set ) chart []
可以给我们提供帮助的编译
Compiling that gives us
(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
从列表中创建一个集合:
(96,39) in this case is the Set.union
function, and of course that is not used correctly, because it requires two sets, but we're passing it one set and a list. We can create a set from the list using Set.ofList
:
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) chart []
同样,我们遇到了另一个错误,所以我们可能正在取得进展:
Again, we're getting a different error, so we're probably making progress:
(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
,让我们开始吧:
(96,80) is the empty list at the end of the line - and of course, that's wrong, because the third argument to Set.fold
needs to be Set<'T>
. The set replacement for an empty list would be Set.empty
, so let's go with that:
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>
.
It compiles! But as you found, it returns Set<Country * Country>
instead of just Set<Country>
.
在这种情况下,类型推断使我们很难了解发生了什么,因此我们应该继续进行操作,并在确切知道类型需要是什么的地方添加类型标注.最明显的地方是函数的返回类型:
Cases like this are when type inference makes it a little harder to see what's going on, so we should go ahead and add type annotations where we know exactly what the types need to be. The most obvious place is the return type of the function:
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
是最后一个参数,所以我们得出了
That error is for the second argument of Set.fold
, and the reason is that once again, the arguments are in the wrong order. The signature of Set.fold
is ('State -> 'T -> 'State) -> 'State -> Set<'T> -> 'State
. If we look at what we already have, 'State
in this case is Set<Country>
, and 'T
is Country * Country
. That means Set.empty
needs to be the second and chart
the last argument, and so we arrive at
let countriesInChart (chart : Chart) =
Set.fold(fun set (x,y) -> [x; y] |> Set.ofList |> Set.union set) Set.empty chart
函数式编程的最重要规则是:让类型指导您! ;-)
The most important rule of functional programming is this: Let the types guide you! ;-)
这篇关于Set.union F#麻烦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!