2017-08-12 3 views
3

Existe-t-il un moyen de faire correspondre le modèle au seul constructeur indépendant de l'arité du constructeur? Parfois, dans une correspondance de modèle, je m'intéresse uniquement au constructeur et non aux données qui lui sont associées. Mon souci est que quand je change l'arité d'un constructeur dans un ADT, je dois passer par et changer toutes mes correspondances, même celles qui rejettent tous les "champs" (quel est le bon terme?) Sur le constructeur de données.Le modèle Ocaml correspond au constructeur de données indépendamment de son arité

Supposons que j'ai un ADT avec plusieurs constructeurs

(* time * message *) 
type log_message = 
    Warning of float * string 
    | Error of float * string 

et je veux vérifier une valeur de ce type, mais ne se soucient du constructeur que je dois écrire quelque chose comme

let is_error_message x = match x with 
    | Warning _, _ -> false 
    | Error _, _ -> true 

Si plus tard, je veux revenir en arrière et ajouter un champ de gravité à l'avertissement, en me donnant

type log_message = 
    Warning of float * string * int 
| Error of float * string 

Je dois ajouter un nouveau caractère générique au motif dans is_error_message pour satisfaire le vérificateur de type.

let is_error_message x = match x with 
    | Warning _, _, _ -> false 
    | Error _, _ -> true 

Répondre

4

La définition de type

type log_message = 
    | Warning of float * string 
    | Error of float * string 

signifie que les deux constructeurs (Warning et Error) n'acceptent pas deux arguments, mais plutôt un produit (à savoir tuple) d'entre eux. Donc, vous instatiate comme suit:

Warning (4.0, "you better be warned") 

Lorsque la correspondance des modèles sur une instance de cette variante, vous pouvez simplement utiliser _ pour spécifier un tuple de longueur arbitraire (si vous ne se soucient pas des paramètres passés au constructeur):

type log_message = 
    | Warning of float * string 
    | Error of float * string;; 

let is_error_message x = match x with 
    | Warning _ -> false 
    | Error _ -> true;; 

is_error_message (Warning (2.0, "totally not an error"));; 
- : bool = false 
+0

Je pense que je voulais dire 'Avertissement (float string *)' & c ... pour un constructeur multi-paramètre au lieu d'un constructeur unaire prendre un tuple je viens foiré la syntaxe ... (et ne s'est pas rendu compte pourquoi 'Warning _ _' n'était pas valide). Ce que vous dites est tout à fait correct, donc je ne veux pas simplement régler la question en silence. –

+1

Ceci n'est pas correct, les arguments d'un constructeur normal ne sont pas un tuple. La raison pour laquelle '_' peut correspondre à plusieurs arguments est que cela a été ajouté en tant que fonctionnalité pour couvrir ce cas d'utilisation. – gsg

+0

@gsg quelle version a été ajoutée? –