m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
⊢ SatisfiesM q (Subtype.val <$> x >>= f)
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x
hf : ∀ (a : α), p a → SatisfiesM q (f a)
⊢ SatisfiesM q (x >>= f)
match x, hx with | _, ⟨x, rfl⟩ => ?_
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ SatisfiesM q (Subtype.val <$> x >>= f)
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
⊢ SatisfiesM q (Subtype.val <$> x >>= f)
have g a ha := Classical.indefiniteDescription _ (hf a ha)
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ (Subtype.val <$> do
      let x ← x
      match x with
        | { val := a, property := h } => (g a h).val) =
    Subtype.val <$> x >>= f
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ SatisfiesM q (Subtype.val <$> x >>= f)
refine ⟨x >>= fun ⟨a, h⟩ => g a h, ?_⟩
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ (do
      let x ← x
      let a ← (g x.val (_ : p x.val)).val
      pure a.val) =
    do
    let x ← x
    f x.val
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ (Subtype.val <$> do
      let x ← x
      match x with
        | { val := a, property := h } => (g a h).val) =
    Subtype.val <$> x >>= f
simp [← bind_pure_comp]
case e_a
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ (fun x => do
      let a ← (g x.val (_ : p x.val)).val
      pure a.val) =
    fun x => f x.val
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ (do
      let x ← x
      let a ← (g x.val (_ : p x.val)).val
      pure a.val) =
    do
    let x ← x
    f x.val
congr
case e_a.h
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
a : α
h : p a
⊢ (do
      let a ← (g { val := a, property := h }.val (_ : p { val := a, property := h }.val)).val
      pure a.val) =
    f { val := a, property := h }.val
case e_a
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
⊢ (fun x => do
      let a ← (g x.val (_ : p x.val)).val
      pure a.val) =
    fun x => f x.val
funext ⟨a, h⟩
no goals
case e_a.h
m : Type u_1 → Type u_2
α β : Type u_1
p : α → Prop
x✝ : m α
q : β → Prop
inst✝¹ : Monad m
inst✝ : LawfulMonad m
f : α → m β
hx : SatisfiesM p x✝
hf : ∀ (a : α), p a → SatisfiesM q (f a)
x : m { a // p a }
g : (a : α) → p a → { x // Subtype.val <$> x = f a }
a : α
h : p a
⊢ (do
      let a ← (g { val := a, property := h }.val (_ : p { val := a, property := h }.val)).val
      pure a.val) =
    f { val := a, property := h }.val
simp [← (g a h).2, ← bind_pure_comp]