Lean Kernel Arena / perf/folded-constant-first

Test "perf/folded-constant-first"

Expected: 👍 accept · Size: 52.0 KB · Lines: 1.3 k · lean4export: 3.1.0 · Lean: 4.29.1 · 📄 Declaration · 🔗 Source

The declaration to check compares

tagged (count #n)      and      (false, count #n)

where tagged m = (isZero m, m), so unfolding the left side leaves the same application count #n in both components, forced by isZero in one and plain in the other.

The plain occurrences are identical, for Θ(1); the forced one evaluates count #n once. The order matters for a checker that leaves a constant unfolded once it reduces it: reducing the forced component first replaces count #n by its value on one side, and the plain comparison then faces a folded application against an evaluated one. Here the forcing component comes first; folded-constant-last.lean swaps them, and the ratio between the two files is what that costs.

N=1000 in the Lean source. From Courant and Leroy, POPL 2026, §10, where the two orders cost Rocq 3 × 10⁻⁵ s and 0.078 s.

Checker Result ⏱️ 🧠
mathgraph 👍 3 ms (÷15) 50.6 MB (-26%)
ind-models 👍 79 ms (+93%) 109.4 MB (+59%)
official-nightly 👍 41 ms (0%) 66.9 MB (-3%)
evmlean 🚫 2.3 s 139.1 MB
nanoda 👍 7 ms (÷5.8) 4.5 MB (÷15)
mini 💥 51.1 s 91.0 MB
lean4lean 👍 47 ms (+14%) 101.4 MB (+48%)
sokonanoda 👍 3 ms (÷14) 50.5 MB (-27%)
zignodamus 👍 3 ms (÷12) 9.5 MB (÷7.2)
nanoclo 👍 4 ms (÷10) 54.4 MB (-21%)
nanobruijn 👍 7 ms (÷5.8) 17.4 MB (÷3.9)
kiota 👍 7 ms (÷6.2) 13.5 MB (÷5.1)
official 👍 41 ms (0%) 68.7 MB (0%)
vow-lean-kernel 👍 217 ms (×5.3) 22.1 MB (÷3.1)
rpylean 👍 8 ms (÷5.0) 19.6 MB (÷3.5)
official-v4.28.0 👍 48 ms (+19%) 76.9 MB (+12%)
still-nanoda 👍 7 ms (÷5.9) 4.3 MB (÷16)
nyaya 17 ms 13.6 MB
parse-only 👍 30 ms (-26%) 64.0 MB (-7%)