Reputation: 65
I need to take a list of cards and check to see if their colors are the same. if they are return true otherwise return false. The function card_color is used to determine the color of a card.
When I try to implement with a recursive function called match_col and pattern matching I get several errors.
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
I expect the function match_col to return true if the entire list has the same color as the first element in the list. If not then return false. However, the compiler throws:
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'
Upvotes: 0
Views: 336
Reputation: 3784
For the 1st error, your second branch is not returning bool
, you should write:
| x::xs when col = card_color x -> match_col xs col
For the 2nd error, please note that not
is actually a function, so it expects a bool
value not a Color
value, you should write:
| x::xs when not (col = card_color x) -> false
Compiler now still cannot make sure your matching is complete because it cannot know the function card_color
is pure or impure. It will warn you warning FS0025: Incomplete pattern matches on this expression.
So, you should write:
let rec match_col cs col =
match cs with
| [] -> true
| x::xs when col = card_color x -> match_col xs col
| _ -> false
But going through a list and checking if there is an element satisfied a condition is already supported by the List
module. So, you could write:
let match_col cs col =
cs |> List.exists (fun x -> card_color x <> col) |> not
Finally, to access an element of a list, you should use the dot
notation: cs.[0]
not cs[0]
. But when using the dot
notation, you have to provide type annotation, so we have to write:
let all_same_color (cs : Card list) =
let col = card_color cs.[0]
let res = match_col cs col
res
Another way to write without dot notation
:
let all_same_color cs =
let col = card_color (cs |> List.head)
let res = match_col cs col
res
Upvotes: 2