2010-07-25 4 views
8

Ich bin ziemlich fest mit dem folgenden Funktor Problem in OCaml. Ich füge einen Teil des Codes ein, damit Sie es verstehen. GrundsätzlichFunktoren in OCaml verstehen

I definiert diese beiden Module in pctl.ml:

module type ProbPA = sig 
    include Hashtbl.HashedType 
    val next: t -> (t * float) list 
    val print: t -> float -> unit 
end 

module type M = sig 
    type s 
    val set_error: float -> unit 
    val check: s -> formula -> bool 
    val check_path: s -> path_formula -> float 
    val check_suite: s -> suite -> unit 
end 

und die folgende Funktors:

module Make(P: ProbPA): (M with type s = P.t) = struct 
    type s = P.t 
    (* implementation *) 
end 

Dann tatsächlich diese Module verwenden I definiert ein neues Modul direkt in einer Datei prism.ml genannt:

type state = value array 
type t = state 
type value = 
    | VBOOL of bool 
    | VINT of int 
    | VFLOAT of float 
    | VUNSET 
(* all the functions required *) 

Von einer dritten Quelle (formulas.ml) Ich habe den Funktors mit Prism Modul verwendet:

module PrismPctl = Pctl.Make(Prism) 
open PrismPctl 

Und schließlich von main.ml

open Formulas.PrismPctl 
(* code to prepare the object *) 
PrismPctl.check_suite s.sys_state suite (* error here *) 

und kompiliert gibt dem folgenden Fehler

Error: This expression has type Prism.state = Prism.value array but an expression was expected of type Formulas.PrismPctl.s

Von dem, was ich dort verstehen kann, eine Art schlechtes Aliasing der Namen, sie sind die gleichen (seit value array ist der Typ definiert als t und es 's verwendet M with type s = P.t im Funktor), aber der Typ Checker betrachtet sie nicht als gleich.

Ich verstehe wirklich nicht, wo das Problem ist, kann mir jemand helfen?

Vielen Dank im Voraus

+0

Ich weiß nicht genug über OCaml, zu helfen, aber es ist möglich, dass diese vorherige Frage ist ein ähnliches Problem? http://StackOverflow.com/Questions/640510/Functors-in-Coaml – Gian

+0

@Gian: Es ist das gleiche Problem root, aber wenn Sie das verstehen, sind Sie bereits auf dem besten Weg, um die Frage in der nicht zu stellen erster Platz. – Gilles

Antwort

6

(Sie senden nicht kompilierbaren Code. Das ist eine schlechte Idee, weil es es für Menschen schwieriger machen kann, Ihnen zu helfen, und weil das Problem auf ein einfaches Beispiel zu reduzieren manchmal genug ist, um es zu lösen. Aber ich denke, ich sehe Ihre Schwierigkeit sowieso.)

Inside formulas.ml, Ocaml kann sehen, dass PrismPctl.s = Pctl.Make(Prism).t = Prism.t; die erste Gleichheit stammt aus der Definition PrismPctl, und die zweite Gleichheit stammt aus der Signatur Pctl.Make (speziell das with type s = P.t Bit).

Wenn Sie keine mli Datei für Formulas schreiben, sollte Ihr Code kompilieren. Das Problem muss also sein, dass die .mli Datei, die Sie geschrieben haben, die richtige Gleichheit nicht erwähnt.Sie zeigen Ihre nicht .mli Dateien (Sie sollten, sie sind Teil des Problems), aber vermutlich schrieb man

module PrismPctl : Pctl.M 

Das ist nicht genug: wenn der Compiler main.ml kompiliert, wird es nicht wissen nichts über PrismPctl das ist nicht in formulas.mli angegeben. Sie müssen entweder

module PrismPctl : Pctl.M with type s = Prism.t 

oder angeben, vorausgesetzt, Sie with type s = P.t in der Signatur von Make in pctl.mli enthalten

module PrismPctl : Pctl.M with type s = Pctl.Make(Prism).s 
+0

Das war das Problem. Ich habe es gestern erkannt, indem ich mir die Antwort auf die Frage angesehen habe, die von gian im Kommentar verlinkt wurde. Ich habe meine '.mli'-Datei nicht eingefügt, weil ich vergessen habe, es zu tun ... meine Schuld! Vielen Dank – Jack

2

Dies ist ein Problem, das ich in so gut lief, wenn Sie mehr über diese zu lernen. Wenn Sie den Funktor erstellen, legen Sie die Signatur des Funktors offen, in diesem Fall M. Es enthält einen abstrakten Typ s, der vom Funktor parametrisiert ist, und alles Spezifische ist nicht nach außen hin offen. Wenn Sie auf ein beliebiges Datensatzelement von s (wie in sys_state) zugreifen, führt dies zu einem Typfehler, wie Sie festgestellt haben.

Der Rest sieht gut aus. Es ist definitiv schwierig, mit Funktoren richtig umzugehen, aber denken Sie daran, dass Sie nur Instanzen des vom Funktor parametrisierten Typs über die Schnittstelle/Signatur manipulieren können, die vom Funktor verfügbar gemacht wird.