Beim Erstellen eines Clients für eine Web-API in C # stieß ich auf ein Problem hinsichtlich null
eines Werts, bei dem zwei verschiedene Dinge dargestellt werden:
- nichts , zB ein
foo
darf oder darf nicht a habenbar
- unbekannt : Standardmäßig enthält die API-Antwort nur eine Teilmenge von Eigenschaften. Sie müssen angeben, welche zusätzlichen Eigenschaften Sie möchten. So unbekannt bedeutet , dass die Eigenschaft wurde nicht von der API angefordert.
Nach einigem Suchen fand ich heraus, wie der Typ Vielleicht (oder Option) in funktionalen Sprachen verwendet wird und wie er Null-Dereferenzierungsprobleme "löst", indem er den Benutzer dazu zwingt, über das mögliche Fehlen eines Werts nachzudenken. In allen Ressourcen, auf die ich gestoßen bin, ging es jedoch darum, null durch Vielleicht zu ersetzen . Ich habe einige Erwähnungen von dreiwertiger Logik gefunden , aber ich verstehe sie nicht vollständig und meistens wurde sie im Zusammenhang mit "es ist eine schlechte Sache" erwähnt.
Ich frage mich jetzt, ob es Sinn macht, sowohl das Konzept von null als auch von Maybe zu haben , um Unbekanntes bzw. Nichts darzustellen . Ist das die dreiwertige Logik, über die ich gelesen habe, oder hat sie einen anderen Namen? Oder ist der beabsichtigte Weg, ein Vielleicht in ein Vielleicht zu nisten?
null
. Es ist eine völlig kaputte Idee.M M x
undM x
sollte die gleiche Semantik haben.Maybe a
das gleiche ist wie , semantisch, ist das gleiche wie ein + 1 + 1 und isomorph geben von @Andej Antwort. Sie können auch für diesen Typ eine eigene Monadeninstanz definieren und daher verschiedene Monadenkombinatoren verwenden.Maybe Maybe a
UserInput a
M (M x)
undM x
die gleiche Semantik haben sollte". Nehmen wirM = List
zum Beispiel: Listen von Listen sind nicht dasselbe wie Listen. WennM
eine Monade ist, gibt es eine Transformation (nämlich die Multiplikation Monade) ausM (M x)
zuM x
dem erklärt die Beziehung zwischen ihnen, aber sie haben nicht „die gleiche Semantik“.Antworten:
Der
null
überall als Standardwert vorhandene Wert ist nur a wirklich kaputte Idee . Vergessen Sie das also.Sie sollten immer genau das Konzept haben, das Ihre tatsächlichen Daten am besten beschreibt. Wenn Sie einen Typ benötigen, der "unbekannt", "nichts" und "Wert" angibt, sollten Sie genau das haben. Aber wenn es nicht Ihren tatsächlichen Bedürfnissen entspricht, sollten Sie es nicht tun. Es ist eine gute Idee zu sehen, was andere Leute verwenden und was sie vorgeschlagen haben, aber Sie müssen ihnen nicht blind folgen.
Leute, die Standardbibliotheken entwerfen, versuchen, gängige Verwendungsmuster zu erraten, und das tun sie normalerweise gut. Wenn Sie jedoch eine bestimmte Sache benötigen, sollten Sie diese selbst definieren. In Haskell können Sie beispielsweise Folgendes definieren:
Es kann sogar vorkommen, dass Sie etwas Beschreibenderes verwenden, an das Sie sich leichter erinnern können:
Sie können 10 solcher Typen definieren, die für verschiedene Szenarien verwendet werden sollen. Der Nachteil ist, dass Sie keine bereits vorhandenen Bibliotheksfunktionen (wie die von
Maybe
) zur Verfügung haben, dies stellt sich jedoch normalerweise als Detail heraus. Es ist nicht so schwer, eigene Funktionen hinzuzufügen.quelle
Soweit ich weiß, ist der Wert
null
in C # je nach Typ ein möglicher Wert für einige Variablen (habe ich recht?). Zum Beispiel Instanzen einer Klasse. Für den Rest der Typen (wieint
,bool
usw.) können Sie diesen Ausnahmewert hinzufügen , indem Sie Variablen mit deklarierteint?
oderbool?
statt (das ist genau das, was derMaybe
Konstruktor tut, wie ich als nächstes beschreiben).Der
Maybe
Typkonstruktor aus der funktionalen Programmierung fügt diesen neuen Ausnahmewert für einen bestimmten Datentyp hinzu. WennInt
es sich also um die Art der Ganzzahlen oderGame
um den Typ des Status eines Spiels handelt,Maybe Int
enthält es alle Ganzzahlen plus einen Nullwert (manchmal auch als Nichts bezeichnet ). Das gleiche gilt fürMaybe Game
. Hier gibt es keine Typen, die mit dem kommennull
Wert geliefert werden. Sie fügen es hinzu, wenn Sie es brauchen.IMO, dieser letzte Ansatz ist der bessere für jede Programmiersprache.
quelle
Maybe
s zu verschachteln undnull
vollständig fallen zu lassen?isinstance
Tests angenähert werden. Scala hat auch einen "richtigen" Mustervergleich, und C♯ hat erst kürzlich auch einfache Muster erhalten.final
(für eine Klasse, von der nicht geerbt werden kann) auchsealed
für a Klasse, die nur innerhalb derselben Kompilierungseinheit erweitert werden kann . Dies bedeutet, dass der Compiler alle möglichen Unterklassen statisch kennen kann (vorausgesetzt, alle sind entweder sie selbstsealed
oderfinal
) und somit Vollständigkeitsprüfungen für Musterübereinstimmungen durchführen, was für eine Sprache mit Laufzeitcode-Laden und uneingeschränkter Vererbung statisch nicht möglich ist.int??
ist in C # illegal.Wenn Sie Typ Gewerkschaften, wie definieren
X or Y
, und wenn Sie einen Typ mit dem Namen ,Null
der nur das repräsentiertnull
Wert (und sonst nichts), dann für jede ArtT
,T or Null
ist eigentlich nicht so verschieden vonMaybe T
. Das einzige Problemnull
besteht darin, dass die Sprache einen TypT
alsT or Null
implizit behandelt undnull
für jeden Typ einen gültigen Wert erstellt (außer für primitive Typen in Sprachen, in denen sie vorhanden sind). Dies ist beispielsweise in Java der Fall, wo eine Funktion, die a übernimmt,String
ebenfalls akzeptiert wirdnull
.Wenn Sie Typen als Wertemenge und
or
als Vereinigung von Mengen behandeln,(T or Null) or Null
stellt dies die Wertemenge darT ∪ {null} ∪ {null}
, die mit identisch istT or Null
. Es gibt Compiler, die diese Art von Analysen (SBCL) durchführen. Wie in den Kommentaren erwähnt, können Sie nicht leicht zwischenMaybe T
und unterscheiden,Maybe Maybe T
wenn Sie Typen als Domänen anzeigen (andererseits ist diese Ansicht für dynamisch typisierte Programme sehr nützlich). Sie können Typen aber auch als algebraische Ausdrücke(T or Null) or Null
beibehalten , wobei mehrere Ebenen von Maybes dargestellt werden.quelle
Maybe (Maybe X)
das nicht dasselbe ist wieMaybe X
.Nothing
ist nicht dasselbe wieJust Nothing
. Der KonfliktMaybe (Maybe X)
mitMaybe X
macht es unmöglich,Maybe _
polymorph zu behandeln .Sie müssen herausfinden, was Sie ausdrücken möchten, und dann einen Weg finden, wie Sie es ausdrücken können.
Erstens haben Sie Werte in Ihrer Problemdomäne (wie Zahlen, Zeichenfolgen, Kundendatensätze, Boolesche Werte usw.). Zweitens haben Sie einige zusätzliche generische Werte zusätzlich zu Ihren Problemdomänenwerten: Zum Beispiel "nichts" (das bekannte Fehlen eines Wertes), "unbekannt" (kein Wissen über das Vorhandensein oder Fehlen eines Wertes), nicht erwähnt wurde " etwas "(es gibt definitiv einen Wert, aber wir wissen nicht, welcher). Vielleicht können Sie sich andere Situationen vorstellen.
Wenn Sie alle Werte plus diese drei zusätzlichen Werte darstellen möchten, erstellen Sie eine Aufzählung mit den Fällen "nichts", "unbekannt", "etwas" und "Wert" und gehen von dort aus.
In einigen Sprachen sind einige Fälle einfacher. Zum Beispiel haben Sie in Swift für jeden Typ T den Typ "optionales T", dessen mögliche Werte Null plus alle Werte von T sind. Auf diese Weise können Sie viele Situationen einfach handhaben und sind perfekt, wenn Sie "nichts" und "nichts" haben. Wert". Sie können es verwenden, wenn Sie "unbekannt" und "Wert" haben. Sie können es nicht verwenden, wenn Sie mit "nichts", "unbekannt" und "Wert" umgehen müssen. Andere Sprachen verwenden möglicherweise "null" oder "vielleicht", aber das ist nur ein anderes Wort.
In JSON haben Sie Wörterbücher mit Schlüssel / Wert-Paaren. Hier fehlt möglicherweise nur ein Schlüssel in einem Wörterbuch oder er hat den Wert null. Wenn Sie also sorgfältig beschreiben, wie Dinge gespeichert werden, können Sie generische Werte plus zwei zusätzliche Werte darstellen.
quelle