C'est en fait juste un constructeur de données normal qui se trouve être défini dans Prelude , qui est la bibliothèque standard qui est importée automatiquement dans chaque module.
Ce qui est peut-être, structurellement
La définition ressemble à ceci:
data Maybe a = Just a
| Nothing
Cette déclaration définit un type, Maybe aqui est paramétré par une variable de type a, ce qui signifie simplement que vous pouvez l'utiliser avec n'importe quel type à la place de a.
Construire et détruire
Le type a deux constructeurs Just aet Nothing. Lorsqu'un type a plusieurs constructeurs, cela signifie qu'une valeur du type doit avoir été construite avec un seul des constructeurs possibles. Pour ce type, une valeur a été construite via JustouNothing , il n'y a pas d'autres possibilités (sans erreur).
Puisque Nothingn'a pas de type de paramètre, lorsqu'il est utilisé comme constructeur, il nomme une valeur constante qui est membre de type Maybe apour tous les types a. Mais le Justconstructeur a un paramètre de type, ce qui signifie que lorsqu'il est utilisé comme constructeur, il agit comme une fonction de type aà Maybe a, c'est- à -dire qu'il a le typea -> Maybe a
Ainsi, les constructeurs d'un type construisent une valeur de ce type; L'autre aspect des choses, c'est quand vous souhaitez utiliser cette valeur, et c'est là que la correspondance de motifs entre en jeu. Contrairement aux fonctions, les constructeurs peuvent être utilisés dans les expressions de liaison de modèles, et c'est ainsi que vous pouvez effectuer une analyse de cas des valeurs appartenant à des types avec plusieurs constructeurs.
Afin d'utiliser une Maybe avaleur dans une correspondance de modèle, vous devez fournir un modèle pour chaque constructeur, comme ceci:
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
Dans ce cas, le premier modèle correspondrait si la valeur était Nothing, et le second correspondrait si la valeur a été construite avec Just. Si le second correspond, il lie également le nom valau paramètre qui a été passé au Justconstructeur lors de la construction de la valeur à laquelle vous correspondez.
Que signifie peut-être
Peut-être que vous saviez déjà comment cela fonctionnait; il n'y a pas vraiment de magie dans les Maybevaleurs, c'est juste un type de données algébrique Haskell normal (ADT). Mais il est assez utilisé car il "soulève" ou étend effectivement un type, comme celui Integerde votre exemple, dans un nouveau contexte dans lequel il a une valeur supplémentaire ( Nothing) qui représente un manque de valeur! Le système de types exige alors que vous vérifiiez cette valeur supplémentaire avant de vous permettre d'accéder à ce Integerqui pourrait être là. Cela évite un nombre remarquable de bugs.
Aujourd'hui, de nombreux langages gèrent ce type de valeur «sans valeur» via des références NULL. Tony Hoare, un éminent informaticien (il a inventé Quicksort et est un lauréat du prix Turing), reconnaît cela comme son "erreur d'un milliard de dollars" . Le type Maybe n'est pas le seul moyen de résoudre ce problème, mais il s'est avéré être un moyen efficace de le faire.
Peut-être en tant que foncteur
L'idée de transformer un type en un autre de sorte que les opérations sur l'ancien type puissent également être transformées pour travailler sur le nouveau type est le concept derrière la classe de type Haskell appelée Functor, qui Maybe aa une instance utile de.
Functorfournit une méthode appelée fmap, qui mappe les fonctions qui s'étendent sur des valeurs du type de base (comme Integer) aux fonctions qui s'étendent sur des valeurs du type levé (comme Maybe Integer). Une fonction transformée avec fmappour travailler sur une Maybevaleur fonctionne comme ceci:
case maybeVal of
Nothing -> Nothing -- there is nothing, so just return Nothing
Just val -> Just (f val) -- there is a value, so apply the function to it
Donc, si vous avez une Maybe Integervaleur m_xet une Int -> Intfonction f, vous pouvez fmap f m_xappliquer la fonction fdirectement au Maybe Integersans vous soucier si elle a réellement une valeur ou non. En fait, vous pouvez appliquer toute une chaîne de Integer -> Integerfonctions levées aux Maybe Integervaleurs et ne vous soucier de vérifier explicitement Nothingqu'une seule fois lorsque vous avez terminé.
Peut-être en tant que Monade
Je ne sais pas à quel point vous connaissez encore le concept de a Monad, mais vous l'avez au moins utilisé IO aauparavant, et la signature de type IO aressemble remarquablement à Maybe a. Bien qu'il IOsoit spécial en ce qu'il ne vous expose pas ses constructeurs et ne peut donc être "exécuté" que par le système d'exécution Haskell, il est toujours aussi Functorun Monad. En fait, il y a un sens important dans lequel a Monadest juste un type spécial Functoravec quelques fonctionnalités supplémentaires, mais ce n'est pas le lieu d'entrer dans cela.
Quoi qu'il en soit, les monades aiment les IOtypes de carte vers de nouveaux types qui représentent des «calculs qui donnent des valeurs» et vous pouvez transformer des fonctions en Monadtypes via une fmapfonction très similaire appelée liftMqui transforme une fonction régulière en un «calcul qui aboutit à la valeur obtenue en évaluant le fonction."
Vous avez probablement deviné (si vous avez lu jusqu'ici) que Maybec'est aussi un fichier Monad. Il représente "des calculs qui pourraient ne pas renvoyer une valeur". Tout comme avec l' fmapexemple, cela vous permet de faire tout un tas de calculs sans avoir à vérifier explicitement les erreurs après chaque étape. Et en fait, la façon dont l' Monadinstance est construite, un calcul sur des Maybevaleurs s'arrête dès que a Nothingest rencontré, donc c'est un peu comme un abandon immédiat ou un retour sans valeur au milieu d'un calcul.
Tu aurais peut-être écrit
Comme je l'ai déjà dit, il n'y a rien d'inhérent au Maybetype qui est intégré à la syntaxe du langage ou au système d'exécution. Si Haskell ne l'a pas fourni par défaut, vous pouvez fournir toutes ses fonctionnalités vous-même! En fait, vous pouvez le réécrire vous-même de toute façon, avec des noms différents, et obtenir la même fonctionnalité.
J'espère que vous comprenez le Maybetype et ses constructeurs maintenant, mais s'il n'y a toujours rien de clair, faites le moi savoir!
Maybelà où d'autres langues utiliseraientnullounil(avec desNullPointerExceptions méchants cachés dans tous les coins). Maintenant, d'autres langages commencent également à utiliser cette construction: Scala asOption, et même Java 8 aura leOptionaltype.