如何比较列表中的值,如果全部匹配,则返回true?

时间:2019-05-19 21:19:39

标签: list types f# pattern-matching

我需要列出一张卡片,并检查它们的颜色是否相同。如果它们返回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'

1 个答案:

答案 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