l3lab/ntp-mathlib huggingface dataset:
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ ω✝ γ✝ : Type u
cmd✝ : StateT σ m α✝
next✝ : Label ω✝ (StateT σ m) γ✝ → α✝ → StateT σ m ω✝
⊢ (callCC fun f => cmd✝ >>= next✝ f) = do
    let x ← cmd✝
    callCC fun f => next✝ f x

Next tactic:
simp [callCC, StateT.callCC, callCC_bind_right]
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ ω✝ γ✝ : Type u
cmd✝ : StateT σ m α✝
next✝ : Label ω✝ (StateT σ m) γ✝ → α✝ → StateT σ m ω✝
⊢ (StateT.mk fun r => do
      let x ← StateT.run cmd✝ r
      callCC fun f => StateT.run (next✝ (StateT.mkLabel f) x.fst) x.snd) =
    do
    let x ← cmd✝
    StateT.mk fun r => callCC fun f' => StateT.run (next✝ (StateT.mkLabel f') x) r

Next tactic:
ext
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; 

Proof state:
case h
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ ω✝ γ✝ : Type u
cmd✝ : StateT σ m α✝
next✝ : Label ω✝ (StateT σ m) γ✝ → α✝ → StateT σ m ω✝
s✝ : σ
⊢ StateT.run
      (StateT.mk fun r => do
        let x ← StateT.run cmd✝ r
        callCC fun f => StateT.run (next✝ (StateT.mkLabel f) x.fst) x.snd)
      s✝ =
    StateT.run
      (do
        let x ← cmd✝
        StateT.mk fun r => callCC fun f' => StateT.run (next✝ (StateT.mkLabel f') x) r)
      s✝

Next tactic:
rfl
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
⊢ ∀ {α : Type u} (β : Type u) (x : α) (dead : Label α (StateT σ m) β → β → StateT σ m α),
    (callCC fun f => goto f x >>= dead f) = pure x

Next tactic:
intros
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
x✝ : α✝
dead✝ : Label α✝ (StateT σ m) β✝ → β✝ → StateT σ m α✝
⊢ (callCC fun f => goto f x✝ >>= dead✝ f) = pure x✝

Next tactic:
simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
x✝ : α✝
dead✝ : Label α✝ (StateT σ m) β✝ → β✝ → StateT σ m α✝
⊢ (StateT.mk fun r => pure (x✝, r)) = pure x✝

Next tactic:
ext
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]; ext; 

Proof state:
case h
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
x✝ : α✝
dead✝ : Label α✝ (StateT σ m) β✝ → β✝ → StateT σ m α✝
s✝ : σ
⊢ StateT.run (StateT.mk fun r => pure (x✝, r)) s✝ = StateT.run (pure x✝) s✝

Next tactic:
rfl
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]; ext; rfl
  callCC_dummy := by
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
⊢ ∀ {α β : Type u} (dummy : StateT σ m α), (callCC fun x => dummy) = dummy

Next tactic:
intros
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]; ext; rfl
  callCC_dummy := by
    intros;
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
dummy✝ : StateT σ m α✝
⊢ (callCC fun x => dummy✝) = dummy✝

Next tactic:
simp [callCC, StateT.callCC, callCC_bind_right, @callCC_dummy m _]
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]; ext; rfl
  callCC_dummy := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_right, @callCC_dummy m _]
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
dummy✝ : StateT σ m α✝
⊢ (StateT.mk fun r => StateT.run dummy✝ r) = dummy✝

Next tactic:
ext
instance {σ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (StateT σ m) where
  callCC_bind_right := by
    intros
    simp [callCC, StateT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_left, StateT.goto_mkLabel]; ext; rfl
  callCC_dummy := by
    intros;
    simp [callCC, StateT.callCC, callCC_bind_right, @callCC_dummy m _]
    ext; 

Proof state:
case h
m : Type u → Type v
inst✝² : Monad m
σ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
dummy✝ : StateT σ m α✝
s✝ : σ
⊢ StateT.run (StateT.mk fun r => StateT.run dummy✝ r) s✝ = StateT.run dummy✝ s✝

Next tactic:
rfl
theorem ReaderT.goto_mkLabel {α ρ β} (x : Label α m β) (i : α) :
    goto (ReaderT.mkLabel ρ x) i = monadLift (goto x i) := by 

Proof state:
m : Type u → Type v
inst✝ : Monad m
α : Type u_1
ρ β : Type u
x : Label α m β
i : α
⊢ goto (mkLabel ρ x) i = monadLift (goto x i)

Next tactic:
cases x
theorem ReaderT.goto_mkLabel {α ρ β} (x : Label α m β) (i : α) :
    goto (ReaderT.mkLabel ρ x) i = monadLift (goto x i) := by cases x; 

Proof state:
case mk
m : Type u → Type v
inst✝ : Monad m
α : Type u_1
ρ β : Type u
i : α
apply✝ : α → m β
⊢ goto (mkLabel ρ { apply := apply✝ }) i = monadLift (goto { apply := apply✝ } i)

Next tactic:
rfl
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
⊢ ∀ {α ω γ : Type u} (cmd : ReaderT ρ m α) (next : Label ω (ReaderT ρ m) γ → α → ReaderT ρ m ω),
    (callCC fun f => cmd >>= next f) = do
      let x ← cmd
      callCC fun f => next f x

Next tactic:
intros
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ ω✝ γ✝ : Type u
cmd✝ : ReaderT ρ m α✝
next✝ : Label ω✝ (ReaderT ρ m) γ✝ → α✝ → ReaderT ρ m ω✝
⊢ (callCC fun f => cmd✝ >>= next✝ f) = do
    let x ← cmd✝
    callCC fun f => next✝ f x

Next tactic:
simp [callCC, ReaderT.callCC, callCC_bind_right]
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ ω✝ γ✝ : Type u
cmd✝ : ReaderT ρ m α✝
next✝ : Label ω✝ (ReaderT ρ m) γ✝ → α✝ → ReaderT ρ m ω✝
⊢ (ReaderT.mk fun r => do
      let x ← ReaderT.run cmd✝ r
      callCC fun f => ReaderT.run (next✝ (ReaderT.mkLabel ρ f) x) r) =
    do
    let x ← cmd✝
    ReaderT.mk fun r => callCC fun f' => ReaderT.run (next✝ (ReaderT.mkLabel ρ f') x) r

Next tactic:
ext
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; 

Proof state:
case h
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ ω✝ γ✝ : Type u
cmd✝ : ReaderT ρ m α✝
next✝ : Label ω✝ (ReaderT ρ m) γ✝ → α✝ → ReaderT ρ m ω✝
ctx✝ : ρ
⊢ ReaderT.run
      (ReaderT.mk fun r => do
        let x ← ReaderT.run cmd✝ r
        callCC fun f => ReaderT.run (next✝ (ReaderT.mkLabel ρ f) x) r)
      ctx✝ =
    ReaderT.run
      (do
        let x ← cmd✝
        ReaderT.mk fun r => callCC fun f' => ReaderT.run (next✝ (ReaderT.mkLabel ρ f') x) r)
      ctx✝

Next tactic:
rfl
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
⊢ ∀ {α : Type u} (β : Type u) (x : α) (dead : Label α (ReaderT ρ m) β → β → ReaderT ρ m α),
    (callCC fun f => goto f x >>= dead f) = pure x

Next tactic:
intros
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
x✝ : α✝
dead✝ : Label α✝ (ReaderT ρ m) β✝ → β✝ → ReaderT ρ m α✝
⊢ (callCC fun f => goto f x✝ >>= dead✝ f) = pure x✝

Next tactic:
simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
    

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
x✝ : α✝
dead✝ : Label α✝ (ReaderT ρ m) β✝ → β✝ → ReaderT ρ m α✝
⊢ (ReaderT.mk fun r => pure x✝) = pure x✝

Next tactic:
ext
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
    ext; 

Proof state:
case h
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
x✝ : α✝
dead✝ : Label α✝ (ReaderT ρ m) β✝ → β✝ → ReaderT ρ m α✝
ctx✝ : ρ
⊢ ReaderT.run (ReaderT.mk fun r => pure x✝) ctx✝ = ReaderT.run (pure x✝) ctx✝

Next tactic:
rfl
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
    ext; rfl
  callCC_dummy := by 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
⊢ ∀ {α β : Type u} (dummy : ReaderT ρ m α), (callCC fun x => dummy) = dummy

Next tactic:
intros
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
    ext; rfl
  callCC_dummy := by intros; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
dummy✝ : ReaderT ρ m α✝
⊢ (callCC fun x => dummy✝) = dummy✝

Next tactic:
simp [callCC, ReaderT.callCC, @callCC_dummy m _]
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
    ext; rfl
  callCC_dummy := by intros; simp [callCC, ReaderT.callCC, @callCC_dummy m _]; 

Proof state:
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
dummy✝ : ReaderT ρ m α✝
⊢ (ReaderT.mk fun r => ReaderT.run dummy✝ r) = dummy✝

Next tactic:
ext
instance {ρ} [MonadCont m] [LawfulMonadCont m] : LawfulMonadCont (ReaderT ρ m) where
  callCC_bind_right := by intros; simp [callCC, ReaderT.callCC, callCC_bind_right]; ext; rfl
  callCC_bind_left := by
    intros; simp [callCC, ReaderT.callCC, callCC_bind_left, ReaderT.goto_mkLabel]
    ext; rfl
  callCC_dummy := by intros; simp [callCC, ReaderT.callCC, @callCC_dummy m _]; ext; 

Proof state:
case h
m : Type u → Type v
inst✝² : Monad m
ρ : Type u
inst✝¹ : MonadCont m
inst✝ : LawfulMonadCont m
α✝ β✝ : Type u
dummy✝ : ReaderT ρ m α✝
ctx✝ : ρ
⊢ ReaderT.run (ReaderT.mk fun r => ReaderT.run dummy✝ r) ctx✝ = ReaderT.run dummy✝ ctx✝

Next tactic:
rfl
/-- reduce the equivalence between two continuation passing monads to the equivalence between
their underlying monad -/
def ContT.equiv {m₁ : Type u₀ → Type v₀} {m₂ : Type u₁ → Type v₁} {α₁ r₁ : Type u₀}
    {α₂ r₂ : Type u₁} (F : m₁ r₁ ≃ m₂ r₂) (G : α₁ ≃ α₂) : ContT r₁ m₁ α₁ ≃ ContT r₂ m₂ α₂ where
  toFun f r := F <| f fun x => F.symm <| r <| G x
  invFun f r := F.symm <| f fun x => F <| r <| G.symm x
  left_inv f := by 

Proof state:
m : Type u → Type v
inst✝ : Monad m
m₁ : Type u₀ → Type v₀
m₂ : Type u₁ → Type v₁
α₁ r₁ : Type u₀
α₂ r₂ : Type u₁
F : m₁ r₁ ≃ m₂ r₂
G : α₁ ≃ α₂
f : ContT r₁ m₁ α₁
⊢ (fun f r => F.symm (f fun x => F (r (G.symm x)))) ((fun f r => F (f fun x => F.symm (r (G x)))) f) = f

Next tactic:
funext r
/-- reduce the equivalence between two continuation passing monads to the equivalence between
their underlying monad -/
def ContT.equiv {m₁ : Type u₀ → Type v₀} {m₂ : Type u₁ → Type v₁} {α₁ r₁ : Type u₀}
    {α₂ r₂ : Type u₁} (F : m₁ r₁ ≃ m₂ r₂) (G : α₁ ≃ α₂) : ContT r₁ m₁ α₁ ≃ ContT r₂ m₂ α₂ where
  toFun f r := F <| f fun x => F.symm <| r <| G x
  invFun f r := F.symm <| f fun x => F <| r <| G.symm x
  left_inv f := by funext r; 

Proof state:
case h
m : Type u → Type v
inst✝ : Monad m
m₁ : Type u₀ → Type v₀
m₂ : Type u₁ → Type v₁
α₁ r₁ : Type u₀
α₂ r₂ : Type u₁
F : m₁ r₁ ≃ m₂ r₂
G : α₁ ≃ α₂
f : ContT r₁ m₁ α₁
r : α₁ → m₁ r₁
⊢ (fun f r => F.symm (f fun x => F (r (G.symm x)))) ((fun f r => F (f fun x => F.symm (r (G x)))) f) r = f r

Next tactic:
simp
/-- reduce the equivalence between two continuation passing monads to the equivalence between
their underlying monad -/
def ContT.equiv {m₁ : Type u₀ → Type v₀} {m₂ : Type u₁ → Type v₁} {α₁ r₁ : Type u₀}
    {α₂ r₂ : Type u₁} (F : m₁ r₁ ≃ m₂ r₂) (G : α₁ ≃ α₂) : ContT r₁ m₁ α₁ ≃ ContT r₂ m₂ α₂ where
  toFun f r := F <| f fun x => F.symm <| r <| G x
  invFun f r := F.symm <| f fun x => F <| r <| G.symm x
  left_inv f := by funext r; simp
  right_inv f := by 

Proof state:
m : Type u → Type v
inst✝ : Monad m
m₁ : Type u₀ → Type v₀
m₂ : Type u₁ → Type v₁
α₁ r₁ : Type u₀
α₂ r₂ : Type u₁
F : m₁ r₁ ≃ m₂ r₂
G : α₁ ≃ α₂
f : ContT r₂ m₂ α₂
⊢ (fun f r => F (f fun x => F.symm (r (G x)))) ((fun f r => F.symm (f fun x => F (r (G.symm x)))) f) = f

Next tactic:
funext r
/-- reduce the equivalence between two continuation passing monads to the equivalence between
their underlying monad -/
def ContT.equiv {m₁ : Type u₀ → Type v₀} {m₂ : Type u₁ → Type v₁} {α₁ r₁ : Type u₀}
    {α₂ r₂ : Type u₁} (F : m₁ r₁ ≃ m₂ r₂) (G : α₁ ≃ α₂) : ContT r₁ m₁ α₁ ≃ ContT r₂ m₂ α₂ where
  toFun f r := F <| f fun x => F.symm <| r <| G x
  invFun f r := F.symm <| f fun x => F <| r <| G.symm x
  left_inv f := by funext r; simp
  right_inv f := by funext r; 

Proof state:
case h
m : Type u → Type v
inst✝ : Monad m
m₁ : Type u₀ → Type v₀
m₂ : Type u₁ → Type v₁
α₁ r₁ : Type u₀
α₂ r₂ : Type u₁
F : m₁ r₁ ≃ m₂ r₂
G : α₁ ≃ α₂
f : ContT r₂ m₂ α₂
r : α₂ → m₂ r₂
⊢ (fun f r => F (f fun x => F.symm (r (G x)))) ((fun f r => F.symm (f fun x => F (r (G.symm x)))) f) r = f r

Next tactic:
simp
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
x y : α
⊢ optionCongr (swap x y) = swap (some x) (some y)

Next tactic:
ext (_ | i)
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  ext (_ | i)
  · 

Proof state:
case H.none.a
α : Type u_1
inst✝ : DecidableEq α
x y a✝ : α
⊢ a✝ ∈ (optionCongr (swap x y)) none ↔ a✝ ∈ (swap (some x) (some y)) none

Next tactic:
simp [swap_apply_of_ne_of_ne]
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  ext (_ | i)
  · simp [swap_apply_of_ne_of_ne]
  · 

Proof state:
case H.some.a
α : Type u_1
inst✝ : DecidableEq α
x y i a✝ : α
⊢ a✝ ∈ (optionCongr (swap x y)) (some i) ↔ a✝ ∈ (swap (some x) (some y)) (some i)

Next tactic:
by_cases hx : i = x
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  ext (_ | i)
  · simp [swap_apply_of_ne_of_ne]
  · by_cases hx : i = x
    

Proof state:
case pos
α : Type u_1
inst✝ : DecidableEq α
x y i a✝ : α
hx : i = x
⊢ a✝ ∈ (optionCongr (swap x y)) (some i) ↔ a✝ ∈ (swap (some x) (some y)) (some i)
case neg
α : Type u_1
inst✝ : DecidableEq α
x y i a✝ : α
hx : ¬i = x
⊢ a✝ ∈ (optionCongr (swap x y)) (some i) ↔ a✝ ∈ (swap (some x) (some y)) (some i)

Next tactic:
simp only [hx, optionCongr_apply, Option.map_some', swap_apply_left, Option.mem_def,
             Option.some.injEq]
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  ext (_ | i)
  · simp [swap_apply_of_ne_of_ne]
  · by_cases hx : i = x
    simp only [hx, optionCongr_apply, Option.map_some', swap_apply_left, Option.mem_def,
             Option.some.injEq]
    

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
x y i a✝ : α
hx : ¬i = x
⊢ a✝ ∈ (optionCongr (swap x y)) (some i) ↔ a✝ ∈ (swap (some x) (some y)) (some i)

Next tactic:
by_cases hy : i = y
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  ext (_ | i)
  · simp [swap_apply_of_ne_of_ne]
  · by_cases hx : i = x
    simp only [hx, optionCongr_apply, Option.map_some', swap_apply_left, Option.mem_def,
             Option.some.injEq]
    by_cases hy : i = y <;> 

Proof state:
case pos
α : Type u_1
inst✝ : DecidableEq α
x y i a✝ : α
hx : ¬i = x
hy : i = y
⊢ a✝ ∈ (optionCongr (swap x y)) (some i) ↔ a✝ ∈ (swap (some x) (some y)) (some i)

Next tactic:
simp [hx, hy, swap_apply_of_ne_of_ne]
@[simp]
theorem Equiv.optionCongr_swap {α : Type*} [DecidableEq α] (x y : α) :
    optionCongr (swap x y) = swap (some x) (some y) := by
  ext (_ | i)
  · simp [swap_apply_of_ne_of_ne]
  · by_cases hx : i = x
    simp only [hx, optionCongr_apply, Option.map_some', swap_apply_left, Option.mem_def,
             Option.some.injEq]
    by_cases hy : i = y <;> 

Proof state:
case neg
α : Type u_1
inst✝ : DecidableEq α
x y i a✝ : α
hx : ¬i = x
hy : ¬i = y
⊢ a✝ ∈ (optionCongr (swap x y)) (some i) ↔ a✝ ∈ (swap (some x) (some y)) (some i)

Next tactic:
simp [hx, hy, swap_apply_of_ne_of_ne]
@[simp]
theorem Equiv.optionCongr_sign {α : Type*} [DecidableEq α] [Fintype α] (e : Perm α) :
    Perm.sign e.optionCongr = Perm.sign e := by
  

Proof state:
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
e : Perm α
⊢ Perm.sign (optionCongr e) = Perm.sign e

Next tactic:
refine Perm.swap_induction_on e ?_ ?_
@[simp]
theorem Equiv.optionCongr_sign {α : Type*} [DecidableEq α] [Fintype α] (e : Perm α) :
    Perm.sign e.optionCongr = Perm.sign e := by
  refine Perm.swap_induction_on e ?_ ?_
  · 

Proof state:
case refine_1
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
e : Perm α
⊢ Perm.sign (optionCongr 1) = Perm.sign 1

Next tactic:
simp [Perm.one_def]
@[simp]
theorem Equiv.optionCongr_sign {α : Type*} [DecidableEq α] [Fintype α] (e : Perm α) :
    Perm.sign e.optionCongr = Perm.sign e := by
  refine Perm.swap_induction_on e ?_ ?_
  · simp [Perm.one_def]
  · 

Proof state:
case refine_2
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
e : Perm α
⊢ ∀ (f : Perm α) (x y : α),
    x ≠ y → Perm.sign (optionCongr f) = Perm.sign f → Perm.sign (optionCongr (swap x y * f)) = Perm.sign (swap x y * f)

Next tactic:
intro f x y hne h
@[simp]
theorem Equiv.optionCongr_sign {α : Type*} [DecidableEq α] [Fintype α] (e : Perm α) :
    Perm.sign e.optionCongr = Perm.sign e := by
  refine Perm.swap_induction_on e ?_ ?_
  · simp [Perm.one_def]
  · intro f x y hne h
    

Proof state:
case refine_2
α : Type u_1
inst✝¹ : DecidableEq α
inst✝ : Fintype α
e f : Perm α
x y : α
hne : x ≠ y
h : Perm.sign (optionCongr f) = Perm.sign f
⊢ Perm.sign (optionCongr (swap x y * f)) = Perm.sign (swap x y * f)

Next tactic:
simp [h, hne, Perm.mul_def, ← Equiv.optionCongr_trans]
@[simp]
theorem map_equiv_removeNone {α : Type*} [DecidableEq α] (σ : Perm (Option α)) :
    (removeNone σ).optionCongr = swap none (σ none) * σ := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
σ : Perm (Option α)
⊢ optionCongr (removeNone σ) = swap none (σ none) * σ

Next tactic:
ext1 x
@[simp]
theorem map_equiv_removeNone {α : Type*} [DecidableEq α] (σ : Perm (Option α)) :
    (removeNone σ).optionCongr = swap none (σ none) * σ := by
  ext1 x
  

Proof state:
case H
α : Type u_1
inst✝ : DecidableEq α
σ : Perm (Option α)
x : Option α
⊢ (optionCongr (removeNone σ)) x = (swap none (σ none) * σ) x

Next tactic:
have : Option.map (⇑(removeNone σ)) x = (swap none (σ none)) (σ x) := by
    cases' x with x
    · simp
    · cases h : σ (some _)
      · simp [removeNone_none _ h]
      · have hn : σ (some x) ≠ none := by simp [h]
        have hσn : σ (some x) ≠ σ none := σ.injective.ne (by simp)
        simp [removeNone_some _ ⟨_, h⟩, ← h, swap_apply_of_ne_of_ne hn hσn]
@[simp]
theorem map_equiv_removeNone {α : Type*} [DecidableEq α] (σ : Perm (Option α)) :
    (removeNone σ).optionCongr = swap none (σ none) * σ := by
  ext1 x
  have : Option.map (⇑(removeNone σ)) x = (swap none (σ none)) (σ x) := by
    

Proof state:
α : Type u_1
inst✝ : DecidableEq α
σ : Perm (Option α)
x : Option α
⊢ Option.map (⇑(removeNone σ)) x = (swap none (σ none)) (σ x)

Next tactic:
cases' x with x
@[simp]
theorem map_equiv_removeNone {α : Type*} [DecidableEq α] (σ : Perm (Option α)) :
    (removeNone σ).optionCongr = swap none (σ none) * σ := by
  ext1 x
  have : Option.map (⇑(removeNone σ)) x = (swap none (σ none)) (σ x) := by
    cases' x with x
    · 

Proof state:
case none
α : Type u_1
inst✝ : DecidableEq α
σ : Perm (Option α)
⊢ Option.map (⇑(removeNone σ)) none = (swap none (σ none)) (σ none)

Next tactic:
simp
@[simp]
theorem map_equiv_removeNone {α : Type*} [DecidableEq α] (σ : Perm (Option α)) :
    (removeNone σ).optionCongr = swap none (σ none) * σ := by
  ext1 x
  have : Option.map (⇑(removeNone σ)) x = (swap none (σ none)) (σ x) := by
    cases' x with x
    · simp
    · 

Proof state:
case some
α : Type u_1
inst✝ : DecidableEq α
σ : Perm (Option α)
x : α
⊢ Option.map (⇑(removeNone σ)) (some x) = (swap none (σ none)) (σ (some x))

Next tactic:
cases h : σ (some _)