Mit welchen Techniken kann ich Code konsequent umgestalten, ohne auf existenzielle Typen angewiesen zu sein? In der Regel werden diese verwendet, um unerwünschte Konstruktionen Ihres Typs zu disqualifizieren und den Konsum mit einem Minimum an Wissen über den angegebenen Typ zu ermöglichen (oder so ist mein Verständnis).
Hat jemand eine einfache, konsistente Methode gefunden, um das Vertrauen in diesen Code zu beseitigen, bei der einige der Vorteile erhalten bleiben? Oder zumindest eine Möglichkeit, in eine Abstraktion zu schlüpfen, die deren Entfernung ermöglicht, ohne dass eine erhebliche Codeabwanderung erforderlich ist, um mit der Änderung fertig zu werden?
Sie können mehr über existentielle Typen lesen Sie hier ( „wenn du dich traust ..“).
quelle
Antworten:
Existenzielle Typen gelten in der funktionalen Programmierung nicht als schlechte Praxis. Ich denke, was Sie auslöst, ist, dass eine der am häufigsten zitierten Verwendungen für Existentials das existentielle Typenklassen-Antimuster ist , das viele Leute für eine schlechte Praxis halten.
Dieses Muster wird häufig als Antwort auf die Frage ausgegeben, wie eine Liste heterogen typisierter Elemente erstellt werden soll, die alle dieselbe Typklasse implementieren. Möglicherweise möchten Sie eine Liste von Werten mit
Show
Instanzen haben:Das Problem mit Code wie diesem ist folgendes:
AnyShape
ist das Abrufen seiner Fläche.AnyShape
Konstruktor verwenden, um einen der Formtypen in denAnyShape
Typ zu bringen.Wie sich herausstellt, bringt Ihnen dieser Code nicht wirklich etwas, was dieser kürzere Code nicht bringt:
Bei Klassen mit mehreren Methoden kann derselbe Effekt im Allgemeinen einfacher durch Verwendung einer Codierung mit "Methodenaufzeichnungen" erzielt werden. Anstatt eine Typklasse zu verwenden
Shape
, definieren Sie einen Datensatztyp, dessen Felder die "Methoden" desShape
Typs sind und Sie schreiben Funktionen, um Ihre Kreise und Quadrate inShape
s umzuwandeln .Das heißt aber nicht, dass existenzielle Typen ein Problem sind! In Rust gibt es beispielsweise eine Funktion namens Merkmalsobjekte , die häufig als existenzieller Typ über einem Merkmal beschrieben werden (Rusts Versionen von Typklassen). Wenn existenzielle Typenklassen in Haskell ein Gegenmuster sind, bedeutet das, dass Rust eine schlechte Lösung ausgewählt hat? Nein! Die Motivation in der Haskell-Welt liegt in der Syntax und Bequemlichkeit, nicht wirklich im Prinzip.
Ein mathematischer Weg , dies zu setzen wird darauf hingewiesen , dass die
AnyShape
Art von oben undDouble
ist isomorph -e eine „lossless Umwandlung“ zwischen ihnen ist (na ja, außer für Punkt precision floating):Genau genommen gewinnt oder verliert man keine Macht, wenn man sich für eine gegen die andere entscheidet. Dies bedeutet, dass die Auswahl auf anderen Faktoren wie Benutzerfreundlichkeit oder Leistung basieren sollte.
Denken Sie auch daran, dass existenzielle Typen außerhalb dieses Beispiels für heterogene Listen andere Verwendungszwecke haben. Es ist also gut, sie zu haben. Beispielsweise verwendet der
ST
Typ von Haskell , der es uns ermöglicht, Funktionen zu schreiben, die äußerlich rein sind, aber intern Speichermutationsoperationen verwenden, eine Technik, die auf existentiellen Typen basiert, um die Sicherheit beim Kompilieren zu gewährleisten.Die allgemeine Antwort lautet also, dass es keine allgemeine Antwort gibt. Verwendungen existenzieller Typen können nur im Kontext beurteilt werden - und die Antworten können unterschiedlich sein, je nachdem, welche Funktionen und Syntax von verschiedenen Sprachen bereitgestellt werden.
quelle
Ich bin mit Haskell nicht allzu vertraut, daher werde ich versuchen, den allgemeinen Teil der Frage als nicht-akademischer funktionaler C # -Entwickler zu beantworten.
Nach einigem Lesen stellt sich heraus, dass:
Java-Platzhalter ähneln existenziellen Typen:
Unterschied zwischen Scalas existenziellen Typen und Javas Wildcard anhand eines Beispiels
Platzhalter werden in C # nicht vollständig implementiert: Die generische Varianz wird unterstützt, die Varianz der Aufrufsite jedoch nicht:
C # -Generics: Platzhalter
Möglicherweise benötigen Sie diese Funktion nicht jeden Tag, aber wenn Sie dies tun, werden Sie es spüren (z. B. müssen Sie einen zusätzlichen Typ einführen, damit die Dinge funktionieren):
Platzhalter in generischen C # -Einschränkungen
Basierend auf diesen Informationen sind existenzielle Typen / Platzhalter nützlich, wenn sie ordnungsgemäß implementiert wurden, und es gibt an sich nichts Falsches daran, aber sie können wahrscheinlich genauso wie andere Sprachfunktionen missbraucht werden.
quelle