2017-12-21 14 views
2

Ich verwechselte mit Modultyp in Ocaml.warum Modul-Typ in Ocaml verwenden?

Ich fragte mich, in welcher Situation sollten wir den Modultyp verwenden?

Normalerweise verwende ich Modul sig in .mli, um einige Details zu enthüllen, und setzen entsprechende Implementierung Modulstruktur in .ml.

Zum Beispiel:

.mli

module A: 
sig 
    type t = T of string 
end 

.ml

module A = 
struct 
    type t = T of string 
end 

Aus diesem Grund denke ich, Ocaml des Moduls wie .h und C-Datei in C.

Ich weiß, dass Modultyp eine Schnittstelle deklarieren kann, aber die Schnittstelle war nicht wie Java-Schnittstelle.

wie ein Beispiel in Buch:

open Core.Std 

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

    module String_id = struct 
    type t = string 
    let of_string x = x 
    let to_string x = x 
    end 

    module Username : ID = String_id 
    module Hostname : ID = String_id 

    type session_info = { user: Username.t; 
        host: Hostname.t; 
        when_started: Time.t; 
       } 

    let sessions_have_same_user s1 s2 = 
     s1.user = s2.host 

Der vorstehende Code hat einen Bug: es vergleicht den Benutzernamen in einer Sitzung mit dem Host in der anderen Sitzung, wann sollte es die Benutzernamen in den beiden zu vergleichen werden Fälle.

Es scheint, dass der Modultyp keinen neuen allgemeinen Supertyp für seine Implementierung bereitstellen kann.

Was die reale Anwendung für Modultyp ??

Antwort

0

module types eng mit functors verwandt sind. Lesen Sie the module system Kapitel.

Das Argument eines Funktors hat einen Modultyp und das hat auch sein Ergebnis.

Funktoren werden häufig verwendet, und die meisten Standardcontainer (z. B. Set -s oder Map -s) sind Funktoren.

Wenn Sie Ihre generischen Container entwickeln, werden Sie sicherlich Funktoren und Modultypen benötigen.

(so functors und Modultypen sind als nützlich in Ocaml als templates geeignet sind, in C++)

5

Dabei wird der Modultyp Verbergen der Typ t den Benutzer des Moduls verwendet.

Wenn man Username.t oder Hostname.t verwendet, kann man sich nicht darauf verlassen, dass diese Typen Zeichenfolgen, ganze Zahlen oder einen bestimmten Typ sind. Der Modultyp macht sie undurchsichtig, als ob sie nicht Teil der Schnittstelle des Moduls wären, sondern nur ein Implementierungsdetail, das der Modulschreiber in der Zukunft ändern wird.

Grundsätzlich kann der Benutzer des Moduls nur über die Modulfunktionen auf den Typ t reagieren.

Der Compiler überprüft, dass der Benutzercode keine Annahmen darüber macht, was diese Typen t tatsächlich sind, so dass der Modul Writer in der Zukunft sie ändern kann, ohne den Benutzercode zu brechen.

+0

Ich nehme an, dass, wenn mein Zweck einige Details verbergen würde, Modul sig genug ist. – qc1iu

+0

Was ist der gemeinsame Super-Typ von Benutzername.t und Hostname.t? Ich nehme an, dass Ocaml ** nicht mit ** Modultyp übereinstimmen kann. – qc1iu

+1

@ qc1iu Es gibt keinen gemeinsamen Supertyp. Schließlich könnte einer von ihnen "string" und der andere "int" sein. Als Benutzer des Moduls können Sie nicht sehen, was genau der Typ ist, Sie können nur die Funktionen ausnutzen, die das Modul zur Verfügung stellt, um an diesem (abstrakten) Typ zu arbeiten. – chi

3

Wie bereits erwähnt, wird hier der Modultyp verwendet, um eine abstraktere Sicht des Typs t zu erreichen. Wenn Sie Username und Hostname als zwei separate Module definieren, heißt das, dass sie logisch unterschiedlich sein müssen und dass die Signatur dieser Module die einzig mögliche Art ist, mit ihnen zu arbeiten.

Aber Sie sind falsch, wenn Sie sagen:

Es dass Modultyp bieten scheint keinen neuen gemeinsamen Supertyp für es Implementierung ist.

Eigentlich können Sie präzisieren, dass Username.t und Hostname.t die gleichen Typen sind.

module Username = (String_id : ID with type t = String_id.t) 
module Hostname = (String_id : ID with type t = String_id.t) 

Username.to_string (Hostname.of_string "hi") 

Hier ist es nutzlos, aber manchmal ist es wirklich hilfreich.