Ich versuche, eine Form von abstrakten Syntaxgraphen zu implementieren, wie Andres Loeh und Bruno beschrieben haben C. d. S. Oliveira . In den meisten Fällen scheint ich die Dinge richtig zu verstehen. Wenn ich jedoch letrec in meine Syntax einfüge, habe ich einige Probleme. Ich denke, es ist einfacher, dieses kleine Codebeispiel zu bearbeiten:
Zuerst ein kleiner Vorspiel:
%Vor%Jetzt kann ich die Syntax für meine Sprache definieren. In diesem Fall versuche ich zwei Ebenen in meinem Videospiel zu beschreiben. Ich habe Vertices (Punkte in der Ebene) und Wände (Liniensegmente zwischen Vertices).
%Vor% Nach PHOAS verwenden wir einen höheren Rank-Typ, um die Parameter über die Wahl von f
zu setzen:
Lassen Sie uns schließlich einen syntaktischen Zucker für letrec
einführen, der automatisch alles mit Var
markiert, wie von der Zeitung vorgeschlagen:
Wir können jetzt einige Programme in dieser Sprache schreiben. Hier ist ein einfacher Ausdruck, der zwei Vertices einführt und eine Wand zwischen ihnen definiert.
%Vor%Das funktioniert gut. Ein äquivalenter Ausdruck wäre, letrec zu verwenden, um zwei Vertices und die Wand zwischen ihnen zu definieren, die alle gebunden sind. Im Körper von letrec können wir einfach die Wandbindung zurückgeben. Wir beginnen damit, die Wand in die Letrec zu bringen und einige Löcher hinzuzufügen, um zu sehen, was GHC weiß:
%Vor%GHC informiert uns:
%Vor% Ok, gut - GHC weiß, dass ts
zwei VertexId
s und eine WallId
enthält. Wir
sollte in der Lage sein, eine Übereinstimmung mit ts
zu finden, um jeden dieser Ausdrücke zu extrahieren.
Wenn ich versuche, das zu prüfen, werde ich mit
vorgestellt %Vor% Warum erwartet GHC jetzt ein TList (LevelExpr f) ts0
, wenn es zuvor neu das ts0 ~ '[VertexId, VertexId, WallId]
?
Typ-Inferenz funktioniert nicht zuverlässig mit GADTs. Sie können den Code reparieren, indem Sie eine einfache Anmerkung eingeben:
%Vor%Tags und Links haskell