Как сравнить значения списка и вернуть true, если все совпадают? - PullRequest
0 голосов
/ 20 мая 2019

Мне нужно взять список карточек и проверить, совпадают ли их цвета. если они возвращают 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 Ответ

2 голосов
/ 20 мая 2019

Для 1-й ошибки ваша вторая ветвь не возвращает bool, вы должны написать:

| x::xs when col = card_color x -> match_col xs col

Для 2-й ошибки, обратите внимание, что 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
...