Ja. Dies wird als "Wörterbuchübergabestil" bezeichnet. Manchmal, wenn ich einige besonders knifflige Dinge mache, muss ich eine Typklasse verschrotten und in ein Wörterbuch verwandeln, da die Wörterbuchübergabe leistungsfähiger ist 1 , aber oft recht umständlich, wodurch konzeptionell einfacher Code ziemlich kompliziert aussieht. Ich verwende manchmal den Wörterbuch-Übergabestil in Sprachen, die nicht Haskell sind, um Typklassen zu simulieren (habe aber gelernt, dass dies normalerweise keine so gute Idee ist, wie es sich anhört).
Wenn es einen Unterschied in der Ausdruckskraft gibt, gibt es natürlich einen Kompromiss. Während Sie eine bestimmte API auf mehr Arten verwenden können, wenn sie mit DPS geschrieben wurde, erhält die API weitere Informationen, wenn Sie dies nicht können. Dies zeigt sich in der Praxis unter anderem Data.Set
darin, dass es nur ein Ord
Wörterbuch pro Typ gibt. Das Set
speichert seine Elemente sortiert nach. Ord
Wenn Sie einen Satz mit einem Wörterbuch erstellen und dann ein Element mit einem anderen einfügen, wie dies mit DPS möglich wäre, können Sie die Set
Invariante brechen und zum Absturz bringen. Dieses Eindeutigkeitsproblem kann mithilfe eines Phantom-Existenzials gemindert werdenGeben Sie ein, um das Wörterbuch zu markieren, aber auf Kosten einer ziemlich nervigen Komplexität in der API. Dies wird auch in der Typeable
API ziemlich ähnlich angezeigt.
Das Einzigartigkeitsbit kommt nicht sehr oft vor. Was Typklassen großartig können, ist das Schreiben von Code für Sie. Zum Beispiel,
catProcs :: (i -> Maybe String) -> (i -> Maybe String) -> (i -> Maybe String)
catProcs f g = f <> g
Das erfordert zwei "Prozessoren", die eine Eingabe annehmen und möglicherweise eine Ausgabe geben und diese verketten, wobei sie abgeflacht werden Nothing
, müsste in DPS wie folgt geschrieben werden:
catProcs f g = (<>) (funcSemi (maybeSemi listSemi)) f g
Wir mussten im Wesentlichen den Typ buchstabieren, bei dem wir ihn erneut verwenden, obwohl wir ihn bereits in der Typensignatur geschrieben haben, und selbst das war überflüssig, da der Compiler bereits alle Typen kennt. Da es nur einen Weg gibt, einen bestimmten Semigroup
Typ zu erstellen, kann der Compiler dies für Sie tun. Dies hat einen Effekt vom Typ "Zinseszins", wenn Sie anfangen, viele parametrische Instanzen zu definieren und die Struktur Ihrer Typen zu verwenden, um wie in den Data.Functor.*
Kombinatoren für Sie zu berechnen , und dies wird mit großer Wirkung verwendet, deriving via
wenn Sie im Wesentlichen alle erhalten können "Standard" algebraische Struktur Ihres Typs für Sie geschrieben.
Und lassen Sie mich nicht einmal mit MPTCs und Fundeps anfangen, die Informationen in Typchecking und Inferenz zurückführen. Ich habe noch nie versucht, so etwas in DPS umzuwandeln - ich vermute, es würde bedeuten, viele Beweise für die Gleichstellung von Typen weiterzugeben -, aber ich bin mir auf jeden Fall sicher, dass es viel mehr Arbeit für mein Gehirn bedeuten würde, als ich mir bequem machen würde mit.
- -
1 U Nless Sie verwenden , reflection
in welchem Fall sie in Kraft äquivalent werden - aber reflection
auch umständlich zu bedienen sein.