All'ICFP 2012, Conor McBride ha fornito una nota chiave con la tessera "Agda-curioso?".Agda: funzione di esecuzione per l'esempio di pila Conor
Ha presentato un'implementazione di una piccola impilatrice.
Il video è su YouTube: http://www.youtube.com/watch?v=XGyJ519RY6Y
Il codice è anche online: http://personal.cis.strath.ac.uk/conor.mcbride/ICFP12Code.tgz
Mi chiedo sulla funzione run
della parte 5 (vale a dire "Part5Done.agda" se è stato scaricato il codice). La conversazione si interrompe prima che venga spiegata la funzione 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' _ _ = {!!}
Qual è il tipo di firma corretta della funzione run
? Come dovrebbe essere implementata la funzione run
?
La funzione di compilazione è spiegata about 55 minutes into the talk.
Il codice completo è available from Conor's webpage.
Hai menzionato la ricomposizione delle informazioni cancellate. Immagino che la funzione 'run' faccia questo. La funzione 'run' sarebbe stata generata anche con ornamenti? Altrimenti, come si può applicare il "teorema generico"? (Mi piacerebbe essere sicuro che anche la funzione 'run' sia corretta. – mrsteve
Nel talk viene anche detto che l'esempio di stack può essere esteso con istruzioni di salto (forse una semplice istruzione 'jump' per implementare subroutine o forse anche' jumpNotZero' loop). Esiste una soluzione semplice come le altre parti (parte 1-5) dell'esempio di stack? Penso che la funzione 'run' non sarebbe più una funzione totale; quindi è necessaria una cosa come la Monade di parzialità presentata a ICFP12 da Nils Danielsson? C'è una soluzione più elegante? – mrsteve
@pigworker Perdonami, ma con il tipo che dai qui mi sembra ancora di essere in grado di scrivere la funzione _incorrect_ 'run' che hai citato nel discorso come la ragione per andare così lontano. Il tipo non esprime il fatto che 'vs' /' vs'' è il valore di runtime degli stack di input/output. Una specifica più forte sarebbe qualcosa come 'run: forall {ts ts 'vs vs'} -> List Inst (ts & vs) (ts '& vs') -> Sg _ (_ == _ vs) -> Sg _ (_ == _ vs ') '? (... anche se sembra strano passare in modo esplicito valori che corrispondono a valori già desunti dal correttore di tipi: c'è un modo migliore?) –