En data
déclaration, qui est un constructeur de type est la chose sur le côté gauche du signe égal. Les données constructeur(s) sont les choses sur la droite du signe égal. Vous utilisez le type des constructeurs où un type est prévu, et que vous utilisez des données constructeurs où une valeur est attendue.
Les données constructeurs
Pour simplifier les choses, nous pouvons commencer avec un exemple d'un type qui représente une couleur.
data Colour = Red | Green | Blue
Ici, nous avons trois constructeurs de données. Colour
est un type, et Green
est un constructeur qui contient une valeur de type Colour
. De même, Red
et Blue
sont les deux constructeurs qui construisent les valeurs de type Colour
. Nous pourrions imaginer d'épice il bien!
data Colour = RGB Int Int Int
Nous avons encore juste le type Colour
, mais RGB
n'est pas une valeur, c'est une fonction prenant trois ints et de retourner une valeur! RGB
a le type
RGB :: Int -> Int -> Int -> Colour
RGB
données constructeur qui est une fonction prenant certaines valeurs comme ses arguments, puis les utilise pour construire une nouvelle valeur. Si vous avez fait toute la programmation orientée objet, vous devez le reconnaître. En programmation orientée objet, les constructeurs de prendre certaines valeurs comme arguments et retourne une nouvelle valeur!
Dans ce cas, si l'on applique RGB
à trois valeurs, nous obtenons une valeur de couleur!
Prelude> RGB 12 92 27
#0c5c1b
Nous avons construit une valeur de type Colour
en appliquant les données constructeur. Données constructeur contient une valeur comme une variable, ou prend d'autres valeurs en argument et qui crée une nouvelle valeur. Si vous avez fait de la programmation précédente, ce concept ne devrait pas être très étrange.
Entracte
Si vous voulez construire un arbre binaire pour stocker String
s, vous pouvez imaginer faire quelque chose comme
data SBTree = Leaf String
| Branch String SBTree SBTree
Ce que nous voyons ici est un type SBTree
qui contient deux constructeurs de données. En d'autres termes, il existe deux fonctions (à savoir, Leaf
et Branch
) qui permettra de construire des valeurs de l' SBTree
type. Si vous n'êtes pas familier avec la façon d'arbres binaires de travail, tout y accrocher. Vous n'avez pas réellement besoin de savoir comment les arbres binaires de travail, ce que c'est que l'on stocke String
s, d'une certaine façon.
Nous voyons aussi que les deux constructeurs de données prennent un String
de l'argument – c'est la Chaîne qu'ils vont conserver dans l'arbre.
Mais! Que faire si nous voulions aussi être en mesure de stocker Bool
, il faudrait créer un nouvel arbre binaire. Il pourrait ressembler à quelque chose comme ceci:
data BBTree = Leaf Bool
| Branch Bool BBTree BBTree
Type de constructeurs
Les deux SBTree
et BBTree
sont de type des constructeurs. Mais il y a un problème flagrant. Voyez-vous comment ils se ressemblent? C'est un signe que vous voulez vraiment un paramètre quelque part.
Donc, nous pouvons faire ceci:
data BTree a = Leaf a
| Branch a (BTree a) (BTree a)
Maintenant, nous introduisons une variable de type a
en tant que paramètre au constructeur de type. Dans cette déclaration, BTree
est devenu une fonction. Il faut un type comme argument et retourne un nouveau type.
Il est important ici de considérer la différence entre un type de béton (les exemples incluent Int
, [Char]
et Maybe Bool
) qui est un type qui peut être attribué à une valeur dans votre programme, et un constructeur de type fonction dont vous avez besoin pour nourrir un type de pouvoir être attribué à une valeur. Une valeur ne peut jamais être de type "liste", parce qu'elle doit être une "liste de quelque chose". Dans le même esprit, une valeur ne peut jamais être de type "arbre binaire", parce qu'il doit être un "arbre binaire de stocker quelque chose".
Si nous passons, disons, Bool
comme un argument à l' BTree
, il retourne le type BTree Bool
, ce qui est un arbre binaire qui stocke Bool
s. Remplacer chaque occurrence de la variable de type a
avec le type Bool
, et vous pouvez voir par vous-même combien c'est vrai.
Si vous le souhaitez, vous pouvez visualiser BTree
comme une fonction du genre
BTree :: * -> *
Les types sont un peu comme les types – *
indique un type de béton, de sorte que nous disons BTree
est à partir d'un béton de type pour un type de béton.
L'emballage jusqu'à
L'étape de retour ici un moment et de prendre note des similitudes.
Une des données constructeur est une "fonction" qui prend 0 ou plusieurs valeurs et vous donne en retour une nouvelle valeur.
Un constructeur de type est une "fonction" qui prend 0 ou plusieurs types et vous donne un nouveau type.
Les données constructeurs avec paramètres sont cool si nous voulons que de légères variations dans nos valeurs, nous avons mis ces variations des paramètres et de laisser le gars qui crée la valeur de décider quels sont les arguments qu'ils vont mettre en. Dans le même sens, le type de constructeurs avec paramètres sont cool si nous voulons que de légères variations dans nos types! Nous avons mis ces variations de paramètres et de laisser le gars qui a crée le type décider quels sont les arguments qu'ils vont mettre en.
Une étude de cas
Comme le tronçon de la maison ici, on peut considérer l' Maybe a
type. C'est la définition est
data Maybe a = Nothing
| Just a
Ici, Maybe
est un constructeur de type, qui retourne un type concret. Just
données constructeur qui retourne une valeur. Nothing
données constructeur qui contient une valeur. Si l'on regarde le type d' Just
,, nous voyons que
Just :: a -> Maybe a
En d'autres termes, Just
prend une valeur de type a
et renvoie une valeur de type Maybe a
. Si l'on regarde le type d' Maybe
,, nous voyons que
Maybe :: * -> *
En d'autres termes, Maybe
prend un type de béton et renvoie un type concret.
Une fois de plus! La différence entre un type de béton et un constructeur de type fonction. Vous ne pouvez pas créer une liste d' Maybe
s. Si vous essayez d'exécuter
[] :: [Maybe]
vous recevrez un message d'erreur. Vous pouvez toutefois créer une liste d' Maybe Int
ou Maybe a
. C'est parce qu' Maybe
est un constructeur de type fonction, mais une liste doit contenir des valeurs d'un type concret. Maybe Int
et Maybe a
sont des types de béton (ou si vous le souhaitez, des appels au constructeur de type des fonctions qui retournent des types de béton.)