75TM37DMPXA7YQPWZ4672OA3CUJNHYVIE5UFM2H6FHZMPGVMQS2AC axi[$x = y in NN [x in NN, y in NN]$],uni(right_label: "(3, 6)")[$"suc"(x) = "suc"(y) in NN [x in NN, y in NN]$],
axi[$x in NN$],axi[$y in "Eq"(NN, "natrec"(x, 0, (u, v) "suc"(v)), x)$],bin(right_label: "(5)")[$"natrec"(x, 0, (u, v) "suc"(v)) = x in NN$],uni(right_label: "(3)")[$"suc"("natrec"(x, 0, (u, v) "suc"(v))) = "suc"(x) in NN$],uni(right_label: "natrec")[$"natrec"("suc"(x), 0, (u, v) "suc"(v))) = "suc"(x) in NN$],
#tree(axi[$"eq"_"xy-suc" in "Eq"(NN, "suc"(x), "suc"(y)) ["eq"_"xy" in "Eq"(NN, x, y), x in NN, y in NN]$],uni[$lambda(("eq"_"xy") "eq"_"xy-suc") in "Eq"(NN, x, y) arrow.r "Eq"(NN, "suc"(x), "suc"(y))$],)
// #tree(// axi[$"eq"_"xy-suc" in "Eq"(NN, "suc"(x), "suc"(y)) ["eq"_"xy" in "Eq"(NN, x, y), x in NN, y in NN]$],// uni[$lambda(("eq"_"xy") "eq"_"xy-suc") in "Eq"(NN, x, y) arrow.r "Eq"(NN, "suc"(x), "suc"(y))$],// )
#tree(axi[$"eq" in "Eq"(NN, "natrec"(x, 0, (u, v) "suc"(v)), x) [x in NN]$],uni[$"natrec"(x, 0, (u, v) "suc"(v)) = x in NN [x in NN]$],uni(right_label: "macro")[$plus.circle(x, 0) = x in NN [x in NN]$],)
// #tree(// axi[$"eq" in "Eq"(NN, "natrec"(x, 0, (u, v) "suc"(v)), x) [x in NN]$],// uni[$"natrec"(x, 0, (u, v) "suc"(v)) = x in NN [x in NN]$],// uni(right_label: "macro")[$plus.circle(x, 0) = x in NN [x in NN]$],// )
tree(// axi[$c in "Eq"(NN, split1, 0), x)$],axi[$split1 equiv x in NN [x in NN]$],uni(right_label: "macro")[$plus.circle(x, 0) equiv x in NN [x in NN]$],)
// tree(// // axi[$c in "Eq"(NN, split1, 0), x)$],// axi[$split1 equiv x in NN [x in NN]$],// uni(right_label: "macro")[$plus.circle(x, 0) equiv x in NN [x in NN]$],// )
tree(axi[$plus.circle(x, 0) equiv split1 [x in NN]$],axi[$split1 equiv x [x in NN]$],bin(right_label: "trans")[$plus.circle(x, 0) equiv x in NN [x in NN]$],)}
// tree(// axi[$plus.circle(x, 0) equiv split1 [x in NN]$],// axi[$split1 equiv x [x in NN]$],// bin(right_label: "trans")[$plus.circle(x, 0) equiv x in NN [x in NN]$],// )// }
module extraexercises whereopen import Data.Natopen import Relation.Binary.PropositionalEquality as Eqopen Eq.≡-Reasoning
/*** Terms e ::= x | () | λx. e | e e | (e : A)* Types A, B, C ::= 1 | α | ^α | ∀α. A | A → B* Monotypes τ, σ ::= 1 | α | ^α | τ → σ* Contexts Γ, ∆, Θ ::= · | Γ, α | Γ, x : A* | Γ, ^α | Γ, ^α = τ | Γ, I^α* Complete Contexts Ω ::= · | Ω, α | Ω, x : A* | Ω, ^α = τ | Ω, I^*/export type Term =| { kind: "var"; name: string }| { kind: "unit" }| { kind: "lambda"; name: string; body: Term }| { kind: "app"; func: Term; arg: Term }| { kind: "annot"; term: Term; type: Type };export type Type =| { kind: "unit" }| { kind: "var"; name: string }| { kind: "existential"; name: string }| { kind: "poly"; name: string; type: Type }| { kind: "arrow"; input: Type; output: Type };export type Monotype =| { kind: "unit" }| { kind: "var"; name: string }| { kind: "existential"; name: string }| { kind: "arrow"; input: Monotype; output: Monotype };export type ContextEntry =| { kind: "typeVar"; name: string }| { kind: "termAnnot"; name: string; type: Type }| { kind: "existentialVar"; name: string }| { kind: "existentialSolved"; name: string; type: Monotype }| { kind: "marker"; name: string };export type CompleteContextEntry =| { kind: "typeVar"; name: string }| { kind: "termAnnot"; name: string; type: Type }| { kind: "existentialSolved"; name: string; type: Monotype }| { kind: "marker"; name: string };
// Helper functions for dealing with contextsimport { ContextEntry, Type } from "./data";import { isEqual } from "lodash";/** Γ |- A (is the given type in this context?) */export function isTypeInContext(type: Type, ctx: ContextEntry[]): boolean {for (const entry of ctx) {switch (entry.kind) {case "termAnnot":if (isEqual(entry.type, type)) return true;break;default:continue;}}return false;}
import { isTypeInContext } from "./contexts";import { ContextEntry, Term, Type } from "./data";function check(ctx: ContextEntry[],term: Term,type: Type): [boolean, ContextEntry[]] {switch (term.kind) {case "var":break;case "unit":return [type.kind === "unit", ctx];case "lambda": {// Get A and B firstif (type.kind !== "arrow") return [false, ctx];const { input: A, output: B } = type;}case "app":break;case "annot":break;}}function synthesize(ctx: ContextEntry[], term: Term): [Type, ContextEntry[]] {switch (term.kind) {case "var": {const res = lookupTypeVariable(ctx, term.name);if (!res) throw new Error("wtf?");return [res, ctx];}case "unit":return [{ kind: "unit" }, ctx];case "lambda": {}case "app":break;case "annot": {// Require that the type existsif (!isTypeInContext(term.type, ctx))throw new Error("type doesn't exist");// Require that the term checks against the typeconst [result, outputCtx] = check(ctx, term.term, term.type);if (!result) throw new Error("invalid annotation: term doesn't check");return [term.type, outputCtx];}}}function synthesizeApp(ctx: ContextEntry[],funcType: Type,term: Term): [Type, ContextEntry[]] {}