Une autre façon de voir les choses est que vous avez une relation d'équivalence pour votre type, c'est-à-dire que vous avez des endroits où vous voulez traiter tous les types de données. MAlpha
est le même, tous les MBeta
est le même, et tous les MGamma
est le même. Une manipulation standard pour les relations d'équivalence consiste à choisir un élément représentatif qui représente l'ensemble des valeurs équivalentes (la classe d'équivalence).
Dans votre cas, vous pourriez utiliser MAlpha
pour représenter tous les MAlpha
(mais il n'y en a qu'un seul), MBeta []
pour représenter tous les MBeta
et MGamma ("", 0)
pour représenter tous les MGamma
s. Vous auriez une fonction pour calculer la valeur représentative à partir d'une valeur donnée :
let malpha = MAlpha
let mbeta = MBeta []
let mgamma = MGamma ("", 0)
let canonicalize =
function
| MAlpha -> malpha
| MBeta _ -> mbeta
| MGamma _ -> mgamma
let find_first where what =
canonicalize (List.find (fun x -> List.mem (canonicalize x) what) where)
let main () =
let where_to_find = [MGamma ("a", 3); MAlpha; MBeta [3; 4]] in
let what_to_find = [malpha; mbeta] in
try
let found = find_first where_to_find what_to_find
in
if found = malpha then (* what to do *)
else if found = mbeta then (* what to do *)
else (* what to do *)
with Not_found -> (* nothing was there *)
J'ai déjà écrit du code comme ça et ça n'est pas si mal. Dans votre cas, cela vous permet de spécifier le what
paramètre un peu naturellement. Un inconvénient, cependant, c'est que vous ne pouvez pas faire de correspondance de motif avec malpha
, mbeta
y mgamma
. Vous devez faire des comparaisons d'égalité avec eux.
Il se peut que vous vouliez trouver la valeur spécifique dans la liste, plutôt que la valeur canonisée. Je pense que les changements pour ce cas devraient être assez clairs.
Cela répond également à la deuxième partie de votre question. Le site List.find
s'arrêtera dès qu'elle aura trouvé ce qu'elle cherche.
OCaml définit une relation d'ordre pour tous les types qui ne contiennent pas de valeurs fonctionnelles. Si cet ordre intégré (polymorphe) ne fait pas ce que vous voulez, vous devez définir le vôtre. Vous auriez certainement besoin de le faire pour comparer des valeurs de deux types différents, mais ce n'est pas ce que vous faites ici.
Si aucun élément de la liste ne ressemble à ce que vous avez dit que vous vouliez, cette version de la fonction find_first
soulèvera l'exception Not_found
. C'est une autre chose à laquelle il faut penser.