La seule difficulté provient de la carte Joker, qui peut remplacer n'importe quelle autre carte. Un joker est compatibles avec deux cartes qui ne sont pas compatibles entre elles. La relation de compatibilité n'est donc pas une relation d'équivalence.

On définit la relation asymétrique binaire remplaçable_par: la carte Roi est remplaçable par la carte Joker, mais pas l'inverse.

let remplacable_par x y = match x, y with Carte u, Carte v -> u.figure = v.figure | _, Joker -> true | Joker, Carte _ -> false let non_remplacable_par x y = not (remplacable_par y x);;

La fonction compatibles est définie pas induction. Si la main est vide, l'ensemble des parties compatibles est vide. Si le premier élément de la main est un joker, alors les parties compatibles sont celles du reste de la main dans chacune desquelles il faut ajouter un joker. Sinon, le premier élément est une carte ordinaire: les parties compatibles sont d'une part l'ensemble des cartes compatibles avec celle-ci, et l'ensemble des parties compatibles avec les cartes qui ne sont pas compatibles avec celle-ci.

let rec compatibles carte = match carte with | Joker :: t -> List.map (fun p -> Joker::p) (compatibles t) | h :: t -> let found = h :: List.find_all (remplaçable_par h) t in let rest = compatibles (List.find_all (non_remplaçable_par h) t) in found :: rest | [] -> [];;