Podczas ICFP 2012, Conor McBride wygłosił przemówienie z pytaniem "Agda-curious?".Agda: funkcja run dla przykładu stosu Conora
Zawierała implementację małego stosu maszyn.
Film jest na youtube: http://www.youtube.com/watch?v=XGyJ519RY6Y
Kod jest zbyt online: http://personal.cis.strath.ac.uk/conor.mcbride/ICFP12Code.tgz
Zastanawiam o funkcji run
części 5 (czyli "Part5Done.agda" jeśli pobrać kod). Dyskusja zatrzymuje się przed wyjaśnieniem funkcji run
.
data Inst : Rel Sg SC Stk where
PUSH : {t : Ty} (v : El t) -> forall {ts vs} ->
Inst (ts & vs) ((t , ts) & (E v , vs))
ADD : {x y : Nat}{ts : SC}{vs : Stk ts} ->
Inst ((nat , nat , ts) & (E y , E x , vs))
((nat , ts) & (E (x + y) , vs))
IFPOP : forall {ts vs ts' vst vsf b} ->
List Inst (ts & vs) (ts' & vst) -> List Inst (ts & vs) (ts' & vsf)
-> Inst ((bool , ts) & (E b , vs)) (ts' & if b then vst else vsf)
postulate
Level : Set
zl : Level
sl : Level -> Level
{-# BUILTIN LEVEL Level #-}
{-# BUILTIN LEVELZERO zl #-}
{-# BUILTIN LEVELSUC sl #-}
data _==_ {l : Level}{X : Set l}(x : X) : X -> Set l where
refl : x == x
{-# BUILTIN EQUALITY _==_ #-}
{-# BUILTIN REFL refl #-}
fact : forall {T S} -> (b : Bool)(t f : El T)(s : Stk S) ->
(E (if b then t else f) , s) ==
(if b then (E t , s) else (E f , s))
fact tt t f s = refl
fact ff t f s = refl
compile : {t : Ty} -> (e : Expr t) -> forall {ts vs} ->
List Inst (ts & vs) ((t , ts) & (E (eval e) , vs))
compile (val y) = PUSH y , []
compile (e1 +' e2) = compile e1 ++ compile e2 ++ ADD , []
compile (if' e0 then e1 else e2) {vs = vs}
rewrite fact (eval e0) (eval e1) (eval e2) vs
= compile e0 ++ IFPOP (compile e1) (compile e2) , []
{-
-- ** old run function from Part4Done.agda
run : forall {ts ts'} -> List Inst ts ts' -> List Elt ts [] -> List Elt ts' []
run [] vs = vs
run (PUSH v , is) vs = run is (E v , vs)
run (ADD , is) (E v2 , E v1 , vs) = run is (E 0 , vs)
run (IFPOP is1 is2 , is) (E tt , vs) = run is (run is2 vs)
run (IFPOP is1 is2 , is) (E ff , vs) = run is (run is1 vs)
-}
run : forall {i j} -> List Inst i j -> Sg Stack (λ s -> s == i) → (Sg SC Stk)
run {vs & vstack} [] _
= (vs & vstack)
run _ _ = {!!} -- I have no clue about the other cases...
--Perhaps the correct type is:
run' : forall {i j} -> List Inst i j -> Sg Stack (λ s -> s == i) → Sg (Sg SC Stk) (λ s → s == j)
run' _ _ = {!!}
Jaki jest poprawny typ podpisu funkcji run
? W jaki sposób należy zaimplementować funkcję run
?
Funkcja kompilacji została wyjaśniona about 55 minutes into the talk. Pełny kod to available from Conor's webpage.
Wspomniał Pan o ponownym obliczeniu wymazanych informacji. Chyba funkcja 'run' to robi. Czy funkcja "biegania" byłaby generowana również z ornamentami? Jeśli nie, w jaki sposób można zastosować "ogólne twierdzenie"? (Chciałbym mieć pewność, że funkcja 'run' również jest poprawna.) – mrsteve
W rozmowie wspomina się również, że przykład stosu można rozszerzyć za pomocą instrukcji skoku (może to być prosta instrukcja 'jump' do implementacji podprogramów lub też pętli' jumpNotZero'). Czy istnieje rozwiązanie, które jest równie proste, jak inne części (część 1-5) przykładu stosu? Myślę, że funkcja 'run' nie byłaby już pełnią funkcji; więc coś takiego jak Partiality Monad przedstawione na ICFP12 przez Nilsa Danielssona jest potrzebne? Czy istnieje bardziej eleganckie rozwiązanie? – mrsteve
@pigworker Wybacz mi, ale z typem, który tu podajesz, wciąż wydaje mi się, że mogę napisać funkcję _incorrect_ 'run', o której wspomniałeś w rozmowie, jako powód, dla którego podążałeś tak długo. Typ nie wyraża faktu, że 'vs' /' vs'' jest wartością runtime stosów wejścia/wyjścia. Czy silniejsza specyfikacja będzie czymś w stylu 'run: forall {ts ts 'vs vs'} -> List Inst (ts & vs) (ts 'i v') -> Sg _ (_ == _ vs) -> Sg _ (_ == _ vs ') '? (... chociaż wydaje się dziwne, że wyraźnie przechodzimy wokół wartości, które są w przybliżeniu równe wartościom już wywiedzionym przez kontroler typu, czy jest lepszy sposób?) –