我需要列出一张卡片,并检查它们的颜色是否相同。如果它们返回true,否则返回false。函数card_color用于确定卡的颜色。
当我尝试使用名为match_col和模式匹配的递归函数实现时,会遇到一些错误。
type Suit = Clubs | Diamonds | Hearts | Spades
type Rank = Jack | Queen | King | Ace | Num of int
type Card = Rank * Suit
type Color = Red | Black
type Move = Discard of Card | Draw
let card_color (c:Card) =
match c with
| _, Clubs -> Black
| _, Spades -> Black
| _, Diamonds -> Red
| _, Hearts -> Red
let rec match_col cs col =
match cs with
| [] -> true
| x::xs when col = card_color x -> match_col xs
| x::xs when not col = card_color x -> false
let all_same_color cs =
let col = card_color (cs[0])
let res = match_col cs col
res
如果整个列表的颜色与列表中的第一个元素相同,我希望函数match_col返回true。如果不是,则返回false。但是,编译器会抛出:
fs(40,40): error FS0001:All branches of a pattern match expression must have the same type. This expression was expected to have type 'bool', but here has type 'Color-> bool'.
fs(41,28): error FS0001: This expression was expected to have type
'bool'
but here has type
'Color'
fs(45,23): error FS0001: This expression was expected to have type
'Card list'
but here has type
'int list -> Card'
答案 0 :(得分:2)
对于第一个错误,您的第二个分支未返回bool
,您应输入:
| x::xs when col = card_color x -> match_col xs col
对于第二个错误,请注意not
实际上是一个函数,因此它期望一个bool
值而不是一个Color
值,您应该编写:
| x::xs when not (col = card_color x) -> false
编译器现在仍然不能确保您的匹配完成,因为它不知道函数card_color
是纯函数还是不纯函数。它会警告您warning FS0025: Incomplete pattern matches on this expression.
因此,您应该输入:
let rec match_col cs col =
match cs with
| [] -> true
| x::xs when col = card_color x -> match_col xs col
| _ -> false
但是List
模块已经支持遍历列表并检查是否存在满足条件的元素。因此,您可以这样写:
let match_col cs col =
cs |> List.exists (fun x -> card_color x <> col) |> not
最后,要访问列表的元素,应使用dot
表示法:cs.[0]
而不是cs[0]
。但是,当使用dot
表示法时,您必须提供类型标注,因此我们必须编写:
let all_same_color (cs : Card list) =
let col = card_color cs.[0]
let res = match_col cs col
res
没有dot notation
的另一种书写方式:
let all_same_color cs =
let col = card_color (cs |> List.head)
let res = match_col cs col
res