2010-03-13 4 views
22

Ich habe Mühe zu verstehen, was genau es bedeutet, wenn ein Wert A @cpsParam[B,C] hat und welche Typen dieser Form ich zuordnen soll Meine Werte bei Verwendung der Begrenzten Fortsetzungsfunktion.Verstehen Sie nicht die Eingabe von Scalas abgegrenzten Fortsetzungen (A @cpsParam [B, C])

Ich habe bei einigen Quellen sah:

http://lamp.epfl.ch/~rompf/continuations-icfp09.pdf

http://www.scala-lang.org/node/2096

http://dcsobral.blogspot.com/2009/07/delimited-continuations-explained-in.html

http://blog.richdougherty.com/2009/02/delimited-continuations-in-scala_24.html

aber sie haben mir nicht viel Intuition in diese geben. Im letzten Link versucht der Autor, eine explizite Erklärung zu geben, aber es ist sowieso nicht klar genug.

Das A steht für die Ausgabe der Berechnung, die auch die Eingabe für ihre Fortsetzung ist. Das B stellt den Rückgabetyp dieser Fortsetzung dar, und das C stellt seinen "letzten" Rückgabetyp dar - weil Shift den zurückgegebenen Wert weiter verarbeiten und seinen Typ ändern kann.

Ich verstehe nicht den Unterschied zwischen "Ausgabe der Berechnung", "Rückgabetyp der Fortsetzung" und "endgültigen Rückgabetyp der Fortsetzung". Sie klingen wie Synonyme.

+2

Ich bin immer traurig, wenn Leute meinen Blogbeitrag nicht sehen können: http://suereth.blogspot.com/2010/03/how-you-should-think-about-delimited.html I beziehe das im Detail, da es mich frustrierte, dass ich mir bestehende Quellen im Internet sehr ansehe. – jsuereth

+0

Danke Josh, ich werde auf deinen Beitrag schauen. – jkff

Antwort

20

Also, die Leute haben mir mit diesem hier woanders geholfen. Hier ist die Antwort:

reset ({ 
    ... 
    ...shift((k:A=>B) => ...::C)::A... 
    ... 
}::B)::C 

So shift ist ein Loch vom Typ A in einer Berechnung {...} vom Typ B. Das Argument shift gibt einen Wert vom Typ C zurück und deshalb hat reset ({...}) den Typ C.

Der Schlüsseltrick beim Verstehen dieses Zeugs war zu sehen, dass {...} und reset {...} unterschiedliche Typen haben, je nachdem, welchen Typ das shift Argument zurückgibt.

Zum Beispiel:

reset ({ 
    "number "+shift((k:Int=>String) => List(k(1), k(2), k(3))) 
}) 

kehrt List("number 1", "number 2", "number 3").

Hier A ist Int, BString ist, C ist List[String] weil {"number" + _} (hier) ist eine Funktion Int-String und das Argument von shift, da die Funktion, erzeugt ein List[String], das Ergebnis der reset({...}) wird.

+0

Sehr gute Erklärung! – hotzen

1

Ich bin immer noch dabei herauszufinden, welche genauen Regeln/Implikationen hier enthalten sind.

Es scheint einfach/einfacher, wenn die Typen in den Beispielen "einfach genug" sind, um "gut zu passen", wie oben gezeigt, aber es wird interessanter/schwieriger (zumindest für mich) im Vergleich mit der Typisierung geben durch tiark Rompf:

|- e: [email protected][B,C]; {[|r|]}: U 
----------------------------------------------------- 
[|val x: A = e; r|] = [|e|].map((x: A) => {[|r|]}) 

so das Ergebnis [|e|].map((x: A) => {[|r|]}) wird die Art in tiark Papier gegeben Shift[U,B,C] nach der Definition der Karte hat.

Hier ist U nicht unbedingt das gleiche sein wie B.

Bisher habe ich verstehe nicht, warum U von B ohne so etwas wie U <: B in der Definition der Karte in tiark Papier gegeben, anders zu sein erlaubt.

Was vermisse ich repsectivy hier nicht zu verstehen?

Irgendwelche Tipps/Ideen?

Verwandte Themen