Built with
doc-gen4 , running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+↑ Ctrl+↓ to navigate,
Ctrl+🖱️ to focus.
On Mac, use
Cmd instead of
Ctrl .
/-
Copyright (c) 2019 Simon Hudon. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Simon Hudon
! This file was ported from Lean 3 source module data.fin_enum
! leanprover-community/mathlib commit 9003f28797c0664a49e4179487267c494477d853
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Control.Monad.Basic
import Mathlib.Data.Fintype.Basic
import Mathlib.Data.List.ProdSigma
/-!
Type class for finitely enumerable types. The property is stronger
than `Fintype` in that it assigns each element a rank in a finite
enumeration.
-/
universe u v
open Finset
/- ./././Mathport/Syntax/Translate/Command.lean:379:30:
infer kinds are unsupported in Lean 4: #[`Equiv] [] -/
/-- `FinEnum α` means that `α` is finite and can be enumerated in some order,
i.e. `α` has an explicit bijection with `Fin n` for some n. -/
class FinEnum ( α : Sort _ ) where
/-- `FinEnum.card` is the cardinality of the `FinEnum` -/
card : ℕ
/-- `FinEnum.Equiv` states that type `α` is in bijection with `Fin card`,
the size of the `FinEnum` -/
Equiv : α ≃ Fin card
[ decEq : DecidableEq : Sort ?u.13 → Sort (max1?u.13) DecidableEq α ]
#align fin_enum FinEnum
attribute [ instance 100] FinEnum.decEq
namespace FinEnum
variable { α : Type u } { β : α → Type v }
/-- transport a `FinEnum` instance across an equivalence -/
def ofEquiv ( α ) { β } [ FinEnum α ] ( h : β ≃ α ) : FinEnum β
where
card := card α
Equiv := h . trans : {α : Sort ?u.76} → {β : Sort ?u.75} → {γ : Sort ?u.74} → α ≃ β → β ≃ γ → α ≃ γ trans ( Equiv )
decEq := ( h . trans : {α : Sort ?u.101} → {β : Sort ?u.100} → {γ : Sort ?u.99} → α ≃ β → β ≃ γ → α ≃ γ trans ( Equiv )). decidableEq
#align fin_enum.of_equiv FinEnum.ofEquiv
/-- create a `FinEnum` instance from an exhaustive list without duplicates -/
def ofNodupList [ DecidableEq : Sort ?u.240 → Sort (max1?u.240) DecidableEq α ] ( xs : List α ) ( h : ∀ x : α , x ∈ xs ) ( h' : List.Nodup xs ) : FinEnum : Sort ?u.290 → Sort (max1?u.290) FinEnum α
where
card := xs . length
Equiv :=
⟨ fun x => ⟨ xs . indexOf : {α : Type ?u.326} → [inst : BEq α ] → α → List α → ℕ indexOf x , by rw [ List.indexOf_lt_length ] ; apply h ⟩, fun ⟨ i , h ⟩ =>
xs . nthLe _ h , fun x => by simp , fun ⟨ i , h ⟩ => by
simp [*] ⟩
#align fin_enum.of_nodup_list FinEnum.ofNodupList
/-- create a `FinEnum` instance from an exhaustive list; duplicates are removed -/
def ofList [ DecidableEq : Sort ?u.2715 → Sort (max1?u.2715) DecidableEq α ] ( xs : List α ) ( h : ∀ x : α , x ∈ xs ) : FinEnum : Sort ?u.2760 → Sort (max1?u.2760) FinEnum α :=
ofNodupList xs . dedup ( by simp [*] ) ( List.nodup_dedup _ )
#align fin_enum.of_list FinEnum.ofList
/-- create an exhaustive list of the values of a given type -/
def toList ( α ) [ FinEnum : Sort ?u.5235 → Sort (max1?u.5235) FinEnum α ] : List α :=
( List.finRange ( card α )). map ( Equiv ). symm : {α : Sort ?u.5261} → {β : Sort ?u.5260} → α ≃ β → β ≃ α symm
#align fin_enum.to_list FinEnum.toList
open Function
@[ simp ]
theorem mem_toList [ FinEnum : Sort ?u.5447 → Sort (max1?u.5447) FinEnum α ] ( x : α ) : x ∈ toList α := by
simp [ toList ] ; exists Equiv x ↑Equiv .symm (↑Equiv x ) = x ; ↑Equiv .symm (↑Equiv x ) = x simp
#align fin_enum.mem_to_list FinEnum.mem_toList
@[ simp ]
theorem nodup_toList [ FinEnum : Sort ?u.9188 → Sort (max1?u.9188) FinEnum α ] : List.Nodup ( toList α ) := by
simp [ toList ] ; apply List.Nodup.map <;> [ apply Equiv.injective ; apply List.nodup_finRange ]
#align fin_enum.nodup_to_list FinEnum.nodup_toList
/-- create a `FinEnum` instance using a surjection -/
def ofSurjective { β } ( f : β → α ) [ DecidableEq : Sort ?u.9423 → Sort (max1?u.9423) DecidableEq α ] [ FinEnum : Sort ?u.9432 → Sort (max1?u.9432) FinEnum β ] ( h : Surjective : {α : Sort ?u.9436} → {β : Sort ?u.9435} → (α → β ) → Prop Surjective f ) : FinEnum : Sort ?u.9445 → Sort (max1?u.9445) FinEnum α :=
ofList (( toList β ). map f ) ( by intro ; simp ; exact h _ )
#align fin_enum.of_surjective FinEnum.ofSurjective
/-- create a `FinEnum` instance using an injection -/
noncomputable def ofInjective { α β } ( f : α → β ) [ DecidableEq : Sort ?u.13150 → Sort (max1?u.13150) DecidableEq α ] [ FinEnum : Sort ?u.13159 → Sort (max1?u.13159) FinEnum β ] ( h : Injective : {α : Sort ?u.13163} → {β : Sort ?u.13162} → (α → β ) → Prop Injective f ) :
FinEnum : Sort ?u.13171 → Sort (max1?u.13171) FinEnum α :=
ofList (( toList β ). filterMap ( partialInv : {α : Type ?u.13278} → {β : Sort ?u.13277} → (α → β ) → β → Option α partialInv f ))
( by
intro x
simp only [ mem_toList , true_and_iff , List.mem_filterMap ]
use f x
simp only [ h , Function.partialInv_left ] )
#align fin_enum.of_injective FinEnum.ofInjective
instance pempty : FinEnum : Sort ?u.13742 → Sort (max1?u.13742) FinEnum PEmpty :=
ofList [] fun x => PEmpty.elim x
#align fin_enum.pempty FinEnum.pempty
instance empty : FinEnum : Sort ?u.13937 → Sort (max1?u.13937) FinEnum Empty :=
ofList [] fun x => Empty.elim x
#align fin_enum.empty FinEnum.empty
instance punit : FinEnum : Sort ?u.14099 → Sort (max1?u.14099) FinEnum PUnit :=
ofList [ PUnit.unit ] fun x => by cases x ; simp
#align fin_enum.punit FinEnum.punit
/- ./././Mathport/Syntax/Translate/Expr.lean:177:8: unsupported: ambiguous notation -/
instance prod { β } [ FinEnum : Sort ?u.14369 → Sort (max1?u.14369) FinEnum α ] [ FinEnum : Sort ?u.14372 → Sort (max1?u.14372) FinEnum β ] : FinEnum : Sort ?u.14375 → Sort (max1?u.14375) FinEnum ( α × β ) :=
ofList ( toList α ×ˢ toList β ) fun x => by cases x ; simp
#align fin_enum.prod FinEnum.prod
instance sum { β } [ FinEnum : Sort ?u.17708 → Sort (max1?u.17708) FinEnum α ] [ FinEnum : Sort ?u.17711 → Sort (max1?u.17711) FinEnum β ] : FinEnum : Sort ?u.17714 → Sort (max1?u.17714) FinEnum ( Sum : Type ?u.17716 → Type ?u.17715 → Type (max?u.17716?u.17715) Sum α β ) :=
ofList (( toList α ). map Sum.inl : {α : Type ?u.17820} → {β : Type ?u.17819} → α → α ⊕ β Sum.inl ++ ( toList β ). map Sum.inr : {α : Type ?u.17840} → {β : Type ?u.17839} → β → α ⊕ β Sum.inr) fun x => by cases x <;> simp
#align fin_enum.sum FinEnum.sum
instance fin { n } : FinEnum : Sort ?u.29329 → Sort (max1?u.29329) FinEnum ( Fin n ) :=
ofList ( List.finRange _ ) ( by simp )
#align fin_enum.fin FinEnum.fin
instance Quotient.enum [ FinEnum : Sort ?u.32009 → Sort (max1?u.32009) FinEnum α ] ( s : Setoid : Sort ?u.32012 → Sort (max1?u.32012) Setoid α ) [ DecidableRel : {α : Sort ?u.32015} → (α → α → Prop ) → Sort (max1?u.32015) DecidableRel ( (· ≈ ·) : α → α → Sort ?u.32028 (· ≈ ·) : α → α → Prop )] :
FinEnum : Sort ?u.32058 → Sort (max1?u.32058) FinEnum ( Quotient s ) :=
FinEnum.ofSurjective Quotient.mk'' fun x => Quotient.inductionOn x fun x => ⟨ x , rfl : ∀ {α : Sort ?u.32244} {a : α }, a = a rfl⟩
#align fin_enum.quotient.enum FinEnum.Quotient.enum
/-- enumerate all finite sets of a given type -/
def Finset.enum [ DecidableEq : Sort ?u.32394 → Sort (max1?u.32394) DecidableEq α ] : List α → List ( Finset α )
| [] => [ ∅ ]
| x :: xs => do
let r ← Finset.enum xs
[ r , { x } ∪ r ]
#align fin_enum.finset.enum FinEnum.Finset.enum
@[ simp ]
theorem Finset.mem_enum [ DecidableEq : Sort ?u.33067 → Sort (max1?u.33067) DecidableEq α ] ( s : Finset α ) ( xs : List α ) :
s ∈ Finset.enum xs ↔ ∀ x ∈ s , x ∈ xs := by
induction' xs with xs_hd generalizing s nil cons s ∈ enum (xs_hd :: tail✝ ) ↔ ∀ (x : α ), x ∈ s → x ∈ xs_hd :: tail✝ <;> nil cons s ∈ enum (xs_hd :: tail✝ ) ↔ ∀ (x : α ), x ∈ s → x ∈ xs_hd :: tail✝ simp [*, Finset.enum ] cons (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) ↔ ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝
· nil cons (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) ↔ ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ simp [ Finset.eq_empty_iff_forall_not_mem : ∀ {α : Type ?u.51711} {s : Finset α }, s = ∅ ↔ ∀ (x : α ), ¬ x ∈ s Finset.eq_empty_iff_forall_not_mem]
· cons (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) ↔ ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ cons (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) ↔ ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ constructor cons.mp (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) → ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a )
cons (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) ↔ ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ · cons.mp (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) → ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ cons.mp (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) → ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) rintro ⟨a, h, h'⟩ : (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ⟨a ⟨a, h, h'⟩ : (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) , h : ∀ (x : α ), x ∈ a → x ∈ tail✝ h ⟨a, h, h'⟩ : (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) , h' : s = a ∨ s = {xs_hd } ∪ a h' ⟨a, h, h'⟩ : (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ⟩ x hx
cons.mp (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) → ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ cases' h' : s = a ∨ s = {xs_hd } ∪ a h' with _ h' a b cons.mp.intro.intro.inl cons.mp.intro.intro.inr
cons.mp (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) → ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ · cons.mp.intro.intro.inl cons.mp.intro.intro.inr right cons.mp.intro.intro.inl.h
apply h : ∀ (x : α ), x ∈ a → x ∈ tail✝ h cons.mp.intro.intro.inl.h.a
subst a cons.mp.intro.intro.inl.h.a
exact hx
cons.mp (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) → ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ · simp only [ h' , mem_union , mem_singleton : ∀ {α : Type ?u.52491} {a b : α }, b ∈ {a } ↔ b = a mem_singleton] at hx ⊢
cases' hx with hx hx' cons.mp.intro.intro.inr.inl cons.mp.intro.intro.inr.inr
· cons.mp.intro.intro.inr.inl cons.mp.intro.intro.inr.inl cons.mp.intro.intro.inr.inr exact Or.inl : ∀ {a b : Prop }, a → a ∨ b Or.inl hx
· cons.mp.intro.intro.inr.inr cons.mp.intro.intro.inr.inr exact Or.inr : ∀ {a b : Prop }, b → a ∨ b Or.inr ( h : ∀ (x : α ), x ∈ a → x ∈ tail✝ h _ hx' )
cons (∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) ) ↔ ∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ · cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) intro h cons.mpr ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a )
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) exists s \ ({ xs_hd } : Finset α ) cons.mpr (∀ (x : α ), x ∈ s \ {xs_hd } → x ∈ tail✝ ) ∧ (s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } )
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) simp only [ and_imp : ∀ {a b c : Prop }, a ∧ b → c ↔ a → b → c and_imp, mem_sdiff , mem_singleton : ∀ {α : Type ?u.52982} {a b : α }, b ∈ {a } ↔ b = a mem_singleton] cons.mpr (∀ (x : α ), x ∈ s → ¬ x = xs_hd → x ∈ tail✝ ) ∧ (s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } )
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) simp only [ or_iff_not_imp_left : ∀ {a b : Prop }, a ∨ b ↔ ¬ a → b or_iff_not_imp_left] at h cons.mpr (∀ (x : α ), x ∈ s → ¬ x = xs_hd → x ∈ tail✝ ) ∧ (s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } )
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) exists h : ∀ (x : α ), x ∈ s → ¬ x = xs_hd → x ∈ tail✝ h cons.mpr s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd }
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) by_cases h : xs_hd ∈ s pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd }
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) · pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } have : { xs_hd } ⊆ s this pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd }
pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } simp only [ HasSubset.Subset , *, forall_eq : ∀ {α : Sort ?u.53574} {p : α → Prop } {a' : α }, (∀ (a : α ), a = a' → p a ) ↔ p a' forall_eq, mem_singleton : ∀ {α : Type ?u.53589} {a b : α }, b ∈ {a } ↔ b = a mem_singleton] pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd }
pos s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } simp only [ union_sdiff_of_subset this , or_true_iff , Finset.union_sdiff_of_subset ,
eq_self_iff_true : ∀ {α : Sort ?u.53850} (a : α ), a = a ↔ True eq_self_iff_true]
cons.mpr (∀ (x : α ), x ∈ s → x = xs_hd ∨ x ∈ tail✝ ) → ∃ a , (∀ (x : α ), x ∈ a → x ∈ tail✝ ) ∧ (s = a ∨ s = {xs_hd } ∪ a ) · neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } left
neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } symm
neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } simp only [ sdiff_eq_self ]
neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } intro a
neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } simp only [ and_imp : ∀ {a b c : Prop }, a ∧ b → c ↔ a → b → c and_imp, mem_inter , mem_singleton : ∀ {α : Type ?u.54349} {a b : α }, b ∈ {a } ↔ b = a mem_singleton] neg.h a ∈ s → a = xs_hd → a ∈ ∅
neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } rintro h₀ rfl
neg s = s \ {xs_hd } ∨ s = {xs_hd } ∪ s \ {xs_hd } exact ( h h₀ ). elim
#align fin_enum.finset.mem_enum FinEnum.Finset.mem_enum
instance Finset.finEnum [ FinEnum : Sort ?u.54806 → Sort (max1?u.54806) FinEnum α ] : FinEnum : Sort ?u.54809 → Sort (max1?u.54809) FinEnum ( Finset α ) :=
ofList ( Finset.enum ( toList α )) ( by intro ; simp )
#align fin_enum.finset.fin_enum FinEnum.Finset.finEnum
instance Subtype.finEnum [ FinEnum : Sort ?u.58275 → Sort (max1?u.58275) FinEnum α ] ( p : α → Prop ) [ DecidablePred : {α : Sort ?u.58282} → (α → Prop ) → Sort (max1?u.58282) DecidablePred p ] : FinEnum : Sort ?u.58292 → Sort (max1?u.58292) FinEnum { x // p x } :=
ofList (( toList α ). filterMap fun x => if h : p x then some ⟨ _ , h ⟩ else none )
( by rintro ⟨ x , h ⟩ mk { val := x , property := h } ∈ List.filterMap (fun x => if h : p x then some { val := x , property := h } else none ) (toList α ) ; mk { val := x , property := h } ∈ List.filterMap (fun x => if h : p x then some { val := x , property := h } else none ) (toList α ) simp mk ∃ a , (if h : p a then some { val := a , property := h } else none ) = some { val := x , property := h } ; mk ∃ a , (if h : p a then some { val := a , property := h } else none ) = some { val := x , property := h } exists x mk (if h : p x then some { val := x , property := h } else none ) = some { val := x , property := h } ; mk (if h : p x then some { val := x , property := h } else none ) = some { val := x , property := h } simp [*] )
#align fin_enum.subtype.fin_enum FinEnum.Subtype.finEnum
instance ( β : α → Type v ) [ FinEnum : Sort ?u.64034 → Sort (max1?u.64034) FinEnum α ] [∀ a , FinEnum : Sort ?u.64041 → Sort (max1?u.64041) FinEnum ( β a )] : FinEnum : Sort ?u.64045 → Sort (max1?u.64045) FinEnum ( Sigma : {α : Type ?u.64047} → (α → Type ?u.64046 ) → Type (max?u.64047?u.64046) Sigma β ) :=
ofList (( toList α ). bind fun a => ( toList ( β a )). map <| Sigma.mk : {α : Type ?u.64175} → {β : α → Type ?u.64174 } → (fst : α ) → β fst → Sigma β Sigma.mk a )
( by intro x ; cases x ; simp )
instance PSigma.finEnum [ FinEnum : Sort ?u.70850 → Sort (max1?u.70850) FinEnum α ] [∀ a , FinEnum : Sort ?u.70857 → Sort (max1?u.70857) FinEnum ( β a )] : FinEnum : Sort ?u.70861 → Sort (max1?u.70861) FinEnum (Σ' a , β a ) :=
FinEnum.ofEquiv _ ( Equiv.psigmaEquivSigma : {α : Type ?u.70896} → (β : α → Type ?u.70895 ) → (i : α ) ×' β i ≃ (i : α ) × β i Equiv.psigmaEquivSigma _ : ?m.70897 → Type ?u.70895 _)
#align fin_enum.psigma.fin_enum FinEnum.PSigma.finEnum
instance PSigma.finEnumPropLeft { α : Prop } { β : α → Type v } [∀ a , FinEnum : Sort ?u.71045 → Sort (max1?u.71045) FinEnum ( β a )] [ Decidable α ] :
FinEnum : Sort ?u.71051 → Sort (max1?u.71051) FinEnum (Σ' a , β a ) :=
if h : α then ofList (( toList ( β h )). map <| PSigma.mk : {α : Sort ?u.71176} → {β : α → Sort ?u.71175 } → (fst : α ) → β fst → PSigma β PSigma.mk h ) fun ⟨ a , Ba ⟩ => by simp
else ofList [] fun ⟨ a , Ba ⟩ => ( h a ). elim
#align fin_enum.psigma.fin_enum_prop_left FinEnum.PSigma.finEnumPropLeft
instance PSigma.finEnumPropRight { β : α → Prop } [ FinEnum : Sort ?u.74269 → Sort (max1?u.74269) FinEnum α ] [∀ a , Decidable ( β a )] :
FinEnum : Sort ?u.74279 → Sort (max1?u.74279) FinEnum (Σ' a , β a ) :=
FinEnum.ofEquiv { a // β a }
⟨ fun ⟨ x , y ⟩ => ⟨ x , y ⟩, fun ⟨ x , y ⟩ => ⟨ x , y ⟩, fun ⟨_, _⟩ => rfl : ∀ {α : Sort ?u.74627} {a : α }, a = a rfl, fun ⟨_, _⟩ => rfl : ∀ {α : Sort ?u.74765} {a : α }, a = a rfl⟩
#align fin_enum.psigma.fin_enum_prop_right FinEnum.PSigma.finEnumPropRight
instance PSigma.finEnumPropProp { α : Prop } { β : α → Prop } [ Decidable α ] [∀ a , Decidable ( β a )] :
FinEnum : Sort ?u.75138 → Sort (max1?u.75138) FinEnum (Σ' a , β a ) :=
if h : ∃ a , β a then ofList [⟨ h . fst , h . snd ⟩] ( by ∀ (x : (a : α ) ×' β a ), x ∈ [{ fst := (_ : α ) , snd := (_ : β (_ : α ) ) } ] rintro ⟨⟩ mk { fst := fst✝ , snd := snd✝ } ∈ [{ fst := (_ : α ) , snd := (_ : β (_ : α ) ) } ] ∀ (x : (a : α ) ×' β a ), x ∈ [{ fst := (_ : α ) , snd := (_ : β (_ : α ) ) } ] ; mk { fst := fst✝ , snd := snd✝ } ∈ [{ fst := (_ : α ) , snd := (_ : β (_ : α ) ) } ] ∀ (x : (a : α ) ×' β a ), x ∈ [{ fst := (_ : α ) , snd := (_ : β (_ : α ) ) } ] simp )
else ofList [] fun a => ( h ⟨ a . fst , a . snd : ∀ {α : Sort ?u.75721} {β : α → Sort ?u.75720 } (self : PSigma β ), β (_ : α ) snd⟩). elim
#align fin_enum.psigma.fin_enum_prop_prop FinEnum.PSigma.finEnumPropProp
instance ( priority := 100) [ FinEnum : Sort ?u.76093 → Sort (max1?u.76093) FinEnum α ] : Fintype α where
elems := univ . map ( Equiv ). symm : {α : Sort ?u.76163} → {β : Sort ?u.76162} → α ≃ β → β ≃ α symm . toEmbedding : {α : Sort ?u.76169} → {β : Sort ?u.76168} → α ≃ β → α ↪ β toEmbedding
complete := by intros ; simp
/-- For `Pi.cons x xs y f` create a function where every `i ∈ xs` is mapped to `f i` and
`x` is mapped to `y` -/
def Pi.cons : [inst : DecidableEq α ] → (x : α ) → (xs : List α ) → β x → ((a : α ) → a ∈ xs → β a ) → (a : α ) → a ∈ x :: xs → β a Pi.cons [ DecidableEq : Sort ?u.76508 → Sort (max1?u.76508) DecidableEq α ] ( x : α ) ( xs : List α ) ( y : β x ) ( f : (a : α ) → a ∈ xs → β a f : ∀ a , a ∈ xs → β a ) :
∀ a , a ∈ ( x :: xs : List α ) → β a
| b , h => if h' : b = x then cast : {α β : Sort ?u.76650} → α = β → α → β cast ( by rw [ h' ] ) y else f : (a : α ) → a ∈ xs → β a f b ( List.mem_of_ne_of_mem : ∀ {α : Type ?u.76660} {a y : α } {l : List α }, a ≠ y → a ∈ y :: l → a ∈ l List.mem_of_ne_of_mem h' h )
#align fin_enum.pi.cons FinEnum.Pi.cons : {α : Type u} →
{β : α → Type v } →
[inst : DecidableEq α ] → (x : α ) → (xs : List α ) → β x → ((a : α ) → a ∈ xs → β a ) → (a : α ) → a ∈ x :: xs → β a FinEnum.Pi.cons
/-- Given `f` a function whose domain is `x :: xs`, produce a function whose domain
is restricted to `xs`. -/
def Pi.tail : {x : α } → {xs : List α } → ((a : α ) → a ∈ x :: xs → β a ) → (a : α ) → a ∈ xs → β a Pi.tail { x : α } { xs : List α } ( f : (a : α ) → a ∈ x :: xs → β a f : ∀ a , a ∈ ( x :: xs : List α ) → β a ) : ∀ a , a ∈ xs → β a
| a , h => f : (a : α ) → a ∈ x :: xs → β a f a ( List.mem_cons_of_mem : ∀ {α : Type ?u.77088} (y : α ) {a : α } {l : List α }, a ∈ l → a ∈ y :: l List.mem_cons_of_mem _ h )
#align fin_enum.pi.tail FinEnum.Pi.tail : {α : Type u} → {β : α → Type v } → {x : α } → {xs : List α } → ((a : α ) → a ∈ x :: xs → β a ) → (a : α ) → a ∈ xs → β a FinEnum.Pi.tail
/-- `pi xs f` creates the list of functions `g` such that, for `x ∈ xs`, `g x ∈ f x` -/
def pi { β : α → Type max u v : Type ((maxuv)+1) Type max u v} [ DecidableEq : Sort ?u.77329 → Sort (max1?u.77329) DecidableEq α ] :
∀ xs : List α , (∀ a , List ( β a )) → List (∀ a , a ∈ xs → β a )
| [], _ => [ fun x h => ( List.not_mem_nil : ∀ {α : Type ?u.77433} (a : α ), ¬ a ∈ [] List.not_mem_nil x h ). elim ]
| x :: xs , fs => FinEnum.Pi.cons : {α : Type ?u.77526} →
{β : α → Type ?u.77525 } →
[inst : DecidableEq α ] → (x : α ) → (xs : List α ) → β x → ((a : α ) → a ∈ xs → β a ) → (a : α ) → a ∈ x :: xs → β a FinEnum.Pi.cons x xs <$> fs x <*> pi xs fs
#align fin_enum.pi FinEnum.pi
theorem mem_pi : ∀ {β : α → Type (maxuu_1) } [inst : FinEnum α ] [inst_1 : (a : α ) → FinEnum (β a ) ] (xs