mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-17 18:34:06 +00:00
This PR adds a warning to any `def` of class type that does not also declare an appropriate reducibility. The warning check runs after elaboration (checking the actual reducibility status via `getReducibilityStatus`) rather than syntactically checking modifiers before elaboration. This is necessary to accommodate patterns like `@[to_additive (attr := implicit_reducible)]` in Mathlib, where the reducibility attribute is applied during `.afterCompilation` by another attribute, and would be missed by a purely syntactic check. --------- Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com> Co-authored-by: Kim Morrison <kim@tqft.net> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
345 lines
8.6 KiB
Lean4
345 lines
8.6 KiB
Lean4
set_option warn.classDefReducibility false
|
||
|
||
-- Minimisation of a timeout triggered by leanprover/lean4#3124
|
||
-- in Mathlib.Computability.PartrecCode
|
||
|
||
set_option autoImplicit true
|
||
|
||
section Std.Data.Nat.Basic
|
||
|
||
def sqrt (n : Nat) : Nat :=
|
||
if n ≤ 1 then n else
|
||
iter n (n / 2)
|
||
where
|
||
iter (n guess : Nat) : Nat :=
|
||
let next := (guess + n / guess) / 2
|
||
if _h : next < guess then
|
||
iter n next
|
||
else
|
||
guess
|
||
termination_by guess
|
||
|
||
end Std.Data.Nat.Basic
|
||
|
||
section Mathlib.Logic.Equiv.Defs
|
||
|
||
structure Equiv (α : Sort _) (β : Sort _) where
|
||
protected toFun : α → β
|
||
protected invFun : β → α
|
||
|
||
infixl:25 " ≃ " => Equiv
|
||
|
||
namespace Equiv
|
||
|
||
protected def symm (e : α ≃ β) : β ≃ α := ⟨e.invFun, e.toFun⟩
|
||
|
||
def sigmaEquivProd (α β : Type _) : (Σ _ : α, β) ≃ α × β :=
|
||
⟨fun a => ⟨a.1, a.2⟩, fun a => ⟨a.1, a.2⟩⟩
|
||
|
||
end Equiv
|
||
|
||
end Mathlib.Logic.Equiv.Defs
|
||
|
||
section Mathlib.Data.Nat.Pairing
|
||
|
||
namespace Nat
|
||
|
||
def pair (a b : Nat) : Nat :=
|
||
if a < b then b * b + a else a * a + a + b
|
||
|
||
def unpair (n : Nat) : Nat × Nat :=
|
||
let s := sqrt n
|
||
if n - s * s < s then (n - s * s, s) else (s, n - s * s - s)
|
||
|
||
theorem unpair_right_le (n : Nat) : (unpair n).2 ≤ n := sorry
|
||
|
||
end Nat
|
||
|
||
end Mathlib.Data.Nat.Pairing
|
||
|
||
section Mathlib.Logic.Encodable.Basic
|
||
|
||
open Nat
|
||
|
||
class Encodable (α : Type _) where
|
||
encode : α → Nat
|
||
decode : Nat → Option α
|
||
encodek : ∀ a, decode (encode a) = some a
|
||
|
||
namespace Encodable
|
||
|
||
def ofLeftInjection [Encodable α] (f : β → α) (finv : α → Option β)
|
||
(linv : ∀ b, finv (f b) = some b) : Encodable β :=
|
||
⟨fun b => encode (f b), fun n => (decode n).bind finv, fun b => sorry⟩
|
||
|
||
def ofLeftInverse [Encodable α] (f : β → α) (finv : α → β) (linv : ∀ b, finv (f b) = b) :
|
||
Encodable β :=
|
||
ofLeftInjection f (some ∘ finv) sorry
|
||
|
||
def ofEquiv (α) [Encodable α] (e : β ≃ α) : Encodable β :=
|
||
ofLeftInverse e.toFun e.invFun sorry
|
||
|
||
instance _root_.Nat.encodable : Encodable Nat :=
|
||
⟨id, some, fun _ => rfl⟩
|
||
|
||
instance _root_.Option.encodable {α : Type _} [h : Encodable α] : Encodable (Option α) :=
|
||
⟨fun o => Option.casesOn o Nat.zero fun a => succ (encode a), fun n =>
|
||
Nat.casesOn n (some none) fun m => (decode m).map some, sorry⟩
|
||
|
||
section Sigma
|
||
|
||
variable {γ : α → Type _} [Encodable α] [∀ a, Encodable (γ a)]
|
||
|
||
def encodeSigma : Sigma γ → Nat
|
||
| ⟨a, b⟩ => pair (encode a) (encode b)
|
||
|
||
def decodeSigma (n : Nat) : Option (Sigma γ) :=
|
||
let (n₁, n₂) := unpair n
|
||
(decode n₁).bind fun a => (decode n₂).map <| Sigma.mk a
|
||
|
||
instance _root_.Sigma.encodable : Encodable (Sigma γ) :=
|
||
⟨encodeSigma, decodeSigma, sorry⟩
|
||
|
||
end Sigma
|
||
|
||
instance Prod.encodable [Encodable α] [Encodable β] : Encodable (α × β) :=
|
||
ofEquiv _ (Equiv.sigmaEquivProd α β).symm
|
||
|
||
end Encodable
|
||
|
||
end Mathlib.Logic.Encodable.Basic
|
||
|
||
section Mathlib.Logic.Denumerable
|
||
|
||
class Denumerable (α : Type _) extends Encodable α where
|
||
|
||
namespace Denumerable
|
||
|
||
def mk' {α} (e : α ≃ Nat) : Denumerable α where
|
||
encode := e.toFun
|
||
decode := some ∘ e.invFun
|
||
encodek _ := sorry
|
||
|
||
instance nat : Denumerable Nat := ⟨⟩
|
||
|
||
end Denumerable
|
||
|
||
end Mathlib.Logic.Denumerable
|
||
|
||
section Mathlib.Logic.Equiv.List
|
||
|
||
open Nat List
|
||
|
||
namespace Encodable
|
||
|
||
variable [Encodable α]
|
||
|
||
def encodeList : List α → Nat
|
||
| [] => 0
|
||
| a :: l => succ (pair (encode a) (encodeList l))
|
||
|
||
def decodeList : Nat → Option (List α)
|
||
| 0 => some []
|
||
| succ v =>
|
||
match unpair v, unpair_right_le v with
|
||
| (v₁, v₂), h =>
|
||
have : v₂ < succ v := lt_succ_of_le h
|
||
(· :: ·) <$> decode (α := α) v₁ <*> decodeList v₂
|
||
|
||
instance _root_.List.encodable : Encodable (List α) :=
|
||
⟨encodeList, decodeList, sorry⟩
|
||
|
||
end Encodable
|
||
|
||
end Mathlib.Logic.Equiv.List
|
||
|
||
section Mathlib.Computability.Primrec
|
||
|
||
open Denumerable Encodable Function
|
||
|
||
namespace Nat
|
||
|
||
@[simp, reducible]
|
||
def unpaired {α} (f : Nat → Nat → α) (n : Nat) : α :=
|
||
f n.unpair.1 n.unpair.2
|
||
|
||
protected inductive Primrec : (Nat → Nat) → Prop
|
||
| zero : Nat.Primrec fun _ => 0
|
||
| protected succ : Nat.Primrec succ
|
||
| left : Nat.Primrec fun n => n.unpair.1
|
||
| right : Nat.Primrec fun n => n.unpair.2
|
||
| pair {f g} : Nat.Primrec f → Nat.Primrec g → Nat.Primrec fun n => pair (f n) (g n)
|
||
| comp {f g} : Nat.Primrec f → Nat.Primrec g → Nat.Primrec fun n => f (g n)
|
||
| prec {f g} :
|
||
Nat.Primrec f →
|
||
Nat.Primrec g →
|
||
Nat.Primrec (unpaired fun z n => n.rec (f z) fun y IH => g <| pair z <| pair y IH)
|
||
|
||
end Nat
|
||
|
||
class Primcodable (α : Type _) extends Encodable α where
|
||
prim : Nat.Primrec fun n => Encodable.encode (decode n)
|
||
|
||
namespace Primcodable
|
||
|
||
instance (priority := 10) ofDenumerable (α) [Denumerable α] : Primcodable α := ⟨sorry⟩
|
||
|
||
instance option {α : Type _} [h : Primcodable α] : Primcodable (Option α) := ⟨sorry⟩
|
||
|
||
end Primcodable
|
||
|
||
def Primrec {α β} [Primcodable α] [Primcodable β] (f : α → β) : Prop :=
|
||
Nat.Primrec fun n => encode ((@decode α _ n).map f)
|
||
|
||
namespace Primrec
|
||
|
||
variable {α : Type _} {β : Type _} {σ : Type _}
|
||
|
||
variable [Primcodable α] [Primcodable β] [Primcodable σ]
|
||
|
||
protected theorem encode : Primrec (@encode α _) := sorry
|
||
|
||
theorem comp {f : β → σ} {g : α → β} (hf : Primrec f) (hg : Primrec g) : Primrec fun a => f (g a) :=
|
||
sorry
|
||
|
||
end Primrec
|
||
|
||
namespace Primcodable
|
||
|
||
open Nat.Primrec
|
||
|
||
instance prod {α β} [Primcodable α] [Primcodable β] : Primcodable (α × β) :=
|
||
⟨sorry⟩
|
||
|
||
end Primcodable
|
||
|
||
namespace Primrec
|
||
|
||
variable {α : Type _} {σ : Type _} [Primcodable α] [Primcodable σ]
|
||
|
||
open Nat.Primrec
|
||
|
||
theorem fst {α β} [Primcodable α] [Primcodable β] : Primrec (@Prod.fst α β) := sorry
|
||
|
||
theorem snd {α β} [Primcodable α] [Primcodable β] : Primrec (@Prod.snd α β) := sorry
|
||
|
||
end Primrec
|
||
|
||
def Primrec₂ {α β σ} [Primcodable α] [Primcodable β] [Primcodable σ] (f : α → β → σ) :=
|
||
Primrec fun p : α × β => f p.1 p.2
|
||
|
||
section Comp
|
||
|
||
variable {α : Type _} {β : Type _} {γ : Type _} {σ : Type _}
|
||
|
||
variable [Primcodable α] [Primcodable β] [Primcodable γ] [Primcodable σ]
|
||
|
||
theorem Primrec₂.comp {f : β → γ → σ} {g : α → β} {h : α → γ} (hf : Primrec₂ f) (hg : Primrec g)
|
||
(hh : Primrec h) : Primrec fun a => f (g a) (h a) := sorry
|
||
|
||
end Comp
|
||
|
||
namespace Primrec
|
||
|
||
variable {α : Type _} {β : Type _} {σ : Type _}
|
||
|
||
variable [Primcodable α] [Primcodable β] [Primcodable σ]
|
||
|
||
theorem option_bind {f : α → Option β} {g : α → β → Option σ} (hf : Primrec f) (hg : Primrec₂ g) :
|
||
Primrec fun a => (f a).bind (g a) := sorry
|
||
|
||
end Primrec
|
||
|
||
section
|
||
|
||
variable {α : Type _} {β : Type _} {σ : Type _}
|
||
|
||
variable [Primcodable α] [Primcodable β] [Primcodable σ]
|
||
|
||
variable (H : Nat.Primrec fun n => Encodable.encode (@decode (List β) _ n))
|
||
|
||
open Primrec
|
||
|
||
private def prim : Primcodable (List β) := ⟨H⟩
|
||
|
||
end
|
||
|
||
namespace Primcodable
|
||
|
||
variable {α : Type _} {β : Type _}
|
||
|
||
variable [Primcodable α] [Primcodable β]
|
||
|
||
open Primrec
|
||
|
||
instance list : Primcodable (List α) := ⟨sorry⟩
|
||
|
||
end Primcodable
|
||
|
||
namespace Primrec
|
||
|
||
variable {α : Type _}
|
||
|
||
variable [Primcodable α]
|
||
|
||
theorem list_get? : Primrec₂ (@List.get?Internal α) := sorry
|
||
|
||
end Primrec
|
||
|
||
end Mathlib.Computability.Primrec
|
||
|
||
section Mathlib.Computability.PartrecCode
|
||
|
||
open Encodable Denumerable Primrec
|
||
|
||
namespace Nat.Partrec
|
||
|
||
inductive Code : Type
|
||
| zero : Code
|
||
| succ : Code
|
||
| left : Code
|
||
| right : Code
|
||
| pair : Code → Code → Code
|
||
| comp : Code → Code → Code
|
||
| prec : Code → Code → Code
|
||
| rfind' : Code → Code
|
||
|
||
end Nat.Partrec
|
||
|
||
namespace Nat.Partrec.Code
|
||
|
||
def encodeCode : Code → Nat
|
||
| zero => 0
|
||
| succ => 1
|
||
| left => 2
|
||
| right => 3
|
||
| pair cf cg => 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 4
|
||
| comp cf cg => 2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg) + 1) + 4
|
||
| prec cf cg => (2 * (2 * Nat.pair (encodeCode cf) (encodeCode cg)) + 1) + 4
|
||
| rfind' cf => (2 * (2 * encodeCode cf + 1) + 1) + 4
|
||
|
||
def ofNatCode : Nat → Code
|
||
| 0 => zero
|
||
| 1 => succ
|
||
| 2 => left
|
||
| 3 => right
|
||
| _ => zero -- garbage value!
|
||
|
||
instance instDenumerable : Denumerable Code :=
|
||
mk' ⟨encodeCode, ofNatCode⟩
|
||
|
||
open Primrec
|
||
|
||
private def lup (L : List (List (Option Nat))) (p : Nat × Code) (n : Nat) := do
|
||
let l ← L.get?Internal (encode p)
|
||
let o ← l.get?Internal n
|
||
o
|
||
|
||
-- This used to work in under 20000, but need over 6 million after leanprover/lean4#3124
|
||
set_option maxHeartbeats 40000 in
|
||
private theorem hlup : Primrec fun p : _ × (_ × _) × _ => lup p.1 p.2.1 p.2.2 :=
|
||
Primrec.option_bind
|
||
(Primrec.list_get?.comp Primrec.fst (Primrec.encode.comp <| Primrec.fst.comp Primrec.snd))
|
||
(Primrec.option_bind (Primrec.list_get?.comp Primrec.snd <| Primrec.snd.comp <|
|
||
Primrec.snd.comp Primrec.fst) Primrec.snd)
|