2017-09-04 4 views
4

Ich bin neu in Ocaml und ich habe einen seltsamen Fehler aufgetreten, als ich einen Interpreter für Lambda-Kalkül schrieb.anonyme Variablen in ocaml Typ Inferenz

let rec valof : exp -> env -> value = 
    fun exp env -> 
    match exp with 
     Var n -> exp2value (lookup env n) 
    | Lambda (name , body) -> Clos (name , body , env) (*some thing wrong here*) 
    | _ -> Err 
;; 

exp, value und env sind wie definiert:

type exp = 
    Num of int 
    | Str of string 
    | Err 
    | Var of string 
    | Lambda of string * exp 
    | App of exp * exp 
;; 

type value = 
    Num of int 
    | Str of string 
    | Clos of string * exp * env 
    | Err 
;; 

type env = 
    Empty 
    | Cons of string * exp * env 
;; 

Beim Kompilieren der Compiler auf die Lambda-Linie des Interpreters beschwerte:

Error: This expression has type env/1490 
     but an expression was expected of type env/1457 

Irgendwelche Ideen, wo ich aufgeschraubt oben? Danke!

+4

Dies bedeutet, dass 'env' zweimal auf verschiedenen Zeilen in verschiedenen Bereichen deklariert wurde. Die beiden Typen haben den gleichen Namen, sind aber nicht gleich. – Bergi

+0

(Machen Sie das eine Antwort :-) –

+0

Ich werde morgen einige richtige Referenzen finden und dann einen schreiben. – Bergi

Antwort

1
Error: This expression has type env/1490 
but an expression was expected of type env/1457 

Diese Art von Fehler ist ziemlich häufig, wenn Sie Ihren Code in einer interaktiven Toplevel debuggen (ers) und es bedeutet, dass Sie die Art erklärt env zweimal. Das kann passieren, wenn Sie Ihren Code in eine REPL kopieren.


Sie brauchen nicht alle ;; nach jeder Anweisung anhängen. Der OCaml-Compiler benötigt sie nicht. Nichtsdestoweniger, da ;; bedeutet, dass es in der Toplevel und nur dort nützlich ist.


Wie Sie wissen, kann die erste | weggelassen werden, wenn Sie ein Pattern-Matching tun oder wenn Sie eine Summe Typ definieren. Da Sie die Ausrichtung jedoch auf jeden Fall beibehalten möchten, wird es häufig als eine gute Vorgehensweise angesehen, die Zeile | in jede Zeile aufzunehmen, auch wenn dies keine Verpflichtung ist.


Hier sind Sie Typ schließen sich nicht ab, sondern value hängt von exp und env und hängt von exp das bedeutet, dass Sie die Typen in der richtigen Reihenfolge zu vorsichtig declare haben. Aber aus Gründen der Übersichtlichkeit möchten Sie sie möglicherweise in einer anderen Reihenfolge darstellen, die logischer erscheinen kann. (Ich meine nicht, dass diese Reihenfolge besser ist als eine andere Ich möchte nur, dass Sie wissen, dass Sie die folgende Syntax verwenden können).

Zum Beispiel, wenn Sie Ihren Typ top-down (von der Bild-Sache (dh die Umgebung) auf die interne Sache (dh. Werte) präsentieren möchten, können Sie die and Syntax, die den Compiler das sagt die Typen sind voneinander abhängig.

type env = 
    | Empty 
    | Cons of string * exp * env 

and exp = 
    | Num of int 
    | Str of string 
    | Err 
    | Var of string 
    | Lambda of string * exp 
    | App of exp * exp 

and value = 
    | Num of int 
    | Str of string 
    | Clos of string * exp * env 
    | Err 

Letzte Sache, die beide value und exp enthalten die folgenden Konstruktoren Num of int und Str of string kann OCaml nicht sagen, ob Int 1 ein value oder exp sein sollte. Genauer gesagt wird OCaml wählen, dass der Konstruktor Int sich auf env oder exp bezieht (dasjenige, das es wählt, hängt von der Reihenfolge ab, in der Sie es deklariert haben). Daher wird empfohlen, verschiedene Namen für Konstruktoren zu wählen.