Sagen wir, ich habe den folgenden Code
%Vor%Sagen Sie, später, ich habe die folgenden
%Vor%Und rufe folgendes auf, um die beiden Argumente falsch zu verstehen:
%Vor%Dies wird leider erfolgreich kompiliert, und zur Laufzeit werden stattdessen große tote Menschen anstelle von kurzlebigen Menschen gefunden.
Ich möchte das obige Beispiel nicht kompilieren.
Mein erster Versuch war:
%Vor%Aber dann kann ich sowas nicht machen.
%Vor% As not
ist nicht definiert in IsTall
s, nur Bool
s.
Ich könnte die Bool
s jederzeit explizit extrahieren, aber das hat den Zweck weitgehend zunichte gemacht.
Grundsätzlich möchte ich, dass IsTall
s mit anderen IsTall
s interagiert, genauso wie sie Bool
s sind, außer dass sie nicht mit Bool
s und IsAlive
s interagieren, ohne eine explizite Umwandlung .
Was ist der beste Weg, dies zu erreichen?
ps. Ich denke, dass ich dies mit Zahlen erreicht habe, indem ich in GHC mache:
%Vor%(d. h. Benutzer-IDs und Gruppen-IDs sollten nicht interagieren)
aber ich kann das anscheinend nicht mit Bool
s machen (das Ableiten von Bool funktioniert nicht). Ich bin mir nicht einmal sicher ob das Obenstehende der beste Weg ist.
Sie können etwas erreichen, indem Sie newtype
s und eine Klasse verwenden, wenn Sie das Prelude importieren, das die booleschen Funktionen versteckt, die Sie mit den Werten IsTall
und IsAlive
verwenden möchten. Sie definieren die booleschen Funktionen als Methoden in der Klasse neu, für die Sie dann Instanzen für alle 3 der Typen Bool
, IsTall
und IsAlive
erstellen. Wenn Sie GeneralizedNewtypeDeriving
verwenden, können Sie sogar die Instanzen IsTall
und IsAlive
abrufen, ohne dass Sie das Wrapping / Unpacking-Boilerplate von Hand schreiben müssen.
Hier ist ein Beispielskript, das ich in ghci ausprobiert habe:
%Vor% Sie können jetzt die Werte &&
, ||
und not
eines der drei Typen angeben, aber nicht zusammen. Da es sich um separate Typen handelt, können Ihre Funktionssignaturen nun einschränken, welche der drei Signaturen akzeptiert werden sollen.
Funktionen höherer Ordnung, die in anderen Modulen definiert sind, funktionieren wie folgt:
%Vor% Aber Sie können% ce_de% nicht an eine andere Funktion übergeben, die an anderer Stelle definiert ist und die IsTall
erwartet, weil das andere Modul weiterhin die Prelude-Version der booleschen Funktionen verwendet. Sprachkonstrukte wie Bool
sind immer noch ein Problem (obwohl ein Kommentar von hammar zu Norman Ramseys Antwort besagt, dass Sie dies mit einer anderen GHC-Erweiterung beheben können). Ich würde wahrscheinlich eine if ... then ... else ...
-Methode zu dieser Klasse hinzufügen, um die Rückkehr zu regulären toBool
s zu unterstützen, um solche Probleme zu mildern.
Wenn Sie Ihren Datentyp leicht ändern, können Sie ihn zu einer Instanz von Functor machen, und Sie können dann fmap verwenden, um Operationen auf dem Booleschen
auszuführen %Vor%- BEARBEITEN
für Operationen wie & amp; & amp; Sie können es zu einer Instanz von Applicative machen
%Vor%und dann können Sie (& amp; & amp;) mit liftA2
Beispiel:
%Vor%Sie können mehr darüber in Ссылка
lesenSie können entweder algebraische Datentypen wie
definieren %Vor% oder um neue Operatoren zu definieren, z. B. &&&
, |||
, complement
und um sie auf den Typ Ihrer Wahl zu überladen. Aber selbst mit Überladung können Sie sie nicht mit if
verwenden.
Ich bin mir nicht sicher, ob Boolesche Operationen auf Höhe überhaupt Sinn ergeben. Wie rechtfertigst du eine Schlussfolgerung, dass "groß und kurz gleich kurz" ist, aber "groß oder kurz gleich groß"?
Ich schlage vor, dass Sie nach verschiedenen Namen für Ihre Connectives suchen, die Sie dann überladen können.
P.S. Haskell bekommt immer neue Funktionen, also kann ich am besten sagen, dass wenn ich if
überladen kann, ich mir dessen nicht bewusst bin. Über Haskell zu sagen, dass "das und das nicht möglich ist", ist immer gefährlich ...
Tags und Links haskell type-safety types casting