Zulip Chat Archive
Stream: general
Topic: Proving property of function nested inside a function
Mai (Feb 17 2026 at 14:48):
I am not sure how to go about proving something like this (sorry for all the fluff definitions :smile:)
import Mathlib
structure TypeVar where
n : Nat
deriving DecidableEq
mutual
@[grind]
structure PosUnion where
types : List PosType
inductive PosType where
| func : List (TypeVar × List Constraint) -> NegType -> PosUnion -> PosType
| var : TypeVar -> PosType
inductive NegType where
| var : TypeVar -> NegType
inductive Constraint where
| isFunc : PosType -> NegType -> Constraint
end
mutual
def PosUnion.freeVars (u : PosUnion) : List TypeVar :=
u.types.flatMap fun t => t.freeVars
termination_by sizeOf u
decreasing_by grind [List.sizeOf_lt_of_mem ‹t ∈ u.types›]
def PosType.freeVars (τ : PosType) : List TypeVar :=
match τ with
| .func vars dom codom =>
let bound := vars.unzip.1
let consVars := vars.flatMap fun v => v.2.flatMap fun c => c.freeVars
(consVars ∪ dom.freeVars ∪ codom.freeVars) \ bound
| .var v => [v]
termination_by sizeOf τ
decreasing_by
· grind [List.sizeOf_lt_of_mem ‹c ∈ v.snd›, List.sizeOf_lt_of_mem ‹v ∈ vars›]
· decreasing_tactic
def NegType.freeVars (τ : NegType) : List TypeVar :=
match τ with
| .var v => [v]
termination_by sizeOf τ
def Constraint.freeVars (c : Constraint) : List TypeVar :=
match c with
| .isFunc dom codom => dom.freeVars ∪ codom.freeVars
termination_by sizeOf c
end
structure Ctx where
types : List PosUnion
def Ctx.freeVars (Γ : Ctx) : List TypeVar :=
Γ.types.flatMap PosUnion.freeVars
def reachableVars (Γ : Ctx) (cons : List (TypeVar × Constraint)) : List TypeVar :=
let f s := s ∪ (cons
|>.filter (fun c => c.1 ∈ s)
|>.flatMap (fun c => c.2.freeVars))
f^[cons.length] Γ.freeVars
lemma reachableVars_correct :
let s := reachableVars Γ cons
Γ.freeVars ⊆ s ∧ ∀ c ∈ cons, c.1 ∈ s -> c.2.freeVars ⊆ s := by
apply And.intro
· sorry
· sorry
Yury G. Kudryashov (Feb 17 2026 at 17:12):
Could you please provide a summary of what's your issue? Is it the fact that f inside reachableVars isn't available as a separate entity to prove properties about it? If yes, then you can try using
def reachableVars ... :=
f^[cons.length] Γ.freeVars
where f := ...
syntax so that Lean defines reachableVars.f and you can prove lemmas about it before proving lemmas about reachableVars.
Mai (Feb 17 2026 at 17:20):
That's precisely the issue, I think. Thank you
Mai (Feb 17 2026 at 19:18):
I am still having a very hard time finishing this proof. any ideas what to do? nevermind, got it :laughing:
import Mathlib
structure TypeVar where
n : Nat
deriving DecidableEq
mutual
@[grind]
structure PosUnion where
types : List PosType
inductive PosType where
| func : List (TypeVar × List Constraint) -> NegType -> PosUnion -> PosType
| var : TypeVar -> PosType
inductive NegType where
| var : TypeVar -> NegType
inductive Constraint where
| isFunc : PosType -> NegType -> Constraint
end
mutual
def PosUnion.freeVars (u : PosUnion) : List TypeVar :=
u.types.flatMap fun t => t.freeVars
termination_by sizeOf u
decreasing_by grind [List.sizeOf_lt_of_mem ‹t ∈ u.types›]
def PosType.freeVars (τ : PosType) : List TypeVar :=
match τ with
| .func vars dom codom =>
let bound := vars.unzip.1
let consVars := vars.flatMap fun v => v.2.flatMap fun c => c.freeVars
(consVars ∪ dom.freeVars ∪ codom.freeVars) \ bound
| .var v => [v]
termination_by sizeOf τ
decreasing_by
· grind [List.sizeOf_lt_of_mem ‹c ∈ v.snd›, List.sizeOf_lt_of_mem ‹v ∈ vars›]
· decreasing_tactic
def NegType.freeVars (τ : NegType) : List TypeVar :=
match τ with
| .var v => [v]
termination_by sizeOf τ
def Constraint.freeVars (c : Constraint) : List TypeVar :=
match c with
| .isFunc dom codom => dom.freeVars ∪ codom.freeVars
termination_by sizeOf c
end
structure Ctx where
types : List PosUnion
def Ctx.freeVars (Γ : Ctx) : List TypeVar :=
Γ.types.flatMap PosUnion.freeVars
def reachableVars (Γ : Ctx) (cons : List (TypeVar × Constraint)) : List TypeVar :=
f^[cons.length] Γ.freeVars
where f s := s ∪ (cons.filter fun c => c.1 ∈ s).flatMap fun c => c.2.freeVars
lemma reachableVars_f_inflationary : s ⊆ reachableVars.f cons s := by
intro v h
exact List.mem_union_left h _
lemma reachableVars_includes_Γ_freeVars :
Γ.freeVars ⊆ reachableVars Γ cons := by
unfold reachableVars
induction cons.length
case zero => simp
case succ prev =>
sorry
Last updated: Feb 28 2026 at 14:05 UTC