Based on the discussion at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/for.2C.20unexpected.20need.20for.20type.20ascription/near/269083574 The consensus seemed to be that "auto pure" is more confusing than its worth.
35 lines
905 B
Text
35 lines
905 B
Text
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
|