This PR completes support for injective functions in grind. See
examples:
```lean
/-! Add some injectivity theorems. -/
def double (x : Nat) := 2*x
@[grind inj] theorem double_inj : Function.Injective double := by
grind [Function.Injective, double]
structure InjFn (α : Type) (β : Type) where
f : α → β
h : Function.Injective f
instance : CoeFun (InjFn α β) (fun _ => α → β) where
coe s := s.f
@[grind inj] theorem fn_inj (F : InjFn α β) : Function.Injective (F : α → β) := by
grind [Function.Injective, cases InjFn]
def toList (a : α) : List α := [a]
@[grind inj] theorem toList_inj : Function.Injective (toList : α → List α) := by
grind [Function.Injective, toList]
/-! Examples -/
example (x y : Nat) : toList (double x) = toList (double y) → x = y := by
grind
example (f : InjFn (List Nat) α) (x y z : Nat)
: f (toList (double x)) = f (toList y) →
y = double z →
x = z := by
grind
```
41 lines
1.3 KiB
Text
41 lines
1.3 KiB
Text
/-
|
||
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Leonardo de Moura
|
||
-/
|
||
module
|
||
prelude
|
||
public import Init.Data.Function
|
||
public import Init.Classical
|
||
public section
|
||
namespace Lean.Grind
|
||
open Function
|
||
|
||
theorem _root_.Function.Injective.leftInverse
|
||
{α β} (f : α → β) (hf : Injective f) [hα : Nonempty α] :
|
||
∃ g : β → α, LeftInverse g f := by
|
||
classical
|
||
cases hα; next a0 =>
|
||
let g : β → α := fun b =>
|
||
if h : ∃ a, f a = b then Classical.choose h else a0
|
||
exists g
|
||
intro a
|
||
have h : ∃ a', f a' = f a := ⟨a, rfl⟩
|
||
have hfa : f (Classical.choose h) = f a := Classical.choose_spec h
|
||
have : Classical.choose h = a := hf hfa
|
||
simp [g, h, this]
|
||
|
||
noncomputable def leftInv {α : Sort u} {β : Sort v} (f : α → β) (hf : Injective f) [Nonempty α] : β → α :=
|
||
Classical.choose (hf.leftInverse f)
|
||
|
||
theorem leftInv_eq {α : Sort u} {β : Sort v} (f : α → β) (hf : Injective f) [Nonempty α] (a : α) : leftInv f hf (f a) = a :=
|
||
Classical.choose_spec (hf.leftInverse f) a
|
||
|
||
@[app_unexpander leftInv]
|
||
meta def leftInvUnexpander : PrettyPrinter.Unexpander := fun stx => do
|
||
match stx with
|
||
| `($_ $f:term $_) => `($f⁻¹)
|
||
| `($_ $f:term $_ $a:term) => `($f⁻¹ $a)
|
||
| _ => throw ()
|
||
|
||
end Lean.Grind
|