Compare commits

...

12 Commits

Author SHA1 Message Date
Sebastian Graf
51a21895b1 WIP 2025-10-21 09:15:19 +02:00
Sebastian Graf
f5637092cd WIP 2025-10-20 18:49:30 +02:00
Sebastian Graf
e820485dbc chore: typo in docstring for SeqRight 2025-10-20 18:49:21 +02:00
Sebastian Graf
4ce6b57392 chore: add missing spec lemmas for OptionT 2025-10-20 18:49:21 +02:00
Sebastian Graf
d54a68cb8a chore: generalize MonadExceptOf Unit (OptionT m) to MonadExceptOf PUnit (OptionT m) 2025-10-20 12:30:14 +02:00
Sebastian Graf
3048fa2a6e chore: expose Option definitions for proofs 2025-10-20 12:30:12 +02:00
Sebastian Graf
8eaf736764 WIP 2025-10-17 09:05:50 +02:00
Sebastian Graf
40e7873ba1 Nested do blocks 2025-10-16 09:57:38 +02:00
Sebastian Graf
f994332c66 simplifications and comments 2025-10-16 09:44:43 +02:00
Sebastian Graf
03dd86469a Full working duplicable continuations 2025-10-15 18:17:08 +02:00
Sebastian Graf
9e71f23203 WIP 2025-10-15 09:02:37 +02:00
Sebastian Graf
962f2ae6f8 chore: document getLevel 2025-10-13 17:17:06 +02:00
8 changed files with 1804 additions and 19 deletions

View File

@@ -28,7 +28,7 @@ failure occurred.
/--
Executes an action that might fail in the underlying monad `m`, returning `none` in case of failure.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def OptionT.run {m : Type u Type v} {α : Type u} (x : OptionT m α) : m (Option α) :=
x
@@ -70,7 +70,7 @@ instance {m : Type u → Type v} [Pure m] : Inhabited (OptionT m α) where
/--
Recovers from failures. Typically used via the `<|>` operator.
-/
@[always_inline, inline] protected def orElse (x : OptionT m α) (y : Unit OptionT m α) : OptionT m α := OptionT.mk do
@[always_inline, inline, expose] protected def orElse (x : OptionT m α) (y : Unit OptionT m α) : OptionT m α := OptionT.mk do
match ( x) with
| some a => pure (some a)
| _ => y ()
@@ -78,7 +78,7 @@ Recovers from failures. Typically used via the `<|>` operator.
/--
A recoverable failure.
-/
@[always_inline, inline] protected def fail : OptionT m α := OptionT.mk do
@[always_inline, inline, expose] protected def fail : OptionT m α := OptionT.mk do
pure none
instance : Alternative (OptionT m) where
@@ -91,7 +91,7 @@ Converts a computation from the underlying monad into one that could fail, even
This function is typically implicitly accessed via a `MonadLiftT` instance as part of [automatic
lifting](lean-manual://section/monad-lifting).
-/
@[always_inline, inline] protected def lift (x : m α) : OptionT m α := OptionT.mk do
@[always_inline, inline, expose] protected def lift (x : m α) : OptionT m α := OptionT.mk do
return some ( x)
instance : MonadLift m (OptionT m) := OptionT.lift
@@ -101,11 +101,11 @@ instance : MonadFunctor m (OptionT m) := ⟨fun f x => f x⟩
/--
Handles failures by treating them as exceptions of type `Unit`.
-/
@[always_inline, inline] protected def tryCatch (x : OptionT m α) (handle : Unit OptionT m α) : OptionT m α := OptionT.mk do
let some a x | handle ()
@[always_inline, inline, expose] protected def tryCatch (x : OptionT m α) (handle : PUnit OptionT m α) : OptionT m α := OptionT.mk do
let some a x | handle
pure <| some a
instance : MonadExceptOf Unit (OptionT m) where
instance : MonadExceptOf PUnit (OptionT m) where
throw := fun _ => OptionT.fail
tryCatch := OptionT.tryCatch

View File

@@ -3703,7 +3703,7 @@ When thinking about `f` as potential side effects, `*>` evaluates first the left
argument for their side effects, discarding the value of the left argument and returning the value
of the right argument.
For most applications, `Applicative` or `Monad` should be used rather than `SeqLeft` itself.
For most applications, `Applicative` or `Monad` should be used rather than `SeqRight` itself.
-/
class SeqRight (f : Type u Type v) : Type (max (u+1) v) where
/--

View File

@@ -129,6 +129,12 @@ private def inferProjType (structName : Name) (idx : Nat) (e : Expr) : MetaM Exp
def throwTypeExpected {α} (type : Expr) : MetaM α :=
throwError "type expected{indentExpr type}"
/--
If `type : sort` and `sort` reduces to `Sort u` for some `u`, then `getLevel type` returns `u`.
If `sort` is an assignable MVar, then `getLevel type` produces a fresh level metavariable `?u`,
assigns the MVar to `Sort ?u` and returns `?u`.
-/
def getLevel (type : Expr) : MetaM Level := do
let typeType inferType type
let typeType whnfD typeType

View File

@@ -165,6 +165,13 @@ theorem Spec.monadLift_ExceptT [Monad m] [WPMonad m ps] (x : m α) (Q : PostCond
(wpx (fun a => Q.1 a, Q.2.2))
Q := by simp [Triple, SPred.entails.refl]
@[spec]
theorem Spec.monadLift_OptionT [Monad m] [WPMonad m ps] (x : m α) (Q : PostCond α (.except PUnit ps)) :
Triple (ps:=.except PUnit ps)
(MonadLift.monadLift x : OptionT m α)
(wpx (fun a => Q.1 a, Q.2.2))
Q := by simp [Triple, SPred.entails.refl]
/-! # `MonadLiftT` -/
attribute [spec] liftM instMonadLiftTOfMonadLift instMonadLiftT
@@ -186,8 +193,16 @@ theorem Spec.monadMap_ExceptT [Monad m] [WP m ps]
(f : {β}, m β m β) {α} (x : ExceptT ε m α) (Q : PostCond α (.except ε ps)) :
Triple (ps:=.except ε ps)
(MonadFunctor.monadMap (m:=m) f x)
(wpf x.run (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2))
Q := by simp only [Triple, WP.monadMap_ExceptT]; rfl
(wpf x.run (fun e => e.casesOn Q.2.1 Q.1, Q.2.2))
Q := by simp [Triple]
@[spec]
theorem Spec.monadMap_OptionT [Monad m] [WP m ps]
(f : {β}, m β m β) {α} (x : OptionT m α) (Q : PostCond α (.except PUnit ps)) :
Triple (ps:=.except PUnit ps)
(MonadFunctor.monadMap (m:=m) f x)
(wpf x.run (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2))
Q := by simp [Triple]
/-! # `MonadFunctorT` -/
@@ -228,6 +243,14 @@ theorem Spec.liftWith_ExceptT [Monad m] [WPMonad m ps]
(wpf (fun x => x.run) (Q.1, Q.2.2))
Q := by simp [Triple]
@[spec]
theorem Spec.liftWith_OptionT [Monad m] [WPMonad m ps]
(f : ({β}, OptionT m β m (Option β)) m α) :
Triple (ps := .except PUnit ps)
(MonadControl.liftWith (m:=m) f)
(wpf (fun x => x.run) (Q.1, Q.2.2))
Q := by simp [Triple]
@[spec]
theorem Spec.restoreM_StateT [Monad m] [WPMonad m ps] (x : m (α × σ)) :
Triple
@@ -246,8 +269,15 @@ theorem Spec.restoreM_ReaderT [Monad m] [WPMonad m ps] (x : m α) :
theorem Spec.restoreM_ExceptT [Monad m] [WPMonad m ps] (x : m (Except ε α)) :
Triple (ps := .except ε ps)
(MonadControl.restoreM x : ExceptT ε m α)
(wpx (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2))
Q := by simp [Triple]; rfl
(wpx (fun e => e.casesOn Q.2.1 Q.1, Q.2.2))
Q := by simp [Triple]
@[spec]
theorem Spec.restoreM_OptionT [Monad m] [WPMonad m ps] (x : m (Option α)) :
Triple (ps := .except PUnit ps)
(MonadControl.restoreM x : OptionT m α)
(wpx (fun e => e.casesOn (Q.2.1 ) Q.1, Q.2.2))
Q := by simp [Triple]
/-! # `MonadControlT` -/
@@ -362,6 +392,46 @@ theorem Spec.orElse_Except (Q : PostCond α (.except ε .pure)) :
Triple (OrElse.orElse x h : Except ε α) (spred(wpx (Q.1, fun _ => wph () Q, Q.2.2))) spred(Q) := by
simp [Triple]
/-! # `OptionT` -/
@[spec]
theorem Spec.run_OptionT [WP m ps] (x : OptionT m α) :
Triple (ps:=ps)
(x.run : m (Option α))
(wpx (fun a => Q.1 (.some a), fun _ => Q.1 .none, Q.2))
Q := by simp [Triple]
@[spec]
theorem Spec.throw_OptionT [Monad m] [WPMonad m ps] :
Triple (MonadExceptOf.throw e : OptionT m α) (spred(Q.2.1 e)) spred(Q) := by
simp [Triple]
@[spec]
theorem Spec.tryCatch_OptionT [Monad m] [WPMonad m ps] (Q : PostCond α (.except PUnit ps)) :
Triple (MonadExceptOf.tryCatch x h : OptionT m α) (spred(wpx (Q.1, fun e => wph e Q, Q.2.2))) spred(Q) := by
simp [Triple]
@[spec]
theorem Spec.orElse_OptionT [Monad m] [WPMonad m ps] (Q : PostCond α (.except PUnit ps)) :
Triple (OrElse.orElse x h : OptionT m α) (spred(wpx (Q.1, fun _ => wph () Q, Q.2.2))) spred(Q) := by
simp [Triple]
/-! # `Option` -/
@[spec]
theorem Spec.throw_Option [Monad m] [WPMonad m ps] :
Triple (MonadExceptOf.throw e : Option α) (spred(Q.2.1 e)) spred(Q) := SPred.entails.rfl
@[spec]
theorem Spec.tryCatch_Option (Q : PostCond α (.except PUnit .pure)) :
Triple (MonadExceptOf.tryCatch x h : Option α) (spred(wpx (Q.1, fun e => wph e Q, Q.2.2))) spred(Q) := by
simp [Triple]
@[spec]
theorem Spec.orElse_Option (Q : PostCond α (.except PUnit .pure)) :
Triple (OrElse.orElse x h : Option α) (spred(wpx (Q.1, fun _ => wph () Q, Q.2.2))) spred(Q) := by
simp [Triple]
/-! # `EStateM` -/
@[spec]
@@ -431,7 +501,19 @@ theorem Spec.throw_StateT [WP m ps] [Monad m] [MonadExceptOf ε m] (Q : PostCond
theorem Spec.throw_ExceptT_lift [WP m ps] [MonadExceptOf ε m] (Q : PostCond α (.except ε' ps)) :
Triple (ps:=.except ε' ps)
(MonadExceptOf.throw e : ExceptT ε' m α)
(wpMonadExceptOf.throw (ε:=ε) e : m (Except ε' α) (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2))
(wpMonadExceptOf.throw (ε:=ε) e : m (Except ε' α) (fun e => e.casesOn Q.2.1 Q.1, Q.2.2))
Q := by
simp [Triple]
apply (wp _).mono
simp
intro x
split <;> rfl
@[spec]
theorem Spec.throw_Option_lift [WP m ps] [MonadExceptOf ε m] (Q : PostCond α (.except PUnit ps)) :
Triple (ps:=.except PUnit ps)
(MonadExceptOf.throw e : OptionT m α)
(wpMonadExceptOf.throw (ε:=ε) e : m (Option α) (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2))
Q := by
simp [Triple]
apply (wp _).mono
@@ -452,7 +534,20 @@ theorem Spec.tryCatch_ExceptT_lift [WP m ps] [MonadExceptOf ε m] (Q : PostCond
Triple
(ps:=.except ε' ps)
(MonadExceptOf.tryCatch x h : ExceptT ε' m α)
(wpMonadExceptOf.tryCatch (ε:=ε) x h : m (Except ε' α) (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2))
(wpMonadExceptOf.tryCatch (ε:=ε) x h : m (Except ε' α) (fun e => e.casesOn Q.2.1 Q.1, Q.2.2))
Q := by
simp only [Triple]
apply (wp _).mono
simp
intro x
split <;> rfl
@[spec]
theorem Spec.tryCatch_OptionT_lift [WP m ps] [MonadExceptOf ε m] (Q : PostCond α (.except PUnit ps)) :
Triple
(ps:=.except PUnit ps)
(MonadExceptOf.tryCatch x h : OptionT m α)
(wpMonadExceptOf.tryCatch (ε:=ε) x h : m (Option α) (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2))
Q := by
simp only [Triple]
apply (wp _).mono

View File

@@ -44,6 +44,13 @@ theorem ExceptT_run [WP m ps] (x : ExceptT ε m α) :
congr
(ext x; cases x) <;> rfl
@[simp]
theorem OptionT_run [WP m ps] (x : OptionT m α) :
wpx.run Q = wpx (fun a => Q.1 (.some a), fun _ => Q.1 .none, Q.2) := by
simp [wp, OptionT.run]
congr
(ext x; cases x) <;> rfl
/-! ## `WPMonad` -/
@[simp]
@@ -83,6 +90,11 @@ theorem monadLift_ExceptT [Monad m] [WPMonad m ps] (x : m α) (Q : PostCond α (
wpMonadLift.monadLift x : ExceptT ε m α Q = wpx (fun a => Q.1 a, Q.2.2) := by
simp [wp, MonadLift.monadLift, ExceptT.lift, ExceptT.mk]
@[simp]
theorem monadLift_OptionT [Monad m] [WPMonad m ps] (x : m α) (Q : PostCond α (.except PUnit ps)) :
wpMonadLift.monadLift x : OptionT m α Q = wpx (fun a => Q.1 a, Q.2.2) := by
simp [wp, MonadLift.monadLift, OptionT.lift, OptionT.mk]
@[simp]
theorem monadLift_trans [WP o ps] [MonadLift n o] [MonadLiftT m n] :
wpMonadLiftT.monadLift x : o α Q = wpMonadLift.monadLift (m:=n) (MonadLiftT.monadLift (m:=m) x) : o α Q := rfl
@@ -101,6 +113,9 @@ theorem lift_StateT [WP m ps] [Monad m] (x : m α) :
theorem lift_ExceptT [WP m ps] [Monad m] (x : m α) :
wpExceptT.lift x : ExceptT ε m α Q = wpMonadLift.monadLift x : ExceptT ε m α Q := rfl
@[simp]
theorem lift_OptionT [WP m ps] [Monad m] (x : m α) :
wpOptionT.lift x : OptionT m α Q = wpMonadLift.monadLift x : OptionT m α Q := rfl
-- MonadReader
@@ -251,10 +266,17 @@ theorem monadMap_ReaderT [Monad m] [WP m ps]
@[simp]
theorem monadMap_ExceptT [Monad m] [WP m ps]
(f : {β}, m β m β) {α} (x : ExceptT ε m α) (Q : PostCond α (.except ε ps)) :
wpmmap (m:=m) f x Q = wpf x.run (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2) := by
wpmmap (m:=m) f x Q = wpf x.run (fun e => e.casesOn Q.2.1 Q.1, Q.2.2) := by
simp [wp, MonadFunctor.monadMap, ExceptT.run]
congr; ext; split <;> rfl
@[simp]
theorem monadMap_OptionT [Monad m] [WP m ps]
(f : {β}, m β m β) {α} (x : OptionT m α) (Q : PostCond α (.except PUnit ps)) :
wpmmap (m:=m) f x Q = wpf x.run (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2) := by
simp [wp, MonadFunctor.monadMap, OptionT.run]
congr; ext; split <;> rfl
@[simp]
theorem monadMap_trans [WP o ps] [MonadFunctor n o] [MonadFunctorT m n] :
wpMonadFunctorT.monadMap f x : o α Q = wpMonadFunctor.monadMap (m:=n) (MonadFunctorT.monadMap (m:=m) f) x : o α Q := rfl
@@ -308,6 +330,13 @@ theorem liftWith_ExceptT [Monad m] [WPMonad m ps]
-- For some reason, the spec for `liftM` does not apply.
simp [wp, MonadControl.liftWith, ExceptT.run, liftM, monadLift, MonadLift.monadLift, ExceptT.lift, ExceptT.mk]
@[simp]
theorem liftWith_OptionT [Monad m] [WPMonad m ps]
(f : ({β}, OptionT m β m (Option β)) m α) :
wpMonadControl.liftWith (m:=m) f Q = wpf (fun x => x.run) (Q.1, Q.2.2) := by
-- For some reason, the spec for `liftM` does not apply.
simp [wp, MonadControl.liftWith, OptionT.run, liftM, monadLift, MonadLift.monadLift, OptionT.lift, OptionT.mk]
@[simp]
theorem liftWith_trans [WP o ps] [MonadControl n o] [MonadControlT m n]
(f : ({β}, o β m (stM m o β)) m α) :
@@ -330,7 +359,15 @@ theorem restoreM_ReaderT [Monad m] [WPMonad m ps] (x : m α) :
@[simp]
theorem restoreM_ExceptT [Monad m] [WPMonad m ps] (x : m (Except ε α)) :
wpMonadControl.restoreM (m:=m) x : ExceptT ε m α Q = wpx (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2) := by
wpMonadControl.restoreM (m:=m) x : ExceptT ε m α Q = wpx (fun e => e.casesOn Q.2.1 Q.1, Q.2.2) := by
simp [wp, MonadControl.restoreM]
congr
ext
split <;> rfl
@[simp]
theorem restoreM_OptionT [Monad m] [WPMonad m ps] (x : m (Option α)) :
wpMonadControl.restoreM (m:=m) x : OptionT m α Q = wpx (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2) := by
simp [wp, MonadControl.restoreM]
congr
ext
@@ -385,6 +422,16 @@ theorem throw_ExceptT [Monad m] [WPMonad m ps] :
wpMonadExceptOf.throw e : ExceptT ε m α Q = Q.2.1 e := by
simp [wp, MonadExceptOf.throw, ExceptT.mk]
@[simp]
theorem throw_Option :
wpMonadExceptOf.throw e : Option α Q = Q.2.1 e := by
simp [wp, MonadExceptOf.throw, Id.run]
@[simp]
theorem throw_OptionT [Monad m] [WPMonad m ps] :
wpMonadExceptOf.throw e : OptionT m α Q = Q.2.1 e := by
simp [wp, MonadExceptOf.throw, OptionT.fail, OptionT.mk]
@[simp]
theorem throw_EStateM :
wpMonadExceptOf.throw e : EStateM ε σ α Q = Q.2.1 e := by
@@ -402,12 +449,22 @@ theorem throw_StateT [WP m sh] [Monad m] [MonadExceptOf ε m] :
-- for lifting throw
@[simp]
theorem throw_lift_ExceptT [WP m sh] [Monad m] [MonadExceptOf ε m] :
wpMonadExceptOf.throw (ε:=ε) e : ExceptT ε' m α Q = wpMonadExceptOf.throw (ε:=ε) e : m (Except ε' α) (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2) := by
wpMonadExceptOf.throw (ε:=ε) e : ExceptT ε' m α Q = wpMonadExceptOf.throw (ε:=ε) e : m (Except ε' α) (fun e => e.casesOn Q.2.1 Q.1, Q.2.2) := by
simp only [wp, MonadExceptOf.throw, PredTrans.pushExcept_apply]
congr
ext x
split <;> rfl
-- The following lemma is structurally different to StateT and others because of weird definitions
-- for lifting throw
@[simp]
theorem throw_lift_OptionT [WP m sh] [Monad m] [MonadExceptOf ε m] :
wpMonadExceptOf.throw (ε:=ε) e : OptionT m α Q = wpMonadExceptOf.throw (ε:=ε) e : m (Option α) (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2) := by
simp only [wp, MonadExceptOf.throw, PredTrans.pushOption_apply]
congr
ext x
split <;> rfl
@[simp]
theorem tryCatch_MonadExcept [MonadExceptOf ε m] [WP m ps] :
wptryCatch x h : m α Q = wpMonadExceptOf.tryCatch x h : m α Q := rfl
@@ -429,7 +486,22 @@ theorem tryCatch_ExceptT [Monad m] [WPMonad m ps] :
simp only [wp, MonadExceptOf.tryCatch, ExceptT.tryCatch, ExceptT.mk, bind, PredTrans.pushExcept_apply]
congr
ext x
split <;> simp
cases x <;> simp
@[simp]
theorem tryCatch_Option :
wpMonadExceptOf.tryCatch x h : Option α Q = wpx (Q.1, fun e => wph e Q, Q.2.2) := by
simp only [wp, PredTrans.pure, Id.run, MonadExceptOf.tryCatch, Option.tryCatch,
PredTrans.pushOption_apply]
cases x <;> simp
@[simp]
theorem tryCatch_OptionT [Monad m] [WPMonad m ps] :
wpMonadExceptOf.tryCatch x h : OptionT m α Q = wpx (Q.1, fun e => wph e Q, Q.2.2) := by
simp only [wp, MonadExceptOf.tryCatch, OptionT.tryCatch, OptionT.mk, bind, PredTrans.pushOption_apply]
congr
ext x
cases x <;> simp
open EStateM.Backtrackable in
@[simp]
@@ -451,12 +523,20 @@ theorem tryCatch_StateT [WP m sh] [Monad m] [MonadExceptOf ε m] :
@[simp]
theorem tryCatch_lift_ExceptT [WP m sh] [Monad m] [MonadExceptOf ε m] :
wpMonadExceptOf.tryCatch (ε:=ε) x h : ExceptT ε' m α Q = wpMonadExceptOf.tryCatch (ε:=ε) x h : m (Except ε' α) (fun | .ok a => Q.1 a | .error e => Q.2.1 e, Q.2.2) := by
wpMonadExceptOf.tryCatch (ε:=ε) x h : ExceptT ε' m α Q = wpMonadExceptOf.tryCatch (ε:=ε) x h : m (Except ε' α) (fun e => e.casesOn Q.2.1 Q.1, Q.2.2) := by
simp only [wp, MonadExceptOf.tryCatch, tryCatchThe, PredTrans.pushExcept_apply, ExceptT.mk]
congr
ext x
split <;> rfl
@[simp]
theorem tryCatch_lift_OptionT [WP m sh] [Monad m] [MonadExceptOf ε m] :
wpMonadExceptOf.tryCatch (ε:=ε) x h : OptionT m α Q = wpMonadExceptOf.tryCatch (ε:=ε) x h : m (Option α) (fun o => o.casesOn (Q.2.1 ) Q.1, Q.2.2) := by
simp only [wp, MonadExceptOf.tryCatch, tryCatchThe, PredTrans.pushOption_apply, OptionT.mk]
congr
ext x
split <;> rfl
/-
example :
wp (m:= ReaderT Char (StateT Bool (ExceptT Nat Id))) (do set true; throw 42; set false; get) =
@@ -495,4 +575,17 @@ theorem orElse_ExceptT [Monad m] [WPMonad m ps] :
wpOrElse.orElse x h : ExceptT ε m α Q = wpx (Q.1, fun _ => wph () Q, Q.2.2) := by
simp [OrElse.orElse, MonadExcept.orElse]
@[simp]
theorem orElse_Option :
wpOrElse.orElse x h : Option α Q = wpx (Q.1, fun _ => wph () Q, Q.2.2) := by
cases x <;> simp [OrElse.orElse, Option.orElse, wp, Id.run]
@[simp]
theorem orElse_OptionT [Monad m] [WPMonad m ps] :
wpOrElse.orElse x h : OptionT m α Q = wpx (Q.1, fun _ => wph () Q, Q.2.2) := by
simp [OrElse.orElse, Alternative.orElse, OptionT.orElse, OptionT.mk, wp]
congr
ext x
cases x <;> simp
end OrElse

View File

@@ -0,0 +1,108 @@
import Std
variable {ps : Type u}
class TransShape (ps : Type u) where
Assertion : Type u
ExceptConds : Type u
open TransShape (Assertion ExceptConds)
abbrev PostCond (α : Type u) (ps : Type u) [TransShape ps] :=
(α Assertion ps) ×' ExceptConds ps
class TransShape.Entails (ps : Type u) extends TransShape ps where
assertionEntails : Assertion Assertion Prop
exceptCondsEntails : ExceptConds ExceptConds Prop
abbrev TransShape.Entails.postCondEntails [TransShape.Entails ps]
(p q : PostCond α ps) : Prop :=
( a, assertionEntails (p.1 a) (q.1 a)) exceptCondsEntails p.2 q.2
infixr:25 " ⊢ₛ " => TransShape.Entails.assertionEntails
infixr:25 " ⊢ₑ " => TransShape.Entails.exceptCondsEntails
infixr:25 " ⊢ₚ " => TransShape.Entails.postCondEntails
class TransShape.EntailsPre (ps : Type u) extends TransShape.Entails ps where
assertionPreorder : @Std.IsPreorder Assertion assertionEntails
exceptCondsPreorder : @Std.IsPreorder ExceptConds exceptCondsEntails
theorem TransShape.EntailsPre.postCondPreorder [TransShape.EntailsPre ps]
: @Std.IsPreorder (PostCond α ps) TransShape.Entails.postCondEntails :=
let : LE (PostCond α ps) := TransShape.Entails.postCondEntails
let ap := assertionPreorder (ps := ps)
let ep := exceptCondsPreorder (ps := ps)
{ le_refl x := by
constructor
· intro a; apply ap.le_refl
· apply ep.le_refl
, le_trans := by
intro x y z hxy hyz
constructor
· intro a; apply ap.le_trans _ _ _ (hxy.1 a) (hyz.1 a)
· apply ep.le_trans _ _ _ (hxy.2) (hyz.2)
}
/-- The stronger the postcondition, the stronger the transformed precondition. -/
def PredTrans.Monotonic [TransShape.Entails ps] (t : PostCond α ps Assertion ps) : Prop :=
Q₁ Q₂, (Q₁ Q₂) (t Q₁) (t Q₂)
/--
The type of predicate transformers for a given `ps : TransShape` and return type `α : Type`.
A predicate transformer `x : PredTrans ps α` is a function that takes a postcondition
`Q : PostCond α ps` and returns a precondition `x.apply Q : Assertion ps`.
-/
@[ext]
structure PredTrans (ps : Type u) [TransShape.Entails ps] (α : Type u) : Type u where
/-- Apply the predicate transformer to a postcondition. -/
apply : PostCond α ps Assertion ps
mono : PredTrans.Monotonic apply
/-- The predicate transformer is conjunctive: `t (Q₁ ∧ₚ Q₂) ⊣⊢ₛ t Q₁ ∧ t Q₂`.
So the stronger the postcondition, the stronger the resulting precondition. -/
-- conjunctive : PredTrans.Conjunctive apply
structure Prop' : Type u
structure PMF' (α : Type u) : Type u
structure Arg' (σ : Type u) (ps : Type u) : Type u
structure Except' (ε : Type u) (ps : Type u) : Type u
instance : TransShape Prop' where
Assertion := ULift Prop
ExceptConds := PUnit
instance [inst : TransShape ps'] : TransShape (Arg' σ ps') where
Assertion := σ Assertion ps'
ExceptConds := inst.ExceptConds
instance [inst : TransShape ps'] : TransShape (Except' ε ps') where
Assertion := inst.Assertion
ExceptConds := (ε inst.Assertion) ×' inst.ExceptConds
example : Assertion (Arg' σ (Except' ε Prop')) :=
fun s => ULift.up True
example : PostCond α (Arg' σ Prop') :=
fun r s => ULift.up True,
example : PostCond α (Arg' σ (Except' ε Prop')) :=
fun r s => ULift.up True, fun e => ULift.up False,
example : PostCond α (Except' ε (Arg' σ (Except' ε Prop'))) :=
fun r s => ULift.up True, fun e s => ULift.up False, fun e => ULift.up False,
class WP (m : Type u Type v) (ps : outParam (Type u)) extends TransShape ps where
wp : {α}, m α PredTrans ps α
instance : WP Id Prop' := sorry
instance [WP m ps] : WP (StateT σ m) (Arg' σ ps) := sorry
instance [WP m ps] : WP (ExceptT ε m) (Except' ε ps) := sorry
instance : WP (EStateM ε σ) (Except' ε (Arg' σ Prop')) := sorry
def Triple [WP m ps] (x : m α) (P Q : α Assertion ps) := True
theorem spec {α : Type} {ps} [WP m ps] (prog : m α) (P : α Assertion ps) :
Triple prog P P := sorry
#guard_msgs (error) in
#check (spec _ (fun p s => p.1 = p.2 s = 4)
: @Triple (MProd (Option Nat) Nat) (Arg' Nat Prop') _ _ _ _ _)
#check ε σ α s (prog : EStateM ε σ α) (P : σ Prop),
Triple prog (fun s' => s' = s) P P s

1396
tests/lean/run/newdo.lean Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/-!
# Definitional equality on a definition the unfolding of which is stuck on an MVar
-/
namespace One
def Pred (σs : List Type) := match σs with
| [] => Prop
| σ::σs => σ Pred σs
def Blah (x : Nat) := x
def trp {α : Type} {σs : List Type} (P Q : α Pred σs) : Prop := sorry
theorem spec {α : Type} {σs : List Type} {a : α} (P : α Pred σs) :
trp P P := sorry
/--
info: spec fun p s =>
p.fst = some p.snd ∧ s = 4 : trp (fun p s => p.fst = some p.snd ∧ s = 4) fun p s => p.fst = some p.snd ∧ s = 4
-/
#guard_msgs in
#check (spec (σs := [Nat]) (fun p s => p.1 = p.2 s = 4)
: @trp (MProd (Option Nat) Nat) [Nat] _ _)
/-!
This used to have a failure on `(fun p s => p.1 = p.2 ∧ s = 4)` because the definitional equality
?m.547 p → Prop =?= Pred ?m.504
used to return `false` instead of being stuck on `?m.504`.
-/
set_option trace.Meta.isDefEq.stuckMVar true in
/--
error: Application type mismatch: The argument
fun p s => ?m.11 = ?m.13 ∧ s = 4
has type
(p : ?m.5) → ?m.19 p → Prop
but is expected to have type
?m.5 → Pred ?m.6
in the application
spec fun p s => ?m.11 = ?m.13 ∧ s = 4
-/
#guard_msgs (error) in
#check (spec (fun p s => p.1 = p.2 s = 4)
: @trp (MProd (Option Nat) Nat) [Nat] _ _)
end One
namespace I8766
class WP (m : Type Type) (l : outParam Type) where
instance [WP m l] : WP (StateT σ m) (σ l) where
instance : WP (EStateM ε σ) (σ Prop) where
def Triple [WP m l] (x : m α) (P Q : l) := True
/-!
Similarly to the above, reduction of `SPred ?m.1250` is stuck on `?m.1250`.
It will eventually be solved once `WP (EStateM ε σ) [σ]` has been synthesized.
-/
set_option trace.Meta.isDefEq.stuckMVar true in
#guard_msgs (error) in
#check ε σ α s (prog : EStateM ε σ α) (P : σ Prop),
Triple prog (fun s' => s' = s) P P s
end I8766
namespace I87662
class WP (m : Type Type) (l : outParam Type) where
instance [WP m l] : WP (StateT σ m) (σ l) where
instance : WP (EStateM ε σ) (σ Prop) where
def Triple [WP m l] (x : m α) (P Q : l) := True
/-!
Similarly to the above, reduction of `SPred ?m.1250` is stuck on `?m.1250`.
It will eventually be solved once `WP (EStateM ε σ) [σ]` has been synthesized.
-/
set_option trace.Meta.isDefEq.stuckMVar true in
#check ε σ α s (prog : EStateM ε σ α) (P : σ Prop),
Triple prog (fun s' => s' = s) P P s
end I8766