Navigation

Proof Basics

The first proof examples stay close to computation. You write a HOAS proposition, give refl as evidence, and let the kernel normalize both sides. When the normal forms match, the checker accepts the proof.

Later sections use the same checker with dependent pairs and eliminators. The full source lives at examples/proof-basics.nix.

Computational equality

Addition, boolean negation, list length, and append are defined with eliminators. The equality proof is still refl; the work happens in normalization.

add = m: n:
  ind 0 (lam "_" nat (_: nat)) n
    (lam "k" nat (_: lam "ih" nat (ih: succ ih)))
    m;

addThreeFive =
  (checkHoas (eq nat (add (natLit 3) (natLit 5)) (natLit 8)) refl)
    .tag == "desc-con";

doubleNegTrue =
  (checkHoas (eq bool (not_ (not_ true_)) true_) refl).tag == "desc-con";

Dependent witnesses

A sigma value packages a witness with proof that the witness has the requested property. These examples use concrete witnesses whose proof component reduces to reflexivity.

witnessAddResult =
  let
    ty = sigma "x" nat (x: eq nat (add (natLit 3) (natLit 5)) x);
    tm = pair (natLit 8) refl;
  in
  (checkHoas ty tm).tag == "pair";

Eliminators as programs

Natural, boolean, list, and sum eliminators let the proof examples define small programs inside HOAS. Each checked assertion ties the computed result back to an equality.

listSum =
  let
    sumList = xs: listElim 0 nat (lam "_" (listOf nat) (_: nat)) zero
      (lam "h" nat (h: lam "t" (listOf nat) (_:
        lam "ih" nat (ih: add h ih))))
      xs;
  in
  (checkHoas (eq nat (sumList list123) (natLit 6)) refl).tag == "desc-con";

Polymorphism and impossibility

The final examples leave concrete computation and check reusable functions: a universe-polymorphic identity and the eliminator from Void.

polyId =
  let
    ty = forall "A" (u 0) (a: forall "x" a (_: a));
    tm = lam "A" (u 0) (a: lam "x" a (x: x));
  in
  (checkHoas ty tm).tag == "lam";

exFalso =
  let
    ty = forall "A" (u 0) (a: forall "x" void (_: a));
    tm = lam "A" (u 0) (a: lam "x" void (x: absurd a x));
  in
  (checkHoas ty tm).tag == "lam";