gpt4 book ai didi

f# - 模式匹配类型转换类型

转载 作者:行者123 更新时间:2023-12-03 15:09:28 26 4
gpt4 key购买 nike

我是 F# 的新手,一直在按照指南尝试使一段代码工作,但它没有。

我通过继承创造了单人和合作运动的类型。

然后我使用模式匹配来了解类型,如果它是一项合作运动,还可以获得玩家数量。然后相应地对每个进行排名。

但是,我一直收到错误消息。我在这方面遵循了 Microsoft 示例,但我并不真正理解这些错误。我没有函数式编程背景。

type Sport (name: string) =
member x.Name = name

type Individual(name: string) =
inherit Sport(name)

type Team(name: string, numberOfPlayers : int) =
inherit Sport(name)
member x.numberOfPlayers = numberOfPlayers


let MK = new Individual("Combate Mortal")
let SF = new Individual("Lutadores de Rua")
let Tk = new Individual("Tekken Chupa")

let MvC = new Team("Marvel Contra Capcom", 3)
let Dbz = new Team("Bolas do Dragao", 3)

let interpretSport (sport:string) (players:int) =
match sport with
| "Combate Mortal" -> printfn "Rank1"
| "Lutadores de Rua" -> printfn "Rank2"
| "Tekken Chupa" -> printfn "Rank3"
| "Bolas do Dragao" -> printfn "Rank4. No of players: %d " players
| "Marvel Contra Capcom" -> printfn "Rank5. No of players: %d" players
| _ -> printfn "not a sport in our list..."



let matchSport (sport:Sport) =
match sport with
| :? Individual -> interpretSport(sport.Name)
| :? Team as teamSport -> interpretSport(teamSport.Name,teamSport.numberOfPlayers)
| _ -> printfn "not a sport"

matchSport(MK)
matchSport(SF)
matchSport(Tk)
matchSport(MvC)
matchSport(Dbz)

调用具有 1 个以上参数的函数时出现第一个错误:


打印时的第二个错误:

最佳答案

这个问题已经回答了,但是因为提问者说他​​是 F# 的新手,也许值得稍微迭代一下。
首先,您定义一个带有两个参数的函数:

let interpreteSport (sport:string) (player:int) =

在 F# 中,没有与 C# 中存在相同意义的可选参数的概念,因此如果您声明一个带有两个参数的函数,并且您想调用它并获取它的返回值,则必须提供所有参数放入它的定义。
所以在匹配表达式的第一个分支中,当你写:
:? Individual -> interpretSport(sport.Name)

你犯了一个错误,只将一个参数传递给一个需要两个参数的函数。

可是等等! 为什么编译器不会用错误提醒您,说您正在调用一个带有一个参数的函数,而它需要两个参数?
因为事实证明,您编写的内容,即使它没有像您相信的那样调用 interpreteSport 函数,它也是 F# 中完美有效的表达式。
它返回的是一个称为“部分应用函数”的表达式,即一个函数已经收到它的第一个参数,正在等待另一个参数。
如果你将这样一个表达式的结果赋给一个值,让我们说:
let parzFun = interpretSport sport.Name 

然后你可以在你的代码中传递这个值,当你准备好提供缺少的参数时,像这样评估它:
let result = parzFun 1

这就是编译器在谈论 'int -> unit' 时告诉您的内容:F# 中的函数签名以这种形式给出:
a -> b -> c -> d -> retval , 其中 a, b, c, d 等是参数的类型,retVal 是返回值。

您的 interpreteSport 函数的签名为: string -> int -> unit ,其中 unit是特殊类型,表示“无值”,类似于 C# void,但最大的不同在于 unit 是一个可以正确赋值的表达式,而 void 只是一个关键字,不能将变量赋值给 void在 C# 中。

好的,所以,当你调用你的函数只传递第一个参数(一个字符串)时,你得到的是一个 int -> unit 类型的表达式。 ,这是另一个期望和整数并返回单位的函数。

因为这个表达式在一个匹配表达式的一个分支中,并且因为一个匹配表达式的所有分支必须返回相同的类型,所以其他 2 个分支也应该返回一个 int -> unit函数,它不是什么,这就解释了你的第二个错误。

稍后会详细介绍,但在此之前,我们必须查看编译器报告的第一个错误,由这行代码引起:
:? Team as teamSport -> interpretSport(teamSport.Name,teamSport.numberOfPlayers)

在这里,您认为您正在使用 2 个参数调用您的函数,但您实际上不是:当您将 2 个值放在括号中并用逗号分隔时,您正在创建一个元组,即由两个或多个组成的单个值值。就像您再次仅传递第一个参数,但现在类型错误:函数的第一个参数是字符串,而您传递的是元组:('a * 'b) 是 F# 表示元组的方式:表示由类型为 'a (泛型,在您的情况下为字符串)和另一个类型为 'b (泛型,在您的情况下为整数)的值组成的单个值。
要正确调用您的函数,您必须这样调用它:
:? Team as teamSport -> interpretSport teamSport.Name teamSport.numberOfPlayers

但是,即使您将自己限制在此更正范围内,您也会遇到第二个错误,因为请记住,您的匹配项的第一个表达式返回部分应用函数,因此 int -> unit (一个需要整数并返回一个单位的函数)而您的第二个和第三个表达式现在是类型 unit ,因为它们实际上调用了两个返回 unit 的函数( interpreteSportprintfn )。要完全修复您的代码,正如其他答案中已经说过的那样,您必须向第一次调用提供缺少的整数参数,因此:
let matchSport (sport:Sport)  = 
match sport with
| :? Individual -> interpretSport sport.Name 1
| :? Team as teamSport -> interpretSport teamSport.Name teamSport.numberOfPlayers
| _ -> printfn "not a sport"

关于f# - 模式匹配类型转换类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49403901/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com