Zulip Chat Archive
Stream: new members
Topic: matching on Finset
Simon Daniel (Apr 01 2025 at 10:04):
Hi, im wondering on what is the most elegant way to match on a finset. what i try:
def f: ({"a", "b"}:Finset String) -> Nat
| ⟨"a", _⟩ => 1
| ⟨"b", _⟩ => 2
| _ => sorry --maybe solve by contradiction somehow?
can Lean figure out the dead branch here itself? What i rather would write is
def f': ({"a", "b"}:Finset String) -> Nat
| "a" => 1
| "b" => 2
Eric Wieser (Apr 01 2025 at 12:03):
Note it works fine for integers:
def f: ({11, 12}:Finset Nat) -> Nat
| ⟨11, _⟩ => 1
| ⟨12, _⟩ => 2
I think the problem is that string decidable equality is not reducible
Aaron Liu (Apr 01 2025 at 12:11):
It's not running any decidable equality procedure, but using dependent elimination to eliminate the remaining cases
Aaron Liu (Apr 01 2025 at 12:25):
I think the problem is docs#Nat.isValidChar, which has these huge numbers in it.
Aaron Liu (Apr 01 2025 at 12:36):
This works, but it takes a while
import Mathlib
example : ({'a', 'b'} : Finset Char) → Nat
| ⟨Char.mk (UInt32.ofBitVec 97) _, _⟩ => 1
| ⟨Char.mk (UInt32.ofBitVec 98) _, _⟩ => 2
Aaron Liu (Apr 01 2025 at 12:43):
It's also very bloated
import Mathlib
/-
[result]
def f (x_1 : u32) : obj :=
let x_2 : obj := UInt32.toNat x_1;
let x_3 : obj := 0;
let x_4 : obj := 1;
let x_5 : obj := Nat.sub x_2 x_4;
dec x_2;
let x_6 : obj := Nat.sub x_5 x_4;
dec x_5;
let x_7 : obj := Nat.sub x_6 x_4;
dec x_6;
let x_8 : obj := Nat.sub x_7 x_4;
dec x_7;
let x_9 : obj := Nat.sub x_8 x_4;
dec x_8;
let x_10 : obj := Nat.sub x_9 x_4;
dec x_9;
let x_11 : obj := Nat.sub x_10 x_4;
dec x_10;
let x_12 : obj := Nat.sub x_11 x_4;
dec x_11;
let x_13 : obj := Nat.sub x_12 x_4;
dec x_12;
let x_14 : obj := Nat.sub x_13 x_4;
dec x_13;
let x_15 : obj := Nat.sub x_14 x_4;
dec x_14;
let x_16 : obj := Nat.sub x_15 x_4;
dec x_15;
let x_17 : obj := Nat.sub x_16 x_4;
dec x_16;
let x_18 : obj := Nat.sub x_17 x_4;
dec x_17;
let x_19 : obj := Nat.sub x_18 x_4;
dec x_18;
let x_20 : obj := Nat.sub x_19 x_4;
dec x_19;
let x_21 : obj := Nat.sub x_20 x_4;
dec x_20;
let x_22 : obj := Nat.sub x_21 x_4;
dec x_21;
let x_23 : obj := Nat.sub x_22 x_4;
dec x_22;
let x_24 : obj := Nat.sub x_23 x_4;
dec x_23;
let x_25 : obj := Nat.sub x_24 x_4;
dec x_24;
let x_26 : obj := Nat.sub x_25 x_4;
dec x_25;
let x_27 : obj := Nat.sub x_26 x_4;
dec x_26;
let x_28 : obj := Nat.sub x_27 x_4;
dec x_27;
let x_29 : obj := Nat.sub x_28 x_4;
dec x_28;
let x_30 : obj := Nat.sub x_29 x_4;
dec x_29;
let x_31 : obj := Nat.sub x_30 x_4;
dec x_30;
let x_32 : obj := Nat.sub x_31 x_4;
dec x_31;
let x_33 : obj := Nat.sub x_32 x_4;
dec x_32;
let x_34 : obj := Nat.sub x_33 x_4;
dec x_33;
let x_35 : obj := Nat.sub x_34 x_4;
dec x_34;
let x_36 : obj := Nat.sub x_35 x_4;
dec x_35;
let x_37 : obj := Nat.sub x_36 x_4;
dec x_36;
let x_38 : obj := Nat.sub x_37 x_4;
dec x_37;
let x_39 : obj := Nat.sub x_38 x_4;
dec x_38;
let x_40 : obj := Nat.sub x_39 x_4;
dec x_39;
let x_41 : obj := Nat.sub x_40 x_4;
dec x_40;
let x_42 : obj := Nat.sub x_41 x_4;
dec x_41;
let x_43 : obj := Nat.sub x_42 x_4;
dec x_42;
let x_44 : obj := Nat.sub x_43 x_4;
dec x_43;
let x_45 : obj := Nat.sub x_44 x_4;
dec x_44;
let x_46 : obj := Nat.sub x_45 x_4;
dec x_45;
let x_47 : obj := Nat.sub x_46 x_4;
dec x_46;
let x_48 : obj := Nat.sub x_47 x_4;
dec x_47;
let x_49 : obj := Nat.sub x_48 x_4;
dec x_48;
let x_50 : obj := Nat.sub x_49 x_4;
dec x_49;
let x_51 : obj := Nat.sub x_50 x_4;
dec x_50;
let x_52 : obj := Nat.sub x_51 x_4;
dec x_51;
let x_53 : obj := Nat.sub x_52 x_4;
dec x_52;
let x_54 : obj := Nat.sub x_53 x_4;
dec x_53;
let x_55 : obj := Nat.sub x_54 x_4;
dec x_54;
let x_56 : obj := Nat.sub x_55 x_4;
dec x_55;
let x_57 : obj := Nat.sub x_56 x_4;
dec x_56;
let x_58 : obj := Nat.sub x_57 x_4;
dec x_57;
let x_59 : obj := Nat.sub x_58 x_4;
dec x_58;
let x_60 : obj := Nat.sub x_59 x_4;
dec x_59;
let x_61 : obj := Nat.sub x_60 x_4;
dec x_60;
let x_62 : obj := Nat.sub x_61 x_4;
dec x_61;
let x_63 : obj := Nat.sub x_62 x_4;
dec x_62;
let x_64 : obj := Nat.sub x_63 x_4;
dec x_63;
let x_65 : obj := Nat.sub x_64 x_4;
dec x_64;
let x_66 : obj := Nat.sub x_65 x_4;
dec x_65;
let x_67 : obj := Nat.sub x_66 x_4;
dec x_66;
let x_68 : obj := Nat.sub x_67 x_4;
dec x_67;
let x_69 : obj := Nat.sub x_68 x_4;
dec x_68;
let x_70 : obj := Nat.sub x_69 x_4;
dec x_69;
let x_71 : obj := Nat.sub x_70 x_4;
dec x_70;
let x_72 : obj := Nat.sub x_71 x_4;
dec x_71;
let x_73 : obj := Nat.sub x_72 x_4;
dec x_72;
let x_74 : obj := Nat.sub x_73 x_4;
dec x_73;
let x_75 : obj := Nat.sub x_74 x_4;
dec x_74;
let x_76 : obj := Nat.sub x_75 x_4;
dec x_75;
let x_77 : obj := Nat.sub x_76 x_4;
dec x_76;
let x_78 : obj := Nat.sub x_77 x_4;
dec x_77;
let x_79 : obj := Nat.sub x_78 x_4;
dec x_78;
let x_80 : obj := Nat.sub x_79 x_4;
dec x_79;
let x_81 : obj := Nat.sub x_80 x_4;
dec x_80;
let x_82 : obj := Nat.sub x_81 x_4;
dec x_81;
let x_83 : obj := Nat.sub x_82 x_4;
dec x_82;
let x_84 : obj := Nat.sub x_83 x_4;
dec x_83;
let x_85 : obj := Nat.sub x_84 x_4;
dec x_84;
let x_86 : obj := Nat.sub x_85 x_4;
dec x_85;
let x_87 : obj := Nat.sub x_86 x_4;
dec x_86;
let x_88 : obj := Nat.sub x_87 x_4;
dec x_87;
let x_89 : obj := Nat.sub x_88 x_4;
dec x_88;
let x_90 : obj := Nat.sub x_89 x_4;
dec x_89;
let x_91 : obj := Nat.sub x_90 x_4;
dec x_90;
let x_92 : obj := Nat.sub x_91 x_4;
dec x_91;
let x_93 : obj := Nat.sub x_92 x_4;
dec x_92;
let x_94 : obj := Nat.sub x_93 x_4;
dec x_93;
let x_95 : obj := Nat.sub x_94 x_4;
dec x_94;
let x_96 : obj := Nat.sub x_95 x_4;
dec x_95;
let x_97 : obj := Nat.sub x_96 x_4;
dec x_96;
let x_98 : obj := Nat.sub x_97 x_4;
dec x_97;
let x_99 : obj := Nat.sub x_98 x_4;
dec x_98;
let x_100 : obj := Nat.sub x_99 x_4;
dec x_99;
let x_101 : obj := Nat.sub x_100 x_4;
dec x_100;
let x_102 : u8 := Nat.decEq x_101 x_3;
dec x_101;
case x_102 : u8 of
Bool.false →
let x_103 : obj := 2;
ret x_103
Bool.true →
let x_104 : obj := 1;
ret x_104
def f._boxed (x_1 : obj) : obj :=
let x_2 : u32 := unbox x_1;
dec x_1;
let x_3 : obj := f x_2
-/
set_option trace.compiler.ir.result true in
def f : ({'a', 'b'} : Finset Char) → Nat
| ⟨Char.mk (UInt32.ofBitVec 97) _, _⟩ => 1
| ⟨Char.mk (UInt32.ofBitVec 98) _, _⟩ => 2
/-
function size: 365
matcher size: 2739221
-/
run_cmd do
let f ← Lean.getConstInfo ``f
let matcher ← Lean.getConstInfo ``f.match_1
Lean.logInfo m!"function size: {f.value!.size}\nmatcher size: {matcher.value!.size}"
Aaron Liu (Apr 01 2025 at 13:02):
In contrast, this is not bloat:
import Mathlib
/-
[result]
def f (x_1 : u32) : obj :=
let x_2 : u32 := 97;
let x_3 : u8 := UInt32.decEq x_1 x_2;
case x_3 : u8 of
Bool.false →
let x_4 : obj := 2;
ret x_4
Bool.true →
let x_5 : obj := 1;
ret x_5
def f._boxed (x_1 : obj) : obj :=
let x_2 : u32 := unbox x_1;
dec x_1;
let x_3 : obj := f x_2;
ret x_3
-/
set_option trace.compiler.ir.result true in
def f (x : ({'a', 'b'} : Finset Char)) : Nat :=
if ha : x = 'a' then 1
else if hb : x = 'b' then 2
else False.elim <| by
fin_cases x <;> contradiction
/-
function size: 605
proof size: 43185
-/
run_cmd do
let f ← Lean.getConstInfo ``f
let prf ← Lean.getConstInfo ``f.proof_1
Lean.logInfo m!"function size: {f.value!.size}\nproof size: {prf.value!.size}"
Aaron Liu (Apr 01 2025 at 13:07):
I imagine this works for Finset String
as well
Eric Wieser (Apr 01 2025 at 13:36):
Aaron Liu said:
It's not running any decidable equality procedure, but using dependent elimination to eliminate the remaining cases
{a, b}
invokes decidable equality of a
and b
to reduce to a constructor, so I think decidability is still to blame
Last updated: May 02 2025 at 03:31 UTC