2016-06-13 26 views
11

Es ist bekannt, dass OCaml einen parametrischen Polymorphismus hat und dies zu einigen Einschränkungen führt. Haskell bietet durch seine Typklassen einen ad hoc Polymorphismus, der offensichtlich in verschiedenen Situationen sehr praktisch ist. Es ist auch bekannt, dass das System von Modulen und Funktoren von OCaml es ermöglicht, eine Art ad hoc Polymorphismus zu erstellen. Sehen Sie die große aktuelle Antwort von Simon Shine here zum Beispiel.OCaml-Funktoren, Haskell-Typklassen und Mehrfachableitungen

Mein Punkt ist, dass es in Haskell möglich ist, Typen zu erstellen, die mehrere Typen Klassen ableiten. Zum Beispiel:

data Person = Person { firstName :: String 
       , lastName :: String 
       , age :: Int 
       } deriving (Eq, Show, Read) 

Dies ist sehr praktisch Typen mit mehreren Funktionen (so dass Werte des Typs Person auf Gleichheit Tests zu unterstützen, sein bedruckbar, und in dem gegebenen Beispiel lesbar sein) zu definieren.

Meine Frage ist die folgende: Können wir das gleiche tun, einfach, in OCaml? Durch einfach ich meine mit der Grundsyntax der Sprache und ohne viele Kunstgriffe.

ein etwas konkretes Beispiel zu geben, nehmen wir haben zwei OCaml Unterschriften

module type Showable = sig 
    type t 
    val to_string : t -> string 
end 

module type Readable = sig 
    type t 
    val from_string : string -> t 
end 

Ziel ist ein Funktor F von einem Modul parametrisiert zu schreiben, die sowohl Showable und Readable implementiert.

+2

Das muss eine der besten geschriebenen Fragen sein, die ich je gesehen habe! Hoffe, jemand wird eine Antwort finden! – Lhooq

Antwort

10

Sicher, das ist eigentlich ziemlich einfach, verwenden Sie Modul Aufnahme. ganz http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234
Der Rest ist reguläres Modul Sachen (siehe Handbuch für eine vollständige Erklärung)

Einige Funktors schwere Bibliothek verlassen sich auf diese Art von Struktur Subtyping:

module type S = sig 
    include Showable 
    include Readable with type t := t (* destructive substitution *) 
end 

module F (M : S) = struct 
    let fake_id x = M.from_string @@ M.to_string x 
end 

Destructive Substitution wird im Handbuch erklärt viel. Zum Beispiel definiert jeder Funktor in ocamlgraph sein eigenes Modultypargument. Hier ist ein Beispiel mit der Kruskal module. Der Funktor erwartet ein Modul vom Typ Kruskal.G, das eine Subsignatur von Sig.G implementiert (die von den meisten Graph-Modulen implementiert wird).

+0

Danke, das ist eigentlich ganz einfach! Können wir in gewissem Sinne sagen, dass das System der Typklassen von Haskell und das der Module und Funktoren von OCaml gleichwertig sind? –

+2

Sie sind nicht gleichwertig. Wie in [Modular Type Classes] (http://www.cse.unsw.edu.au/~chak/papers/mtc-popl.pdf) beschrieben, ist das ML-Modulsystem flexibler und allgemeiner als die Klassen von Haskell, aber don Rekursion nicht zulassen. Wenn Sie sie kombinieren, müssen Sie die funktor-Anwendung nicht manuell schreiben, sondern Sie vermeiden auch das Haskell-Problem, dass nur eine importierte Typklasseninstanz pro Typ vorhanden ist. Für eine Zusammenfassung der Unterschiede siehe Stefan Wehrs [ML-Module und Haskell-Typklassen: Ein konstruktiver Vergleich] (http://www.stefanwehr.de/publications/Wehr_ML_modules_and_Haskell_type_classes.pdf) S. 107-110. –

+3

Korrektur: Schlauere Personen als ich darauf hinweisen; Oleg Kiselyov hat eine Äquivalenz zwischen den beiden bewiesen (einige veraltete Definition von Haskell-Typ-Klassen gegeben), obwohl ich diesen Artikel nicht finden kann, während moderne Haskell-Typ-Klassen stärker als ML-Module sind, da sie Typ-Level-Funktionen bereitstellen. Ich vermeide es, kühne Aussagen zu machen und werde wieder coole Code-Snippets schreiben. ;-) –