Es ist eigentlich nur ein normaler Datenkonstruktor, der zufällig im Prelude definiert wird. Dies ist die Standardbibliothek, die automatisch in jedes Modul importiert wird.
Was vielleicht strukturell ist
Die Definition sieht ungefähr so aus:
data Maybe a = Just a
| Nothing
Diese Deklaration definiert einen Typ, Maybe ader durch eine Typvariable parametrisiert wird. aDies bedeutet lediglich, dass Sie ihn mit jedem Typ anstelle von verwenden können a.
Konstruieren und zerstören
Der Typ hat zwei Konstruktoren Just aund Nothing. Wenn ein Typ mehrere Konstruktoren hat, bedeutet dies, dass ein Wert des Typs mit nur einem der möglichen Konstruktoren erstellt worden sein muss. Für diesen Typ wurde ein Wert entweder über Justoder erstellt Nothing, es gibt keine anderen (fehlerfreien) Möglichkeiten.
Da Nothinges keinen Parametertyp gibt, benennt es bei Verwendung als Konstruktor einen konstanten Wert, der Maybe afür alle Typen vom Typ type ist a. Der JustKonstruktor verfügt jedoch über einen Typparameter. Wenn er als Konstruktor verwendet wird, verhält er sich wie eine Funktion von Typ abis Maybe a, dh er hat den Typa -> Maybe a
Die Konstruktoren eines Typs erstellen also einen Wert dieses Typs. Die andere Seite der Dinge ist, wenn Sie diesen Wert verwenden möchten, und hier kommt der Mustervergleich ins Spiel. Im Gegensatz zu Funktionen können Konstruktoren in Musterbindungsausdrücken verwendet werden. Auf diese Weise können Sie Fallanalysen von Werten durchführen, die zu Typen mit mehr als einem Konstruktor gehören.
Um einen Maybe aWert in einer Musterübereinstimmung zu verwenden, müssen Sie für jeden Konstruktor ein Muster bereitstellen, wie folgt:
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
In diesem Fall würde das erste Muster übereinstimmen, wenn der Wert wäre Nothing, und das zweite würde übereinstimmen, wenn der Wert mit konstruiert wurde Just. Wenn der zweite übereinstimmt, bindet er auch den Namen valan den Parameter, der an den JustKonstruktor übergeben wurde, als der Wert erstellt wurde, mit dem Sie übereinstimmen.
Was vielleicht bedeutet
Vielleicht waren Sie bereits damit vertraut, wie das funktionierte; MaybeWerte sind nicht wirklich magisch , sondern nur ein normaler alaskischer Haskell-Datentyp (ADT). Aber es wird ziemlich oft verwendet, weil es einen Typ, wie Integeraus Ihrem Beispiel, effektiv in einen neuen Kontext "hebt" oder erweitert, in dem es einen zusätzlichen Wert ( Nothing) hat, der einen Wertmangel darstellt! Das Typsystem erfordert dann , dass Sie für diesen Mehrwert zu überprüfen , bevor es Sie an dem erhalten lassen , Integerdie vielleicht da sein. Dies verhindert eine bemerkenswerte Anzahl von Fehlern.
Viele Sprachen verarbeiten diese Art von "No-Value" -Wert heutzutage über NULL-Referenzen. Tony Hoare, ein bedeutender Informatiker (er hat Quicksort erfunden und ist Turing-Preisträger), hält dies für seinen "Milliarden-Dollar-Fehler" . Der Vielleicht-Typ ist nicht der einzige Weg, dies zu beheben, aber er hat sich als effektiver Weg erwiesen, dies zu tun.
Vielleicht als Funktor
Die Idee, einen Typ in einen anderen zu transformieren, sodass Operationen für den alten Typ auch so transformiert werden können, dass sie für den neuen Typ funktionieren, ist das Konzept hinter der aufgerufenen Haskell-Typklasse Functor, die Maybe aeine nützliche Instanz von hat.
Functorstellt eine aufgerufene Methode bereit fmap, die Funktionen, die über Werte vom Basistyp (z. B. Integer) liegen, Funktionen zuordnet, die über Werte vom angehobenen Typ (z. B. Maybe Integer) reichen . Eine Funktion, die transformiert wurde fmap, um an einem MaybeWert zu arbeiten, funktioniert folgendermaßen:
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
Wenn Sie also einen Maybe IntegerWert m_xund eine Int -> IntFunktion haben f, können Sie fmap f m_xdie Funktion fdirekt auf die anwenden , Maybe Integerohne sich Sorgen machen zu müssen, ob sie tatsächlich einen Wert hat oder nicht. Tatsächlich können Sie eine ganze Kette von angehobenen Integer -> IntegerFunktionen auf Maybe IntegerWerte anwenden und müssen sich nur noch Nothingeinmal explizit darum kümmern, wenn Sie fertig sind.
Vielleicht als Monade
Ich bin mir nicht sicher, wie vertraut Sie mit dem Konzept eines sind Monad, aber Sie haben es zumindest schon einmal verwendet IO a, und die Typensignatur IO asieht bemerkenswert ähnlich aus Maybe a. Obwohl IOes insofern besonders ist, als es seine Konstruktoren nicht für Sie verfügbar macht und daher nur vom Haskell-Laufzeitsystem "ausgeführt" werden kann, ist es Functorneben dem auch noch ein Monad. In der Tat gibt es einen wichtigen Sinn, in dem a Monadnur eine besondere Art Functormit einigen zusätzlichen Funktionen ist, aber dies ist nicht der richtige Ort, um darauf einzugehen.
Wie auch immer, Monaden mögen IOZuordnungstypen zu neuen Typen, die "Berechnungen, die zu Werten führen" darstellen, und Sie können Funktionen Monadüber eine sehr fmapähnliche Funktion liftM, die eine reguläre Funktion in eine "Berechnung umwandelt, die zu dem Wert führt, der durch Auswertung der Werte erhalten wird, in Typen umwandeln Funktion."
Sie haben wahrscheinlich erraten (wenn Sie so weit gelesen haben), dass dies Maybeauch ein ist Monad. Es stellt "Berechnungen dar, bei denen möglicherweise kein Wert zurückgegeben wird". Genau wie im fmapBeispiel können Sie so eine ganze Reihe von Berechnungen durchführen, ohne nach jedem Schritt explizit nach Fehlern suchen zu müssen. Tatsächlich wird bei der Art und Weise, wie die MonadInstanz aufgebaut ist, eine Berechnung der MaybeWerte gestoppt , sobald eine gefunden Nothingwird. Dies ist also wie ein sofortiger Abbruch oder eine wertlose Rückkehr mitten in einer Berechnung.
Du hättest vielleicht schreiben können
Wie ich bereits sagte, ist dem MaybeTyp, der in die Sprachsyntax oder das Laufzeitsystem integriert ist, nichts inhärent . Wenn Haskell es nicht standardmäßig zur Verfügung gestellt hat, können Sie alle Funktionen selbst bereitstellen! Tatsächlich könnten Sie es trotzdem selbst mit unterschiedlichen Namen erneut schreiben und die gleiche Funktionalität erhalten.
Hoffentlich verstehen Sie den MaybeTyp und seine Konstruktoren jetzt, aber wenn noch etwas unklar ist, lassen Sie es mich wissen!
Maybewo andere Sprachen verwenden würdennullodernil(mit bösenNullPointerExceptionlauern in jeder Ecke). Jetzt verwenden auch andere Sprachen dieses Konstrukt: Scala asOptionund sogar Java 8 haben denOptionalTyp.