Theorem: Multiset.nodup_bind
File: Mathlib/Data/Multiset/Bind.lean

tactic: have : ∀ a, ∃ l : List β, f a = l := fun a => Quot.induction_on (f a) fun l => ⟨l, rfl⟩
state_before: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s
state_after: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
this : ∀ (a : α), ∃ l, f a = ↑l
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s

tactic: choose f' h' using this
state_before: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
this : ∀ (a : α), ∃ l, f a = ↑l
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s
state_after: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s

tactic: have : f = fun a ↦ ofList (f' a) := funext h'
state_before: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s
state_after: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
this : f = fun a => ↑(f' a)
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s

tactic: have hd : Symmetric fun a b ↦ List.Disjoint (f' a) (f' b) := fun a b h ↦ h.symm
state_before: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
this : f = fun a => ↑(f' a)
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s
state_after: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
this : f = fun a => ↑(f' a)
hd : Symmetric fun a b => (f' a).Disjoint (f' b)
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s

tactic: exact Quot.induction_on s <| by simp [this, List.nodup_bind, pairwise_coe_iff_pairwise hd]
state_before: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
this : f = fun a => ↑(f' a)
hd : Symmetric fun a b => (f' a).Disjoint (f' b)
⊢ (s.bind f).Nodup ↔ (∀ a ∈ s, (f a).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) s
state_after: no goals

tactic: simp [this, List.nodup_bind, pairwise_coe_iff_pairwise hd]
state_before: α : Type u_1
β : Type v
γ : Type u_2
δ : Type u_3
a : α
s t : Multiset α
f g : α → Multiset β
f' : α → List β
h' : ∀ (a : α), f a = ↑(f' a)
this : f = fun a => ↑(f' a)
hd : Symmetric fun a b => (f' a).Disjoint (f' b)
⊢ ∀ (a : List α),
    (bind (Quot.mk Setoid.r a) f).Nodup ↔
      (∀ a_1 ∈ Quot.mk Setoid.r a, (f a_1).Nodup) ∧ Pairwise (fun a b => (f a).Disjoint (f b)) (Quot.mk Setoid.r a)
state_after: no goals