Fragen:
Versuch von Antworten über weitere Fragen...
let x = bodyx in y
> abstraction over x; application of that abstraction with bodyx
(lx.y) bodyx
l func.l funcin. (l upin.(l upout.(l lowin.(l lowout.lowout) (low lowin)) upout.z) (up upin)) funcin.y
Die Outlet-Expression eines Patches ist im innersten sämtlicher Abstraktionen versteckt. Sie greift dabei auf die darüberliegenden Abstraktionen zurück, die die Outputs und Inputs von Funktionsapplikationen darstellen.
Somit lässt sich ein FunktionsPatch als Abstraktion über seinen tupled Input begreifen. Der Körper der Expression stellt den Output des FunktionsPatches dar.
Um diesen Output formulieren zu können werden neue Abstraktionen aufgesetzt angefangen mit denen, die sich auf triviale Weise aus den Patch-Input formulieren lassen. Der Formulierung des Outputs wird von oben kommend immer weiter nach innen vertagt, während durch neue Abstraktionen auf mehr Symbole leicht verwiesen werden kann.
Bei typisierten Abstraktionen lx:T1.t2 wird x:T1 in das TypeEnv von t2 aufgenommen. Das heisst für die Anwendung auf Patches, dass die Typen von oben nach unten durchgereicht würden, wenn bei jeder Abstraktion (node-inputs, node-outputs) eine explizite Typisierung angegeben wäre.
Man kann dies jedoch vernachlässigen, da die Schachtelung rein evaluationstechnisch bedingt ist. Das heisst die Schachtelung der Abstraktionen ist nur dem Zweck der Formulierbarkeit geschuldet. Dadurch, dass in einem Funktionspatch alle Knoteneingänge und -ausgänge durch eindeutige Abstraktionen beschrieben werden, die nicht mit einander kollidieren können (die eindeutige Namensgebung muss sichergestellt sein), kann von einem TypisierungsEnvironment pro Funktionspatch gesprochen werden. Typen, die für bestimmte Variablen (Abstraktionen) feststehen (erwartet werden), können sich damit von oben nach unten und vice versa propagieren. Eine andere Sicht der Dinge wäre, dass bei SourceCode-Änderungen oder sich ändernder Typsierung benutzter Knoten das Type-Environment des Patches ändert, auf das sich alle Knoten und Pins, die noch nicht bekannt sind (offen generische Typen besitzen) alle Regeln ansehen und u.U. deren Typ festsetzen oder verfeinern. Das kann jedoch unperformant sein. Typen können sich in reinen Funktionspatches nur über links zu pins, von pins zu knoten, von knoten zu pins und von pins wieder zu links übertragen. Insofern könnte ein Algorithmus zur Propagierung über diese Elemente schneller sein. Dieser Algorithmus müsste sich allerdings die schon besuchten Elemente merken um eine Endlosrekursion zu vermeiden. Die Liste der besuchten Elemente müsste im Falle einer neuen TypInferenz und deren Aufnahme in die Environment allerdings wieder gelöscht werden, um allen Elementen auch diese Neuerung zugänglich zu machen...
Besonders herzhaft wird das Ganze, wenn ein Link auf beiden Seiten (source und sink) einen offen generischen Typen besitzt. Sprechen wir mal vom einfachsten Fall, dass ein Outputpin den Typ A besitzt - z.B. bezogen auf den FunktionNode CAR<A>, der das erste Element einer Liste zurückgibt. Der Typ a wurde sozusagen vom Funktionsknoten als Typparameter in die Welt gesetzt. Nehmen wir weiter einen Input des GetTreeDepth<TLink,TNode>-Knotens, der vom Typ TNode ist. Mit dem Verbinden der beiden Pins muss einer der beiden Typen durch den anderen ersetzt werden, um ausdrücken zu können, dass beide Pins vom gleichen Typen sein müssen (bzw. deren zukünftigen Werte in Zukunft vom gleichen Typ sein werden).
Der Typ eines Pins wird also auch verändert werden müssen, wenn dadurch keine geschlossenere Form erreicht wird. Problematisch wird das besonders dann, wenn dadurch Typparameter-Namenskonflikte auftreten. Nehmen wir einen Knoten<A,B> der einen Pin vom Typ A und einen anderen Input vom Typ B besitzt. Wird nun an den Pin vom Typ B ein Output von Typ A angeschlossen wird hätte auch der zweite Input also Typ A. Das Problem dabei ist, dass dieser Typ A typischerweise von einem anderen Knoten<A> in die Welt gesetzt wurde und schlicht ein Platzhalter ist, der mit dem anderen Platzhaltertyp A von Knoten<A,B> rein gar nichts zu tun hat. Weiterhin sollte der Knoten<A,B> zwei unterschiedliche Typenvariablen besitzen. Eine Neubenennung des oberen Typen wäre plötzlich notwendig. (z.B. in CAR_A). Der untere Knoten hätte nun Inputs mit den Typen A und CAR_A...
Am Ende wäre des weiteren das Ziel auch generisch zu patchen können, d.h. dass auch patches mit in und outlets offen generische Typen besitzen dürfen und der komplette Patch Typparameter einführt. Patch<A, B> also. Erst bei Anwendung des Patches würde natürlich irgendwann die Auflösung notwendig werden.
anonymous user login
~3mth ago
~4mth ago
~4mth ago
~4mth ago
~4mth ago
~4mth ago
~4mth ago
~4mth ago
~5mth ago
~5mth ago