2017-05-04 1 views
5

J'ai quelques problèmes d'emballage de tête autour des types d'union en orme. Je comprends le cas simple d'utilisation commeComprendre les types d'union d'orme

type Visibility = All | Active | Completed 

Cela signifie donc que la valeur de tous peut être Visibilité, en cours ou terminés. Jusqu'ici tout va bien. Où je suis confus cependant est

type Msg 
    = OnFetchMails (WebData (List Mail)) 
    | OnFetchSmss (WebData (List SMS)) 

Comment dois-je interpréter cela? Cela signifie-t-il que Msg peut être de la fonction type OnFetchMails qui prend une fonction de type WebData qui prend une liste de messages? Ou comment dois-je interpréter cela? Je ne pense pas que (WebData (List Mail)) est la charge utile?

assez drôle je peux le faire fonctionner sans le comprendre

Répondre

6

En fait, oui, vous pouvez le considérer comme une charge utile qui va de pair avec chaque branche.

type Msg 
    = OnFetchMails (WebData (List Mail)) 
    | OnFetchSmss (WebData (List SMS)) 

signifie qu'une valeur de type Msg peut être OnFetchMails, ce qui aura une valeur de type WebData (List Mail) pour aller avec elle; ou il peut être OnFetchSmss avec un WebData (List SMS) l'accompagnant.

Ils sont parfois appelés taggés syndicats, car ils agissent un peu comme un style C union construction livré avec une valeur d'étiquette qui dit que l'option de l'union est celui qui est actuellement en cours de validité (et en fait beaucoup de langues avec ce genre de structure les implémentent de cette façon).

Ils pourraient également être modélisés comme une série de sous-classes d'un type de base abstraite Msg, ajoutant un stockage pour leurs charges utiles dans chaque sous-classe et exigeant que les charges utiles soient fournies en tant que paramètres constructeurs.

8

Lors de la définition d'un type d'union, vous répertoriez toutes les manières de construire une valeur de ce type. Dans sa forme la plus simple, cette définition ressemble à ceci:

type Visibility 
    = All 
    | Active 
    | Completed 

Comme vous l'avez deviné, ce type Visibility déclare et définit trois valeurs, tous de type Visibility. La seule façon de construire une valeur de type Visibility consiste à utiliser l'une de ces trois options. Pour cette raison, nous les appelons souvent «constructeurs».

Voici une définition de type union un peu plus compliqué:

type TrainStatus 
    = OnTime 
    | Delayed Int 

Comme on peut s'y attendre, cela définit deux nouveaux "constructeurs" OnTime et Delayed. Mais regardez leurs types:

OnTime : TrainStatus 
Delayed : Int -> TrainStatus 

Le constructeur OnTime prend zéro arguments, et est donc simplement une valeur; c'est déjà un TrainStatus. Mais Delayed est déclaré en tant que constructeur à un argument: c'est une fonction qui crée un nouveau TrainStatus sur un Int. En tant que tels, Delayed 5, Delayed 10 et Delayed 100 sont toutes des valeurs TrainStatus valides. (Nous pouvons les interpréter comme "retardé de 5 minutes" ou quelque chose de similaire.

Un constructeur peut prendre plusieurs arguments; par exemple, si nous aimerions inclure, en tant que chaîne, une raison d'un retard:

type TrainStatus 
    = OnTime 
    | Delayed Int String 

ts : TrainStatus 
ts = Delayed 20 "The conductor took a short nap." 

qui définit Delayed : Int -> String -> TrainStatus.

Si vous êtes donné un TrainStatus, vous pouvez extraire le Int et String à l'intérieur de celui-ci en utilisant la correspondance de motif:

case ts of 
    OnTime -> 
    "Your train is on time!" 

    Delayed minutes reason -> 
    "Your train has been delayed by " ++ toString minutes ++ " because " ++ reason