Created
July 20, 2025 17:40
-
-
Save VictorTaelin/274d7d4ac0078b5cb31d717e72c93bca to your computer and use it in GitHub Desktop.
AGI prompt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Bend prelude | |
# ------------ | |
type Maybe<A: Set>: | |
case @None: | |
case @Some: | |
value: A | |
type Result<F: Set, D: Set>: | |
case @Done: | |
d: D | |
case @Fail: | |
f: F | |
def String() -> Set: | |
Char[] | |
def Not(A: Set) -> Set: | |
A -> Empty | |
def Bool/or(a: Bool, b: Bool) -> Bool: | |
match a: | |
case True: | |
True | |
case False: | |
b | |
def Nat/add(a: Nat, b: Nat) -> Nat: | |
match a: | |
case 0n: | |
b | |
case 1n + p: | |
1n + Nat/add(p, b) | |
# Natural number equality function | |
def Nat/eql(a: Nat, b: Nat) -> Bool: | |
match a b: | |
case 0n 0n: | |
return True | |
case 1n+a 0n: | |
return False | |
case 0n 1n+b: | |
return False | |
case 1n+a 1n+b: | |
return Nat/eql(a, b) | |
def Nat/show(a: Nat) -> String: | |
match a: | |
case 0n: | |
"0" | |
case 1n + p: | |
'↑' <> Nat/show(p) | |
# Returns the element at index i | |
def List/get<A>(xs: A[], i: Nat) -> Maybe<A>: | |
match xs i: | |
case [] 0n: | |
return @None | |
case (x <> xs) 0n: | |
return @Some{x} | |
case [] 1n+i: | |
return @None | |
case (x <> xs) 1n+i: | |
return List/get<A>(xs, i) | |
def List/append<A>(xs: A[], ys: A[]) -> A[]: | |
match xs: | |
case []: | |
ys | |
case x <> xs: | |
x <> List/append<A>(xs, ys) | |
def List/flat<A>(xss: A[][]) -> A[]: | |
match xss: | |
case []: | |
[] | |
case xs <> xss: | |
List/append<A>(xs, List/flat<A>(xss)) | |
def String/equal(a: String, b: String) -> Bool: | |
match a: | |
with b | |
case []: | |
match b: | |
case []: | |
True | |
case y<>ys: | |
False | |
case x<>xs: | |
match b: | |
case []: | |
False | |
case y<>ys: | |
(x === y) and String/equal(xs, ys) | |
def String/flat(xs: String[]) -> String: | |
List/flat<Char>(xs) | |
# Type | |
# ---- | |
type Term: | |
# Variables | |
case @Var: # x | |
i: Nat | |
case @Nam: # x | |
s: String | |
case @Sub: # x | |
t: Term | |
# Enumeration | |
case @Low: # l - h | |
l: Term | |
h: Term | |
# References | |
case @Ref: # @Name : Term = value | |
k: String | |
f: Term | |
t: Term | |
# Definitions | |
case @Let: # let x : T = v; f | |
T: Term | |
v: Term | |
f: Term -> Term | |
# Fixed Point | |
case @Fix: # μx. f | |
f: Term -> Term | |
# Universe | |
case @Set: # * | |
# Function | |
case @All: # ∀A.B | |
a: Term | |
b: Term | |
case @Lam: # λx.f | |
f: Term -> Term | |
case @App: # (f x) | |
f: Term | |
x: Term | |
# Empty | |
case @Emp: # ⊥ | |
case @EmpM: # λ{} | |
# Unit | |
case @Uni: # ⊤ | |
case @One: # () | |
case @UniM: # λ{ (): f } | |
f: Term | |
# Bit | |
case @Bit: # 𝔹 | |
case @Bt0: # #0 | |
case @Bt1: # #1 | |
case @BitM: # λ{ #0: f ; #1: t } | |
f: Term | |
t: Term | |
# Nat | |
case @Nat: # ℕ | |
case @Zer: # 0 | |
case @Suc: # ↑n | |
n: Term | |
case @NatM: # λ{ 0: z ; ↑: s } | |
z: Term | |
s: Term | |
# List | |
case @Lst: # T[] | |
t: Term | |
case @Nil: # [] | |
case @Con: # h<>t | |
h: Term | |
t: Term | |
case @LstM: # λ{ []: n ; <>: c } | |
n: Term | |
c: Term | |
# Pair | |
case @Sig: # ΣA.B | |
a: Term | |
b: Term | |
case @Tup: # (a,b) | |
a: Term | |
b: Term | |
case @SigM: # λ{ (,): f } | |
f: Term | |
# Equality | |
case @Eql: # T{a == b} | |
t: Term | |
a: Term | |
b: Term | |
case @Rwt: # ~e : P ; f | |
e: Term | |
P: Term | |
f: Term | |
# Errors | |
# ------ | |
type Error: | |
case @CantInfer: | |
ctx : Term[] | |
case @Mismatch: | |
ctx : Term[] | |
typ : Term | |
gol : Term | |
# Arguments | |
# --------- | |
def Arg(n: Nat) -> Set: | |
match n: | |
case 0n: | |
Term | |
case 1n + p: | |
Term -> Arg(p) | |
type LHS: | |
case @LHS: | |
skp: Nat | |
arg: Arg<1n+skp> | |
ars: Term[] | |
# Stringification | |
# --------------- | |
def name(n: Nat) -> String: | |
... | |
def show(d: Nat, term: Term) -> String: | |
match term: | |
case @Let{T, v, f}: | |
return String/flat(["let ",name(d)," : ",show(d,T)," = ",show(d,v),"; ",show(1n+d,f(@Var{d}))]) | |
case @Var{i}: | |
return name(i) | |
case @Nam{k}: | |
return k | |
case @Sub{t}: | |
return show(d,t) | |
case @Low{l, h}: | |
return String/flat([show(d,l),"-",show(d,h)]) | |
case @Ref{k, f, t}: | |
return String/flat([k]) | |
case @Fix{f}: | |
#return name(d) | |
return String/flat(["μ",name(d),".",show(1n+d,f(@Var{d}))]) | |
case @Set: | |
return "*" | |
case @All{a, b}: | |
return String/flat(["∀",show(d,a),".",show(d,b)]) | |
case @Lam{f}: | |
return String/flat(["λ",name(d),".",show(1n+d,f(@Var{d}))]) | |
case @App{f, x}: | |
return String/flat(["(",show(d,f)," ",show(d,x),")"]) | |
case @Emp: | |
return "⊥" | |
case @EmpM: | |
return "λ{}" | |
case @Uni: | |
return "⊤" | |
case @One: | |
return "()" | |
case @UniM{f}: | |
return String/flat(["λ{():",show(d,f),"}"]) | |
case @Bit: | |
return "𝔹" | |
case @Bt0: | |
return "#0" | |
case @Bt1: | |
return "#1" | |
case @BitM{f, t}: | |
return String/flat(["λ{#0:",show(d,f),";#1:",show(d,t),"}"]) | |
case @Nat: | |
return "ℕ" | |
case @Zer: | |
return "0" | |
case @Suc{n}: | |
return String/flat(["↑",show(d,n)]) | |
case @NatM{z, s}: | |
return String/flat(["λ{0:",show(d,z),";↑:",show(d,s),"}"]) | |
case @Lst{t}: | |
return String/flat([show(d,t),"[]"]) | |
case @Nil: | |
return "[]" | |
case @Con{h, t}: | |
return String/flat([show(d,h),"<>",show(d,t)]) | |
case @LstM{n, c}: | |
return String/flat(["λ{[]:",show(d,n),";<>:",show(d,c),"}"]) | |
case @Sig{a, b}: | |
return String/flat(["Σ",show(d,a),".",show(d,b)]) | |
case @Tup{a, b}: | |
return String/flat(["(",show(d,a),",",show(d,b),")"]) | |
case @SigM{f}: | |
return String/flat(["λ{(,):",show(d,f),"}"]) | |
case @Eql{t, a, b}: | |
return String/flat([show(d,t),"{",show(d,a),"==",show(d,b),"}"]) | |
case @Rwt{e, P, f}: | |
return String/flat(["~",show(d,e),":",show(d,P),";",show(d,f)]) | |
def show_error(error: Error) -> String: | |
match error: | |
case @CantInfer{ctx}: | |
String/flat(["CantInfer"]) | |
case @Mismatch{ctx, typ, gol}: | |
String/flat(["TypeMismatch\n- goal: ", show(0n, normal(gol)), "\n- type: ", show(0n, normal(typ))]) | |
def show_all(fns: Term[]) -> String: | |
match fns: | |
case []: | |
"" | |
case fn <> fns: | |
# FIXME: bring back the formatting (lost on whnf_ref refactor) | |
String/flat([show(0n, deref(fn)), " ", show_all(fns)]) | |
# Evaluator | |
# --------- | |
def whnf(term: Term) -> Term: | |
#log String/flat(["WHNF:", show(0n,term)]) | |
match term: | |
case @Ref{k, f, t}: | |
#whnf_ref(0n, k, f, λk.k, f) | |
whnf_ref(k, f, @KL{0n, λk.k}, f) | |
case @Let{T, v, f}: | |
whnf_let(T, v, f) | |
case @Fix{f}: | |
whnf_fix(f) | |
case @App{f, x}: | |
whnf_app(f, x) | |
case @Eql{t, a, b}: | |
whnf_eql(t, a, b) | |
case @Rwt{e, P, f}: | |
whnf_rwt(e, P, f) | |
case x: | |
x | |
def whnf_let(T: Term, v: Term, f: Term -> Term) -> Term: | |
whnf(f(v)) | |
def whnf_fix(f: Term -> Term) -> Term: | |
whnf(f(whnf(@Fix{f}))) | |
def whnf_app(f: Term, x: Term) -> Term: | |
match whnf(f): | |
with x | |
case @Lam{f}: | |
whnf(f(whnf(x))) | |
case @UniM{f}: | |
whnf_uni(x, f) | |
case @BitM{f, t}: | |
whnf_bit(x, f, t) | |
case @NatM{z, s}: | |
whnf_nat(x, z, s) | |
case @LstM{n, c}: | |
whnf_lst(x, n, c) | |
case @SigM{f}: | |
whnf_sig(x, f) | |
case f: | |
@App{f, x} | |
def whnf_uni(x: Term, f: Term) -> Term: | |
match whnf(x): | |
with f | |
case @One: | |
whnf(f) | |
case x: | |
@App{@UniM{f}, x} | |
def whnf_bit(x: Term, f: Term, t: Term) -> Term: | |
match whnf(x): | |
with f | |
with t | |
case @Bt0: | |
whnf(f) | |
case @Bt1: | |
whnf(t) | |
case x: | |
@App{@BitM{f, t}, x} | |
def whnf_nat(x: Term, z: Term, s: Term) -> Term: | |
match whnf(x): | |
with z | |
with s | |
case @Zer: | |
whnf(z) | |
case @Suc{n}: | |
whnf(@App{s, whnf(n)}) | |
case x: | |
@App{@NatM{z, s}, x} | |
def whnf_lst(x: Term, n: Term, c: Term) -> Term: | |
match whnf(x): | |
with n | |
with c | |
case @Nil: | |
whnf(n) | |
case @Con{h, t}: | |
whnf(@App{@App{c, whnf(h)}, whnf(t)}) | |
case x: | |
@App{@LstM{n, c}, x} | |
def whnf_sig(x: Term, f: Term) -> Term: | |
match whnf(x): | |
with f | |
case @Tup{a, b}: | |
whnf(@App{@App{f, whnf(a)}, whnf(b)}) | |
case x: | |
@App{@SigM{f}, x} | |
def whnf_eql(T: Term, a: Term, b: Term) -> Term: | |
match whnf(T): | |
with a | |
with b | |
case @Uni: | |
match a b: | |
case @One @One: | |
@Uni | |
case a b: | |
@Eql{@Bit, a, b} | |
case @Bit: | |
match whnf(a) whnf(b): | |
case @Bt0 @Bt0: | |
@Uni | |
case @Bt1 @Bt1: | |
@Uni | |
case @Bt0 @Bt1: | |
@Emp | |
case @Bt1 @Bt0: | |
@Emp | |
case a b: | |
@Eql{@Bit, a, b} | |
case @Nat: | |
match whnf(a) whnf(b): | |
case @Zer @Zer: | |
@Uni | |
case @Zer @Suc{b}: | |
@Emp | |
case @Suc{a} @Zer: | |
@Emp | |
case @Suc{a} @Suc{b}: | |
whnf(@Eql{@Nat, a, b}) | |
case a b: | |
@Eql{@Nat, a, b} | |
case @Lst{T}: | |
match whnf(a) whnf(b): | |
case @Nil @Nil: | |
@Uni | |
case @Nil @Con{bh,bt}: | |
@Emp | |
case @Con{ah,at} @Nil: | |
@Emp | |
case @Con{ah,at} @Con{bh,bt}: | |
whnf(@Sig{@Eql{T, ah, bh}, @Lam{λ_. @Eql{@Lst{T}, at, bt}}}) | |
case a b: | |
@Eql{@Lst{T}, a, b} | |
case @Sig{X,Y}: | |
match whnf(a) whnf(b): | |
case @Tup{ax,ay} @Tup{bx,by}: | |
whnf(@Sig{@Eql{X, ax, bx}, @Lam{λ_. @Eql{@App{Y, ax}, ay, by}}}) | |
case a b: | |
@Eql{@Sig{X,Y}, a, b} | |
case @All{X,Y}: | |
@All{X, @Lam{λx. @Eql{@App{Y,x}, @App{a,x}, @App{b,x}}}} | |
case T: | |
@Eql{T, a, b} | |
def whnf_rwt(e: Term, P: Term, f: Term) -> Term: | |
match whnf(e): | |
with P | |
with f | |
case @Uni: | |
whnf(f) | |
case @Emp: | |
* | |
case e: | |
@Rwt{e, P, f} | |
## Guarded Deref: | |
## Converts the Ref's body into a "guarded matcher" that eliminates received args | |
## until it either succeeds, or gets stuck against a var. This emulates Agda-like | |
## clauses, giving us recursive recursive Refs that don't unroll infinitely. | |
## FIXME: review. Only the Nat case was implemented, the rest are AI-generated. | |
#def whnf_ref(A: Nat, K: String, F: Term, xs: Term -> Arg<A>, body: Term) -> Term: | |
#match A: | |
#with K | |
#with F | |
#with xs | |
#with body | |
#case 0n: | |
#match body: | |
#with K | |
#with F | |
#with xs | |
#case @EmpM: | |
#@Lam{λx. @App{(xs @Nam{K}),x}} | |
#case @UniM{f}: | |
#@Lam{λx. | |
#match x: | |
#case @One: | |
#whnf_ref(0n, K, F, λk.@App{(xs k),@One}, f) | |
#case x: | |
#@App{(xs @Nam{K}),x}} | |
#case @BitM{f,t}: | |
#@Lam{λx. | |
#match x: | |
#case @Bt0: | |
#whnf_ref(0n, K, F, λk.@App{(xs k),@Bt0}, f) | |
#case @Bt1: | |
#whnf_ref(0n, K, F, λk.@App{(xs k),@Bt1}, t) | |
#case x: | |
#@App{(xs @Nam{K}),x}} | |
#case @NatM{z,s}: | |
#@Lam{λx. | |
#match x: | |
#case @Zer: | |
#whnf_ref(0n, K, F, λk.@App{(xs k),@Zer}, z) | |
#case @Suc{xp}: | |
#@App{whnf_ref(1n, K, F, λxp.λk.@App{(xs k),@Suc{xp}}, s), xp} | |
#case x: | |
#@App{(xs @Nam{K}),x}} | |
#case @LstM{n,c}: | |
#@Lam{λx. | |
#match x: | |
#with xs | |
#with F | |
#case @Nil: | |
#whnf_ref(0n, K, F, λk.@App{(xs k),@Nil}, n) | |
#case @Con{h,t}: | |
#@App{@App{whnf_ref(2n, K, F, λh.λt.λk.@App{(xs k),@Con{h,t}}, c), h}, t} | |
#case x: | |
#@App{(xs @Nam{K}),x}} | |
#case @SigM{f}: | |
#@Lam{λx. | |
#match x: | |
#case @Tup{a,b}: | |
#@App{@App{whnf_ref(2n, K, F, λa.λb.λk.@App{(xs k),@Tup{a,b}}, f), a}, b} | |
#case x: | |
#@App{(xs @Nam{K}),x}} | |
#case @Lam{f}: | |
#@Lam{λx. whnf_ref(0n, K, F, λk.@App{(xs k),x}, f(@Emp))} | |
#case body: | |
#xs(F) | |
#case 1n+A: | |
#match body: | |
#with K | |
#with F | |
#with xs | |
#case @EmpM: | |
#@Lam{λx. @App{whnf_ref(A, K, F, xs(x), @EmpM), x}} | |
#case @UniM{f}: | |
#@Lam{λx. | |
#match x: | |
#case @One: | |
#whnf_ref(A, K, F, xs(@One), f) | |
#case x: | |
#whnf_ref(A, K, F, xs(x), @UniM{f})} | |
#case @BitM{f,t}: | |
#@Lam{λx. | |
#match x: | |
#case @Bt0: | |
#whnf_ref(A, K, F, xs(@Bt0), f) | |
#case @Bt1: | |
#whnf_ref(A, K, F, xs(@Bt1), t) | |
#case x: | |
#whnf_ref(A, K, F, xs(x), @BitM{f,t})} | |
#case @NatM{z,s}: | |
#@Lam{λx. | |
#match x: | |
#case @Zer: | |
#whnf_ref(A, K, F, xs(@Zer), z) | |
#case @Suc{xp}: | |
#@App{whnf_ref(1n+A, K, F, λk.(xs @Suc{k}), s), xp} | |
#case x: | |
#whnf_ref(A, K, F, xs(x), @NatM{z,s})} | |
#case @LstM{n,c}: | |
#@Lam{λx. | |
#match x: | |
#case @Nil: | |
#whnf_ref(A, K, F, xs(@Nil), n) | |
#case @Con{h,t}: | |
#@App{@App{whnf_ref(2n+A, K, F, λh.λt.(xs @Con{h,t}), c), h}, t} | |
#case x: | |
#whnf_ref(A, K, F, xs(x), @LstM{n,c})} | |
#case @SigM{f}: | |
#@Lam{λx. | |
#match x: | |
#case @Tup{a,b}: | |
#@App{@App{whnf_ref(2n+A, K, F, λa.λb.(xs @Tup{a,b}), f), a}, b} | |
#case x: | |
#whnf_ref(A, K, F, xs(x), @SigM{f})} | |
#case @Lam{f}: | |
#@Lam{λx. whnf_ref(A, K, F, xs(x), f(@Emp))} | |
#case body: | |
#@Lam{λx. whnf_ref(A, K, F, xs(x), body)} | |
# TODO: refactor the function above to use a modular KL structure | |
type KL: | |
case @KL: | |
K: Nat | |
L: Term -> Arg<K> | |
def kl_ctr_new(L: Term -> Term, N: Nat, ctr: Arg<N>, k: Term) -> Arg<N>: | |
match N: | |
case 0n: | |
log String/flat(["A0 - ctr is ", show(0n, ctr), " ; L(k) is ", show(0n, L(k))]) | |
@App{L(k), ctr} | |
case 1n+Np: | |
log "A1" | |
λx. kl_ctr_new(L, Np, ctr(x), k) | |
def kl_ctr_ext(K: Nat, L: Term -> Arg<1n+K>, N: Nat, ctr: Arg<N>) -> Arg<1n+Nat/add(N,K)>: | |
match N: | |
case 0n: | |
log "B0" | |
L(ctr) | |
case 1n+Np: | |
log "B1" | |
λx. kl_ctr_ext(K, L, Np, ctr(x)) | |
def kl_ctr(kl: KL, N: Nat, ctr: Arg<N>) -> KL: | |
@KL{K,L} = kl | |
log String/flat(["kl_ctr N=", Nat/show(N), " K=", Nat/show(K)]) | |
match K: | |
case 0n: | |
log "X" | |
@KL{N, kl_ctr_new(L, N, ctr)} | |
case 1n+K: | |
log "Y" | |
@KL{Nat/add(N,K), kl_ctr_ext(K, L, N, ctr)} | |
### Guarded Deref: | |
### Converts the Ref's body into a "guarded matcher" that eliminates received args | |
### until it either succeeds, or gets stuck against a var. This emulates Agda-like | |
### clauses, giving us recursive recursive Refs that don't unroll infinitely. | |
#def whnf_ref(k: String, F: Term, kl: KL, body: Term) -> Term: | |
#match body: | |
#... | |
#case @NatM{z,s}: | |
#@Lam{λx. | |
#match x: | |
#case @Zer: | |
#log "A" | |
#whnf_ref(k, F, kl_ctr(kl, 0n, @Zer), z) | |
#case @Suc{xp}: | |
#log "B" | |
#@App{whnf_ref(k, F, kl_ctr(kl, 1n, λp.@Suc{p}), s), xp} | |
#case x: | |
#log "C" | |
#whnf_ref_undo(k, F, kl, @NatM{z,s}, x)} | |
#... | |
# NOTE: the kl functions have been added. above we provide a draft of the | |
# updated whnf_ref. it is greatly simplified with this new format! sadly, | |
# our draft is incomplete. your goal is to complete it. | |
# GOAL: COMPLETE THE WHNF_REF DRAFT WITH *ALL* THE MISSING CASES. | |
# PRESERVE THE SAME OBSERVATIONAL BEHAVIOR AS THE ORIGINAL WHNF_REF. | |
# WRITE THE COMPLETE WHNF_REF FN BELOW: | |
# think carefully about the last cases. reason thoroughly to get them right. | |
# Guarded Deref: | |
# Converts the Ref's body into a "guarded matcher" that eliminates received args | |
# until it either succeeds, or gets stuck against a var. This emulates Agda-like | |
# clauses, giving us recursive recursive Refs that don't unroll infinitely. | |
def whnf_ref(k: String, F: Term, kl: KL, body: Term) -> Term: | |
log String/flat(["whnf_ref ", show(0n,F), " - ", show(0n,body)]) | |
match body: | |
case @EmpM: | |
@KL{K,L} = kl | |
match K: | |
case 0n: | |
L(@Nam{k}) | |
case 1n+K: | |
@Lam{λx. whnf_ref(k, F, @KL{K, L(x)}, @EmpM)} | |
case @UniM{f}: | |
@Lam{λx. | |
match x: | |
case @One: | |
whnf_ref(k, F, kl_ctr(kl, 0n, @One), f) | |
case x: | |
whnf_ref_undo(k, F, kl, @UniM{f}, x)} | |
case @BitM{f,t}: | |
@Lam{λx. | |
match x: | |
case @Bt0: | |
whnf_ref(k, F, kl_ctr(kl, 0n, @Bt0), f) | |
case @Bt1: | |
whnf_ref(k, F, kl_ctr(kl, 0n, @Bt1), t) | |
case x: | |
whnf_ref_undo(k, F, kl, @BitM{f,t}, x)} | |
case @NatM{z,s}: | |
@Lam{λx. | |
log String/flat(["... x is ", show(0n,x)]) | |
match x: | |
case @Zer: | |
log "... zer" | |
whnf_ref(k, F, kl_ctr(kl, 0n, @Zer), z) | |
case @Suc{xp}: | |
log String/flat(["... suc ... xp is ", show(0n,xp)]) | |
@App{whnf_ref(k, F, kl_ctr(kl, 1n, λp.@Suc{p}), s), xp} | |
case x: | |
whnf_ref_undo(k, F, kl, @NatM{z,s}, x)} | |
case @LstM{n,c}: | |
@Lam{λx. | |
match x: | |
case @Nil: | |
whnf_ref(k, F, kl_ctr(kl, 0n, @Nil), n) | |
case @Con{h,t}: | |
@App{@App{whnf_ref(k, F, kl_ctr(kl, 2n, λh.λt.@Con{h,t}), c), h}, t} | |
case x: | |
whnf_ref_undo(k, F, kl, @LstM{n,c}, x)} | |
case @SigM{f}: | |
@Lam{λx. | |
match x: | |
case @Tup{a,b}: | |
@App{@App{whnf_ref(k, F, kl_ctr(kl, 2n, λa.λb.@Tup{a,b}), f), a}, b} | |
case x: | |
whnf_ref_undo(k, F, kl, @SigM{f}, x)} | |
case @Lam{f}: | |
@Lam{λx. whnf_ref(k, F, kl_ctr(kl, 0n, x), f(@Emp))} | |
case body: | |
@KL{K,L} = kl | |
match K: | |
case 0n: | |
L(F) | |
case 1n+K: | |
@Lam{λx. whnf_ref(k, F, @KL{K, L(x)}, body)} | |
# When an Ref call gets stuck (in a var), keep its original form. | |
def whnf_ref_undo(k: String, f: Term, kl: KL, body: Term, x: Term) -> Term: | |
@KL{K,L} = kl | |
match K: | |
case 0n: | |
@App{L(@Nam{k}), x} | |
case 1n+K: | |
whnf_ref(k, f, @KL{K, L(x)}, body) | |
# Normalizer | |
# ---------- | |
def normal(term: Term) -> Term: | |
match whnf(term): | |
case @Var{i}: | |
@Var{i} | |
case @Nam{k}: | |
@Nam{k} | |
case @Sub{t}: | |
t | |
case @Low{l,h}: | |
@Low{normal(l),normal(h)} | |
case @Ref{k,f,t}: | |
@Ref{k,normal(f),normal(t)} | |
case @Let{T,v,f}: | |
@Let{normal(T),normal(v),λx.normal(f(@Sub{x}))} | |
case @Fix{f}: | |
#@Fix{f} | |
@Fix{λx.normal(f(@Sub{x}))} | |
case @Set: | |
@Set | |
case @All{a,b}: | |
@All{normal(a),normal(b)} | |
case @Lam{f}: | |
#@Lam{f} | |
@Lam{λx.normal(f(@Sub{x}))} | |
case @App{f,x}: | |
@App{normal_fun(f), normal(x)} | |
case @Emp: | |
@Emp | |
case @EmpM: | |
@EmpM | |
case @Uni: | |
@Uni | |
case @One: | |
@One | |
case @UniM{f}: | |
@UniM{normal(f)} | |
case @Bit: | |
@Bit | |
case @Bt0: | |
@Bt0 | |
case @Bt1: | |
@Bt1 | |
case @BitM{f,t}: | |
@BitM{normal(f),normal(t)} | |
case @Nat: | |
@Nat | |
case @Zer: | |
@Zer | |
case @Suc{n}: | |
@Suc{normal(n)} | |
case @NatM{z,s}: | |
@NatM{normal(z),normal(s)} | |
case @Lst{t}: | |
@Lst{normal(t)} | |
case @Nil: | |
@Nil | |
case @Con{h,t}: | |
@Con{normal(h),normal(t)} | |
case @LstM{n,c}: | |
@LstM{normal(n),normal(c)} | |
case @Sig{a,b}: | |
@Sig{normal(a),normal(b)} | |
case @Tup{a,b}: | |
@Tup{normal(a),normal(b)} | |
case @SigM{f}: | |
@SigM{normal(f)} | |
case @Eql{t,a,b}: | |
@Eql{normal(t),normal(a),normal(b)} | |
case @Rwt{e,P,f}: | |
@Rwt{normal(e),normal(P),normal(f)} | |
def normal_fun(f: Term) -> Term: | |
match f: | |
case @App{f,x}: | |
@App{normal_fun(f), normal(x)} | |
case f: | |
f | |
# To (Low/High) | |
# ------------- | |
... | |
# Equal | |
# ----- | |
... | |
# API | |
# --- | |
... | |
def DEF(name: String, ty: Term, tm: Term -> Term) -> Term: | |
@Fix{λF. @Ref{name, tm(F), ty}} | |
def GEN(name: String, ty: Term, ctx: Ctx) -> Term: | |
synth(name, ty, ctx) | |
... | |
# Tests | |
# ------ | |
def mul2 : Term = | |
@Ref{"mul2", | |
@NatM{@Zer,@Lam{λap.@Suc{@Suc{@App{mul2,ap}}}}}, | |
@All{@Nat,@Lam{λx.@Nat}}} | |
def main : String = | |
show(0n, normal(@App{mul2,@Suc{@Zer}})) | |
######################################### | |
PROBLEM: when running the file above, I get: | |
```sh | |
whnf_ref λ{0:0;↑:λa.↑↑(mul2 a)} - λ{0:0;↑:λa.↑↑(mul2 a)} | |
... x is ↑0 | |
... suc ... xp is 0 | |
whnf_ref λ{0:0;↑:λa.↑↑(mul2 a)} - λa.↑↑(mul2 a) | |
whnf_ref λ{0:0;↑:λa.↑↑(mul2 a)} - ↑↑(mul2 ⊥) | |
kl_ctr N=↑0 K=0 | |
X | |
kl_ctr N=0 K=↑0 | |
Y | |
B0 | |
A1 | |
A0 - ctr is ↑λ{0:0;↑:λa.↑↑(mul2 a)} ; L(k) is 0 | |
whnf_ref λ{0:0;↑:λa.↑↑(mul2 a)} - λ{0:0;↑:λa.↑↑(mul2 a)} | |
... x is a | |
"(0 ↑λ{0:0;↑:λa.↑↑(mul2 a)})" | |
``` | |
which is wrong. the final output is `(0 ↑λ{0:0;↑:λa.↑↑(mul2 a)})` rather than | |
`↑↑0`. previously, with the old whnf_ref, this example worked fine. this | |
suggests there is some error on the new, simplified whnf_ref function, which | |
causes it to malfunction. | |
your goal is to study this file and then answer what is the *specific error* | |
that causes this test to output the expression above, rather than ↑↑0. point | |
the exact part of the code that is incorrect, and propose a simple fix that | |
will solve this issue, and make it output ↑↑0, as desired. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment