Set.union F#麻烦 [英] Set.union F# trouble

查看:100
本文介绍了Set.union F#麻烦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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.如果我们查看已有的内容,在这种情况下,'StateSet<Country>,而'TCountry * 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆