web-dev-qa-db-fra.com

Correspondance de modèle d'enregistrement Haskell

Je cherche un moyen de simplifier les modèles de fonction lorsque les données réelles ne sont pas nécessaires:

data X = A | B String | C Int Int String
myfn :: X -> Int
myfn A = 50
myfn (B _) = 200
myfn (C _ _ _) = 500

Existe-t-il un moyen de créer un modèle plus simple pour faire correspondre C, en rejetant simplement les valeurs?

hsdev ajoute un conseil "Conseil: utilisez des modèles d'enregistrement", mais Google ne m'a pas aidé là-bas.

29
theduke

Vous pouvez utiliser des modèles d'enregistrement comme celui-ci:

data X = A | B {name :: String} | C {x::Int, y::Int, name::String}

myfn :: X -> Int
myfn A = 50
myfn B{} = 200
myfn C{} = 500

Les modèles d'enregistrement vous permettent de donner des noms aux champs des constructeurs. vous pouvez également faire des choses comme:

myfn C{name=n} = length n

vous pouvez donc voir que vous ne pouvez faire correspondre les motifs que sur le champ spécifique dont vous avez besoin.

Remarque: vous pouvez utiliser le modèle d'enregistrement vide même avec des types de données qui n'utilisent pas la syntaxe d'enregistrement:

data A = A Int | B Int Int

myfn A{} = 1
myfn B{} = 2

C'est bon. Il existe un certain nombre d'autres extensions liées aux modèles d'enregistrement:

  • RecordWildCards vous permet d'écrire des choses comme C{..} qui est équivalent au motif: C{x=x, y=y, name=name}, c'est-à-dire qu'il correspond à tous les champs et vous avez maintenant dans la portée x avec la valeur correspondant au champ x etc.

  • NamedFieldPuns vous permet d'écrire C{name} pour être équivalent à C{name=name}, de sorte que name est désormais dans la portée et contient la valeur correspondant au champ name.

Gardez à l'esprit que l'utilisation de modèles d'enregistrement ne vous empêche pas d'utiliser vos constructeurs de manière positionnelle, vous pouvez donc toujours écrire:

myfn (B _) = 200

Seul ajoute des fonctionnalités.

62
Bakuriu