namespace TryCatchWithAutolift structure M (α : Type) where σ : ExceptT String IO α instance : Monad M where pure x := { σ := pure x } bind x f := { σ := do (f (← x.σ)).σ } map f x := { σ := return f (← x.σ) } instance : MonadLiftT IO M where monadLift {α : Type} (act : IO α) : M α := { σ := monadLift act } instance : MonadFinally M where tryFinally' := fun x h => M.mk do tryFinally' x.σ fun e => (h e).σ def t : M Unit := do liftM $ IO.println "bad" try do pure () -- Error catch ex : IO.Error => do pure () finally do pure () instance : MonadExceptOf IO.Error M where throw e := { σ := throwThe IO.Error e } tryCatch x handle := { σ := tryCatchThe IO.Error x.σ fun e => handle e |>.σ } def t2 : M Unit := do liftM $ IO.println "bad" try do pure () catch ex : IO.Error => do pure () finally do pure () end TryCatchWithAutolift