Skip to content

Instantly share code, notes, and snippets.

@scott-fleischman
Last active February 23, 2018 00:11
Show Gist options
  • Save scott-fleischman/b5bd1c13fb682b85e97ebf69e1861f2b to your computer and use it in GitHub Desktop.
Save scott-fleischman/b5bd1c13fb682b85e97ebf69e1861f2b to your computer and use it in GitHub Desktop.
OPLSS 2014 - My reworkings of Ulf Norell's Introduction to Agda
module _ where
data 𝔹 : Set where
true false : 𝔹
if_then_else_ : {A : Set} (b : 𝔹) (t f : A) β†’ A
if true then t else f = t
if false then t else f = f
data β„• : Set where
zero : β„•
suc : β„• β†’ β„•
{-# BUILTIN NATURAL β„• #-}
_+_ : (m n : β„•) β†’ β„•
zero + n = n
suc m + n = suc (m + n)
data List (A : Set) : Set where
[] : List A
_∷_ : (x : A) (xs : List A) β†’ List A
infixr 5 _∷_
infixl 3 _∈_
data _∈_ {A : Set} (x : A) : List A β†’ Set where
zero : {xs : List A} β†’ x ∈ x ∷ xs
suc : {y : A} {xs : List A} (p : x ∈ xs) β†’ x ∈ y ∷ xs
lookup : {A : Set} {x : A} {xs : List A} (i : x ∈ xs) β†’ A
lookup {x = x} zero = x
lookup (suc i) = lookup i
data All {A : Set} (P : A β†’ Set) : List A β†’ Set where
[] : All P []
_∷_ : {xs : List A} {x : A} (px : P x) (pxs : All P xs) β†’ All P (x ∷ xs)
lookup-all : {A : Set} {x : A} {xs : List A} {P : A β†’ Set} (i : x ∈ xs) (a : All P xs) β†’ P x
lookup-all zero (px ∷ pxs) = px
lookup-all (suc i) (px ∷ pxs) = lookup-all i pxs
data Type : Set where
nat bool : Type
data Expr (Ξ“ : List Type) : Type β†’ Set where
var : {x : Type} (i : x ∈ Ξ“) β†’ Expr Ξ“ x
value : (n : β„•) β†’ Expr Ξ“ nat
true false : Expr Ξ“ bool
add : (m n : Expr Ξ“ nat) β†’ Expr Ξ“ nat
if : {r : Type} (b : Expr Ξ“ bool) (t f : Expr Ξ“ r) β†’ Expr Ξ“ r
Value : Type β†’ Set
Value nat = β„•
Value bool = 𝔹
eval : {t : Type} {Ξ“ : List Type} (env : All Value Ξ“) (expr : Expr Ξ“ t) β†’ Value t
eval env (var i) = lookup-all i env
eval env (value n) = n
eval env true = true
eval env false = false
eval env (add m n) = eval env m + eval env n
eval env (if b t f) = if (eval env b) then (eval env t) else (eval env f)
module Test where
open import Agda.Builtin.Equality
Ξ“ : List Type
Ξ“ = bool ∷ bool ∷ nat ∷ []
env : All Value Ξ“
env = true ∷ false ∷ 21 ∷ []
p1 : eval env (add (value 10) (if (var zero) (var (suc (suc zero))) (value 6))) ≑ 31
p1 = refl
module _ where
data βŠ₯ : Set where
βŠ₯-elim : {A : Set} β†’ βŠ₯ β†’ A
βŠ₯-elim ()
open import Agda.Builtin.Bool
open import Agda.Builtin.Equality
open import Agda.Builtin.Nat hiding (_+_) renaming (Nat to β„•)
open import Agda.Builtin.String
cong : {A B : Set} (f : A β†’ B) {x y : A} (eq : x ≑ y) β†’ f x ≑ f y
cong f refl = refl
sym : {A : Set} {x y : A} (eq : x ≑ y) β†’ y ≑ x
sym refl = refl
data List (A : Set) : Set where
[] : List A
_∷_ : (x : A) (xs : List A) β†’ List A
infixr 5 _∷_
record _Γ—_ (A B : Set) : Set where
constructor _,_
field
fst : A
snd : B
record Ξ£ (A : Set) (B : A β†’ Set) : Set where
constructor _,_
field
fst : A
snd : B fst
data _+_ (A B : Set) : Set where
inl : A β†’ A + B
inr : B β†’ A + B
over-inr : {A B1 B2 : Set} (f : B1 β†’ B2) (e : A + B1) β†’ A + B2
over-inr f (inl x) = inl x
over-inr f (inr x) = inr (f x)
data Dec {A : Set} (x y : A) : Set where
eq : x ≑ y β†’ Dec x y
neq : (x ≑ y β†’ βŠ₯) β†’ Dec x y
_>>=_ : {A B C : Set} β†’ A + B β†’ (B β†’ A + C) β†’ A + C
inl x >>= f = inl x
inr x >>= f = f x
dec-string : (x y : String) β†’ Dec x y
dec-string x y with primStringEquality x y
dec-string x y | false = neq (βŠ₯-elim trustme) where postulate trustme : βŠ₯
dec-string x y | true = eq primTrustMe where open import Agda.Builtin.TrustMe
data All {A : Set} (P : A β†’ Set) : List A β†’ Set where
[] : All P []
_∷_ : {x : A} {xs : List A} (px : P x) (pxs : All P xs) β†’ All P (x ∷ xs)
data Any {A : Set} (P : A β†’ Set) : List A β†’ Set where
zero : {x : A} {xs : List A} β†’ Any P (x ∷ xs)
suc : {x : A} {xs : List A} (p : Any P xs) β†’ Any P (x ∷ xs)
_∈_ : {A : Set} (x : A) (xs : List A) β†’ Set
x ∈ xs = Any (x ≑_) xs
data Type : Set where
Nat : Type
_β‡’_ : (A B : Type) β†’ Type
injlβ‡’ : {A B C D : Type} β†’ (A β‡’ B) ≑ (C β‡’ D) -> A ≑ C
injl⇒ refl = refl
injrβ‡’ : {A B C D : Type} β†’ (A β‡’ B) ≑ (C β‡’ D) -> B ≑ D
injr⇒ refl = refl
dec-type : (S T : Type) β†’ Dec S T
dec-type Nat Nat = eq refl
dec-type Nat (T β‡’ T₁) = neq (Ξ» ())
dec-type (S β‡’ S₁) Nat = neq (Ξ» ())
dec-type (S β‡’ T) (P β‡’ Q) with dec-type S P
dec-type (S β‡’ T) (P β‡’ Q) | eq p rewrite p with dec-type T Q
dec-type (S β‡’ T) (P β‡’ Q) | eq p | eq q rewrite q = eq refl
dec-type (S ⇒ T) (P ⇒ Q) | eq p | neq q = neq λ r → q (injr⇒ r)
dec-type (S ⇒ T) (P ⇒ Q) | neq p = neq λ r → p (injl⇒ r)
data TermU : Set where
var : (name : String) β†’ TermU
lit : β„• β†’ TermU
suc : (num : TermU) β†’ TermU
lam : (name : String) (T : Type) (body : TermU) β†’ TermU
app : (fun arg : TermU) β†’ TermU
data TermT (Ξ“ : List (String Γ— Type)) : Type β†’ Set where
var : (name : String) (T : Type) (valid : (name , T) ∈ Ξ“) β†’ TermT Ξ“ T
lit : β„• β†’ TermT Ξ“ Nat
suc : (num : TermT Ξ“ Nat) β†’ TermT Ξ“ Nat
lam : (name : String) (S : Type) {T : Type} (body : TermT (name , S ∷ Ξ“) T) β†’ TermT Ξ“ T
app : {S T : Type} (fun : TermT Ξ“ (S β‡’ T)) (arg : TermT Ξ“ S) β†’ TermT Ξ“ T
forgetTypes : {Ξ“ : List (String Γ— Type)} {T : Type} β†’ TermT Ξ“ T β†’ TermU
forgetTypes (var name T valid) = var name
forgetTypes (lit x) = lit x
forgetTypes (suc t) = suc (forgetTypes t)
forgetTypes (lam name S b) = lam name S (forgetTypes b)
forgetTypes (app f x) = app (forgetTypes f) (forgetTypes x)
data Checked (Ξ“ : List (String Γ— Type)) : TermU β†’ Set where
ok : {u : TermU} (T : Type) (t : TermT Ξ“ T) (same : forgetTypes t ≑ u) β†’ Checked Ξ“ u
checkSuc : βˆ€ {Ξ“ u} β†’ Checked Ξ“ u β†’ String + Checked Ξ“ (suc u)
checkSuc (ok Nat t same) = inr (ok Nat (suc t) (cong suc same))
checkSuc (ok (T β‡’ T₁) t same) = inl "Can't do suc of function"
checkLam : βˆ€ name T {Ξ“ u} β†’ Checked ((name , T) ∷ Ξ“) u β†’ String + Checked Ξ“ (lam name T u)
checkLam name S (ok T t same) = inr (ok T (lam name S t) (cong (lam name S) same))
checkAppEq : βˆ€ {S Ξ“ T} (tf : TermT Ξ“ (S β‡’ T)) (tx : TermT Ξ“ S)
(f x : TermU) β†’
forgetTypes tf ≑ f β†’
forgetTypes tx ≑ x β†’
forgetTypes (app tf tx) ≑ app f x
checkAppEq tf tx f x same-f same-x rewrite same-f | same-x = refl
checkApp : βˆ€ {Ξ“ f x} β†’ Checked Ξ“ f β†’ Checked Ξ“ x β†’ String + Checked Ξ“ (app f x)
checkApp (ok Nat tf same-f) (ok TX tx same-x) = inl "Can't apply a Nat to an argument"
checkApp (ok {f} (S β‡’ T) tf same-f) (ok {x} TX tx same-x) with dec-type S TX
checkApp (ok {f} (S β‡’ T) tf same-f) (ok {x} TX tx same-x) | eq p rewrite p = inr (ok T (app tf tx) (checkAppEq tf tx f x same-f same-x))
checkApp (ok (S β‡’ T) tf same-f) (ok TX tx same-x) | neq x = inl "Arg type does not match function type"
weakenVar : βˆ€ {n v T Ξ“} β†’ Checked Ξ“ (var n) β†’ Checked ((v , T) ∷ Ξ“) (var n)
weakenVar (ok T (var name .T valid) same) = ok T (var name T (suc valid)) same
weakenVar (ok .Nat (lit x) ())
weakenVar (ok .Nat (suc t) ())
weakenVar (ok T (lam name S t) ())
weakenVar (ok T (app t t₁) ())
lookupVar : βˆ€ name Ξ“ β†’ String + Checked Ξ“ (var name)
lookupVar n [] = inl (primStringAppend "Var not found: " n)
lookupVar n ((v , T) ∷ Ξ“) with dec-string n v
lookupVar n ((v , T) ∷ Ξ“) | eq p = inr (ok T (var n T zero) refl)
lookupVar n ((v , T) ∷ Ξ“) | neq p = lookupVar n Ξ“ >>= Ξ» c β†’ inr (weakenVar c)
typeCheck : (Ξ“ : List (String Γ— Type)) (u : TermU) β†’ String + Checked Ξ“ u
typeCheck Ξ“ (var name) = lookupVar name Ξ“
typeCheck Ξ“ (lit x) = inr (ok Nat (lit x) refl)
typeCheck Ξ“ (suc u) = typeCheck Ξ“ u >>= checkSuc
typeCheck Ξ“ (lam name T u) = typeCheck (name , T ∷ Ξ“) u >>= checkLam name T
typeCheck Ξ“ (app f x) =
typeCheck Ξ“ f >>= Ξ» tf β†’
typeCheck Ξ“ x >>= Ξ» tx β†’
checkApp tf tx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment