8
votes

Comment mettre en œuvre «ORD» pour les types de données algébriques dans HASKELLL?

Imaginez que vous avez une note comme

Rating = OneStar | TwoStars | ThreeStars | FourStars | FiveStars


0 commentaires

4 Réponses :


15
votes

Le meilleur moyen serait de simplement ajouter dérivé (eq, ord) à la définition du type.

Étant donné que vous avez répertorié vos constructeurs en ordre croissant, l'instance Dérive ORD vous donnera exactement la commande souhaitée.

Toutefois, si la modification de la commande dans la définition n'est pas une option pour une raison quelconque, vous pouvez toujours dériver l'équation, car pour que l'ordre n'a pas d'importance. Compte tenu d'une instance d'équation, nous pouvons écrire manuellement une instance pour ORD. La manière la plus succincte de définir la comparaison serait probablement d'épeler toutes les combinaisons pour lesquelles la comparaison devrait renvoyer lt, puis utiliser simplement comparer x y | x == Y = EQ; Comparez _ _ = GT pour les combinaisons restantes.


5 commentaires

Merci, je ne savais pas que la commande est préservée.


Question bonus: Que se passe-t-il si la commande dans le Définiton ne refléterait pas l'ordre numérique?


@Lenny: Ensuite, vous auriez instancier ORD et définir comparer à la main (en supposant que la modification de la commande dans la définition n'est pas une option pour une raison quelconque) - Vous pouvez toujours dériver l'équation possible car pour que le L'ordre n'a pas d'importance. Le moyen le plus succinct de définir comparer serait probablement d'épeler toutes les combinaisons pour lesquelles la comparaison doit renvoyer lt, puis utiliser simplement comparer x y | x == Y = EQ; Comparez _ _ = gt pour les combinaisons restantes.


@Lenny Solution plus facile: changez la définition de sorte qu'il s'agit d'une commande ascendante!


@Lenny pour certains protocoles Travail J'ai même ajouté des espaces réservés non utilisés: Data X = VAL0 | Val1 | Val2 | Inutilisé3 | Inutilisé4 | VAL5 . Idiot, est juste parfois le moyen le plus rapide et le plus simple d'aller (mais pas si vous avez de grandes lacunes, évidemment).



3
votes

Comme cela n'a été mentionné, vous pouvez dériver eq code> et ord code>. Ou vous pouvez dériver enum code> et ensuite faire

instance Eq Rating where
    OneStar == OneStar = True
    TwoStar == TwoStar = True
...
    _ == _ = False


0 commentaires

2
votes

Pour quiconque se demande, voici la mise en œuvre complète, explicite et de la chaudière:

Utilisation de chiffres romains.
Utilisation de case pour la facilité de lecture. xxx


1 commentaires

Merci beaucoup! Cela m'a pris pour toujours pour trouver un exemple de châssis entièrement écrit!



0
votes

Un autre moyen d'implémenter Comparer code> est de tomber sur un type qui est déjà une instance de ord code>.

data Rating = OneStar | TwoStars | ThreeStars | FourStars | FiveStars
    deriving (Show, Eq)

instance Ord Rating where
  compare x y = compare (r2n x) (r2n y)
    where
      r2n OneStar = 1
      r2n TwoStars = 2
      r2n ThreeStars = 3
      r2n FourStars = 4
      r2n FiveStars = 5


0 commentaires