Skip to content

Instantly share code, notes, and snippets.

@AndrasKovacs
Last active June 30, 2019 21:11
Show Gist options
  • Select an option

  • Save AndrasKovacs/83e7dcbb4bd0a4dc11f3 to your computer and use it in GitHub Desktop.

Select an option

Save AndrasKovacs/83e7dcbb4bd0a4dc11f3 to your computer and use it in GitHub Desktop.
Embedding of predicative polymorphic System F in Agda.
open import Function
open import Data.Nat hiding (_βŠ”_)
open import Data.Fin renaming (_+_ to _f+_)
open import Data.Unit
open import Relation.Binary.PropositionalEquality
open import Data.Product
open import Data.Sum
open import Data.Vec
open import Data.Vec.Properties
import Level as L
--------------------------------- Helpers --------------------------------------------
fromβ„•' : βˆ€ n β†’ Fin (n + 1)
fromβ„•' zero = zero
fromβ„•' (suc n) = suc (fromβ„•' n)
_βŠ”_ : βˆ€ {n} β†’ Fin n β†’ Fin n β†’ Fin n
zero βŠ” b = b
suc a βŠ” zero = suc a
suc a βŠ” suc b = suc (a βŠ” b)
veclast :
βˆ€ {a}{A : Set a} n x (xs : Vec A n)
β†’ lookup (fromβ„•' n) (xs ++ x ∷ []) ≑ x
veclast zero x [] = refl
veclast (suc n) x (y ∷ ys) = veclast n x ys
tighten : βˆ€ {n}(i : Fin (n + 1)) β†’ (i ≑ fromβ„•' n) ⊎ (βˆƒ Ξ» (i' : Fin n) β†’ i ≑ inject+ 1 i')
tighten {zero} zero = inj₁ refl
tighten {zero} (suc ())
tighten {suc n} zero = injβ‚‚ (zero , refl)
tighten {suc n} (suc i) with tighten {n} i
tighten {suc n} (suc .(fromβ„•' n)) | inj₁ refl = inj₁ refl
tighten {suc n} (suc .(inject+ 1 proj₁)) | injβ‚‚ (proj₁ , refl) = injβ‚‚ (suc proj₁ , refl)
------------------------------------- Types -------------------------------------------
infixr 5 _β‡’_
data Type (f b : β„•) : (level : Fin 2) β†’ Set where
free : Fin f β†’ Type f b zero
bound : Fin b β†’ Type f b zero
unit : Type f b zero
_β‡’_ : βˆ€ {l1 l2} β†’ Type f b l1 β†’ Type f b l2 β†’ Type f b (l1 βŠ” l2)
βˆ€' : βˆ€ {l} β†’ Type f (suc b) l β†’ Type f b (suc zero βŠ” l)
relaxBound : βˆ€ {f b l} n β†’ Type f b l β†’ Type f (b + n) l
relaxBound n (free x) = free x
relaxBound n (bound x) = bound (inject+ n x)
relaxBound n unit = unit
relaxBound n (a β‡’ b) = relaxBound n a β‡’ relaxBound n b
relaxBound n (βˆ€' t) = βˆ€' (relaxBound n t)
raiseFree : βˆ€ {f b l} n β†’ Type f b l β†’ Type (n + f) b l
raiseFree n (free x) = free (raise n x)
raiseFree n (bound x) = bound x
raiseFree n unit = unit
raiseFree n (a β‡’ b) = raiseFree n a β‡’ raiseFree n b
raiseFree n (βˆ€' x) = βˆ€' (raiseFree n x)
inst : βˆ€ {f b l} β†’ Type f 0 zero β†’ Type f (b + 1) l β†’ Type f b l
inst t' (free x) = free x
inst {_}{b} t' (bound x) = [ const (relaxBound b t') , bound ∘ proj₁ ]β€² (tighten x)
inst t' unit = unit
inst t' (a β‡’ b) = inst t' a β‡’ inst t' b
inst t' (βˆ€' x) = βˆ€' (inst t' x)
abst : βˆ€ {f b l} β†’ Type (suc f) b l β†’ Type f (b + 1) l
abst {_}{b}(free zero) = bound (fromβ„•' b)
abst (free (suc x)) = free x
abst (bound x) = bound (inject+ 1 x)
abst unit = unit
abst (a β‡’ b) = abst a β‡’ abst b
abst (βˆ€' x) = βˆ€' (abst x)
-- ----------------------------------- Language -----------------------------------------------
data Context : β„• β†’ Set where
[] : Context 0
term : βˆ€ {f l} β†’ Type f 0 l β†’ Context f β†’ Context f
type : βˆ€ {f} β†’ Context f β†’ Context (suc f)
data Var {l : Fin 2} : βˆ€ {f} β†’ Context f β†’ Type f 0 l β†’ Set where
here : βˆ€ {f cxt t} β†’ Var {f = f}(term t cxt) t
term : βˆ€ {f cxt t l' t'} β†’ Var {l} cxt t β†’ Var {f = f} (term {l = l'} t' cxt) t
type : βˆ€ {f cxt t} β†’ Var cxt t β†’ Var {f = suc f} (type cxt) (raiseFree 1 t)
infixl 5 _$'_
data Term {f : β„•} (cxt : Context f) : βˆ€ {l} β†’ Type f 0 l β†’ Set where
unit : Term cxt unit
var : βˆ€ {l t} β†’ Var {l} cxt t β†’ Term cxt {l} t
Ξ»' : βˆ€ {l1 l2 b} a β†’ Term (term {l = l1} a cxt) {l2} b β†’ Term cxt {l1 βŠ” l2} (a β‡’ b)
_$'_ : βˆ€ {l1 l2 a b} β†’ Term cxt {l1 βŠ” l2} (a β‡’ b) β†’ Term cxt {l1} a β†’ Term cxt {l2} b
Ξ› : βˆ€ {l t} β†’ Term (type cxt) {l} t β†’ Term cxt {suc zero βŠ” l}(βˆ€' (abst t))
_$*_ : βˆ€ {l t} β†’ Term cxt (βˆ€' {l = l} t) β†’ (t' : Type f 0 zero) β†’ Term cxt (inst t' t)
-- ------------------------------------ Levels -----------------------------------------------
getLevel : βˆ€ {f b l} β†’ Type f b l β†’ L.Level
getLevel (free x) = L.zero
getLevel (bound x) = L.zero
getLevel unit = L.zero
getLevel (a β‡’ b) = getLevel a L.βŠ” getLevel b
getLevel (βˆ€' t) = L.suc L.zero L.βŠ” getLevel t
level : βˆ€ {n} β†’ Fin n β†’ L.Level
level zero = L.zero
level (suc n) = L.suc (level n)
level-βŠ” : βˆ€ {n} l1 l2 β†’ level {n} l1 L.βŠ” level l2 ≑ level (l1 βŠ” l2)
level-βŠ” zero zero = refl
level-βŠ” zero (suc r2) = refl
level-βŠ” (suc r1) zero = refl
level-βŠ” (suc r1) (suc r2) = cong L.suc (level-βŠ” r1 r2)
level-subst : βˆ€ {l l'} β†’ l ≑ l' β†’ Set l β†’ Set l'
level-subst refl x = x
level-subst-remove : βˆ€ {l l' x} p β†’ level-subst{l}{l'} p x β†’ x
level-subst-remove refl x₁ = x₁
level-subst-add : βˆ€ {l l' x} p β†’ x β†’ level-subst{l}{l'} p x
level-subst-add refl x₁ = x₁
level-cong : βˆ€ {f b l} β†’ (t : Type f b l) β†’ getLevel t ≑ level l
level-cong (free x) = refl
level-cong (bound x) = refl
level-cong unit = refl
level-cong (_β‡’_ {la}{lb} a b) rewrite level-cong a | level-cong b = level-βŠ” la lb
level-cong (βˆ€' {l} t) rewrite level-cong t = level-βŠ” (suc zero) l
-- ----------------------------------- Interpretation ------------------------------------------
interp : βˆ€ {f b l} β†’ Vec Set f β†’ Vec Set b β†’ (t : Type f b l) β†’ Set (getLevel t)
interp fs bs (free x) = lookup x fs
interp fs bs (bound x) = lookup x bs
interp fs bs unit = ⊀
interp fs bs (a β‡’ b) = interp fs bs a β†’ interp fs bs b
interp fs bs (βˆ€' t) = βˆ€ (A : Set) β†’ interp fs (A ∷ bs) t
_⟦_⟧ : βˆ€ {f} fs β†’ Type f 0 zero β†’ Set
_⟦_⟧ fs t = level-subst (level-cong t) (interp fs [] t)
iRaiseFree :
βˆ€ {f b l bs fs x} t
β†’ interp{f}{b}{l} fs bs t
β†’ interp (x ∷ fs) bs (raiseFree 1 t)
iRaiseFree' :
βˆ€ {f b l bs fs x} t
β†’ interp (x ∷ fs) bs (raiseFree 1 t)
β†’ interp{f}{b}{l} fs bs t
iRaiseFree (free x₁) y = y
iRaiseFree (bound x₁) y = y
iRaiseFree unit y = tt
iRaiseFree (a β‡’ b) f y = iRaiseFree b $ f $ iRaiseFree' a y
iRaiseFree (βˆ€' t) g A = iRaiseFree t $ g A
iRaiseFree' (free x₁) y = y
iRaiseFree' (bound x₁) y = y
iRaiseFree' unit y = tt
iRaiseFree' (a β‡’ b) f y = iRaiseFree' b $ f $ iRaiseFree a y
iRaiseFree' (βˆ€' t) g A = iRaiseFree' t $ g A
iRelaxBound :
βˆ€ {b b' bs bs' f fs l} t
β†’ interp {f}{b}{l} fs bs t
β†’ interp fs (bs ++ bs') (relaxBound b' t)
iRelaxBound' :
βˆ€ {b b' bs bs' f fs l} t
β†’ interp fs (bs ++ bs') (relaxBound b' t)
β†’ interp {f}{b}{l} fs bs t
iRelaxBound (free x) y = y
iRelaxBound {bs = bs}{bs' = bs'}(bound x) y rewrite lookup-++-inject+ bs bs' x = y
iRelaxBound unit y = y
iRelaxBound (a β‡’ b) f y = iRelaxBound b $ f $ iRelaxBound' a y
iRelaxBound (βˆ€' t) g A = iRelaxBound t $ g A
iRelaxBound' (free x) y = y
iRelaxBound' {bs = bs}{bs' = bs'}(bound x) y rewrite lookup-++-inject+ bs bs' x = y
iRelaxBound' unit y = y
iRelaxBound' (a β‡’ b) f y = iRelaxBound' b $ f $ iRelaxBound a y
iRelaxBound' (βˆ€' t) g A = iRelaxBound' t $ g A
iAbst :
βˆ€ {f b l bs fs A} t
β†’ interp{suc f}{b}{l} (A ∷ fs) bs t
β†’ interp{f}{b + 1}{l} fs (bs ++ A ∷ []) (abst t)
iAbst' :
βˆ€ {f b l bs fs A} t
β†’ interp{f}{b + 1}{l} fs (bs ++ A ∷ []) (abst t)
β†’ interp{suc f}{b}{l} (A ∷ fs) bs t
iAbst {f}{b}{bs = bs}{A = A}(free zero) y rewrite veclast b A bs = y
iAbst (free (suc x)) y = y
iAbst {bs = bs}{fs = fs}{A = A}(bound x) y rewrite lookup-++-inject+ bs (A ∷ []) x = y
iAbst unit y = y
iAbst (a β‡’ b) f y = iAbst b $ f $ iAbst' a y
iAbst (βˆ€' t) g A = iAbst t $ g A
iAbst' {f}{b}{bs = bs}{A = A}(free zero) y rewrite veclast b A bs = y
iAbst' (free (suc x)) y = y
iAbst' {bs = bs}{fs = fs}{A = A}(bound x) y rewrite lookup-++-inject+ bs (A ∷ []) x = y
iAbst' unit y = y
iAbst' (a β‡’ b) f y = iAbst' b $ f $ iAbst a y
iAbst' (βˆ€' t) g A = iAbst' t $ g A
iInst :
βˆ€ {f b l fs bs t'} t
β†’ interp fs (bs ++ (fs ⟦ t' ⟧) ∷ []) t
β†’ interp {f}{b}{l} fs bs (inst t' t)
iInst' :
βˆ€ {f b l fs bs t'} t
β†’ interp {f}{b}{l} fs bs (inst t' t)
β†’ interp fs (bs ++ (fs ⟦ t' ⟧) ∷ []) t
iInst (free x) y = y
iInst {b = b}(bound x) y with tighten{b} x
iInst {fs = fs}{bs = bs}{t' = t'}(bound ._) y | inj₁ refl
rewrite veclast _ (fs ⟦ t' ⟧) bs = iRelaxBound t' (level-subst-remove (level-cong t') y)
iInst {fs = fs}{bs = bs}{t' = t'}(bound .(inject+ 1 i)) y | injβ‚‚ (i , refl)
rewrite lookup-++-inject+ bs (fs ⟦ t' ⟧ ∷ []) i = y
iInst unit y = y
iInst {f}{b'}(a β‡’ b) g y = iInst{f}{b'} b $ g $ iInst'{f}{b'} a y
iInst {f}{b}(βˆ€' t) g A = iInst {f} {suc b} t (g A)
iInst' (free x) y = y
iInst' {b = b}(bound x) y with tighten {b} x
iInst' {fs = fs}{bs = bs}{t' = t'}(bound ._) y | inj₁ refl
rewrite veclast _ (fs ⟦ t' ⟧) bs = level-subst-add (level-cong t') $ iRelaxBound' t' y
iInst' {fs = fs}{bs = bs}{t' = t'}(bound .(inject+ 1 i)) y | injβ‚‚ (i , refl)
rewrite lookup-++-inject+ bs (fs ⟦ t' ⟧ ∷ []) i = y
iInst' unit y = y
iInst' {f}{b'}(a β‡’ b) g y = iInst'{f}{b'} b $ g $ iInst{f}{b'} a y
iInst' {f}{b}(βˆ€' t) g A = iInst' {f} {suc b} t (g A)
-- ------------------------------------- Evaluation -----------------------------------------------
data Env : βˆ€ {f} β†’ Vec Set f β†’ Context f β†’ Set₁ where
[] : Env [] []
term : βˆ€ {f l ts cxt t} β†’ interp {f}{0}{l} ts [] t β†’ Env ts cxt β†’ Env ts (term t cxt)
type : βˆ€ {f ts cxt t} β†’ Env {f} ts cxt β†’ Env (t ∷ ts) (type cxt)
lookupTerm : βˆ€ {l f fs cxt t} β†’ Var {l} {f} cxt t β†’ Env fs cxt β†’ interp fs [] t
lookupTerm here (term x env) = x
lookupTerm (term v) (term x env) = lookupTerm v env
lookupTerm (type {t = t} v) (type env) = iRaiseFree t $ lookupTerm v env
eval : βˆ€ {f l cxt fs t} β†’ Env fs cxt β†’ Term {f} cxt {l} t β†’ interp fs [] t
eval env unit = tt
eval env (var x) = lookupTerm x env
eval env (Ξ»' _ e) x = eval (term x env) e
eval env (f $' x) = eval env f (eval env x)
eval env (Ξ› {t = t} e) A = iAbst t $ eval (type env) e
eval {fs = fs} env (_$*_ {t = t} f t') = iInst {b = 0} t $ eval env f (fs ⟦ t' ⟧)
-- examples
levelof : βˆ€ {l}{t : Type 0 0 l} β†’ Term [] t β†’ Fin 2
levelof {l} _ = l
-- Ξ› a. Ξ» (x : a). x
ID : Term [] _
ID = Ξ› (Ξ»' (free zero) (var here))
-- Ξ› a b. Ξ» (x : a) (y : b). x
CONST : Term [] _
CONST = Ξ› (Ξ› (Ξ»' (free (suc zero)) (Ξ»' (free zero) (var (term here)))))
-- Ξ› a. Ξ» (x : a). Ξ› b. Ξ» (y : b). x
CONST' : Term [] _
CONST' = Ξ› (Ξ»' (free zero) (Ξ› (Ξ»' (free zero) (var (term (type here))))))
-- Ξ› a. Ξ» (id : Ξ› a. a β†’ a) (x : a). id [a] x
IDAPP : Term [] _
IDAPP = Ξ› (Ξ»' (βˆ€' (bound zero β‡’ bound zero)) (Ξ»' (free zero) (var (term here) $* free zero $' var here)))
evaltest : eval [] IDAPP β„• (eval [] ID) 10 ≑ 10
evaltest = refl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment