Ich habe mir eine interessante video , in denen Typklassen in Haskell verwendet werden, um das sogenannte" Ausdrucksproblem "zu lösen. Ungefähr 15 Minuten später wird gezeigt, wie Typklassen verwendet werden können, um einen Datentyp basierend auf einer diskriminierten Vereinigung für die Erweiterung zu "öffnen" - zusätzliche Diskriminatoren können separat hinzugefügt werden, ohne die ursprüngliche Definition zu modifizieren / neu aufzubauen.
Ich weiß, dass Typklassen in F # nicht verfügbar sind, aber gibt es eine Möglichkeit, andere Sprachfunktionen zu verwenden, um diese Art von Erweiterbarkeit zu erreichen? Wenn nicht, wie nahe kommen wir zur Lösung des Ausdrucksproblems in F #?
Klarstellung: Ich gehe davon aus, dass das Problem wie in vorheriges Video in der Serie - Erweiterbarkeit des Datentyps und Operationen auf den Datentyp mit den Features der Code-Level-Modularisierung und separate Kompilierung (Erweiterungen können als separate Module bereitgestellt werden, ohne den ursprünglichen Code zu ändern oder neu zu kompilieren) sowie statische Sicherheit.
Wie Jörg in einem Kommentar gesagt hat, hängt es davon ab, was Sie mit lösen meinen. Wenn Sie lösen einschließlich einer Art von Typ-Überprüfung, dass Sie eine Implementierung einer Funktion für einen bestimmten Fall nicht verpassen, dann gibt Ihnen F # keine elegant (und ich bin mir nicht sicher, ob die Haskell-Lösung elegant ist). Möglicherweise können Sie es mit der von kvb erwähnten SML-Lösung oder mit einer der OO-basierten Lösungen verschlüsseln .
Wenn ich in Wirklichkeit ein reales System entwickeln würde, das das Problem lösen muss, würde ich eine Lösung wählen, die Ihnen keine vollständige Überprüfung bietet, aber viel einfacher zu benutzen ist.
Eine Skizze wäre, obj
als Repräsentation eines Typs zu verwenden und Reflektion zu verwenden, um Funktionen zu finden, die Implementierung für einzelne Fälle bereitstellen. Ich würde wahrscheinlich alle Teile mit einem Attribut markieren, um die Überprüfung zu erleichtern. Ein Modul, das einem Ausdruck eine Anwendung hinzufügt, könnte folgendermaßen aussehen:
Dies gibt Ihnen keine Typprüfung, aber es gibt Ihnen eine ziemlich elegante Lösung, die einfach zu verwenden und nicht so schwierig zu implementieren ist (durch Reflexion). Die Überprüfung, ob ein Fall nicht fehlt, wird nicht zur Kompilierzeit durchgeführt, Sie können jedoch problemlos Einheitentests dafür schreiben.
Ich weiß, dass Typklassen in F # nicht verfügbar sind, aber gibt es eine Möglichkeit, andere Sprachfunktionen zu verwenden, um diese Art von Erweiterbarkeit zu erreichen?
Ich glaube nicht, nein.
Wenn nicht, wie nahe kommen wir zur Lösung des Ausdrucksproblems in F #?
Das Ausdrucksproblem besteht darin, dem Benutzer zu ermöglichen, den Bibliothekscode mit neuen Funktionen und neuen Typen zu erweitern, ohne die Bibliothek neu kompilieren zu müssen. In F # erleichtern Unionstypen das Hinzufügen neuer Funktionen (aber das Hinzufügen neuer Union-Fälle zu einem vorhandenen Unionstyp ist nicht möglich) und Klassentypen erleichtern das Ableiten neuer Klassentypen (es ist jedoch unmöglich, einer vorhandenen Klassenhierarchie neue Methoden hinzuzufügen) . Dies sind die beiden Formen der Erweiterbarkeit, die in der Praxis erforderlich sind. Die Fähigkeit, sich in beide Richtungen gleichzeitig zu erweitern, ohne die statische Sicherheit zu opfern, ist nur eine akademische Kuriosität, IME.
Übrigens ist der eleganteste Weg, um diese Art der Erweiterbarkeit zu bieten, die ich gesehen habe, die Typsicherheit zu opfern und die sogenannte "regelbasierte Programmierung" zu verwenden. Mathematica macht das. Zum Beispiel kann eine Funktion zur Berechnung der symbolischen Ableitung eines Ausdrucks, der ein ganzzahliges Literal, eine Variable oder eine Addition ist, in Mathematica wie folgt geschrieben werden:
%Vor%Wir können die Unterstützung für die Multiplikation wie folgt nachrüsten:
%Vor%und wir können eine neue Funktion hinzufügen, um einen Ausdruck wie folgt auszuwerten:
%Vor%Für mich ist das viel eleganter als jede der Lösungen, die in Sprachen wie OCaml, Haskell und Scala geschrieben sind, aber natürlich ist es nicht typsicher.
Tags und Links f#