Scala rozdzielany kontynuacje, realizowanej w ramach kontynuacji wtyczki są adaptacją przesunięcia i zresetować operatorów kontroli wprowadzonych przez Danvy i Filiński. Zobacz ich abstrahując sterowania i Reprezentowanie Sterowanie: studium transformacji CPSpapers od 1990 do 1992. W kontekście język maszynowy, praca z zespołem EPFL wydłuża pracę Asai. Zobacz artykuły 2007: here.
To powinno być dużo formalizmu! Spojrzałem na te i niestety wymagają one płynności w notacji rachunku lambda.
Z drugiej strony, znalazłem następujące Programowanie z Shift i Resettutorial i czuje się jak miałem naprawdę przełom w zrozumieniu, kiedy zacząłem tłumaczyć przykłady Scala i kiedy wróciłem do sekcji „2.6 Jak wyodrębnić rozdzielone kontynuacje ".
Operator reset
ogranicza fragment programu. shift
jest używany w miejscu, w którym występuje wartość (w tym prawdopodobnie w jednostce). Możesz myśleć o tym jak o dziurę. Przedstawmy to za pomocą ◉.
Więc spójrzmy na następujących wyrażeń:
reset { 3 + ◉ - 1 } // (1)
reset { // (2)
val s = if (◉) "hello" else "hi"
s + " world"
}
reset { // (3)
val s = "x" + (◉: Int).toString
s.length
}
Co shift
robi to, aby włączyć program wewnątrz reset do funkcji, które można uzyskać dostęp (proces ten nazywany jest reifikacja). W powyższych przypadkach funkcje są następujące:
val f1 = (i: Int) => 3 + i - 1 // (1)
val f2 = (b: Boolean) => {
val s = if (b) "hello" else "hi" // (2)
s + " world"
}
val f3 = (i: Int) => { // (3)
val s = "x" + i.toString
s.length
}
Funkcja nazywana jest kontynuacją i jest podawana jako argument do własnej argumentacji. Przesunięcie jest podpis:
shift[A, B, C](fun: ((A) => B) => C): A
Kontynuacja będzie (A => B) funkcja i kto pisze kod wewnątrz shift
zdecyduje, co zrobić (lub nie robić) z nim. Naprawdę masz poczucie, co może zrobić, jeśli po prostu go zwrócisz. Wynik reset
jest wtedy reified obliczeń sam:
val f1 = reset { 3 + shift{ (k:Int=>Int) => k } - 1 }
val f2 = reset {
val s =
if (shift{(k:Boolean=>String) => k}) "hello"
else "hi"
s + " world"
}
val f3 = reset {
val s = "x" + (shift{ (k:Int=>Int) => k}).toString
s.length
}
myślę aspekt reifikacja jest bardzo ważnym aspektem zrozumienia Scala rozdzielany kontynuacje.
Z perspektywy typu, jeśli funkcja k
ma typ (A => B), wówczas shift
ma typ [email protected][B,C]
. Typ C
jest ściśle określony przez to, co wybrałeś, aby powrócić do wnętrza shift
. Wyrażenie zwracające typ oznaczony cpsParam
lub cps
zostało zakwalifikowane jako zanieczyszczone w papierze EPFL. Jest to przeciwieństwo wyrażenia pure, które nie ma typów z adnotacjami cps.
Zanieczyszczone obliczenia są przekształcane w obiekty Shift[A, B, C]
(obecnie nazywane ControlContext[A, B, C]
w bibliotece standardowej). Obiekty Shift
rozszerzają monadę kontynuacji. Ich formalne wdrożenie znajduje się w EPFL paper, sekcja 3.1 strona 4. Metoda map
łączy czyste obliczenia z obiektem Shift
. Metoda flatMap
łączy nieczyste obliczenia z obiektem Shift
.
Wtyczka kontynuacji wykonuje transformację kodu zgodnie z konturem podanym w sekcji 3.4 EPLF paper. Zasadniczo, shift
są przekształcane w obiekty Shift
. Czyste wyrażenia występujące po połączeniu są łączone z mapami, a nieczyste są łączone z płaskimi mapami (zobacz więcej reguł rysunek 4).Na koniec, gdy wszystko zostanie przekonwertowane do zamykającego resetu, jeśli wszystko zostanie sprawdzone, typ końcowego obiektu Shift po wszystkich mapach i płaskich mapach powinien być Shift[A, A, C]
. Funkcja reset
potwierdza zawarty Shift
i wywołuje funkcję z funkcją tożsamości jako argumentem.
Podsumowując, uważam, że dokument EPLF zawiera formalny opis tego, co się dzieje (sekcja 3.1 i 3.4 oraz rysunek 4). Samouczek, o którym wspomniałem, zawiera bardzo dobrze dobrane przykłady, które dają wspaniałe odczucie dla wytyczonych ścieżek.
Więc 'g: X => ???'? A 'shift' bierze' (X => Y) => Y'? A jeśli istnieje 'B', wynik zawsze będzie" po prostu "' B'? – ziggystar
Muszę też powiedzieć, że twoja notacja "..." nie jest zbyt formalna. Co to znaczy? – ziggystar
@ziggystar Starałem się zachować prostotę, ale proszę bardzo, bardziej formalnie. Nie potrafię jednak uzyskać sformułowania "formalnie", zachowując przy tym prostotę. –