#Logic

    The logical core of HOL: the trusted kernel, Boolean connectives, and derived equality rules.

    Depends on: foundation (for Subst), types (for Type, TypeSubst), terms (for Term, TermSubst)

    #Architecture

    This package contains three layers:

    NamespaceFileRole
    Kernelkernel.mbtLCF kernel: abstract Thm type + 10 primitive inference rules
    BoolSyntaxbool_syntax.mbtConnectives and quantifiers defined from equality
    Equalequal.mbtDerived equality rules (sym, trans, apTerm, ...)

    #Kernel (LCF Architecture)

    The kernel implements the LCF (Logic for Computable Functions) architecture: the type Thm can only be constructed through the inference rules below. Because MoonBit enforces module boundaries, no outside code can fabricate a Thm value -- every theorem is the result of a valid chain of inferences.

    ///|
    struct Thm {
    hyps : Array[Term] // hypotheses (assumptions)
    concl : Term // conclusion
    }

    A theorem { hyps: [h1, ..., hn], concl: phi } asserts: under hypotheses h1, ..., hn, the conclusion phi holds.

    #Primitive Inference Rules

    refl t |- t = t assume phi phi |- phi eqMp (A1 |- phi = psi) (A2 |- phi) A1 U A2 |- psi absThm v (A |- t = u) A |- (\v. t) = (\v. u) appThm (A1 |- f = g) (A2 |- x = y) A1 U A2 |- f x = g y deductAntisym (A1 |- phi) (A2 |- psi) (A1\{psi}) U (A2\{phi}) |- phi = psi termSubst sigma (A |- phi) A[sigma] |- phi[sigma] typeSubst sigma (A |- phi) A[sigma] |- phi[sigma] betaConv (\v. t) u |- (\v. t) u = t[u/v] defineConst c t |- c = t

    Plus defineTypeOp (type definition principle) and new_axiom (adds an axiom -- use sparingly!).

    #Examples

    ///|
    test "kernel: refl, assume, eqMp" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let p = @terms.mk_var("p", @types.bool_ty())

    // |- p = p
    let th_eq = @logic.Kernel::refl(p)
    assert_eq(th_eq.hyps.length(), 0)

    // p |- p
    let th_p = @logic.Kernel::assume_(p)
    assert_eq(th_p.hyps.length(), 1)

    // eqMp (|- p = p) (p |- p) => p |- p
    let th = @logic.Kernel::eqMp(th_eq, th_p)
    assert_true(th.concl == p)
    }

    ///|
    test "kernel: betaConv reduces a lambda application" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let a = @types.mk_var("'a")
    let x = @terms.mk_var("x", a)
    let y = @terms.mk_var("y", a)

    // |- (\x. x) y = y
    let th = @logic.Kernel::betaConv(@terms.Term::mk_abs(x, x), y)
    let (_, rhs) = @terms.Term::dest_eq(th.concl)
    assert_true(rhs == y)
    }

    ///|
    test "kernel: defineConst registers a constant" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let a = @types.mk_var("'a")
    let x = @terms.mk_var("x", a)
    let body = @terms.Term::mk_abs(x, x)

    // |- my_id = (\x. x)
    let th = @logic.Kernel::defineConst("my_id", body)
    assert_eq(th.hyps.length(), 0)
    let (lhs, rhs) = @terms.Term::dest_eq(th.concl)
    assert_true(lhs is Const(_, _))
    assert_true(rhs.aconv(body))
    }

    #BoolSyntax (Connectives and Quantifiers)

    In the HOL Light approach, all connectives and quantifiers are defined in terms of the single primitive = : 'a -> 'a -> bool:

    ConnectiveDefinition
    T(\p. p) = (\p. p)
    /\\p q. (\f. f p q) = (\f. f T T)
    ==>\p q. (p /\ q) = p
    forall\P. P = (\x. T)
    exist\P. forall q. (forall x. P x ==> q) ==> q
    \/\p q. forall r. (p ==> r) ==> (q ==> r) ==> r
    Fforall p. p
    ~\p. p ==> F

    Each connective has a uniform triple of functions:

    • mk_* -- builds the formula
    • dest_* -- takes it apart
    • is_* -- tests whether a term has that form

    ///|
    test "BoolSyntax: implication and negation" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let p = @terms.mk_var("p", @types.bool_ty())
    let q = @terms.mk_var("q", @types.bool_ty())

    // Build p ==> q
    let imp = @logic.BoolSyntax::mk_imp(p, q)
    assert_true(@logic.BoolSyntax::is_imp(imp))
    let (ant, conseq) = @logic.BoolSyntax::dest_imp(imp)
    assert_true(ant == p)
    assert_true(conseq == q)

    // Build ~p, then dest_neg returns the inner term
    let neg = @logic.BoolSyntax::mk_neg(p)
    assert_true(@logic.BoolSyntax::is_neg(neg))
    assert_true(@logic.BoolSyntax::dest_neg(neg) == p)
    }

    ///|
    test "BoolSyntax: quantifiers are applied to abstractions" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let bool_ty = @types.bool_ty()
    let x = @terms.mk_var("x", bool_ty)
    let p = @terms.mk_var("p", bool_ty)

    // forall x. x ==> p is App(forall_inst, Abs(x, x ==> p))
    let body = @logic.BoolSyntax::mk_imp(x, p)
    let fa = @logic.BoolSyntax::mk_forall(x, body)
    assert_true(fa is App(_, _))
    assert_true(fa.type_of() == bool_ty)

    // exist x. x ==> p
    let ex = @logic.BoolSyntax::mk_exists(x, body)
    assert_true(ex is App(_, _))
    }

    #Equal (Derived Equality Rules)

    Derived inference rules built entirely from kernel primitives. Because they compose only sound primitives, they are sound by construction -- no additional trust is needed beyond the kernel.

    RuleGivenConclusion
    symA \|- s = tA \|- t = s
    transA1 \|- s = t, A2 \|- t = uA1 U A2 \|- s = u
    apTermf, A \|- x = yA \|- f x = f y
    apThmx, A \|- f = gA \|- f x = g x
    mkBinopop, A1 \|- l1 = l2, A2 \|- r1 = r2A1 U A2 \|- op l1 r1 = op l2 r2
    alphat1, t2 (alpha-convertible)\|- t1 = t2

    ///|
    test "Equal: sym and trans" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let a = @types.mk_var("'a")
    let x = @terms.mk_var("x", a)
    let y = @terms.mk_var("y", a)
    let z = @terms.mk_var("z", a)

    // x = y |- x = y
    let th_xy = @logic.Kernel::assume_(@terms.Term::mk_eq(x, y))

    // sym: x = y |- y = x
    let sym_th = @logic.Equal::sym(th_xy)
    let (lhs, rhs) = @terms.Term::dest_eq(sym_th.concl)
    assert_true(lhs == y)
    assert_true(rhs == x)

    // trans: {x = y, y = z} |- x = z
    let th_yz = @logic.Kernel::assume_(@terms.Term::mk_eq(y, z))
    let trans_th = @logic.Equal::trans(th_xy, th_yz)
    let (tl, tr) = @terms.Term::dest_eq(trans_th.concl)
    assert_true(tl == x)
    assert_true(tr == z)
    }

    ///|
    test "Equal: alpha produces a theorem from alpha-convertible terms" {
    @types.Type::reset_table()
    @terms.Term::reset_table()
    let a = @types.mk_var("'a")
    let x = @terms.mk_var("x", a)
    let y = @terms.mk_var("y", a)

    // \x. x and \y. y are alpha-equivalent
    let t1 = @terms.Term::mk_abs(x, x)
    let t2 = @terms.Term::mk_abs(y, y)

    // |- (\x. x) = (\y. y)
    let th = @logic.Equal::alpha(t1, t2)
    assert_eq(th.hyps.length(), 0)
    assert_true(@terms.Term::is_eq(th.concl))
    }

    BoolSyntax

    pub enum BoolSyntax {
    }

    Namespace for Boolean connective and quantifier operations in HOL.

    BoolSyntax::conjunction

    Return the conjunction constant /\ : bool -> bool -> bool.

    BoolSyntax::dest_conj

    Decompose a conjunction p /\ q into its two conjuncts.

    BoolSyntax::dest_disj

    Decompose a disjunction p \/ q into its two disjuncts.

    BoolSyntax::dest_eq

    Decompose an equation l = r into its left and right sides.

    BoolSyntax::dest_ex_unique

    Decompose a unique existence ?! x. body into the bound variable and body.

    BoolSyntax::dest_exists

    Decompose an existential quantification exist x. body into the bound variable and body.

    BoolSyntax::dest_forall

    Decompose a universal quantification forall x. body into the bound variable and body.

    BoolSyntax::dest_imp

    Decompose an implication p ==> q into its antecedent and consequent.

    BoolSyntax::dest_neg

    BUG FIX: The SML original returns fm (the whole negation ~ p) here, but that is inconsistent with every other destructor in this file: dest_eq(= l r) returns (l, r) -- the inner operands dest_imp(==> p q) returns (p, q) -- the inner operands dest_conj(/\ p q) returns (p, q) -- the inner operands By analogy, dest_neg(~ p) should return p (the inner term), not ~ p. The mk/dest roundtrip property also requires dest_neg(mk_neg(p)) == p. Decompose a negation ~ p, returning the inner term p.

    BoolSyntax::disjunction

    Return the disjunction constant \/ : bool -> bool -> bool.

    BoolSyntax::equality

    Return the polymorphic equality constant = : 'a -> 'a -> bool.

    BoolSyntax::ex_unique

    Return the unique existence constant ?! : ('a -> bool) -> bool.

    BoolSyntax::existential

    Return the existential quantifier constant exist : ('a -> bool) -> bool.

    BoolSyntax::falsum

    Return the falsity constant F : bool.

    BoolSyntax::implication

    Return the implication constant ==> : bool -> bool -> bool.

    BoolSyntax::is_conj

    fn BoolSyntax::is_conj(fm :
    Term
    ) -> Bool

    Test whether a term is a conjunction p /\ q.

    BoolSyntax::is_disj

    fn BoolSyntax::is_disj(fm :
    Term
    ) -> Bool

    Test whether a term is a disjunction p \/ q.

    BoolSyntax::is_eq

    Test whether a term is an equation l = r.

    BoolSyntax::is_ex_unique

    fn BoolSyntax::is_ex_unique(fm :
    Term
    ) -> Bool

    Test whether a term is a unique existence quantification ?! x. body.

    BoolSyntax::is_exists

    fn BoolSyntax::is_exists(fm :
    Term
    ) -> Bool

    Test whether a term is an existential quantification exist x. body.

    BoolSyntax::is_forall

    fn BoolSyntax::is_forall(fm :
    Term
    ) -> Bool

    Test whether a term is a universal quantification forall x. body.

    BoolSyntax::is_imp

    fn BoolSyntax::is_imp(fm :
    Term
    ) -> Bool

    Test whether a term is an implication p ==> q.

    BoolSyntax::is_ind

    fn BoolSyntax::is_ind(tm :
    Term
    ) -> Bool

    Test whether a term has the individual type ind.

    BoolSyntax::is_neg

    fn BoolSyntax::is_neg(fm :
    Term
    ) -> Bool

    Test whether a term is a negation ~ p.

    BoolSyntax::mk_conj

    Construct a conjunction p /\ q, checking that both arguments have Boolean type.

    BoolSyntax::mk_disj

    Construct a disjunction p \/ q, checking that both arguments have Boolean type.

    BoolSyntax::mk_ex_unique

    Construct a unique existence quantification ?! x. body.

    BoolSyntax::mk_exists

    Construct an existential quantification exist x. body.

    BoolSyntax::mk_forall

    Construct a universal quantification forall x. body.

    BoolSyntax::mk_imp

    Construct an implication p ==> q, checking that both arguments have Boolean type.

    BoolSyntax::mk_neg

    Construct a negation ~ p, checking that the argument has Boolean type.

    BoolSyntax::negation

    Return the negation constant ~ : bool -> bool.

    BoolSyntax::universal

    Return the universal quantifier constant forall : ('a -> bool) -> bool.

    BoolSyntax::verum

    Return the truth constant T : bool.

    Equal

    pub enum Equal {
    }

    Namespace for derived equality rules built from kernel primitives.

    Equal::alpha

    Alpha-conversion: derive |- t1 = t2 when t1 and t2 are alpha-convertible.

    Equal::apTerm

    fn Equal::apTerm(tm :
    Term
    , th : Thm) -> Thm raise

    Apply a term to both sides: from A |- x = y, derive A |- f x = f y.

    Equal::apThm

    fn Equal::apThm(tm :
    Term
    , th : Thm) -> Thm raise

    Apply an argument to both sides: from A |- f = g, derive A |- f x = g x.

    Equal::mkBinop

    fn Equal::mkBinop(binop :
    Term
    , lth : Thm, rth : Thm) -> Thm raise

    Binary operator congruence: from A1 |- l1 = l2 and A2 |- r1 = r2, derive A1 U A2 |- b l1 r1 = b l2 r2.

    Equal::sym

    fn Equal::sym(th : Thm) -> Thm raise

    Symmetry: from A |- s = t, derive A |- t = s.

    Equal::trans

    fn Equal::trans(th1 : Thm, th2 : Thm) -> Thm raise

    Transitivity: from A1 |- s = t and A2 |- t = u, derive A1 U A2 |- s = u.

    Equal::trans_fast

    fn Equal::trans_fast(th1 : Thm, th2 : Thm) -> Thm raise

    Transitivity (fast version): from A1 |- s = t and A2 |- t = u, derive A1 U A2 |- s = u.

    Kernel

    pub enum Kernel {
    }

    Namespace for the HOL Light LCF kernel inference rules.

    Kernel::absThm

    fn Kernel::absThm(v :
    Term
    , th : Thm) -> Thm raise

    Abstraction: from A |- t = u, derive A |- (\v. t) = (\v. u).

    Kernel::appThm

    fn Kernel::appThm(th1 : Thm, th2 : Thm) -> Thm raise

    Congruence: from A1 |- f = g and A2 |- x = y, derive A1 U A2 |- f x = g y.

    Kernel::assume_

    Assumption: phi |- phi.

    Kernel::betaConv

    Beta reduction: |- (\v. t) u = t[u/v].

    Kernel::deductAntisym

    fn Kernel::deductAntisym(th1 : Thm, th2 : Thm) -> Thm

    Deduction antisymmetry: from A1 |- phi and A2 |- psi, derive (A1\{psi}) U (A2\{phi}) |- phi = psi.

    Kernel::defineConst

    fn Kernel::defineConst(c : String, tm :
    Term
    ) -> Thm

    Definitional extension: register constant c and return |- c = t.

    Kernel::defineTypeOp

    fn Kernel::defineTypeOp(name~ : String, abs~ : String, rep~ : String, tyvars~ : Array[String], tyax : Thm) -> (Thm, Thm)

    Type definition: given |- P witness, register a new type operator and return |- abs(rep a) = a and |- P r = (rep(abs r) = r).

    Kernel::eqMp

    fn Kernel::eqMp(th1 : Thm, th2 : Thm) -> Thm raise

    Equality modus ponens: from A1 |- phi = psi and A2 |- phi, derive A1 U A2 |- psi.

    Kernel::new_axiom

    fn Kernel::new_axiom(fm :
    Term
    ) -> Thm

    Add an axiom |- phi. Use sparingly -- every axiom is a potential source of inconsistency.

    Kernel::refl

    Reflexivity: |- t = t.

    Kernel::reset_axioms

    fn Kernel::reset_axioms() -> Unit

    Clear all registered axioms.

    Kernel::termSubst

    Term substitution: from A |- phi, derive A[sigma] |- phi[sigma].

    Kernel::typeSubst

    Type substitution: from A |- phi, derive A[sigma] |- phi[sigma].

    Thm

    A proven theorem, consisting of a set of hypotheses and a conclusion (hyps |- concl).
    impl Show for Thm

    Thm::equal

    fn Thm::equal(Thm, Thm) -> Bool

    Thm::not_equal

    fn Thm::not_equal(x : Thm, y : Thm) -> Bool

    Thm::output

    fn Thm::output(self : Thm, logger : &Logger) -> Unit

    Thm::to_repr

    Thm::to_string

    fn Thm::to_string(self : Thm) -> String

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io