Files
lean4/tests/elab/cbv1.lean
Wojciech Różowski 47833725ea feat: add String simprocs to cbv (#12888)
This PR adds `String`-specific simprocs to `cbv` tactic.
2026-03-12 11:52:06 +00:00

351 lines
7.8 KiB
Lean4
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Std
set_option cbv.warning false
def function (n : Nat) : Nat := match n with
| 0 => 0 + 1
| Nat.succ n => function n + 1
termination_by (n,0)
example : function 150 = 151 := by
conv =>
lhs
cbv
example : ((1,1).1,1).1 = 1 := by
conv =>
lhs
cbv
def f : Unit -> Nat × Nat := fun _ => (1, 2)
example : (f ()).2 = 2 := by
conv =>
lhs
cbv
def g : Unit (Nat Nat) × (Nat Nat) := fun _ => (fun x => x + 1, fun x => x + 3)
example : (g ()).1 6 = 7 := by
conv =>
lhs
cbv
example : "abx" ++ "c" = "a" ++ "bxc" := by
conv =>
lhs
cbv
conv =>
rhs
cbv
example : instHAdd.1 2 2 = 4 := by
conv =>
lhs
cbv
example : (fun y : Nat Nat => (fun x => y x)) Nat.succ 1 = 2 := by
conv =>
lhs
cbv
example : (Std.TreeMap.empty.insert "a" "b" : Std.TreeMap String String).toList = [("a", "b")] := by
conv =>
lhs
cbv
theorem array_test : (List.replicate 200 5 : List Nat).reverse = List.replicate 200 5 := by
conv =>
lhs
cbv
conv =>
rhs
cbv
def testFun (l : List Nat) : Nat := Id.run do
let mut i := 0
for _ in l do
i := i + 1
return i
-- Possibly a good benchmark for dealing with let expressions
example : testFun [1,2,3,4,5] = 5 := by
conv =>
lhs
cbv
example : "ab".length + "ab".length = ("ab" ++ "ab").length := by
conv =>
lhs
cbv
conv =>
rhs
cbv
example : (((Std.TreeMap.empty : Std.TreeMap Nat Nat).insert 2 4).toList ++ [(5, 6)]).reverse = [(5,6), (2,4)] := by
conv =>
lhs
cbv
def h := ()
example : h = () := by
conv =>
lhs
cbv
def IsSubseq (s₁ : String) (s₂ : String) : Prop :=
List.Sublist s₁.toList s₂.toList
def vowels : List Char := ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
def removeVowels (s : String) : String :=
String.ofList (s.toList.filter (· vowels))
example : removeVowels "abcdef" = "bcdf" := by
conv =>
lhs
cbv
example : removeVowels "abcdef\nghijklm" = "bcdf\nghjklm" := by
conv =>
lhs
cbv
example : removeVowels "aaaaa" = "" := by
conv =>
lhs
cbv
example : removeVowels "aaBAA" = "B" := by
conv =>
lhs
cbv
example : removeVowels "zbcd" = "zbcd" := by
conv =>
lhs
cbv
def Nat.factorial : Nat Nat
| 0 => 1
| .succ n => Nat.succ n * factorial n
notation:10000 n "!" => Nat.factorial n
def Nat.brazilianFactorial : Nat Nat
| .zero => 1
| .succ n => (Nat.succ n)! * brazilianFactorial n
def special_factorial (n : Nat) : Nat :=
special_factorial.go n 1 1 0
where
go (n fact brazilFact curr : Nat) : Nat :=
if _h: curr >= n
then brazilFact
else
let fact' := (curr + 1) * fact
let brazilFact' := fact' * brazilFact
special_factorial.go n fact' brazilFact' (Nat.succ curr)
termination_by n - curr
example : Nat.brazilianFactorial 4 = 288 := by
conv =>
lhs
cbv
example : special_factorial 4 = 288 := by
conv =>
lhs
cbv
example : Nat.brazilianFactorial 5 = 34560 := by
conv =>
lhs
cbv
example : Nat.brazilianFactorial 7 = 125411328000 := by
conv =>
lhs
cbv
attribute [cbv_opaque] Std.DHashMap.emptyWithCapacity
attribute [cbv_opaque] Std.DHashMap.insert
attribute [cbv_opaque] Std.DHashMap.getEntry
attribute [cbv_opaque] Std.DHashMap.contains
attribute [cbv_eval] Std.DHashMap.contains_emptyWithCapacity
attribute [cbv_eval] Std.DHashMap.contains_insert
example : ((Std.DHashMap.emptyWithCapacity : Std.DHashMap Nat (fun _ => Nat)).insert 5 3).contains 5 = true := by
conv =>
lhs
cbv
@[cbv_opaque] def opaque_const : Nat := Nat.zero
@[cbv_eval] theorem opaque_fn_spec : opaque_const = 0 := by rfl
example : opaque_const = 0 := by conv => lhs; cbv
def myAdd (m n : Nat) := match m with
| 0 => n
| m' + 1 => (myAdd m' n) + 1
@[cbv_eval] theorem myAdd_test : myAdd 22 23 = 45 := by rfl
theorem fast_path : myAdd 22 23 = 45 := by conv => lhs; cbv
/--
info: theorem fast_path : myAdd 22 23 = 45 :=
Eq.mpr
(id
((fun a a_1 e_a =>
Eq.rec (motive := fun a_2 e_a => ∀ (a_3 : Nat), (a = a_3) = (a_2 = a_3)) (fun a_2 => Eq.refl (a = a_2)) e_a)
(myAdd 22 23) 45 (Eq.trans myAdd_test (Eq.refl 45)) 45))
(Eq.refl 45)
-/
#guard_msgs in
#print fast_path
theorem slow_path : myAdd 0 1 = 1 := by conv => lhs; cbv
/--
info: theorem slow_path : myAdd 0 1 = 1 :=
Eq.mpr
(id
((fun a a_1 e_a =>
Eq.rec (motive := fun a_2 e_a => ∀ (a_3 : Nat), (a = a_3) = (a_2 = a_3)) (fun a_2 => Eq.refl (a = a_2)) e_a)
(myAdd 0 1) 1 (Eq.trans (myAdd.eq_1 1) (Eq.refl 1)) 1))
(Eq.refl 1)
-/
#guard_msgs in
#print slow_path
/-! ## Or/And short-circuit evaluation -/
theorem or_test_1 : (1 < 2 (10000).factorial = 0) = True := by cbv
/--
info: theorem or_test_1 : (1 < 2 10000! = 0) = True :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Lean.Sym.or_eq_true_left (1 < 2) (10000! = 0) (Lean.Sym.Nat.lt_eq_true 1 2 (eagerReduce (Eq.refl true)))))
True)
(eq_self True))
-/
#guard_msgs in
#print or_test_1
theorem or_test_2 : (3 < 2 1 < 2) = True := by cbv
/--
info: theorem or_test_2 : (3 < 2 1 < 2) = True :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Eq.trans (Lean.Sym.or_eq_right (3 < 2) (1 < 2) (Lean.Sym.Nat.lt_eq_false 3 2 (eagerReduce (Eq.refl false))))
(Lean.Sym.Nat.lt_eq_true 1 2 (eagerReduce (Eq.refl true)))))
True)
(eq_self True))
-/
#guard_msgs in
#print or_test_2
theorem or_test_3 : (3 < 2 5 < 4) = False := by cbv
/--
info: theorem or_test_3 : (3 < 2 5 < 4) = False :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Eq.trans (Lean.Sym.or_eq_right (3 < 2) (5 < 4) (Lean.Sym.Nat.lt_eq_false 3 2 (eagerReduce (Eq.refl false))))
(Lean.Sym.Nat.lt_eq_false 5 4 (eagerReduce (Eq.refl false)))))
False)
(eq_self False))
-/
#guard_msgs in
#print or_test_3
theorem and_test_1 : (3 < 2 (10000).factorial = 0) = False := by cbv
/--
info: theorem and_test_1 : (3 < 2 ∧ 10000! = 0) = False :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Lean.Sym.and_eq_false_left (3 < 2) (10000! = 0) (Lean.Sym.Nat.lt_eq_false 3 2 (eagerReduce (Eq.refl false)))))
False)
(eq_self False))
-/
#guard_msgs in
#print and_test_1
theorem and_test_2 : (1 < 2 3 < 4) = True := by cbv
/--
info: theorem and_test_2 : (1 < 2 ∧ 3 < 4) = True :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Eq.trans (Lean.Sym.and_eq_left (1 < 2) (3 < 4) (Lean.Sym.Nat.lt_eq_true 1 2 (eagerReduce (Eq.refl true))))
(Lean.Sym.Nat.lt_eq_true 3 4 (eagerReduce (Eq.refl true)))))
True)
(eq_self True))
-/
#guard_msgs in
#print and_test_2
theorem and_test_3 : (1 < 2 5 < 4) = False := by cbv
/--
info: theorem and_test_3 : (1 < 2 ∧ 5 < 4) = False :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Eq.trans (Lean.Sym.and_eq_left (1 < 2) (5 < 4) (Lean.Sym.Nat.lt_eq_true 1 2 (eagerReduce (Eq.refl true))))
(Lean.Sym.Nat.lt_eq_false 5 4 (eagerReduce (Eq.refl false)))))
False)
(eq_self False))
-/
#guard_msgs in
#print and_test_3
theorem or_and : (1 < 2 (3 < 2 (10000).factorial = 0)) = True := by cbv
/--
info: theorem or_and : (1 < 2 3 < 2 ∧ 10000! = 0) = True :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Lean.Sym.or_eq_true_left (1 < 2) (3 < 2 ∧ 10000! = 0)
(Lean.Sym.Nat.lt_eq_true 1 2 (eagerReduce (Eq.refl true)))))
True)
(eq_self True))
-/
#guard_msgs in
#print or_and
theorem and_or : (3 < 2 (1 < 2 (10000).factorial = 0)) = False := by cbv
/--
info: theorem and_or : (3 < 2 ∧ (1 < 2 10000! = 0)) = False :=
of_eq_true
(Eq.trans
(congrFun'
(congrArg Eq
(Lean.Sym.and_eq_false_left (3 < 2) (1 < 2 10000! = 0)
(Lean.Sym.Nat.lt_eq_false 3 2 (eagerReduce (Eq.refl false)))))
False)
(eq_self False))
-/
#guard_msgs in
#print and_or