Introduction
This is the rendered supplement to the paper "‘do’ Unchained: Embracing Local Imperativity in a Purely Functional Language". It contains
- a reference implementation of the described
do
extensions using the Lean 4 macro system (lightly commented) - a Lean formalization of the translation function, the static and dynamic semantics, and the equivalence proof described in the paper in literate style
Basic do
notation
open Lean
declare_syntax_cat stmt
syntax "do'" stmt : term
-- Prevent `if ...` from being parsed as a term
syntax (priority := low) term : stmt
syntax "let" ident "←" stmt:1 ";" stmt : stmt
macro "{" s: TSyntax `stmt
s:stmt "}" : stmt => `($s: TSyntax `stmt
s)
/-
Remark: we annotate `macro`s and `macro_rules` with their corresponding
translation/abbreviation id from the paper.
-/
syntax "d!" stmt : term -- corresponds to `D(s)`
macro_rules
| `(do' $s: TSyntax `stmt
s) => `(d! $s: TSyntax `stmt
s) -- (1)
-- helper function; see usage below
def expandStmt: TSyntax `stmt → MacroM (TSyntax `stmt)
expandStmt (s: TSyntax `stmt
s : TSyntax: SyntaxNodeKinds → Type
TSyntax `stmt: Name
`stmt) : MacroM: Type → Type
MacroM (TSyntax: SyntaxNodeKinds → Type
TSyntax `stmt: Name
`stmt) := do
let s': Syntax
s' ← expandMacros: Syntax → (optParam (SyntaxNodeKind → Bool) fun k => k != `Lean.Parser.Term.byTactic) → MacroM Syntax
expandMacros s: TSyntax `stmt
s
if s: TSyntax `stmt
s == s': Syntax
s' then
Macro.throwUnsupported: {α : Type} → MacroM α
Macro.throwUnsupported
else
-- There is no static guarantee that `expandMacros` stays in the `stmt` category,
-- but it is true for all our macros
return TSyntax.mk: {ks : SyntaxNodeKinds} → Syntax → TSyntax ks
TSyntax.mk s': Syntax
s'
macro_rules
| `(d! $e: TSyntax `term
e:term) => `($e: TSyntax `term
e) -- (D1)
| `(d! let $x: TSyntax `ident
x ← $s: TSyntax `stmt
s; $s': TSyntax `stmt
s') => `((d! $s: TSyntax `stmt
s) >>= fun $x: TSyntax `ident
x => (d! $s': TSyntax `stmt
s')) -- (D2)
| `(d! $s: TSyntax `stmt
s) => do
-- fallback rule: try to expand abbreviation
let s': TSyntax `stmt
s' ← expandStmt: TSyntax `stmt → MacroM (TSyntax `stmt)
expandStmt s: TSyntax `stmt
s
`(d! $s': TSyntax `stmt
s')
macro "let" x: TSyntax `ident
x:ident ":=" e: TSyntax `term
e:term ";" s: TSyntax `stmt
s:stmt : stmt => `(let $x: TSyntax `ident
x ← pure $e: TSyntax `term
e; $s: TSyntax `stmt
s) -- (A1)
-- priority `0` prevents `;` from being used in trailing contexts without braces (see e.g. `:1` above)
macro:0 s₁: TSyntax `stmt
s₁:stmt ";" s₂: TSyntax `stmt
s₂:stmt : stmt => `(let x ← $s₁: TSyntax `stmt
s₁; $s₂: TSyntax `stmt
s₂) -- (A2)
import Do.Basic
import Do.LazyList
Local Mutation
open Lean
Disable the automatic monadic lifting feature described in the paper. We want to make it clear that we do not depend on it.
set_option autoLift false syntax "let" "mut" ident ":=" term ";" stmt : stmt syntax ident ":=" term : stmt syntax "if" term "then" stmt "else" stmt:1 : stmt declare_syntax_cat expander -- generic syntax for traversal-like functions S_y/R/B/L syntax "expand!" expander "in" stmt:1 : stmt syntax "mut" ident : expander -- corresponds to `S_y` -- generic traversal rules macro_rules | `(stmt| expand! $exp in let $exp: TSyntax `expanderx ← $x: TSyntax `idents; $s: TSyntax `stmts') => `(stmt| let $s': TSyntax `stmtx ← expand! $x: TSyntax `identexp in $exp: TSyntax `expanders; expand! $s: TSyntax `stmtexp in $exp: TSyntax `expanders') -- subsumes (R3, B4, L4) | `(stmt| expand! $s': TSyntax `stmtexp in let mut $exp: TSyntax `expanderx := $x: TSyntax `idente; $e: TSyntax `terms') => `(stmt| let mut $s': TSyntax `stmtx := $x: TSyntax `idente; expand! $e: TSyntax `termexp in $exp: TSyntax `expanders') -- subsumes (R4, B5, L5) | `(stmt| expand! $_ in $s': TSyntax `stmtx:ident := $x: TSyntax `idente) => `(stmt| $e: TSyntax `termx:ident := $x: TSyntax `idente) -- subsumes (R5, B6, L6) | `(stmt| expand! $e: TSyntax `termexp in if $exp: TSyntax `expandere then $e: TSyntax `terms₁ else $s₁: TSyntax `stmts₂) => `(stmt| if $s₂: TSyntax `stmte then expand! $e: TSyntax `termexp in $exp: TSyntax `expanders₁ else expand! $s₁: TSyntax `stmtexp in $exp: TSyntax `expanders₂) -- subsumes (S6, R6, B7, L7) | `(stmt| expand! $s₂: TSyntax `stmtexp in $exp: TSyntax `expanders) => do lets: TSyntax `stmts' ←s': TSyntax `stmtexpandStmtexpandStmt: TSyntax `stmt → MacroM (TSyntax `stmt)s `(stmt| expand! $s: TSyntax `stmtexp in $exp: TSyntax `expanders') macro_rules | `(d! let mut $s': TSyntax `stmtx := $x: TSyntax `idente; $e: TSyntax `terms) => `(let $s: TSyntax `stmtx := $x: TSyntax `idente; StateT.run' (d! expand! mut $e: TSyntax `termx in $x: TSyntax `idents) $s: TSyntax `stmtx) -- (D3) | `(d! $x: TSyntax `identx:ident := $_:term) => -- `s!"..."` is an interpolated string. For more information, see https://leanprover.github.io/lean4/doc/stringinterp.html.x: TSyntax `identthrow <|throw: {ε : Type} → {m : Type → Type} → [self : MonadExcept ε m] → {α : Type} → ε → m αMacro.Exception.errorMacro.Exception.error: Syntax → String → Macro.Exceptionx s!"variable '{x: TSyntax `identx.x: TSyntax `identgetId}' is not reassignable in this scope" | `(d! if $getId: Ident → Namee then $e: TSyntax `terms₁ else $s₁: TSyntax `stmts₂) => `(if $s₂: TSyntax `stmte then d! $e: TSyntax `terms₁ else d! $s₁: TSyntax `stmts₂) -- (D4) macro_rules | `(stmt| expand! mut $_ in $s₂: TSyntax `stmte:term) => `(stmt| StateT.lift $e: TSyntax `terme) -- (S1) | `(stmt| expand! mut $e: TSyntax `termy in let $y: TSyntax `identx ← $x: TSyntax `idents; $s: TSyntax `stmts') => -- (S2) ifs': TSyntax `stmtx ==x: TSyntax `identy theny: TSyntax `identthrow <|throw: {ε : Type} → {m : Type → Type} → [self : MonadExcept ε m] → {α : Type} → ε → m αMacro.Exception.errorMacro.Exception.error: Syntax → String → Macro.Exceptionx s!"cannot shadow 'mut' variable '{x: TSyntax `identx.x: TSyntax `identgetId}'" else `(stmt| let $getId: Ident → Namex ← expand! mut $x: TSyntax `identy in $y: TSyntax `idents; let $s: TSyntax `stmty ← get; expand! mut $y: TSyntax `identy in $y: TSyntax `idents') | `(stmt| expand! mut $s': TSyntax `stmty in let mut $y: TSyntax `identx := $x: TSyntax `idente; $e: TSyntax `terms') => -- (S3) ifs': TSyntax `stmtx ==x: TSyntax `identy theny: TSyntax `identthrow <|throw: {ε : Type} → {m : Type → Type} → [self : MonadExcept ε m] → {α : Type} → ε → m αMacro.Exception.errorMacro.Exception.error: Syntax → String → Macro.Exceptionx s!"cannot shadow 'mut' variable '{x: TSyntax `identx.x: TSyntax `identgetId}'" else `(stmt| let mut $getId: Ident → Namex := $x: TSyntax `idente; expand! mut $e: TSyntax `termy in $y: TSyntax `idents') | `(stmt| expand! mut $s': TSyntax `stmty in $y: TSyntax `identx:ident := $x: TSyntax `idente) => ife: TSyntax `termx ==x: TSyntax `identy then `(stmt| set $y: TSyntax `idente) -- (S5) else `(stmt| $e: TSyntax `termx:ident := $x: TSyntax `idente) -- (S4) macro:0 "let" "mut"e: TSyntax `termx:ident "←"x: TSyntax `idents:stmt:1 ";"s: TSyntax `stmts':stmt : stmt => `(let y ← $s': TSyntax `stmts; let mut $s: TSyntax `stmtx := y; $x: TSyntax `idents') -- (A3) macro:0s': TSyntax `stmtx:ident "←"x: TSyntax `idents:stmt:1 : stmt => `(let y ← $s: TSyntax `stmts; $s: TSyntax `stmtx:ident := y) -- (A4) -- a variant of (A4) since we technically cannot make the above macro a `stmt` macro:0x: TSyntax `identx:ident "←"x: TSyntax `idents:stmt:1 ";"s: TSyntax `stmts':stmt : stmt => `(let y ← $s': TSyntax `stmts; $s: TSyntax `stmtx:ident := y; $x: TSyntax `idents') macro "if"s': TSyntax `stmte:term "then"e: TSyntax `terms₁:stmt:1 : stmt => `(if $s₁: TSyntax `stmte then $e: TSyntax `terms₁ else pure ()) -- (A5) macro "unless"s₁: TSyntax `stmte:term "do'"e: TSyntax `terms₂:stmt:1 : stmt => `(if $s₂: TSyntax `stmte then pure () else $e: TSyntax `terms₂) -- (A6) /- The `variable` command instructs Lean to insert the declared variables as bound variables in definitions that refer to them. -/ variable [s₂: TSyntax `stmtMonadMonad: (Type → Type u_1) → Type (max 1 u_1)m] variable (m: Type u_1 → Type u_2mama: m αma' :ma': m αmm: Type u_1 → Type u_2α) /- Mark `map_eq_pure_bind` as a simplification lemma. It is a theorem for `f <$> x = x >>= pure (f a)` -/ attribute [local simp]α: Type ?u.10009map_eq_pure_bind /- Remark: an `example` in Lean is like a "nameless" definition, and it does not update the environment. It is useful for writing tests. -/ /- The instance `[LawfulMonad m]` contains the monadic laws. For more information, see https://github.com/leanprover/lean4/blob/v4.0.0-m4/src/Init/Control/Lawful.lean -/map_eq_pure_bind: ∀ {m : Type u_1 → Type u_2} {α β : Type u_1} [inst : Monad m] [inst_1 : LawfulMonad m] (f : α → β) (x : m α), f <$> x = do let a ← x pure (f a)example [example: ∀ {m : Type u_1 → Type u_2} {α : Type u_1} [inst : Monad m] (ma : m α) [inst_1 : LawfulMonad m], (do let y ← ma let x : α := y StateT.run' (StateT.lift (pure x)) x) = maLawfulMonadLawfulMonad: (m : Type u_1 → Type u_2) → [inst : Monad m] → Propm] : (do' let mutm: Type u_1 → Type u_2x ←x: αma;ma: m αpurepure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αx :x: αmm: Type u_1 → Type u_2α) =α: Type u_1ma :=ma: m αm: Type ?u.10102 → Type ?u.10058
α: Type ?u.10102
inst✝¹: Monad m
ma, ma': m α(do let y ← ma let x : α := y StateT.run' (StateT.lift (pure x)) x) = maGoals accomplished! 🐙example [example: ∀ {m : Type u_1 → Type u_2} {α : Type u_1} [inst : Monad m] (ma ma' : m α) [inst_1 : LawfulMonad m], (do let y ← ma let x : α := y StateT.run' (do let y ← StateT.lift ma' let _ ← get set y let x ← get StateT.lift (pure x)) x) = do let _ ← ma ma'LawfulMonadLawfulMonad: (m : Type u_1 → Type u_2) → [inst : Monad m] → Propm] : (do' let mutm: Type u_1 → Type u_2x ←x: αma; x ←ma: m αma';ma': m αpurepure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αx) = (x: αma >>= fun _ =>ma: m αma') :=ma': m αm: Type ?u.10970 → Type ?u.10750
α: Type ?u.10970
inst✝¹: Monad m
ma, ma': m α(do let y ← ma let x : α := y StateT.run' (do let y ← StateT.lift ma' let _ ← get set y let x ← get StateT.lift (pure x)) x) = do let _ ← ma ma'/- The command `#check_failure <term>` succeeds only if `<term>` fails to be elaborated. -/Goals accomplished! 🐙variable (b :b: BoolBool) -- The following equivalence is true even if `m` does not satisfy the monadic laws.Bool: Typeexample : (do' ifexample: ∀ {m : Type → Type u_1} {α : Type} [inst : Monad m] (ma : m α) (b : Bool), (if b = true then discard ma else pure ()) = if b = true then discard ma else pure ()b then {b: Booldiscarddiscard: {f : Type → Type u_1} → {α : Type} → [inst : Functor f] → f α → f PUnitma }) = (ifma: m αb thenb: Booldiscarddiscard: {f : Type → Type u_1} → {α : Type} → [inst : Functor f] → f α → f PUnitma elsema: m αpure ()) :=pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αrfl theoremrfl: ∀ {α : Type u_1} {a : α}, a = asimple [simple: ∀ [inst : LawfulMonad m], (do let y ← ma let x : α := y StateT.run' (do if b = true then do let y ← StateT.lift ma' let _ ← get set y else StateT.lift (pure ()) let x ← get StateT.lift (pure x)) x) = do let x ← ma if b = true then ma' else pure xLawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] : (do' let mutm: Type → Type u_1x ←x: αma; ifma: m αb then { x ←b: Boolma' };ma': m αpurepure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αx) = (x: αma >>= funma: m αx => ifx: αb thenb: Boolma' elsema': m αpurepure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αx) :=x: αm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool(do let y ← ma let x : α := y StateT.run' (do if b = true then do let y ← StateT.lift ma' let _ ← get set y else StateT.lift (pure ()) let x ← get StateT.lift (pure x)) x) = do let x ← ma if b = true then ma' else pure xm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
false(do let y ← ma let x : α := y StateT.run' (do if false = true then do let y ← StateT.lift ma' let _ ← get set y else StateT.lift (pure ()) let x ← get StateT.lift (pure x)) x) = do let x ← ma if false = true then ma' else pure xm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α(do let y ← ma let x : α := y StateT.run' (do if true = true then do let y ← StateT.lift ma' let _ ← get set y else StateT.lift (pure ()) let x ← get StateT.lift (pure x)) x) = do let x ← ma if true = true then ma' else pure xm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
false(do let y ← ma let x : α := y StateT.run' (do if false = true then do let y ← StateT.lift ma' let _ ← get set y else StateT.lift (pure ()) let x ← get StateT.lift (pure x)) x) = do let x ← ma if false = true then ma' else pure xm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α(do let y ← ma let x : α := y StateT.run' (do if true = true then do let y ← StateT.lift ma' let _ ← get set y else StateT.lift (pure ()) let x ← get StateT.lift (pure x)) x) = do let x ← ma if true = true then ma' else pure xGoals accomplished! 🐙example [example: ∀ {m : Type u_1 → Type u_2} {α : Type u_1} [inst : Monad m] (ma ma' : m α) (b : Bool) [inst_1 : LawfulMonad m] (f : α → α → α), (do let y ← ma let x : α := y StateT.run' (do let y ← if b = true then do let y ← StateT.lift ma let _ ← get set y let _ ← get StateT.lift ma' else StateT.lift ma' let x ← get StateT.lift (pure (f x y))) x) = do let x ← ma if b = true then do let x ← ma let y ← ma' pure (f x y) else do let y ← ma' pure (f x y)LawfulMonadLawfulMonad: (m : Type u_1 → Type u_2) → [inst : Monad m] → Propm] (m: Type u_1 → Type u_2f :f: α → α → αα →α: Type u_1α →α: Type u_1α) : (do' let mutα: Type u_1x ←x: αma; letma: m αy ← ify: αb then { x ←b: Boolma;ma: m αma' } else {ma': m αma' };ma': m αpure (pure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αff: α → α → αxx: αy)) = (y: αma >>= funma: m αx => ifx: αb thenb: Boolma >>= funma: m αx =>x: αma' >>= funma': m αy =>y: αpure (pure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αff: α → α → αxx: αy) elsey: αma' >>= funma': m αy =>y: αpure (pure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αff: α → α → αxx: αy)) :=y: αm: Type ?u.17614 → Type ?u.17083
α: Type ?u.17614
inst✝¹: Monad m
ma, ma': m α
b: Bool
f: α → α → α(do let y ← ma let x : α := y StateT.run' (do let y ← if b = true then do let y ← StateT.lift ma let _ ← get set y let _ ← get StateT.lift ma' else StateT.lift ma' let x ← get StateT.lift (pure (f x y))) x) = do let x ← ma if b = true then do let x ← ma let y ← ma' pure (f x y) else do let y ← ma' pure (f x y)m: Type ?u.17614 → Type ?u.17083
α: Type ?u.17614
inst✝¹: Monad m
ma, ma': m α
f: α → α → α
false(do let y ← ma let x : α := y StateT.run' (do let y ← if false = true then do let y ← StateT.lift ma let _ ← get set y let _ ← get StateT.lift ma' else StateT.lift ma' let x ← get StateT.lift (pure (f x y))) x) = do let x ← ma if false = true then do let x ← ma let y ← ma' pure (f x y) else do let y ← ma' pure (f x y)m: Type ?u.17614 → Type ?u.17083
α: Type ?u.17614
inst✝¹: Monad m
ma, ma': m α
f: α → α → α(do let y ← ma let x : α := y StateT.run' (do let y ← if true = true then do let y ← StateT.lift ma let _ ← get set y let _ ← get StateT.lift ma' else StateT.lift ma' let x ← get StateT.lift (pure (f x y))) x) = do let x ← ma if true = true then do let x ← ma let y ← ma' pure (f x y) else do let y ← ma' pure (f x y)m: Type ?u.17614 → Type ?u.17083
α: Type ?u.17614
inst✝¹: Monad m
ma, ma': m α
f: α → α → α
false(do let y ← ma let x : α := y StateT.run' (do let y ← if false = true then do let y ← StateT.lift ma let _ ← get set y let _ ← get StateT.lift ma' else StateT.lift ma' let x ← get StateT.lift (pure (f x y))) x) = do let x ← ma if false = true then do let x ← ma let y ← ma' pure (f x y) else do let y ← ma' pure (f x y)m: Type ?u.17614 → Type ?u.17083
α: Type ?u.17614
inst✝¹: Monad m
ma, ma': m α
f: α → α → α(do let y ← ma let x : α := y StateT.run' (do let y ← if true = true then do let y ← StateT.lift ma let _ ← get set y let _ ← get StateT.lift ma' else StateT.lift ma' let x ← get StateT.lift (pure (f x y))) x) = do let x ← ma if true = true then do let x ← ma let y ← ma' pure (f x y) else do let y ← ma' pure (f x y)/- Nondeterminism example from Section 2. -/ defGoals accomplished! 🐙choose := @choose: {α : Type u_1} → List α → LazyList αList.toLazy defList.toLazy: {α : Type u_1} → List α → LazyList αex :ex: LazyList NatLazyListLazyList: Type → TypeNat := do' let mutNat: Typex :=x: Nat0; let0: Naty ←y: Natchoose [choose: {α : Type} → List α → LazyList α0,0: Nat1,1: Nat2,2: Nat3]; x :=3: Natx +x: Nat1;1: Natguard (guard: {f : Type → Type} → [inst : Alternative f] → (p : Prop) → [inst : Decidable p] → f Unitx <x: Nat3);3: Natpure (pure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αx +x: Naty) -- Generate all solutionsy: Natex.ex: LazyList NattoListtoList: {α : Type} → LazyList α → List α
LazyList
Nondeterminism Monad
inductiveLazyList (LazyList: Type u → Type uα :α: Type uType u) where |Type u: Type (u + 1)nil :nil: {α : Type u} → LazyList αLazyListLazyList: Type u → Type uα |α: Type ucons (cons: {α : Type u} → α → LazyList α → LazyList αhd :hd: αα) (α: Type utl :tl: LazyList αLazyListLazyList: Type u → Type uα) :α: Type uLazyListLazyList: Type u → Type uα |α: Type udelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αt :t: Thunk (LazyList α)Thunk $Thunk: Type u → Type uLazyListLazyList: Type u → Type uα) :α: Type uLazyListLazyList: Type u → Type uα defα: Type uList.toLazy {List.toLazy: {α : Type u} → List α → LazyList αα :α: Type uType u} :Type u: Type (u + 1)ListList: Type u → Type uα →α: Type uLazyListLazyList: Type u → Type uα | [] =>α: Type uLazyList.nil |LazyList.nil: {α : Type u} → LazyList αh::h: αt =>t: List αLazyList.consLazyList.cons: {α : Type u} → α → LazyList α → LazyList αh (h: αtoLazytoLazy: {α : Type u} → List α → LazyList αt) namespace LazyList variable {t: List αα :α: Type uType u} {Type u: Type (u + 1)β :β: Type vType v} {Type v: Type (v + 1)δ :δ: Type wType w}Type w: Type (w + 1)instance :instance: {α : Type u} → Inhabited (LazyList α)Inhabited (Inhabited: Type u → Type uLazyListLazyList: Type u → Type uα) := ⟨α: Type unil⟩ @[inline] defnil: {α : Type u} → LazyList αpure :pure: α → LazyList αα →α: Type uLazyListLazyList: Type u → Type uα |α: Type ua =>a: αconscons: {α : Type u} → α → LazyList α → LazyList αaa: αnil partial defnil: {α : Type u} → LazyList αisEmpty :isEmpty: LazyList α → BoolLazyListLazyList: Type u → Type uα →α: Type uBool |Bool: Typenil =>nil: {α : Type ?u.1027} → LazyList αtrue |true: Boolcons _ _ =>cons: {α : Type ?u.1036} → α → LazyList α → LazyList αfalse |false: Booldelayeddelayed: {α : Type ?u.1058} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)isEmptyisEmpty: LazyList α → Boolas.as: Thunk (LazyList α)get partial defget: {α : Type u} → Thunk α → αtoList :toList: LazyList α → List αLazyListLazyList: Type u → Type uα →α: Type uListList: Type u → Type uα |α: Type unil =>nil: {α : Type ?u.1187} → LazyList α[] |[]: List αconscons: {α : Type ?u.1199} → α → LazyList α → LazyList αaa: αas =>as: LazyList αa ::a: αtoListtoList: LazyList α → List αas |as: LazyList αdelayeddelayed: {α : Type ?u.1221} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)toListtoList: LazyList α → List αas.as: Thunk (LazyList α)get partial defget: {α : Type u} → Thunk α → αhead [head: {α : Type u} → [inst : Inhabited α] → LazyList α → αInhabitedInhabited: Type u → Type uα] :α: Type uLazyListLazyList: Type u → Type uα →α: Type uα |α: Type unil =>nil: {α : Type ?u.1357} → LazyList αdefault |default: {α : Type u} → [self : Inhabited α] → αconscons: {α : Type ?u.1373} → α → LazyList α → LazyList αaa: α=>a |a: αdelayeddelayed: {α : Type ?u.1393} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)headhead: [inst : Inhabited α] → LazyList α → αas.as: Thunk (LazyList α)get partial defget: {α : Type u} → Thunk α → αtail :tail: {α : Type u} → LazyList α → LazyList αLazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type u → Type uα |α: Type unil =>nil: {α : Type ?u.1530} → LazyList αnil |nil: {α : Type u} → LazyList αconscons: {α : Type ?u.1541} → α → LazyList α → LazyList αas =>as: LazyList αas |as: LazyList αdelayeddelayed: {α : Type ?u.1561} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)tailtail: LazyList α → LazyList αas.as: Thunk (LazyList α)get partial defget: {α : Type u} → Thunk α → αappend :append: {α : Type u} → LazyList α → (Unit → LazyList α) → LazyList αLazyListLazyList: Type u → Type uα → (α: Type uUnit →Unit: TypeLazyListLazyList: Type u → Type uα) →α: Type uLazyListLazyList: Type u → Type uα |α: Type unil,nil: {α : Type ?u.1704} → LazyList αbs =>bs: Unit → LazyList αbsbs: Unit → LazyList α() |(): Unitconscons: {α : Type ?u.1723} → α → LazyList α → LazyList αaa: αas,as: LazyList αbs =>bs: Unit → LazyList αdelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αconscons: {α : Type u} → α → LazyList α → LazyList αa (a: αappendappend: LazyList α → (Unit → LazyList α) → LazyList αasas: LazyList αbs)) |bs: Unit → LazyList αdelayeddelayed: {α : Type ?u.1783} → Thunk (LazyList α) → LazyList αas,as: Thunk (LazyList α)bs =>bs: Unit → LazyList αdelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αappendappend: LazyList α → (Unit → LazyList α) → LazyList αas.as: Thunk (LazyList α)getget: {α : Type u} → Thunk α → αbs)bs: Unit → LazyList αinstance :instance: {α : Type u} → Append (LazyList α)Append (Append: Type u → Type uLazyListLazyList: Type u → Type uα) where appendα: Type uaa: LazyList αb :=b: LazyList αLazyList.appendLazyList.append: {α : Type u} → LazyList α → (Unit → LazyList α) → LazyList αa (fun _ =>a: LazyList αb) partial defb: LazyList αinterleave :interleave: LazyList α → LazyList α → LazyList αLazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type u → Type uα |α: Type unil,nil: {α : Type ?u.2013} → LazyList αbs =>bs: LazyList αbs |bs: LazyList αconscons: {α : Type ?u.2031} → α → LazyList α → LazyList αaa: αas,as: LazyList αbs =>bs: LazyList αdelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αconscons: {α : Type u} → α → LazyList α → LazyList αa (a: αinterleaveinterleave: LazyList α → LazyList α → LazyList αbsbs: LazyList αas)) |as: LazyList αdelayeddelayed: {α : Type ?u.2089} → Thunk (LazyList α) → LazyList αas,as: Thunk (LazyList α)bs =>bs: LazyList αdelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αinterleaveinterleave: LazyList α → LazyList α → LazyList αas.as: Thunk (LazyList α)getget: {α : Type u} → Thunk α → αbs) partial defbs: LazyList αmap (map: (α → β) → LazyList α → LazyList βf :f: α → βα →α: Type uβ) :β: Type vLazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type v → Type vβ |β: Type vnil =>nil: {α : Type ?u.2270} → LazyList αnil |nil: {α : Type v} → LazyList αconscons: {α : Type ?u.2282} → α → LazyList α → LazyList αaa: αas =>as: LazyList αdelayed (delayed: {α : Type v} → Thunk (LazyList α) → LazyList αcons (cons: {α : Type v} → α → LazyList α → LazyList αff: α → βa) (a: αmapmap: (α → β) → LazyList α → LazyList βff: α → βas)) |as: LazyList αdelayeddelayed: {α : Type ?u.2332} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)delayed (delayed: {α : Type v} → Thunk (LazyList α) → LazyList αmapmap: (α → β) → LazyList α → LazyList βff: α → βas.as: Thunk (LazyList α)get) partial defget: {α : Type u} → Thunk α → αmap₂ (map₂: (α → β → δ) → LazyList α → LazyList β → LazyList δf :f: α → β → δα →α: Type uβ →β: Type vδ) :δ: Type wLazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type v → Type vβ →β: Type vLazyListLazyList: Type w → Type wδ |δ: Type wnil, _ =>nil: {α : Type ?u.2498} → LazyList αnil | _,nil: {α : Type w} → LazyList αnil =>nil: {α : Type ?u.2518} → LazyList αnil |nil: {α : Type w} → LazyList αconscons: {α : Type ?u.2536} → α → LazyList α → LazyList αaa: αas,as: LazyList αconscons: {α : Type ?u.2540} → α → LazyList α → LazyList αbb: βbs =>bs: LazyList βdelayed (delayed: {α : Type w} → Thunk (LazyList α) → LazyList αcons (cons: {α : Type w} → α → LazyList α → LazyList αff: α → β → δaa: αb) (b: βmap₂map₂: (α → β → δ) → LazyList α → LazyList β → LazyList δff: α → β → δasas: LazyList αbs)) |bs: LazyList βdelayeddelayed: {α : Type ?u.2607} → Thunk (LazyList α) → LazyList αas,as: Thunk (LazyList α)bs =>bs: LazyList βdelayed (delayed: {α : Type w} → Thunk (LazyList α) → LazyList αmap₂map₂: (α → β → δ) → LazyList α → LazyList β → LazyList δff: α → β → δas.as: Thunk (LazyList α)getget: {α : Type u} → Thunk α → αbs) |bs: LazyList βas,as: LazyList αdelayeddelayed: {α : Type ?u.2644} → Thunk (LazyList α) → LazyList αbs =>bs: Thunk (LazyList β)delayed (delayed: {α : Type w} → Thunk (LazyList α) → LazyList αmap₂map₂: (α → β → δ) → LazyList α → LazyList β → LazyList δff: α → β → δasas: LazyList αbs.bs: Thunk (LazyList β)get) @[inline] defget: {α : Type v} → Thunk α → αzip :zip: LazyList α → LazyList β → LazyList (α × β)LazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type v → Type vβ →β: Type vLazyList (LazyList: Type (max v u) → Type (max v u)α ×α: Type uβ) :=β: Type vmap₂map₂: {α : Type u} → {β : Type v} → {δ : Type (max u v)} → (α → β → δ) → LazyList α → LazyList β → LazyList δProd.mk partial defProd.mk: {α : Type u} → {β : Type v} → α → β → α × βjoin :join: LazyList (LazyList α) → LazyList αLazyList (LazyList: Type u → Type uLazyListLazyList: Type u → Type uα) →α: Type uLazyListLazyList: Type u → Type uα |α: Type unil =>nil: {α : Type ?u.3036} → LazyList αnil |nil: {α : Type u} → LazyList αconscons: {α : Type ?u.3047} → α → LazyList α → LazyList αaa: LazyList αas =>as: LazyList (LazyList α)delayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αappendappend: {α : Type u} → LazyList α → (Unit → LazyList α) → LazyList αa fun _ =>a: LazyList αjoinjoin: LazyList (LazyList α) → LazyList αas) |as: LazyList (LazyList α)delayeddelayed: {α : Type ?u.3102} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList (LazyList α))delayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αjoinjoin: LazyList (LazyList α) → LazyList αas.as: Thunk (LazyList (LazyList α))get) @[inline] partial defget: {α : Type u} → Thunk α → αbind (bind: {α : Type u} → {β : Type v} → LazyList α → (α → LazyList β) → LazyList βx :x: LazyList αLazyListLazyList: Type u → Type uα) (α: Type uf :f: α → LazyList βα →α: Type uLazyListLazyList: Type v → Type vβ) :β: Type vLazyListLazyList: Type v → Type vβ :=β: Type vjoin (join: {α : Type v} → LazyList (LazyList α) → LazyList αx.x: LazyList αmapmap: {α : Type u} → {β : Type v} → (α → β) → LazyList α → LazyList βf)f: α → LazyList βinstance :instance: Monad LazyListMonadMonad: (Type u_1 → Type u_1) → Type (u_1 + 1)LazyList where pure :=LazyList: Type u_1 → Type u_1LazyList.pure bind :=LazyList.pure: {α : Type u_1} → α → LazyList αLazyList.bind map :=LazyList.bind: {α β : Type u_1} → LazyList α → (α → LazyList β) → LazyList βLazyList.mapLazyList.map: {α β : Type u_1} → (α → β) → LazyList α → LazyList βinstance :instance: Alternative LazyListAlternativeAlternative: (Type u_1 → Type u_1) → Type (u_1 + 1)LazyList where failure :=LazyList: Type u_1 → Type u_1nil orElse :=nil: {α : Type u_1} → LazyList αLazyList.append partial defLazyList.append: {α : Type u_1} → LazyList α → (Unit → LazyList α) → LazyList αapprox :approx: Nat → LazyList α → List αNat →Nat: TypeLazyListLazyList: Type u → Type uα →α: Type uListList: Type u → Type uα |α: Type u0,0: Nat=>[] | _,[]: List αnil =>nil: {α : Type ?u.3731} → LazyList α[] |[]: List αi+1,i: Natconscons: {α : Type ?u.3749} → α → LazyList α → LazyList αaa: αas =>as: LazyList αa ::a: αapproxapprox: Nat → LazyList α → List αii: Natas |as: LazyList αi+1,i: Natdelayeddelayed: {α : Type ?u.3839} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)approx (approx: Nat → LazyList α → List αi+i: Nat1)1: Natas.as: Thunk (LazyList α)get partial defget: {α : Type u} → Thunk α → αiterate (iterate: (α → α) → α → LazyList αf :f: α → αα →α: Type uα) :α: Type uα →α: Type uLazyListLazyList: Type u → Type uα |α: Type ux =>x: αconscons: {α : Type u} → α → LazyList α → LazyList αx (x: αdelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αiterateiterate: (α → α) → α → LazyList αf (f: α → αff: α → αx))) partial defx: αiterate₂ (iterate₂: (α → α → α) → α → α → LazyList αf :f: α → α → αα →α: Type uα →α: Type uα) :α: Type uα →α: Type uα →α: Type uLazyListLazyList: Type u → Type uα |α: Type ux,x: αy =>y: αconscons: {α : Type u} → α → LazyList α → LazyList αx (x: αdelayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αiterate₂iterate₂: (α → α → α) → α → α → LazyList αff: α → α → αy (y: αff: α → α → αxx: αy))) partial defy: αfilter (filter: (α → Bool) → LazyList α → LazyList αp :p: α → Boolα →α: Type uBool) :Bool: TypeLazyListLazyList: Type u → Type uα →α: Type uLazyListLazyList: Type u → Type uα |α: Type unil =>nil: {α : Type ?u.4392} → LazyList αnil |nil: {α : Type u} → LazyList αconscons: {α : Type ?u.4403} → α → LazyList α → LazyList αaa: αas =>as: LazyList αdelayed (ifdelayed: {α : Type u} → Thunk (LazyList α) → LazyList αpp: α → Boola thena: αconscons: {α : Type u} → α → LazyList α → LazyList αa (a: αfilterfilter: (α → Bool) → LazyList α → LazyList αpp: α → Boolas) elseas: LazyList αfilterfilter: (α → Bool) → LazyList α → LazyList αpp: α → Boolas) |as: LazyList αdelayeddelayed: {α : Type ?u.4545} → Thunk (LazyList α) → LazyList αas =>as: Thunk (LazyList α)delayed (delayed: {α : Type u} → Thunk (LazyList α) → LazyList αfilterfilter: (α → Bool) → LazyList α → LazyList αpp: α → Boolas.as: Thunk (LazyList α)get) end LazyListget: {α : Type u} → Thunk α → α
import Do.Mut
Early Return
open Lean /- Disable the automatic monadic lifting feature described in the paper. We want to make it clear that we do not depend on it. -/ set_option autoLift false defrunCatch [runCatch: {m : Type u_1 → Type u_2} → {α : Type u_1} → [inst : Monad m] → ExceptT α m α → m αMonadMonad: (Type ?u.9 → Type ?u.8) → Type (max (?u.9 + 1) ?u.8)m] (m: Type u_1 → Type u_2x :x: ExceptT α m αExceptTExceptT: Type u_1 → (Type u_1 → Type u_2) → Type u_1 → Type u_2αα: Type u_1mm: Type u_1 → Type u_2α) :α: Type u_1mm: Type u_1 → Type u_2α :=α: Type u_1ExceptT.runExceptT.run: {ε : Type u_1} → {m : Type u_1 → Type u_2} → {α : Type u_1} → ExceptT ε m α → m (Except ε α)x >>= fun |x: ExceptT α m αExcept.okExcept.ok: {ε : Type ?u.57} → {α : Type ?u.56} → α → Except ε αx =>x: αpurepure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αx |x: αExcept.errorExcept.error: {ε : Type ?u.115} → {α : Type ?u.114} → ε → Except ε αe =>e: αpurepure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αe /-- Count syntax nodes satisfying `p`. -/ partial defe: αLean.Syntax.count (Lean.Syntax.count: Syntax → (Syntax → Bool) → Natstx :stx: SyntaxSyntax) (Syntax: Typep :p: Syntax → BoolSyntax →Syntax: TypeBool) :Bool: TypeNat :=Nat: Typestx.stx: SyntaxgetArgs.getArgs: Syntax → Array Syntaxfoldl (funfoldl: {α β : Type} → (β → α → β) → β → (as : Array α) → optParam Nat 0 → optParam Nat (Array.size as) → βnn: Natarg =>arg: Syntaxn +n: Natarg.arg: Syntaxcountcount: Syntax → (Syntax → Bool) → Natp) (ifp: Syntax → Boolpp: Syntax → Boolstx thenstx: Syntax1 else1: Nat0) syntax "return" term : stmt syntax "return" : expander macro_rules | `(do' $0: Nats) => do -- (1') -- optimization: fall back to original rule (1) if now `return` statement was expanded lets: TSyntax `stmts' ←s': TSyntax `stmtexpandStmtexpandStmt: TSyntax `stmt → MacroM (TSyntax `stmt)(← `(stmt|(← `(stmt| expand! return in $s)): TSyntax `stmtexpand!(← `(stmt| expand! return in $s)): TSyntax `stmt(← `(stmt| expand! return in $s)): TSyntax `stmtreturn(← `(stmt| expand! return in $s)): TSyntax `stmt(← `(stmt| expand! return in $s)): TSyntax `stmtin(← `(stmt| expand! return in $s)): TSyntax `stmt$(← `(stmt| expand! return in $s)): TSyntax `stmtss: TSyntax `stmt)) if(← `(stmt| expand! return in $s)): TSyntax `stmts'.s': TSyntax `stmtraw.raw: {ks : SyntaxNodeKinds} → TSyntax ks → Syntaxcount (· matches `(stmt| return $_)) ==count: Syntax → (Syntax → Bool) → Nats.s: TSyntax `stmtraw.raw: {ks : SyntaxNodeKinds} → TSyntax ks → Syntaxcount (· matches `(stmt| return $_)) then `(d! $count: Syntax → (Syntax → Bool) → Nats) else `(ExceptCpsT.runCatch (d! $s: TSyntax `stmts')) macro_rules | `(stmt| expand! return in return $s': TSyntax `stmte) => `(stmt| throw $e: TSyntax `terme) -- (R1) | `(stmt| expand! return in $e: TSyntax `terme:term) => `(stmt| ExceptCpsT.lift $e: TSyntax `terme) -- (R2) variable [e: TSyntax `termMonadMonad: (Type ?u.3135 → Type ?u.3134) → Type (max (?u.3135 + 1) ?u.3134)m] variable (m: Type ?u.2574 → Type ?u.2573mama: m αma' :ma': m αmm: Type ?u.2585 → Type ?u.2584α) variable (α: Type ?u.2585b :b: BoolBool)Bool: Typeexample [example: ∀ {m : Type u_1 → Type u_2} {α : Type u_1} [inst : Monad m] (ma : m α) [inst_1 : LawfulMonad m], (ExceptCpsT.runCatch do let x ← ExceptCpsT.lift ma throw x) = maLawfulMonadLawfulMonad: (m : Type u_1 → Type u_2) → [inst : Monad m] → Propm] : (do' letm: Type u_1 → Type u_2x ←x: αma; returnma: m αx) =x: αma :=ma: m αm: Type ?u.2639 → Type ?u.2638
α: Type ?u.2639
inst✝¹: Monad m
ma, ma': m α
b: Bool(ExceptCpsT.runCatch do let x ← ExceptCpsT.lift ma throw x) = maGoals accomplished! 🐙example :example: Id.run (ExceptCpsT.runCatch do let x ← ExceptCpsT.lift (pure 1) throw x) = 1Id.run (do' letId.run: {α : Type} → Id α → αx :=x: Nat1; return1: Natx) =x: Nat1 :=1: Natrflrfl: ∀ {α : Type} {a : α}, a = aexample [example: ∀ {m : Type → Type u_1} {α : Type} [inst : Monad m] (ma ma' : m α) (b : Bool) [inst_1 : LawfulMonad m], (ExceptCpsT.runCatch do if b = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift (pure ()) ExceptCpsT.lift ma') = if b = true then ma else ma'LawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] : (do' ifm: Type → Type u_1b then { letb: Boolx ←x: αma; returnma: m αx };x: αma') = (ifma': m αb thenb: Boolma elsema: m αma') :=ma': m αm: Type → Type ?u.3364
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool(ExceptCpsT.runCatch do if b = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift (pure ()) ExceptCpsT.lift ma') = if b = true then ma else ma'm: Type → Type ?u.3364
α: Type
inst✝¹: Monad m
ma, ma': m α
false(ExceptCpsT.runCatch do if false = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift (pure ()) ExceptCpsT.lift ma') = if false = true then ma else ma'm: Type → Type ?u.3364
α: Type
inst✝¹: Monad m
ma, ma': m α(ExceptCpsT.runCatch do if true = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift (pure ()) ExceptCpsT.lift ma') = if true = true then ma else ma'm: Type → Type ?u.3364
α: Type
inst✝¹: Monad m
ma, ma': m α
false(ExceptCpsT.runCatch do if false = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift (pure ()) ExceptCpsT.lift ma') = if false = true then ma else ma'm: Type → Type ?u.3364
α: Type
inst✝¹: Monad m
ma, ma': m α(ExceptCpsT.runCatch do if true = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift (pure ()) ExceptCpsT.lift ma') = if true = true then ma else ma'Goals accomplished! 🐙example [example: ∀ {m : Type u_1 → Type u_2} {α : Type u_1} [inst : Monad m] (ma ma' : m α) (b : Bool) [inst_1 : LawfulMonad m], (ExceptCpsT.runCatch do let y ← if b = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift ma' ExceptCpsT.lift (pure y)) = if b = true then ma else ma'LawfulMonadLawfulMonad: (m : Type u_1 → Type u_2) → [inst : Monad m] → Propm] : (do' letm: Type u_1 → Type u_2y ← ify: αb then { letb: Boolx ←x: αma; returnma: m αx } else {x: αma' };ma': m αpurepure: {f : Type u_1 → Type u_2} → [self : Pure f] → {α : Type u_1} → α → f αy) = (ify: αb thenb: Boolma elsema: m αma') :=ma': m αm: Type ?u.4867 → Type ?u.4866
α: Type ?u.4867
inst✝¹: Monad m
ma, ma': m α
b: Bool(ExceptCpsT.runCatch do let y ← if b = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift ma' ExceptCpsT.lift (pure y)) = if b = true then ma else ma'm: Type ?u.4867 → Type ?u.4866
α: Type ?u.4867
inst✝¹: Monad m
ma, ma': m α
false(ExceptCpsT.runCatch do let y ← if false = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift ma' ExceptCpsT.lift (pure y)) = if false = true then ma else ma'm: Type ?u.4867 → Type ?u.4866
α: Type ?u.4867
inst✝¹: Monad m
ma, ma': m α(ExceptCpsT.runCatch do let y ← if true = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift ma' ExceptCpsT.lift (pure y)) = if true = true then ma else ma'm: Type ?u.4867 → Type ?u.4866
α: Type ?u.4867
inst✝¹: Monad m
ma, ma': m α
false(ExceptCpsT.runCatch do let y ← if false = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift ma' ExceptCpsT.lift (pure y)) = if false = true then ma else ma'm: Type ?u.4867 → Type ?u.4866
α: Type ?u.4867
inst✝¹: Monad m
ma, ma': m α(ExceptCpsT.runCatch do let y ← if true = true then do let x ← ExceptCpsT.lift ma throw x else ExceptCpsT.lift ma' ExceptCpsT.lift (pure y)) = if true = true then ma else ma'Goals accomplished! 🐙
import Do.Return
Iteration
open Lean /- Disable the automatic monadic lifting feature described in the paper. We want to make it clear that we do not depend on it. -/ set_option autoLift false syntax "for" ident "in" term "do'" stmt:1 : stmt syntax "break " : stmt syntax "continue " : stmt syntax "break" : expander syntax "continue" : expander syntax "lift" : expander macro_rules | `(stmt| expand! $_ in break) =>`(stmt|`(stmt| break): MacroM Syntaxbreak`(stmt| break): MacroM Syntax) -- subsumes (S7, R7, B2, L1) | `(stmt| expand! $_ in continue) =>`(stmt| break): MacroM Syntax`(stmt|`(stmt| continue): MacroM Syntaxcontinue`(stmt| continue): MacroM Syntax) -- subsumes (S8, R8, L2) | `(stmt| expand! $`(stmt| continue): MacroM Syntaxexp in for $exp: TSyntax `expanderx in $x: TSyntax `idente do' $e: TSyntax `terms) => `(stmt| for $s: TSyntax `stmtx in $x: TSyntax `idente do' expand! $e: TSyntax `termexp in $exp: TSyntax `expanders) -- subsumes (L8, R9) macro_rules | `(d! for $s: TSyntax `stmtx in $x: TSyntax `idente do' $e: TSyntax `terms) => do -- (D5), optimized like (1') let muts: TSyntax `stmts :=s: TSyntax `stmts lets: TSyntax `stmtsb ←sb: TSyntax `stmtexpandStmtexpandStmt: TSyntax `stmt → MacroM (TSyntax `stmt)(← `(stmt|(← `(stmt| expand! break in $s)): TSyntax `stmtexpand!(← `(stmt| expand! break in $s)): TSyntax `stmt(← `(stmt| expand! break in $s)): TSyntax `stmtbreak(← `(stmt| expand! break in $s)): TSyntax `stmt(← `(stmt| expand! break in $s)): TSyntax `stmtin(← `(stmt| expand! break in $s)): TSyntax `stmt$(← `(stmt| expand! break in $s)): TSyntax `stmtss: TSyntax `stmt)) let(← `(stmt| expand! break in $s)): TSyntax `stmthasBreak :=hasBreak: Propsb.sb: TSyntax `stmtraw.raw: {ks : SyntaxNodeKinds} → TSyntax ks → Syntaxcount (· matches `(stmt| break)) <count: Syntax → (Syntax → Bool) → Nats.s: TSyntax `stmtraw.raw: {ks : SyntaxNodeKinds} → TSyntax ks → Syntaxcount (· matches `(stmt| break)) ifcount: Syntax → (Syntax → Bool) → NathasBreak thenhasBreak: Props :=s: TSyntax `stmtsb letsb: TSyntax `stmtsc ←sc: TSyntax `stmtexpandStmtexpandStmt: TSyntax `stmt → MacroM (TSyntax `stmt)(← `(stmt|(← `(stmt| expand! continue in $s)): TSyntax `stmtexpand!(← `(stmt| expand! continue in $s)): TSyntax `stmt(← `(stmt| expand! continue in $s)): TSyntax `stmtcontinue(← `(stmt| expand! continue in $s)): TSyntax `stmt(← `(stmt| expand! continue in $s)): TSyntax `stmtin(← `(stmt| expand! continue in $s)): TSyntax `stmt$(← `(stmt| expand! continue in $s)): TSyntax `stmtss: TSyntax `stmt)) let(← `(stmt| expand! continue in $s)): TSyntax `stmthasContinue :=hasContinue: Propsc.sc: TSyntax `stmtraw.raw: {ks : SyntaxNodeKinds} → TSyntax ks → Syntaxcount (· matches `(stmt| continue)) <count: Syntax → (Syntax → Bool) → Nats.s: TSyntax `stmtraw.raw: {ks : SyntaxNodeKinds} → TSyntax ks → Syntaxcount (· matches `(stmt| continue)) ifcount: Syntax → (Syntax → Bool) → NathasContinue thenhasContinue: Props :=s: TSyntax `stmtsc let mutsc: TSyntax `stmtbody ← `(d! $body: TSyntax `terms) ifs: TSyntax `stmthasContinue thenhasContinue: Propbody ← `(ExceptCpsT.runCatch $body: TSyntax `termbody) let mutbody: TSyntax `termloop ← `(forM $loop: TSyntax `terme (fun $e: TSyntax `termx => $x: TSyntax `identbody)) ifbody: TSyntax `termhasBreak thenhasBreak: Proploop ← `(ExceptCpsT.runCatch $loop: TSyntax `termloop)loop: TSyntax `termpurepure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αloop | `(d! break%$loop: TSyntax `termb) =>b: Syntaxthrow <|throw: {ε : Type} → {m : Type → Type} → [self : MonadExcept ε m] → {α : Type} → ε → m αMacro.Exception.errorMacro.Exception.error: Syntax → String → Macro.Exceptionbb: Syntax"unexpected 'break' outside loop" | `(d! continue%$"unexpected 'break' outside loop": Stringc) =>c: Syntaxthrow <|throw: {ε : Type} → {m : Type → Type} → [self : MonadExcept ε m] → {α : Type} → ε → m αMacro.Exception.errorMacro.Exception.error: Syntax → String → Macro.Exceptioncc: Syntax"unexpected 'continue' outside loop" macro_rules | `(stmt| expand! break in break) =>"unexpected 'continue' outside loop": String`(stmt| throw ()) -- (B1) | `(stmt| expand! break in $`(stmt| throw ()): MacroM Syntaxe:term) => `(stmt| ExceptCpsT.lift $e: TSyntax `terme) -- (B3) | `(stmt| expand! break in for $e: TSyntax `termx in $x: TSyntax `idente do' $e: TSyntax `terms) => `(stmt| for $s: TSyntax `stmtx in $x: TSyntax `idente do' expand! lift in $e: TSyntax `terms) -- (B8) | `(stmt| expand! continue in continue) =>s: TSyntax `stmt`(stmt| throw ()) | `(stmt| expand! continue in $`(stmt| throw ()): MacroM Syntaxe:term) => `(stmt| ExceptCpsT.lift $e: TSyntax `terme) | `(stmt| expand! continue in for $e: TSyntax `termx in $x: TSyntax `idente do' $e: TSyntax `terms) => `(stmt| for $s: TSyntax `stmtx in $x: TSyntax `idente do' expand! lift in $e: TSyntax `terms) macro_rules | `(stmt| expand! lift in $s: TSyntax `stmte:term) => `(stmt| ExceptCpsT.lift $e: TSyntax `terme) -- (L3) macro_rules | `(stmt| expand! mut $e: TSyntax `termy in for $y: TSyntax `identx in $x: TSyntax `idente do' $e: TSyntax `terms) => `(stmt| for $s: TSyntax `stmtx in $x: TSyntax `idente do' { let $e: TSyntax `termy ← get; expand! mut $y: TSyntax `identy in $y: TSyntax `idents }) -- (S9) variable [s: TSyntax `stmtMonadMonad: (Type ?u.36846 → Type ?u.36845) → Type (max (?u.36846 + 1) ?u.36845)m] variable (m: Type ?u.7311 → Type ?u.7310mama: m αma' :ma': m αmm: Type ?u.7322 → Type ?u.7321α) variable (α: Typeb :b: BoolBool) variable (Bool: Typexs :xs: List αListList: Type → Typeα) (α: Typeact :act: α → m Unitα →α: Typemm: Type → Type u_1Unit) attribute [local simp]Unit: Typemap_eq_pure_bindmap_eq_pure_bind: ∀ {m : Type u_1 → Type u_2} {α β : Type u_1} [inst : Monad m] [inst_1 : LawfulMonad m] (f : α → β) (x : m α), f <$> x = do let a ← x pure (f a)example [example: ∀ {m : Type → Type u_1} {α : Type} [inst : Monad m] (xs : List α) (act : α → m Unit) [inst_1 : LawfulMonad m], (forM xs fun x => act x) = List.forM xs actLawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] : (do' form: Type → Type u_1x inx: αxs do' {xs: List αactact: α → m Unitx }) =x: αxs.xs: List αforMforM: {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → List α → (α → m PUnit) → m PUnitact :=act: α → m Unitm: Type → Type ?u.7430
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit(forM xs fun x => act x) = List.forM xs actm: Type → Type ?u.7430
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
nil(forM [] fun x => act x) = List.forM [] actm: Type → Type ?u.7430
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
head✝: α
tail✝: List α(forM (head✝ :: tail✝) fun x => act x) = List.forM (head✝ :: tail✝) actm: Type → Type ?u.7430
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
nil(forM [] fun x => act x) = List.forM [] actm: Type → Type ?u.7430
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
head✝: α
tail✝: List α(forM (head✝ :: tail✝) fun x => act x) = List.forM (head✝ :: tail✝) actdefGoals accomplished! 🐙ex2 (ex2: {β : Type} → (β → α → m β) → β → List α → m βf :f: β → α → m ββ →β: Typeα →α: Typemm: Type → Type u_1β) (β: Typeinit :init: ββ) (β: Typexs :xs: List αListList: Type → Typeα) :α: Typemm: Type → Type u_1β := do' let mutβ: Typey :=y: βinit; forinit: βx inx: αxs do' { y ←xs: List αff: β → α → m βyy: βx }; returnx: αyy: βexample [example: ∀ {m : Type → Type u_1} {α : Type} [inst : Monad m] (xs : List α) {β : Type} {init : β} [inst_1 : LawfulMonad m] (f : β → α → m β), ex2 f init xs = List.foldlM f init xsLawfulMonadLawfulMonad: (m : Type ?u.8985 → Type ?u.8984) → [inst : Monad m] → Propm] (m: Type → Type u_1f :f: β → α → m ββ →β: Typeα →α: Typemm: Type → Type u_1β) :β: Typeex2ex2: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → {β : Type} → (β → α → m β) → β → List α → m βff: β → α → m βinitinit: βxs =xs: List αxs.xs: List αfoldlMfoldlM: {m : Type → Type u_1} → [inst : Monad m] → {s α : Type} → (s → α → m s) → s → List α → m sff: β → α → m βinit :=init: βm: Type → Type ?u.8948
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
β: Type
init: β
f: β → α → m βex2 f init xs = List.foldlM f init xs;m: Type → Type ?u.8948
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
β: Type
init: β
f: β → α → m βExceptCpsT.runCatch (let y := init; StateT.run' (do forM xs fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y) = List.foldlM f init xsm: Type → Type ?u.8948
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
β: Type
f: β → α → m β
init: β
nilExceptCpsT.runCatch (let y := init; StateT.run' (do forM [] fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y) = List.foldlM f init []m: Type → Type ?u.8948
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
β: Type
f: β → α → m β
head✝: α
tail✝: List α
init: βExceptCpsT.runCatch (let y := init; StateT.run' (do forM (head✝ :: tail✝) fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y) = List.foldlM f init (head✝ :: tail✝)m: Type → Type ?u.8948
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
β: Type
f: β → α → m β
init: β
nilExceptCpsT.runCatch (let y := init; StateT.run' (do forM [] fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y) = List.foldlM f init []m: Type → Type ?u.8948
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
β: Type
f: β → α → m β
head✝: α
tail✝: List α
init: βExceptCpsT.runCatch (let y := init; StateT.run' (do forM (head✝ :: tail✝) fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y) = List.foldlM f init (head✝ :: tail✝)@[simp] theoremGoals accomplished! 🐙List.find?_cons {List.find?_cons: ∀ {x : α} {p : α → Bool} {xs : List α}, find? p (x :: xs) = if p x = true then some x else find? p xsxs :xs: List αListList: Type ?u.17785 → Type ?u.17785α} : (α: Typex::x: αxs).xs: List αfind?find?: {α : Type} → (α → Bool) → List α → Option αp = ifp: α → Boolpp: α → Boolx thenx: αsomesome: {α : Type} → α → Option αx elsex: αxs.xs: List αfind?find?: {α : Type} → (α → Bool) → List α → Option αp :=p: α → Boolm: Type → Type ?u.17767
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
x: α
p: α → Bool
xs: List αfind? p (x :: xs) = if p x = true then some x else find? p xsm: Type → Type ?u.17767
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
x: α
p: α → Bool
xs: List α
h: p x = false
falsefind? p (x :: xs) = if false = true then some x else find? p xsm: Type → Type ?u.17767
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
x: α
p: α → Bool
xs: List α
h: p x = truefind? p (x :: xs) = if true = true then some x else find? p xsm: Type → Type ?u.17767
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
x: α
p: α → Bool
xs: List α
h: p x = false
falsefind? p (x :: xs) = if false = true then some x else find? p xsm: Type → Type ?u.17767
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
x: α
p: α → Bool
xs: List α
h: p x = truefind? p (x :: xs) = if true = true then some x else find? p xsGoals accomplished! 🐙example (example: ∀ {α : Type} (xs : List α) (p : α → Bool), Id.run (ExceptCpsT.runCatch do forM xs fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p xsp :p: α → Boolα →α: TypeBool) :Bool: TypeId.run (do' forId.run: {α : Type} → Id α → αx inx: αxs do' { ifxs: List αpp: α → Boolx then { returnx: αsomesome: {α : Type} → α → Option αx } };x: αpurepure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αnone) =none: {α : Type} → Option αxs.xs: List αfind?find?: {α : Type} → (α → Bool) → List α → Option αp :=p: α → Boolm: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → BoolId.run (ExceptCpsT.runCatch do forM xs fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p xsm: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → BoolId.run (ExceptCpsT.runCatch do forM xs fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p xsm: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → Bool
nilId.run (ExceptCpsT.runCatch do forM [] fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p []Goals accomplished! 🐙m: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → Bool
x: α
tail✝: List α
consId.run (ExceptCpsT.runCatch do forM (x :: tail✝) fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p (x :: tail✝)m: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → Bool
x: α
tail✝: List α
h: p x = false
cons.falseId.run (ExceptCpsT.runCatch do forM (x :: tail✝) fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p (x :: tail✝)m: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → Bool
x: α
tail✝: List α
h: p x = trueId.run (ExceptCpsT.runCatch do forM (x :: tail✝) fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p (x :: tail✝)m: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → Bool
x: α
tail✝: List α
h: p x = false
cons.falseId.run (ExceptCpsT.runCatch do forM (x :: tail✝) fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p (x :: tail✝)m: Type → Type ?u.18571
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → Bool
x: α
tail✝: List α
h: p x = trueId.run (ExceptCpsT.runCatch do forM (x :: tail✝) fun x => if p x = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.find? p (x :: tail✝)variable (Goals accomplished! 🐙p :p: α → m Boolα →α: Typemm: Type → Type ?u.38841Bool) theoremBool: TypebyCases_Bool_bind (byCases_Bool_bind: ∀ {m : Type → Type u_1} [inst : Monad m] {β : Type} (x : m Bool) (f g : Bool → m β), f true = g true → f false = g false → x >>= f = x >>= gx :x: m Boolmm: Type → Type u_1Bool) (Bool: Typeff: Bool → m βg :g: Bool → m βBool →Bool: Typemm: Type → Type u_1β) (β: TypeisTrue :isTrue: f true = g trueff: Bool → m βtrue =true: Boolgg: Bool → m βtrue) (true: BoolisFalse :isFalse: f false = g falseff: Bool → m βfalse =false: Boolgg: Bool → m βfalse) : (false: Boolx >>=x: m Boolf) = (f: Bool → m βx >>=x: m Boolg) :=g: Bool → m βm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g falsex >>= f = x >>= gm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g falsex >>= f = x >>= gm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g falsef = gm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b✝: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g false
b: Bool
hf b = g bm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b✝: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g false
b: Bool
hf b = g bm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g false
h.truef true = g trueGoals accomplished! 🐙m: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g false
h.falsef false = g falseGoals accomplished! 🐙m: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g false
this: f = gx >>= f = x >>= gm: Type → Type u_1
α: Type
inst✝: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
β: Type
x: m Bool
f, g: Bool → m β
isTrue: f true = g true
isFalse: f false = g false
this: f = gx >>= g = x >>= gtheoremGoals accomplished! 🐙eq_findM [eq_findM: ∀ {m : Type → Type u_1} {α : Type} [inst : Monad m] (xs : List α) (p : α → m Bool) [inst_1 : LawfulMonad m], (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xsLawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] : (do' form: Type → Type u_1x inx: αxs do' { letxs: List αb ←b: Boolpp: α → m Boolx; ifx: αb then { returnb: Boolsomesome: {α : Type} → α → Option αx } };x: αpurepure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αnone) =none: {α : Type} → Option αxs.xs: List αfindM?findM?: {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → (α → m Bool) → List α → m (Option α)p :=p: α → m Boolm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
nil(ExceptCpsT.runCatch do forM [] fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p []Goals accomplished! 🐙m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons(ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p (x :: xs)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons(ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p (x :: xs)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons(ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← p x match a with | true => pure (some x) | false => List.findM? p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons(ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← p x match a with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none);m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons(ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← p x match a with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← p x match a with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons.isTrue(ExceptCpsT.runCatch do if true = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = match true with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs(ExceptCpsT.runCatch do if false = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = match false with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs
cons.isTrue(ExceptCpsT.runCatch do if true = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = match true with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findM? p xs(ExceptCpsT.runCatch do if false = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = match false with | true => pure (some x) | false => ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)defGoals accomplished! 🐙ex3 [ex3: [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)MonadMonad: (Type → Type u_1) → Type (max 1 u_1)m] (m: Type → Type u_1p :p: α → m Boolα →α: Typemm: Type → Type u_1Bool) (Bool: Typexss :xss: List (List α)List (List: Type → TypeListList: Type → Typeα)) :α: Typem (m: Type → Type u_1OptionOption: Type → Typeα) := do' forα: Typexs inxs: List αxss do' { forxss: List (List α)x inx: αxs do' { letxs: List αb ←b: Boolpp: α → m Boolx; ifx: αb then { returnb: Boolsomesome: {α : Type} → α → Option αx } } };x: αpurepure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αnone theoremnone: {α : Type} → Option αeq_findSomeM_findM [eq_findSomeM_findM: ∀ {m : Type → Type u_1} {α : Type} [inst : Monad m] (p : α → m Bool) [inst_1 : LawfulMonad m] (xss : List (List α)), ex3 p xss = List.findSomeM? (fun xs => List.findM? p xs) xssLawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] (m: Type → Type u_1xss :xss: List (List α)List (List: Type → TypeListList: Type → Typeα)) :α: Typeex3ex3: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)pp: α → m Boolxss =xss: List (List α)xss.xss: List (List α)findSomeM? (funfindSomeM?: {m : Type → Type u_1} → [inst : Monad m] → {α β : Type} → (α → m (Option β)) → List α → m (Option β)xs =>xs: List αxs.xs: List αfindM?findM?: {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → (α → m Bool) → List α → m (Option α)p) :=p: α → m Boolm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)ex3 p xss = List.findSomeM? (fun xs => List.findM? p xs) xssm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)(ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xssm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)(ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xssm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
nil(ExceptCpsT.runCatch do forM [] fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) []Goals accomplished! 🐙m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM (xs :: xss) fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) (xs :: xss)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← List.findM? p xs match a with | some b => pure (some b) | none => List.findSomeM? (fun xs => List.findM? p xs) xssm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← List.findM? p xs match a with | some b => pure (some b) | none => List.findSomeM? (fun xs => List.findM? p xs) xssm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← List.findM? p xs match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xs: List α
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons(ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
ih: (ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = List.findSomeM? (fun xs => List.findM? p xs) xss
cons.nil(ExceptCpsT.runCatch do forM [] fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM [] fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)Goals accomplished! 🐙m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons.cons(ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none);m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons.cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let x_1 ← p x let a ← ExceptCpsT.runCatch do if x_1 = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons.cons.isTrue(ExceptCpsT.runCatch do if true = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do if true = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)(ExceptCpsT.runCatch do if false = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do if false = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons.cons.isTrue(ExceptCpsT.runCatch do if true = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do if true = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
xss: List (List α)
x: α
xs: List α
ih: (ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)(ExceptCpsT.runCatch do if false = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)) = do let a ← ExceptCpsT.runCatch do if false = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none) match a with | some b => pure (some b) | none => ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)defGoals accomplished! 🐙List.untilM (List.untilM: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → (α → m Bool) → List α → m Unitp :p: α → m Boolα →α: Typemm: Type → Type u_1Bool) :Bool: TypeListList: Type → Typeα →α: Typemm: Type → Type u_1Unit | [] =>Unit: Typepurepure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α() |(): Unita::a: αas =>as: List αpp: α → m Boola >>= fun |a: αtrue =>true: Boolpurepure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α() |(): Unitfalse =>false: Boolas.as: List αuntilMuntilM: (α → m Bool) → List α → m Unitp theoremp: α → m Booleq_untilM [eq_untilM: ∀ [inst : LawfulMonad m], ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xsLawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] : (do' form: Type → Type u_1x inx: αxs do' { letxs: List αb ←b: Boolpp: α → m Boolx; ifx: αb then { break } }) =b: Boolxs.xs: List αuntilMuntilM: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → (α → m Bool) → List α → m Unitp :=p: α → m Boolm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m BoolExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m BoolExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs: List α
act: α → m Unit
p: α → m Bool
nilExceptCpsT.runCatch (forM [] fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p []Goals accomplished! 🐙m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xs
consExceptCpsT.runCatch (forM (x :: xs) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p (x :: xs);m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xs
cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = do let x ← p x match x with | true => pure () | false => List.untilM p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xs
cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = do let x ← p x match x with | true => pure () | false => List.untilM p xsm: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xs
cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = do let x ← p x match x with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()));m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
ih: ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = List.untilM p xs
cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = do let x ← p x match x with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()))m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
cons(do let a ← p x ExceptCpsT.runCatch do if a = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = do let x ← p x match x with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()))m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
cons.isTrue(ExceptCpsT.runCatch do if true = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = match true with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()))m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α(ExceptCpsT.runCatch do if false = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = match false with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()))m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α
cons.isTrue(ExceptCpsT.runCatch do if true = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = match true with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()))m: Type → Type u_1
α: Type
inst✝¹: Monad m
ma, ma': m α
b: Bool
xs✝: List α
act: α → m Unit
p: α → m Bool
x: α
xs: List α(ExceptCpsT.runCatch do if false = true then throw () else ExceptCpsT.lift (pure ()) forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ())) = match false with | true => pure () | false => ExceptCpsT.runCatch (forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw () else ExceptCpsT.lift (pure ()))/- The notation `[0:10]` is a range from 0 to 10 (exclusively). -/Goals accomplished! 🐙do' forx in [x: Nat0:0: Nat10] do' { if10: Natx >x: Nat5 then { break }; for5: Naty in [y: Nat0:0: Natx] do' {x: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Unity; break };y: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Unitx }x: Natdo' forx in [x: Nat0:0: Nat10] do' { if10: Natx >x: Nat5 then { break };5: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Unitx }x: Natdo' forx in [x: Nat0:0: Nat10] do' { if10: Natx %x: Nat2 ==2: Nat0 then { continue }; if0: Natx >x: Nat5 then { break };5: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Unitx }x: Natdo' forx in [x: Nat0:0: Nat10] do' { if10: Natx %x: Nat2 ==2: Nat0 then { continue }; if0: Natx >x: Nat5 then { return () };5: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Unitx } -- set_option trace.compiler.ir.init true defx: Natex1 (ex1: List Nat → Nat → Id Natxs :xs: List NatListList: Type → TypeNat) (Nat: Typez :z: NatNat) :Nat: TypeIdId: Type → TypeNat := do' let mutNat: Types1 :=s1: Nat0; let mut0: Nats2 :=s2: Nat0; for0: Natx inx: Natxs do' { ifxs: List Natx %x: Nat2 ==2: Nat0 then { continue }; if0: Natx ==x: Natz then { returnz: Nats1 }; s1 :=s1: Nats1 +s1: Natx; s2 :=x: Nats2 +s2: Nats1 }; return (s1: Nats1 +s1: Nats2) /- Adding `repeat` and `while` statements -/ -- The "partial" keyword allows users to define non-terminating functions in Lean. -- However, we currently cannot reason about them. @[specialize] partial defs2: NatloopForever [loopForever: [inst : Monad m] → (Unit → m Unit) → m UnitMonadMonad: (Type → Type u_1) → Type (max 1 u_1)m] (m: Type → Type u_1f :f: Unit → m UnitUnit →Unit: Typemm: Type → Type u_1Unit) :Unit: Typemm: Type → Type u_1Unit :=Unit: Typeff: Unit → m Unit() *>(): UnitloopForeverloopForever: [inst : Monad m] → (Unit → m Unit) → m Unitf -- `Loop'` is a "helper" type. It is similar to `Unit`. -- Its `ForM` instance produces an "infinite" sequence of units. inductivef: Unit → m UnitLoop' where |Loop': Typemk :mk: Loop'Loop'Loop': Typeinstance :instance: {m : Type → Type u_1} → ForM m Loop' UnitForMForM: (Type → Type u_1) → Type → outParam Type → Type (max (max 1 u_1) 0)mm: Type → Type u_1Loop'Loop': TypeUnit where forM _Unit: Typef :=f: Unit → m PUnitloopForeverloopForever: {m : Type → Type u_1} → [inst : Monad m] → (Unit → m Unit) → m Unitf macro:0 "repeat"f: Unit → m PUnits:stmt:1 : stmt => `(stmt| for u in Loop'.mk do' $s: TSyntax `stmts)s: TSyntax `stmtdo' let muti :=i: Nat0; repeat { if0: Nati >i: Nat10 then { break };10: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Uniti; i :=i: Nati +i: Nat1 }; return1: Nati macro:0 "while"i: Natc:term "do'"c: TSyntax `terms:stmt:1 : stmt => `(stmt| repeat { unless $s: TSyntax `stmtc do' break; { $c: TSyntax `terms } })s: TSyntax `stmtdo' let muti :=i: Nat0; while (0: Nati <i: Nat10) do' {10: NatIO.printlnIO.println: {α : Type} → [inst : ToString α] → α → IO Uniti; i :=i: Nati +i: Nat1 }; return1: Natii: Nat
import Do.For -- import `runCatch`
import Lean
import Aesop
Formalization of Extended do
Translation
An intrinsically typed representation of the paper's syntax of do
statements as well
of their translation functions and an equivalence proof thereof to a simple denotational semantics.
Contexts
We represent contexts as lists of types and assignments of them as heterogeneous lists over these types. As is common with lists, contexts grow to the left in our presentation. The following encoding of heterogeneous lists avoids the universe bump of the usual inductive definition (https://lists.chalmers.se/pipermail/agda/2010/001826.html).
def HList: List (Type u) → Type u
HList : List: Type (u + 1) → Type (u + 1)
List (Type u: Type (u + 1)
Type u) → Type u: Type (u + 1)
Type u
| [] => PUnit: Type u
PUnit
| α: Type u
α :: αs: List (Type u)
αs => α: Type u
α × HList: List (Type u) → Type u
HList αs: List (Type u)
αs
@[matchPattern] abbrev HList.nil: HList []
HList.nil : HList: List (Type u_1) → Type u_1
HList []: List (Type u_1)
[] := ⟨⟩: PUnit
⟨⟩
@[matchPattern] abbrev HList.cons: {α : Type u_1} → {αs : List (Type u_1)} → α → HList αs → HList (α :: αs)
HList.cons (a: α
a : α: Type u_1
α) (as: HList αs
as : HList: List (Type u_1) → Type u_1
HList αs: List (Type u_1)
αs) : HList: List (Type u_1) → Type u_1
HList (α: Type u_1
α :: αs: List (Type u_1)
αs) := (a: α
a, as: HList αs
as)
We overload the common list notations ::
and [e, ...]
for HList
.
infixr:67 " :: " => HList.cons
syntax (name := hlistCons) "[" term,* "]" : term
macro_rules (kind := hlistCons)
| `([]) => `(HList.nil): Lean.MacroM Lean.Syntax
`(HList.nil)
| `([$x: Lean.TSyntax `term
x]) => `(HList.cons $x: Lean.TSyntax `term
x [])
| `([$x: Lean.TSyntax `term
x, $xs: Lean.Syntax.TSepArray `term ","
xs,*]) => `(HList.cons $x: Lean.TSyntax `term
x [$xs: Lean.Syntax.TSepArray `term ","
xs,*])
Lean's very general, heterogeneous definition of ++
causes some issues with our overloading above in terms
such as a ++ [b]
, so we restrict it to the List
interpretation in the following, which is sufficient for our purposes.
local macro_rules
| `($a: Lean.TSyntax `term
a ++ $b: Lean.TSyntax `term
b) => `(List.append $a: Lean.TSyntax `term
a $b: Lean.TSyntax `term
b)
abbrev Assg: List (Type u_1) → Type u_1
Assg Γ: List (Type u_1)
Γ := HList: List (Type u_1) → Type u_1
HList Γ: List (Type u_1)
Γ
Updating a heterogeneous list at a given, guaranteed in-bounds index.
def HList.set: {αs : List (Type u)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αs
HList.set : {αs: List (Type u)
αs : List: Type (u + 1) → Type (u + 1)
List (Type u: Type (u + 1)
Type u)} → HList: List (Type u) → Type u
HList αs: List (Type u)
αs → (i: Fin (List.length αs)
i : Fin: Nat → Type
Fin αs: List (Type u)
αs.length: {α : Type (u + 1)} → List α → Nat
length) → αs: List (Type u)
αs.get: {α : Type (u + 1)} → (as : List α) → Fin (List.length as) → α
get i: Fin (List.length αs)
i → HList: List (Type u) → Type u
HList αs: List (Type u)
αs
| _ :: _, _ :: as: HList a✝
as, ⟨0: Nat
0, _⟩, b: List.get (α✝ :: a✝) { val := 0, isLt := isLt✝ }
b => b: List.get (α✝ :: a✝) { val := 0, isLt := isLt✝ }
b :: as: HList a✝
as
| _ :: _, a: α✝
a :: as: HList a✝
as, ⟨Nat.succ: Nat → Nat
Nat.succ n: Nat
n, h: Nat.succ n < List.length (α✝ :: a✝)
h⟩, b: List.get (α✝ :: a✝) { val := Nat.succ n, isLt := h }
b => a: α✝
a :: set: {αs : List (Type u)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αs
set as: HList a✝
as ⟨n: Nat
n, Nat.le_of_succ_le_succ: ∀ {n m : Nat}, Nat.succ n ≤ Nat.succ m → n ≤ m
Nat.le_of_succ_le_succ h: Nat.succ n < List.length (α✝ :: a✝)
h⟩ b: List.get (α✝ :: a✝) { val := Nat.succ n, isLt := h }
b
| [], [], _, _ => []: HList []
[]
We write ∅
for empty contexts and assignments and Γ ⊢ α
for the type of values of type α
under the context Γ
- that is, the function type from an assignment to
α
.
instance: EmptyCollection (Assg ∅)
instance : EmptyCollection: Type u_1 → Type u_1
EmptyCollection (Assg: List (Type u_1) → Type u_1
Assg ∅: List (Type u_1)
∅) where
emptyCollection := []: HList []
[]
instance: CoeSort (List (Type u)) (Type u)
instance : CoeSort: Type (u + 1) → outParam (Type (u + 1)) → Type (u + 1)
CoeSort (List: Type (u + 1) → Type (u + 1)
List (Type u: Type (u + 1)
Type u)) (Type u: Type (u + 1)
Type u) := ⟨Assg: List (Type u) → Type u
Assg⟩
notation:30 Γ: Lean.TSyntax `term
Γ " ⊢ " α: Lean.TSyntax `term
α => Assg Γ: Lean.TSyntax `term
Γ → α: Lean.TSyntax `term
α
def Assg.drop: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (α :: Γ) → Assg Γ
Assg.drop : Assg: List (Type u_1) → Type u_1
Assg (α: Type u_1
α :: Γ: List (Type u_1)
Γ) → Assg: List (Type u_1) → Type u_1
Assg Γ: List (Type u_1)
Γ
| _ :: as: HList Γ
as => as: HList Γ
as
In one special case, we will need to manipulate contexts from the right, i.e. the outermost scope.
def Assg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])
Assg.extendBot (x: α
x : α: Type u_1
α) : {Γ: List (Type u_1)
Γ : _: Type (u_1 + 1)
_} → Assg: List (Type u_1) → Type u_1
Assg Γ: List (Type u_1)
Γ → Assg: List (Type u_1) → Type u_1
Assg (Γ: List (Type u_1)
Γ ++ [α: Type u_1
α])
| [], [] => [x: α
x]
| _ :: _, a: α✝
a :: as: HList a✝
as => a: α✝
a :: extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])
extendBot x: α
x as: HList a✝
as
def Assg.dropBot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → Assg Γ
Assg.dropBot : {Γ: List (Type u_1)
Γ : _: Type (u_1 + 1)
_} → Assg: List (Type u_1) → Type u_1
Assg (Γ: List (Type u_1)
Γ ++ [α: Type u_1
α]) → Assg: List (Type u_1) → Type u_1
Assg Γ: List (Type u_1)
Γ
| [], _ => []: HList []
[]
| _ :: _: List (Type u_1)
_, a: α✝
a :: as: HList (List.append tail✝ [α])
as => a: α✝
a :: dropBot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → Assg Γ
dropBot as: HList (List.append tail✝ [α])
as
Intrinsically Typed Representation of do
Statements
where
- m: base monad
- ω:
return
type,m ω
is the type of the entiredo
block - Γ:
do
-local immutable context - Δ:
do
-local mutable context - b:
break
allowed - c:
continue
allowed - α: local result type,
m α
is the type of the statement
The constructor signatures are best understood by comparing them with the corresponding typing rules in the paper.
Note that the choice of de Bruijn indices changes/simplifies some parts, such as obviating freshness checks (x ∉ Δ
).
inductive Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt (m: Type → Type u
m : Type: Type 1
Type → Type u: Type (u + 1)
Type u) (ω: Type
ω : Type: Type 1
Type) : (Γ: List Type
Γ Δ: List Type
Δ : List: Type 1 → Type 1
List Type: Type 1
Type) → (b: Bool
b c: Bool
c : Bool: Type
Bool) → (α: Type
α : Type: Type 1
Type) → Type _: Type ((max 1 u) + 1)
Type _ where
| expr: {m : Type → Type u} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
expr (e: Assg Γ → Assg Δ → m α
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ m: Type → Type u
m α: Type
α) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α
| bind: {m : Type → Type u} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
bind (s: Stmt m ω Γ Δ b c α
s : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α) (s': Stmt m ω (α :: Γ) Δ b c β
s' : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω (α: Type
α :: Γ: List Type
Γ) Δ: List Type
Δ b: Bool
b c: Bool
c β: Type
β) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c β: Type
β -- let _ ← s; s'
| letmut: {m : Type → Type u} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
letmut (e: Assg Γ → Assg Δ → α
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ α: Type
α) (s: Stmt m ω Γ (α :: Δ) b c β
s : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ (α: Type
α :: Δ: List Type
Δ) b: Bool
b c: Bool
c β: Type
β) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c β: Type
β -- let mut _ := e; s
| assg: {m : Type → Type u} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
assg (x: failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)
x : Fin: Nat → Type
Fin Δ: List Type
ΔΔ.length: Nat
.length: {α : Type 1} → List α → Nat
length) (e: failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ Δ: List Type
Δ.get: {α : Type 1} → (as : List α) → Fin (List.length as) → α
get x: failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)
x) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c Unit: Type
Unit -- x := e
| ite: {m : Type → Type u} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
ite (e: Assg Γ → Assg Δ → Bool
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ Bool: Type
Bool) (s₁: Stmt m ω Γ Δ b c α
s₁ s₂: Stmt m ω Γ Δ b c α
s₂ : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α -- if e then s₁ else s₂
| ret: {m : Type → Type u} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
ret (e: Assg Γ → Assg Δ → ω
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ ω: Type
ω) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α -- return e
| sfor: {m : Type → Type u} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
sfor (e: Assg Γ → Assg Δ → List α
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ List: Type → Type
List α: Type
α) (s: Stmt m ω (α :: Γ) Δ true true Unit
s : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω (α: Type
α :: Γ: List Type
Γ) Δ: List Type
Δ true: Bool
true true: Bool
true Unit: Type
Unit) : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c Unit: Type
Unit -- for _ in e do s
| sbreak: {m : Type → Type u} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
sbreak : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ true: Bool
true c: Bool
c α: Type
α -- break
| scont: {m : Type → Type u} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
scont : Stmt: (Type → Type u) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u)
Stmt m: Type → Type u
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b true: Bool
true α: Type
α -- continue
Neutral statements are a restriction of the above type.
inductive Neut: Type → Type → Bool → Bool → Type
Neut (ω: Type
ω α: Type
α : Type: Type 1
Type) : (b: Bool
b c: Bool
c : Bool: Type
Bool) → Type _: Type 1
Type _ where
| val: {ω α : Type} → {b c : Bool} → α → Neut ω α b c
val (a: α
a : α: Type
α) : Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α b: Bool
b c: Bool
c
| ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
ret (o: ω
o : ω: Type
ω) : Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α b: Bool
b c: Bool
c
| rbreak: {ω α : Type} → {c : Bool} → Neut ω α true c
rbreak : Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α true: Bool
true c: Bool
c
| rcont: {ω α : Type} → {b : Bool} → Neut ω α b true
rcont : Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α b: Bool
b true: Bool
true
We elide Neut.val
where unambiguous.
instance: {α ω : Type} → {b c : Bool} → Coe α (Neut ω α b c)
instance : Coe: Type → Type → Type
Coe α: Type
α (Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α b: Bool
b c: Bool
c) := ⟨Neut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b c
Neut.val⟩
instance: {α ω : Type} → {b c : Bool} → Coe (Id α) (Neut ω α b c)
instance : Coe: Type → Type → Type
Coe (Id: Type → Type
Id α: Type
α) (Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α b: Bool
b c: Bool
c) := ⟨Neut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b c
Neut.val⟩
We write e[ρ][σ]
for the substitution of both contexts in e
, a simple application in this encoding.
σ[x ↦ v]
updates σ
at v
(a de Bruijn index).
macro:max (priority := high) e: Lean.TSyntax `term
e:term:max noWs "[" ρ: Lean.TSyntax `term
ρ:term "]" "[" σ: Lean.TSyntax `term
σ:term "]" : term => `($e: Lean.TSyntax `term
e $ρ: Lean.TSyntax `term
ρ $σ: Lean.TSyntax `term
σ)
macro:max (priority := high) σ: Lean.TSyntax `term
σ:term:max noWs "[" x: Lean.TSyntax `term
x:term " ↦ " v: Lean.TSyntax `term
v:term "]" : term => `(HList.set $σ: Lean.TSyntax `term
σ $x: Lean.TSyntax `term
x $v: Lean.TSyntax `term
v)
Dynamic Evaluation Function
A direct encoding of the paper's operational semantics as a denotational function,
generalized over an arbitrary monad.
Note that the immutable context ρ
is accumulated (v :: ρ
) and passed explicitly instead of immutable
bindings being substituted immediately as that is a better match for the above definition of Stmt
.
Iteration over the values of the given list in the for
case introduces a nested, mutually recursive helper
function, with termination of the mutual bundle following from a size argument over the statement primarily
and the length of the list in the for
case secondarily.
@[simp] def Stmt.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
Stmt.eval [Monad: (Type ?u.21808 → Type ?u.21807) → Type (max (?u.21808 + 1) ?u.21807)
Monad m: Type → Type u_1
m] (ρ: Assg Γ
ρ : Assg: List Type → Type
Assg Γ: List Type
Γ) : Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α → Assg: List Type → Type
Assg Δ: List Type
Δ → m: Type → Type u_1
m (Neut: Type → Type → Bool → Bool → Type
Neut ω: Type
ω α: Type
α b: Bool
b c: Bool
c × Assg: List Type → Type
Assg Δ: List Type
Δ)
| expr: {m : Type → Type ?u.32858} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
expr e: Assg Γ → Assg Δ → m α
e, σ: Assg Δ
σ => e: Assg Γ → Assg Δ → m α
e[ρ: Assg Γ
ρ][σ: Assg Δ
σ] >>= fun v: α
v => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨v: α
v, σ: Assg Δ
σ⟩
| bind: {m : Type → Type ?u.33084} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
bind s: Stmt m ω Γ Δ b c α✝
s s': Stmt m ω (α✝ :: Γ) Δ b c α
s', σ: Assg Δ
σ =>
-- defining this part as a separate definition helps Lean with the termination proof
let rec @[simp] cont: (α✝ → Assg Δ → m (Neut ω α b c × Assg Δ)) → Neut ω α✝ b c × Assg Δ → m (Neut ω α b c × Assg Δ)
cont val: α✝ → Assg Δ → m (Neut ω α b c × Assg Δ)
val
| ⟨Neut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b c
Neut.val v: α✝
v, σ': Assg Δ
σ'⟩ => val: α✝ → Assg Δ → m (Neut ω α b c × Assg Δ)
val v: α✝
v σ': Assg Δ
σ'
-- the `Neut` type family forces us to repeat these cases as the LHS/RHS indices are not identical
| ⟨Neut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
Neut.ret o: ω
o, σ': Assg Δ
σ'⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
Neut.ret o: ω
o, σ': Assg Δ
σ'⟩
| ⟨Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true c
Neut.rbreak, σ': Assg Δ
σ'⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true c
Neut.rbreak, σ': Assg Δ
σ'⟩
| ⟨Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b true
Neut.rcont, σ': Assg Δ
σ'⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b true
Neut.rcont, σ': Assg Δ
σ'⟩
s: Stmt m ω Γ Δ b c α✝
s.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
eval ρ: Assg Γ
ρ σ: Assg Δ
σ >>= cont: (α✝ → Assg Δ → m (Neut ω α b c × Assg Δ)) → Neut ω α✝ b c × Assg Δ → m (Neut ω α b c × Assg Δ)
cont (fun v: α✝
v σ': Assg Δ
σ' => s': Stmt m ω (α✝ :: Γ) Δ b c α
s'.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
eval (v: α✝
v :: ρ: Assg Γ
ρ) σ': Assg Δ
σ')
| letmut: {m : Type → Type ?u.33463} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
letmut e: Assg Γ → Assg Δ → α✝
e s: Stmt m ω Γ (α✝ :: Δ) b c α
s, σ: Assg Δ
σ =>
s: Stmt m ω Γ (α✝ :: Δ) b c α
s.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
eval ρ: Assg Γ
ρ (e: Assg Γ → Assg Δ → α✝
e[ρ: Assg Γ
ρ][σ: Assg Δ
σ], σ: Assg Δ
σ) >>= fun ⟨r: Neut ω α b c
r, σ': Assg (α✝ :: Δ)
σ'⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨r: Neut ω α b c
r, σ': Assg (α✝ :: Δ)
σ'.drop: {α : Type} → {Γ : List Type} → Assg (α :: Γ) → Assg Γ
drop⟩
-- `x` is a valid de Bruijn index into `σ` by definition of `assg`
| assg: {m : Type → Type ?u.35837} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e, σ: Assg Δ
σ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨(): Unit
(), σ: Assg Δ
σ[x: Fin (List.length Δ)
x ↦ e: Assg Γ → Assg Δ → List.get Δ x
e[ρ: Assg Γ
ρ][σ: Assg Δ
σ]]⟩
| ite: {m : Type → Type ?u.36112} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
ite e: Assg Γ → Assg Δ → Bool
e s₁: Stmt m ω Γ Δ b c α
s₁ s₂: Stmt m ω Γ Δ b c α
s₂, σ: Assg Δ
σ => if e: Assg Γ → Assg Δ → Bool
e[ρ: Assg Γ
ρ][σ: Assg Δ
σ] then s₁: Stmt m ω Γ Δ b c α
s₁.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
eval ρ: Assg Γ
ρ σ: Assg Δ
σ else s₂: Stmt m ω Γ Δ b c α
s₂.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
eval ρ: Assg Γ
ρ σ: Assg Δ
σ
| ret: {m : Type → Type ?u.36353} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
ret e: Assg Γ → Assg Δ → ω
e, σ: Assg Δ
σ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
Neut.ret e: Assg Γ → Assg Δ → ω
e[ρ: Assg Γ
ρ][σ: Assg Δ
σ], σ: Assg Δ
σ⟩
| sfor: {m : Type → Type ?u.36472} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
sfor e: Assg Γ → Assg Δ → List α✝
e s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s, σ: Assg Δ
σ =>
let rec @[simp] go: Assg Δ → List α✝ → m (Neut ω Unit b c × Assg Δ)
go σ: Assg Δ
σ
| [] => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨(): Unit
(), σ: Assg Δ
σ⟩
| a: α✝
a::as: List α✝
as =>
s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
eval (a: α✝
a :: ρ: Assg Γ
ρ) σ: Assg Δ
σ >>= fun
| ⟨(), σ': Assg Δ
σ'⟩ => go: Assg Δ → List α✝ → m (Neut ω Unit b c × Assg Δ)
go σ': Assg Δ
σ' as: List α✝
as
| ⟨Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b true
Neut.rcont, σ': Assg Δ
σ'⟩ => go: Assg Δ → List α✝ → m (Neut ω Unit b c × Assg Δ)
go σ': Assg Δ
σ' as: List α✝
as
| ⟨Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true c
Neut.rbreak, σ': Assg Δ
σ'⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨(): Unit
(), σ': Assg Δ
σ'⟩
| ⟨Neut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
Neut.ret o: ω
o, σ': Assg Δ
σ'⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
Neut.ret o: ω
o, σ': Assg Δ
σ'⟩
go: Assg Δ → List α✝ → m (Neut ω Unit b c × Assg Δ)
go σ: Assg Δ
σ e: Assg Γ → Assg Δ → List α✝
e[ρ: Assg Γ
ρ][σ: Assg Δ
σ]
| sbreak: {m : Type → Type ?u.36610} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
sbreak, σ: Assg Δ
σ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true c
Neut.rbreak, σ: Assg Δ
σ⟩
| scont: {m : Type → Type ?u.36721} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
scont, σ: Assg Δ
σ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure ⟨Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b true
Neut.rcont, σ: Assg Δ
σ⟩
termination_by
eval s _ => (sizeOf: {α : Type (max 1 u_1)} → [self : SizeOf α] → α → Nat
sizeOf s: Stmt m ω Γ Δ b c α
s, 0: Nat
0)
eval.go as => (sizeOf: {α : Type (max 1 u_1)} → [self : SizeOf α] → α → Nat
sizeOf s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s, as: List α✝
as.length: {α : Type} → List α → Nat
length)
At the top-level statement, the contexts are empty, no loop control flow statements are allowed, and the return and result type are identical.
abbrev Do: (Type → Type u_1) → Type → Type (max 1 u_1)
Do m: Type → Type u_1
m α: Type
α := Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m α: Type
α ∅: List Type
∅ ∅: List Type
∅ false: Bool
false false: Bool
false α: Type
α
def Do.eval: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → Do m α → m α
Do.eval [Monad: (Type → Type u_1) → Type (max 1 u_1)
Monad m: Type → Type u_1
m] (s: Do m α
s : Do: (Type → Type u_1) → Type → Type (max 1 u_1)
Do m: Type → Type u_1
m α: Type
α) : m: Type → Type u_1
m α: Type
α := -- corresponds to the reduction rule `do s ⇒ v` in the paper
Stmt.eval: {m : Type → Type u_1} →
{Γ : List Type} →
{ω : Type} →
{Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)
Stmt.eval ∅: Assg ∅
∅ s: Do m α
s ∅: Assg ∅
∅ >>= fun
| ⟨Neut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b c
Neut.val a: α
a, _⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure a: α
a
| ⟨Neut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b c
Neut.ret o: α
o, _⟩ => pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f α
pure o: α
o
notation "⟦" s: Lean.TSyntax `term
s "⟧" => Do.eval s: Lean.TSyntax `term
s
Translation Functions
We adjust the immutable context where necessary. The mutable context does not have to be adjusted.
@[simp] def Stmt.mapAssg: (_x :
(Γ' : List Type) ×'
(Γ : List Type) ×'
(m : Type → Type u_1) ×'
(ω : Type) ×'
(Δ : List Type) ×' (b : Bool) ×' (c : Bool) ×' (β : Type) ×' (_ : Assg Γ' → Assg Γ) ×' Stmt m ω Γ Δ b c β) →
Stmt _x.2.2.1 _x.2.2.2.1 _x.1 _x.2.2.2.2.1 _x.2.2.2.2.2.1 _x.2.2.2.2.2.2.1 _x.2.2.2.2.2.2.2.1
Stmt.mapAssg (f: Assg Γ' → Assg Γ
f : Assg: List Type → Type
Assg Γ': List Type
Γ' → Assg: List (Type ?u.111841) → Type ?u.111841
Assg Γ: List Type
Γ) : Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c β: Type
β → Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ': List Type
Γ' Δ: List Type
Δ b: Bool
b c: Bool
c β: Type
β
| expr: {m : Type → Type ?u.116778} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
expr e: Assg Γ → Assg Δ → m β
e => expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
expr (e: Assg Γ → Assg Δ → m β
e ∘ f: Assg Γ' → Assg Γ
f)
| bind: {m : Type → Type ?u.116872} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
bind s₁: Stmt m ω Γ Δ b c α✝
s₁ s₂: Stmt m ω (α✝ :: Γ) Δ b c β
s₂ => bind: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
bind (s₁: Stmt m ω Γ Δ b c α✝
s₁.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type u_1} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
mapAssg f: Assg Γ' → Assg Γ
f) (s₂: Stmt m ω (α✝ :: Γ) Δ b c β
s₂.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type u_1} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
mapAssg (fun (a: α✝
a :: as: HList Γ'
as) => (a: α✝
a :: f: Assg Γ' → Assg Γ
f as: HList Γ'
as)))
| letmut: {m : Type → Type ?u.117466} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
letmut e: Assg Γ → Assg Δ → α✝
e s: Stmt m ω Γ (α✝ :: Δ) b c β
s => letmut: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
letmut (e: Assg Γ → Assg Δ → α✝
e ∘ f: Assg Γ' → Assg Γ
f) (s: Stmt m ω Γ (α✝ :: Δ) b c β
s.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type u_1} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
mapAssg f: Assg Γ' → Assg Γ
f)
| assg: {m : Type → Type ?u.117619} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e => assg: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
assg x: Fin (List.length Δ)
x (e: Assg Γ → Assg Δ → List.get Δ x
e ∘ f: Assg Γ' → Assg Γ
f)
| ite: {m : Type → Type ?u.117739} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
ite e: Assg Γ → Assg Δ → Bool
e s₁: Stmt m ω Γ Δ b c β
s₁ s₂: Stmt m ω Γ Δ b c β
s₂ => ite: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
ite (e: Assg Γ → Assg Δ → Bool
e ∘ f: Assg Γ' → Assg Γ
f) (s₁: Stmt m ω Γ Δ b c β
s₁.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type u_1} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
mapAssg f: Assg Γ' → Assg Γ
f) (s₂: Stmt m ω Γ Δ b c β
s₂.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type u_1} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
mapAssg f: Assg Γ' → Assg Γ
f)
| ret: {m : Type → Type ?u.117891} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
ret e: Assg Γ → Assg Δ → ω
e => ret: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
ret (e: Assg Γ → Assg Δ → ω
e ∘ f: Assg Γ' → Assg Γ
f)
| sfor: {m : Type → Type ?u.117980} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
sfor e: Assg Γ → Assg Δ → List α✝
e s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s => sfor: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
sfor (e: Assg Γ → Assg Δ → List α✝
e ∘ f: Assg Γ' → Assg Γ
f) (s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type u_1} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
mapAssg (fun (a: α✝
a :: as: HList Γ'
as) => (a: α✝
a :: f: Assg Γ' → Assg Γ
f as: HList Γ'
as)))
| sbreak: {m : Type → Type ?u.118585} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
sbreak => sbreak: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
sbreak
| scont: {m : Type → Type ?u.118632} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
scont => scont: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
scont
Let us write f ∘ₑ e
for the composition of f : α → β
with e : Γ ⊢ Δ ⊢ α
, which we will use to rewrite embedded terms.
infixr:90 " ∘ₑ " => fun f e => fun ρ σ => f e[ρ][σ]
The formalization of S
creates some technical hurdles. Because it operates on the outer-most mutable binding,
we have to operate on that context from the right, from which we lose some helpful definitional equalities and
have to rewrite types using nested proofs instead.
The helper function shadowSnd
is particularly interesting because it shows how the shadowing in
translation rules (S2) and (S9) is expressed in our de Bruijn encoding: The context α :: β :: α :: Γ
corresponds, in this order, to the y
that has just been bound to the value of get
, then x
from the
respective rule, followed by the y
of the outer scope. We encode the shadowing of y
by dropping the
third element from the context as well as the assignment. We are in fact forced to do so because the corresponding
branches of S
would not otherwise typecheck. The only mistake we could still make is to drop the wrong α
value
from the assignment, which (speaking from experience) would eventually be caught by the correctness proof.
@[simp] def S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S [Monad: (Type ?u.178851 → Type ?u.178850) → Type (max (?u.178851 + 1) ?u.178850)
Monad m: Type → Type
m] : Stmt: (Type → Type) → Type → List Type → List Type → Bool → Bool → Type → Type 1
Stmt m: Type → Type
m ω: Type
ω Γ: List Type
Γ (Δ: List Type
Δ ++ [α: Type
α]) b: Bool
b c: Bool
c β: Type
β → Stmt: (Type → Type) → Type → List Type → List Type → Bool → Bool → Type → Type 1
Stmt (StateT: Type → (Type → Type) → Type → Type
StateT α: Type
α m: Type → Type
m) ω: Type
ω (α: Type
α :: Γ: List Type
Γ) Δ: List Type
Δ b: Bool
b c: Bool
c β: Type
β
/-(S1)-/ | Stmt.expr: {m : Type → Type ?u.189083} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr e: Assg Γ → Assg (List.append Δ [α]) → m β
e => Stmt.expr: {m : Type → Type} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (StateT.lift: {σ : Type} → {m : Type → Type} → [inst : Monad m] → {α : Type} → m α → StateT σ m α
StateT.lift ∘ₑ unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut e: Assg Γ → Assg (List.append Δ [α]) → m β
e)
/-(S2)-/ | Stmt.bind: {m : Type → Type ?u.189320} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind s₁: Stmt m ω Γ (List.append Δ [α]) b c α✝
s₁ s₂: Stmt m ω (α✝ :: Γ) (List.append Δ [α]) b c β
s₂ => Stmt.bind: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S s₁: Stmt m ω Γ (List.append Δ [α]) b c α✝
s₁) (Stmt.bind: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (Stmt.expr: {m : Type → Type} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (fun _ _ => get: {σ : Type} → {m : Type → Type} → [self : MonadState σ m] → m σ
get)) (Stmt.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
Stmt.mapAssg shadowSnd: {β : Type} → Assg (α :: β :: α :: Γ) → Assg (α :: β :: Γ)
shadowSnd (S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S s₂: Stmt m ω (α✝ :: Γ) (List.append Δ [α]) b c β
s₂)))
/-(S3)-/ | Stmt.letmut: {m : Type → Type ?u.189575} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg (List.append Δ [α]) → α✝
e s: Stmt m ω Γ (α✝ :: List.append Δ [α]) b c β
s => Stmt.letmut: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut (unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut e: Assg Γ → Assg (List.append Δ [α]) → α✝
e) (S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S s: Stmt m ω Γ (α✝ :: List.append Δ [α]) b c β
s)
| Stmt.assg: {m : Type → Type ?u.189691} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length (List.append Δ [α]))
x e: Assg Γ → Assg (List.append Δ [α]) → List.get (List.append Δ [α]) x
e =>
if h: ¬x.val < List.length Δ
h : x: Fin (List.length (List.append Δ [α]))
x < Δ: List Type
Δ.length: {α : Type 1} → List α → Nat
length then
/-(S4)-/ Stmt.assg: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg ⟨x: Fin (List.length (List.append Δ [α]))
x, h: x.val < List.length Δ
h⟩ (fun (y: α
y :: ρ: HList Γ
ρ) σ: Assg Δ
σ => List.get_append_left: ∀ {α : Type 1} {i : Nat} (as bs : List α) (h : i < List.length as) {h' : i < List.length (as ++ bs)},
List.get (as ++ bs) { val := i, isLt := h' } = List.get as { val := i, isLt := h }
List.get_append_left .. ▸ e: Assg Γ → Assg (List.append Δ [α]) → List.get (List.append Δ [α]) x
e ρ: HList Γ
ρ (Assg.extendBot: {α : Type} → α → {Γ : List Type} → Assg Γ → Assg (List.append Γ [α])
Assg.extendBot y: α
y σ: Assg Δ
σ))
else
/-(S5)-/ Stmt.expr: {m : Type → Type} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (set: {σ : Type} → {m : Type → Type} → [self : MonadStateOf σ m] → σ → m PUnit
set (σ := α: Type
α) ∘ₑ cast: {α β : Type} → α = β → α → β
cast (List.get_last: ∀ {α : Type 1} {a : α} {as : List α} {i : Fin (List.length (as ++ [a]))},
¬i.val < List.length as → List.get (as ++ [a]) i = a
List.get_last h: ¬x.val < List.length Δ
h) ∘ₑ unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut e: Assg Γ → Assg (List.append Δ [α]) → List.get (List.append Δ [α]) x
e)
/-(S6)-/ | Stmt.ite: {m : Type → Type ?u.190593} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg (List.append Δ [α]) → Bool
e s₁: Stmt m ω Γ (List.append Δ [α]) b c β
s₁ s₂: Stmt m ω Γ (List.append Δ [α]) b c β
s₂ => Stmt.ite: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite (unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut e: Assg Γ → Assg (List.append Δ [α]) → Bool
e) (S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S s₁: Stmt m ω Γ (List.append Δ [α]) b c β
s₁) (S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S s₂: Stmt m ω Γ (List.append Δ [α]) b c β
s₂)
-- unreachable case; could be eliminated by a more precise specification of `ω`, but the benefit would be minimal
| Stmt.ret: {m : Type → Type ?u.190711} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg (List.append Δ [α]) → ω
e => Stmt.ret: {m : Type → Type} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret (unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut e: Assg Γ → Assg (List.append Δ [α]) → ω
e)
/-(S7)-/ | Stmt.sbreak: {m : Type → Type ?u.190795} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak => Stmt.sbreak: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak
/-(S8)-/ | Stmt.scont: {m : Type → Type ?u.190845} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont => Stmt.scont: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont
/-(S9)-/ | Stmt.sfor: {m : Type → Type ?u.190894} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg (List.append Δ [α]) → List α✝
e s: Stmt m ω (α✝ :: Γ) (List.append Δ [α]) true true Unit
s => Stmt.sfor: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor (unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut e: Assg Γ → Assg (List.append Δ [α]) → List α✝
e) (Stmt.bind: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (Stmt.expr: {m : Type → Type} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (fun _ _ => get: {σ : Type} → {m : Type → Type} → [self : MonadState σ m] → m σ
get)) (Stmt.mapAssg: {Γ' Γ : List Type} →
{m : Type → Type} →
{ω : Type} →
{Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c β
Stmt.mapAssg shadowSnd: {β : Type} → Assg (α :: β :: α :: Γ) → Assg (α :: β :: Γ)
shadowSnd (S: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} →
{β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c β
S s: Stmt m ω (α✝ :: Γ) (List.append Δ [α]) true true Unit
s)))
where
@[simp] unmut: {β : Type} → (Assg Γ → Assg (List.append Δ [α]) → β) → Assg (α :: Γ) → Assg Δ → β
unmut {β: Type
β} (e: Assg Γ → Assg (List.append Δ [α]) → β
e : Γ: List Type
Γ ⊢ Δ: List Type
Δ ++ [α: Type
α] ⊢ β: Type
β) : α: Type
α :: Γ: List Type
Γ ⊢ Δ: List Type
Δ ⊢ β: Type
β
| y: α
y :: ρ: HList Γ
ρ, σ: Assg Δ
σ => e: Assg Γ → Assg (List.append Δ [α]) → β
e ρ: HList Γ
ρ (Assg.extendBot: {α : Type} → α → {Γ : List Type} → Assg Γ → Assg (List.append Γ [α])
Assg.extendBot y: α
y σ: Assg Δ
σ)
@[simp] shadowSnd: {Γ : List Type} → {α β : Type} → Assg (α :: β :: α :: Γ) → Assg (α :: β :: Γ)
shadowSnd {β: Type
β} : Assg: List Type → Type
Assg (α: Type
α :: β: Type
β :: α: Type
α :: Γ: List Type
Γ) → Assg: List Type → Type
Assg (α: Type
α :: β: Type
β :: Γ: List Type
Γ)
| a': α
a' :: b: β
b :: _ :: ρ: HList Γ
ρ => a': α
a' :: b: β
b :: ρ: HList Γ
ρ
@[simp] def R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R [Monad: (Type ?u.239464 → Type ?u.239463) → Type (max (?u.239464 + 1) ?u.239463)
Monad m: Type → Type u_1
m] : Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α → Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt (ExceptT: Type → (Type → Type u_1) → Type → Type u_1
ExceptT ω: Type
ω m: Type → Type u_1
m) Empty: Type
Empty Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α
/-(R1)-/ | Stmt.ret: {m : Type → Type ?u.242023} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (throw: {ε : Type} → {m : Type → Type u_1} → [self : MonadExcept ε m] → {α : Type} → ε → m α
throw ∘ₑ e: Assg Γ → Assg Δ → ω
e)
/-(R2)-/ | Stmt.expr: {m : Type → Type ?u.242193} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr e: Assg Γ → Assg Δ → m α
e => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m α
ExceptT.lift ∘ₑ e: Assg Γ → Assg Δ → m α
e)
/-(R3)-/ | Stmt.bind: {m : Type → Type ?u.242398} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind s: Stmt m ω Γ Δ b c α✝
s s': Stmt m ω (α✝ :: Γ) Δ b c α
s' => Stmt.bind: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s: Stmt m ω Γ Δ b c α✝
s) (R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s': Stmt m ω (α✝ :: Γ) Δ b c α
s')
/-(R4)-/ | Stmt.letmut: {m : Type → Type ?u.242495} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e s: Stmt m ω Γ (α✝ :: Δ) b c α
s => Stmt.letmut: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e (R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s: Stmt m ω Γ (α✝ :: Δ) b c α
s)
/-(R5)-/ | Stmt.assg: {m : Type → Type ?u.242597} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e => Stmt.assg: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e
/-(R6)-/ | Stmt.ite: {m : Type → Type ?u.242681} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e s₁: Stmt m ω Γ Δ b c α
s₁ s₂: Stmt m ω Γ Δ b c α
s₂ => Stmt.ite: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e (R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s₁: Stmt m ω Γ Δ b c α
s₁) (R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s₂: Stmt m ω Γ Δ b c α
s₂)
/-(R7)-/ | Stmt.sbreak: {m : Type → Type ?u.242784} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak => Stmt.sbreak: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak
/-(R8)-/ | Stmt.scont: {m : Type → Type ?u.242831} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont => Stmt.scont: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont
/-(R9)-/ | Stmt.sfor: {m : Type → Type ?u.242877} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s => Stmt.sfor: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e (R: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s)
@[simp] def L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L [Monad: (Type ?u.255179 → Type ?u.255178) → Type (max (?u.255179 + 1) ?u.255178)
Monad m: Type → Type u_1
m] : Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α → Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt (ExceptT: Type → (Type → Type u_1) → Type → Type u_1
ExceptT Unit: Type
Unit m: Type → Type u_1
m) ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α
/-(L1)-/ | Stmt.sbreak: {m : Type → Type ?u.256306} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak => Stmt.sbreak: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak
/-(L2)-/ | Stmt.scont: {m : Type → Type ?u.256353} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont => Stmt.scont: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont
/-(L3)-/ | Stmt.expr: {m : Type → Type ?u.256399} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr e: Assg Γ → Assg Δ → m α
e => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m α
ExceptT.lift ∘ₑ e: Assg Γ → Assg Δ → m α
e)
/-(L4)-/ | Stmt.bind: {m : Type → Type ?u.256604} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind s: Stmt m ω Γ Δ b c α✝
s s': Stmt m ω (α✝ :: Γ) Δ b c α
s' => Stmt.bind: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s: Stmt m ω Γ Δ b c α✝
s) (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s': Stmt m ω (α✝ :: Γ) Δ b c α
s')
/-(L5)-/ | Stmt.letmut: {m : Type → Type ?u.256701} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e s: Stmt m ω Γ (α✝ :: Δ) b c α
s => Stmt.letmut: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s: Stmt m ω Γ (α✝ :: Δ) b c α
s)
/-(L6)-/ | Stmt.assg: {m : Type → Type ?u.256803} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e => Stmt.assg: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e
/-(L7)-/ | Stmt.ite: {m : Type → Type ?u.256899} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e s₁: Stmt m ω Γ Δ b c α
s₁ s₂: Stmt m ω Γ Δ b c α
s₂ => Stmt.ite: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s₁: Stmt m ω Γ Δ b c α
s₁) (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s₂: Stmt m ω Γ Δ b c α
s₂)
| Stmt.ret: {m : Type → Type ?u.257003} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e => Stmt.ret: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e
/-(L8)-/ | Stmt.sfor: {m : Type → Type ?u.257074} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s => Stmt.sfor: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s)
@[simp] def B: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c α
B [Monad: (Type ?u.268935 → Type ?u.268934) → Type (max (?u.268935 + 1) ?u.268934)
Monad m: Type → Type u_1
m] : Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ b: Bool
b c: Bool
c α: Type
α → Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt (ExceptT: Type → (Type → Type u_1) → Type → Type u_1
ExceptT Unit: Type
Unit m: Type → Type u_1
m) ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ false: Bool
false c: Bool
c α: Type
α
/-(B1)-/ | Stmt.sbreak: {m : Type → Type ?u.270257} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α
Stmt.sbreak => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (fun _ _ => throw: {ε : Type} → {m : Type → Type u_1} → [self : MonadExcept ε m] → {α : Type} → ε → m α
throw (): Unit
())
/-(B2)-/ | Stmt.scont: {m : Type → Type ?u.270390} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont => Stmt.scont: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont
/-(B3)-/ | Stmt.expr: {m : Type → Type ?u.270436} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr e: Assg Γ → Assg Δ → m α
e => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m α
ExceptT.lift ∘ₑ e: Assg Γ → Assg Δ → m α
e)
/-(B4)-/ | Stmt.bind: {m : Type → Type ?u.270641} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind s: Stmt m ω Γ Δ b c α✝
s s': Stmt m ω (α✝ :: Γ) Δ b c α
s' => Stmt.bind: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (B: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c α
B s: Stmt m ω Γ Δ b c α✝
s) (B: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c α
B s': Stmt m ω (α✝ :: Γ) Δ b c α
s')
/-(B5)-/ | Stmt.letmut: {m : Type → Type ?u.270738} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e s: Stmt m ω Γ (α✝ :: Δ) b c α
s => Stmt.letmut: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e (B: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c α
B s: Stmt m ω Γ (α✝ :: Δ) b c α
s)
/-(B6)-/ | Stmt.assg: {m : Type → Type ?u.270840} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e => Stmt.assg: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e
/-(B7)-/ | Stmt.ite: {m : Type → Type ?u.270936} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e s₁: Stmt m ω Γ Δ b c α
s₁ s₂: Stmt m ω Γ Δ b c α
s₂ => Stmt.ite: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e (B: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c α
B s₁: Stmt m ω Γ Δ b c α
s₁) (B: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c α
B s₂: Stmt m ω Γ Δ b c α
s₂)
| Stmt.ret: {m : Type → Type ?u.271040} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e => Stmt.ret: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e
/-(B8)-/ | Stmt.sfor: {m : Type → Type ?u.271111} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s => Stmt.sfor: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s)
-- (elided in the paper)
@[simp] def C: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false α
C [Monad: (Type ?u.277926 → Type ?u.277925) → Type (max (?u.277926 + 1) ?u.277925)
Monad m: Type → Type u_1
m] : Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt m: Type → Type u_1
m ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ false: Bool
false c: Bool
c α: Type
α → Stmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)
Stmt (ExceptT: Type → (Type → Type u_1) → Type → Type u_1
ExceptT Unit: Type
Unit m: Type → Type u_1
m) ω: Type
ω Γ: List Type
Γ Δ: List Type
Δ false: Bool
false false: Bool
false α: Type
α
| Stmt.scont: {m : Type → Type ?u.278871} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α
Stmt.scont => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (fun _ _ => throw: {ε : Type} → {m : Type → Type u_1} → [self : MonadExcept ε m] → {α : Type} → ε → m α
throw (): Unit
())
| Stmt.expr: {m : Type → Type ?u.278996} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr e: Assg Γ → Assg Δ → m α
e => Stmt.expr: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α
Stmt.expr (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m α
ExceptT.lift ∘ₑ e: Assg Γ → Assg Δ → m α
e)
| Stmt.bind: {m : Type → Type ?u.279194} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind s: Stmt m ω Γ Δ false c α✝
s s': Stmt m ω (α✝ :: Γ) Δ false c α
s' => Stmt.bind: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c β
Stmt.bind (C: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false α
C s: Stmt m ω Γ Δ false c α✝
s) (C: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false α
C s': Stmt m ω (α✝ :: Γ) Δ false c α
s')
| Stmt.letmut: {m : Type → Type ?u.279281} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e s: Stmt m ω Γ (α✝ :: Δ) false c α
s => Stmt.letmut: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c β
Stmt.letmut e: Assg Γ → Assg Δ → α✝
e (C: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false α
C s: Stmt m ω Γ (α✝ :: Δ) false c α
s)
| Stmt.assg: {m : Type → Type ?u.279374} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e => Stmt.assg: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit
Stmt.assg x: Fin (List.length Δ)
x e: Assg Γ → Assg Δ → List.get Δ x
e
| Stmt.ite: {m : Type → Type ?u.279463} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e s₁: Stmt m ω Γ Δ false c α
s₁ s₂: Stmt m ω Γ Δ false c α
s₂ => Stmt.ite: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} →
{α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α
Stmt.ite e: Assg Γ → Assg Δ → Bool
e (C: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false α
C s₁: Stmt m ω Γ Δ false c α
s₁) (C: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false α
C s₂: Stmt m ω Γ Δ false c α
s₂)
| Stmt.ret: {m : Type → Type ?u.279557} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e => Stmt.ret: {m : Type → Type u_1} →
{ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α
Stmt.ret e: Assg Γ → Assg Δ → ω
e
| Stmt.sfor: {m : Type → Type ?u.279621} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s => Stmt.sfor: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{α : Type} →
{b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unit
Stmt.sfor e: Assg Γ → Assg Δ → List α✝
e (L: {m : Type → Type u_1} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c α
L s: Stmt m ω (α✝ :: Γ) Δ true true Unit
s)
The remaining function to be translated is D
, which is straightforward as well except for its termination proof,
as it recurses on the results of S
(D3) and C ∘ B
(D5). Because of rules (S2, S9) that introduce new bindings,
S
may in fact increase the size of the input, and the same is true for C
and B
for the sizeOf
function
automatically generated by Lean. Thus we introduce a new measure numExts
that counts the number of special statements
on top of basic do
notation and prove that all three functions do not increase the size according to that measure.
Because the rules (D3) and (D5) each eliminate such a special statement, it follows that D
terminates because either
the number of special statements decreases in each case, or it remains the same and the total number of statements decreases.
@[simp] defStmt.numExts :Stmt.numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatStmtStmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolα →α: TypeNat |Nat: Typeexpr _ =>expr: {m : Type → Type ?u.314493} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c α0 |0: Natbindbind: {m : Type → Type ?u.314556} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βs₁s₁: Stmt m ω Γ Δ b c α✝s₂ =>s₂: Stmt m ω (α✝ :: Γ) Δ b c αs₁.s₁: Stmt m ω Γ Δ b c α✝numExts +numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nats₂.s₂: Stmt m ω (α✝ :: Γ) Δ b c αnumExts |numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Natletmut _letmut: {m : Type → Type ?u.314678} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c βs =>s: Stmt m ω Γ (α✝ :: Δ) b c αs.s: Stmt m ω Γ (α✝ :: Δ) b c αnumExts +numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nat1 |1: Natassg _ _ =>assg: {m : Type → Type ?u.314809} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit1 |1: Natite _ite: {m : Type → Type ?u.314889} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c αs₁s₁: Stmt m ω Γ Δ b c αs₂ =>s₂: Stmt m ω Γ Δ b c αs₁.s₁: Stmt m ω Γ Δ b c αnumExts +numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nats₂.s₂: Stmt m ω Γ Δ b c αnumExts |numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Natret _ =>ret: {m : Type → Type ?u.315027} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α1 |1: Natsfor _sfor: {m : Type → Type ?u.315088} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Units =>s: Stmt m ω (α✝ :: Γ) Δ true true Units.s: Stmt m ω (α✝ :: Γ) Δ true true UnitnumExts +numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nat1 |1: Natsbreak =>sbreak: {m : Type → Type ?u.315212} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → Stmt m ω Γ Δ true c α1 |1: Natscont =>scont: {m : Type → Type ?u.315254} → {ω : Type} → {Γ Δ : List Type} → {b : Bool} → {α : Type} → Stmt m ω Γ Δ b true α1 @[simp] theorem1: NatStmt.numExts_mapAssg (Stmt.numExts_mapAssg: ∀ {Γ' Γ : List Type} {m : Type → Type u_1} {ω : Type} {Δ : List Type} {b c : Bool} {β : Type} (f : Assg Γ' → Assg Γ) (s : Stmt m ω Γ Δ b c β), numExts (mapAssg f s) = numExts sf :f: Assg Γ' → Assg ΓAssgAssg: List Type → TypeΓ' →Γ': List TypeAssgAssg: List Type → TypeΓ) (Γ: List Types :s: Stmt m ω Γ Δ b c βStmtStmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolβ) :β: TypenumExts (numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatmapAssgmapAssg: {Γ' Γ : List Type} → {m : Type → Type u_1} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c βff: Assg Γ' → Assg Γs) =s: Stmt m ω Γ Δ b c βnumExtsnumExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nats :=s: Stmt m ω Γ Δ b c βΓ', Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
f: Assg Γ' → Assg Γ
s: Stmt m ω Γ Δ b c βnumExts (mapAssg f s) = numExts sΓ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → m α✝
Γ': List Type
f: Assg Γ' → Assg Γ✝
exprnumExts (mapAssg f (expr e✝)) = numExts (expr e✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (bind s✝ s'✝)) = numExts (bind s✝ s'✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (letmut e✝ s✝)) = numExts (letmut e✝ s✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (assg x✝ e✝)) = numExts (assg x✝ e✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (ite e✝ s₁✝ s₂✝)) = numExts (ite e✝ s₁✝ s₂✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → ω
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (ret e✝)) = numExts (ret e✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (sfor e✝ s✝)) = numExts (sfor e✝ s✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
c✝: Bool
α✝: Type
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f sbreak) = numExts sbreakΓ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝: Bool
α✝: Type
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f scont) = numExts scontΓ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → m α✝
Γ': List Type
f: Assg Γ' → Assg Γ✝
exprnumExts (mapAssg f (expr e✝)) = numExts (expr e✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (bind s✝ s'✝)) = numExts (bind s✝ s'✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (letmut e✝ s✝)) = numExts (letmut e✝ s✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (assg x✝ e✝)) = numExts (assg x✝ e✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (ite e✝ s₁✝ s₂✝)) = numExts (ite e✝ s₁✝ s₂✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → ω
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (ret e✝)) = numExts (ret e✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f (sfor e✝ s✝)) = numExts (sfor e✝ s✝)Γ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
c✝: Bool
α✝: Type
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f sbreak) = numExts sbreakΓ: List Type
m: Type → Type u_1
ω: Type
Δ: List Type
b, c: Bool
β: Type
Γ✝, Δ✝: List Type
b✝: Bool
α✝: Type
Γ': List Type
f: Assg Γ' → Assg Γ✝numExts (mapAssg f scont) = numExts sconttheoremGoals accomplished! 🐙Stmt.numExts_S [Stmt.numExts_S: ∀ {m : Type → Type} {ω : Type} {Γ Δ : List Type} {α : Type} {b c : Bool} {β : Type} [inst : Monad m] (s : Stmt m ω Γ (List.append Δ [α]) b c β), numExts (S s) ≤ numExts sMonadMonad: (Type ?u.330075 → Type ?u.330074) → Type (max (?u.330075 + 1) ?u.330074)m] (m: Type → Types :s: Stmt m ω Γ (List.append Δ [α]) b c βStmtStmt: (Type → Type) → Type → List Type → List Type → Bool → Bool → Type → Type 1mm: Type → Typeωω: TypeΓ (Γ: List TypeΔ ++ [Δ: List Typeα])α: Typebb: Boolcc: Boolβ) :β: TypenumExts (numExts: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatSS: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c βs) ≤s: Stmt m ω Γ (List.append Δ [α]) b c βnumExtsnumExts: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nats :=s: Stmt m ω Γ (List.append Δ [α]) b c βm: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
s: Stmt m ω Γ (List.append Δ [α]) b c βnumExts (S s) ≤ numExts sm: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m∀ (s : Stmt m ω Γ (List.append Δ [α]) b c β), numExts (S s) ≤ numExts sm: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m∀ {Δ' : List Type} (s : Stmt m ω Γ Δ' b c β) (h : Δ' = List.append Δ [α]), numExts (S (h ▸ s)) ≤ numExts sm: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ': List Type
s: Stmt m ω Γ Δ' b c β
h: Δ' = List.append Δ [α]numExts (S (h ▸ s)) ≤ numExts sm: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ': List Type
s: Stmt m ω Γ Δ' b c β
h: Δ' = List.append Δ [α]numExts (S (h ▸ s)) ≤ numExts sm: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
Δ: List Type
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → α✝
s✝: Stmt m ω Γ✝ (α✝ :: List.append Δ [α]) b✝ c✝ β✝
ih: ∀ {Δ_1 : List Type} (h : α✝ :: List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s✝)) ≤ numExts s✝
letmutnumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ letmut e✝ s✝)) ≤ numExts (letmut e✝ s✝)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
Δ: List Type
s✝: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) b✝ c✝ β✝
ih₁: ∀ {Δ_1 : List Type} (h : List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s✝)) ≤ numExts s✝
ih₂: ∀ {Δ_1 : List Type} (h : List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s'✝)) ≤ numExts s'✝
bindnumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ bind s✝ s'✝)) ≤ numExts (bind s✝ s'✝)Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
Δ: List Type
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → α✝
s✝: Stmt m ω Γ✝ (α✝ :: List.append Δ [α]) b✝ c✝ β✝
ih: ∀ {Δ_1 : List Type} (h : α✝ :: List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s✝)) ≤ numExts s✝
letmutnumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ letmut e✝ s✝)) ≤ numExts (letmut e✝ s✝)Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
Δ: List Type
x✝: Fin (List.length (List.append Δ [α]))
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → List.get (List.append Δ [α]) x✝
assgnumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ assg x✝ e✝)) ≤ numExts (assg x✝ e✝)Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝: Type
Δ: List Type
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
ih₁: ∀ {Δ_1 : List Type} (h : List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s₁✝)) ≤ numExts s₁✝
ih₂: ∀ {Δ_1 : List Type} (h : List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s₂✝)) ≤ numExts s₂✝
itenumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ ite e✝ s₁✝ s₂✝)) ≤ numExts (ite e✝ s₁✝ s₂✝)Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ {Δ_1 : List Type} (h : List.append Δ [α] = List.append Δ_1 [α]), numExts (S (h ▸ s✝)) ≤ numExts s✝
sfornumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ sfor e✝ s✝)) ≤ numExts (sfor e✝ s✝)Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝: Type
Δ: List Type
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → ω
retnumExts (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ ret e✝)) ≤ numExts (ret e✝)theoremGoals accomplished! 🐙Stmt.numExts_L_L [Stmt.numExts_L_L: ∀ {m : Type → Type u_1} {ω : Type} {Γ Δ : List Type} {b c : Bool} {β : Type} [inst : Monad m] (s : Stmt m ω Γ Δ b c β), numExts (L (L s)) ≤ numExts sMonadMonad: (Type ?u.339386 → Type ?u.339385) → Type (max (?u.339386 + 1) ?u.339385)m] (m: Type → Type u_1s :s: Stmt m ω Γ Δ b c βStmtStmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolβ) :β: TypenumExts (numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatL (L: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c αLL: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c αs)) ≤s: Stmt m ω Γ Δ b c βnumExtsnumExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nats :=s: Stmt m ω Γ Δ b c βm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
s: Stmt m ω Γ Δ b c βnumExts (L (L s)) ≤ numExts sm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → m α✝
exprnumExts (L (L (expr e✝))) ≤ numExts (expr e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝numExts (L (L (bind s✝ s'✝))) ≤ numExts (bind s✝ s'✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝numExts (L (L (letmut e✝ s✝))) ≤ numExts (letmut e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝numExts (L (L (assg x✝ e✝))) ≤ numExts (assg x✝ e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝numExts (L (L (ite e✝ s₁✝ s₂✝))) ≤ numExts (ite e✝ s₁✝ s₂✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → ωnumExts (L (L (ret e✝))) ≤ numExts (ret e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true UnitnumExts (L (L (sfor e✝ s✝))) ≤ numExts (sfor e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
c✝: Bool
α✝: TypenumExts (L (L sbreak)) ≤ numExts sbreakm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝: Bool
α✝: TypenumExts (L (L scont)) ≤ numExts scontm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → m α✝
exprnumExts (L (L (expr e✝))) ≤ numExts (expr e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝numExts (L (L (bind s✝ s'✝))) ≤ numExts (bind s✝ s'✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝numExts (L (L (letmut e✝ s✝))) ≤ numExts (letmut e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝numExts (L (L (assg x✝ e✝))) ≤ numExts (assg x✝ e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝numExts (L (L (ite e✝ s₁✝ s₂✝))) ≤ numExts (ite e✝ s₁✝ s₂✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → ωnumExts (L (L (ret e✝))) ≤ numExts (ret e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true UnitnumExts (L (L (sfor e✝ s✝))) ≤ numExts (sfor e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
c✝: Bool
α✝: TypenumExts (L (L sbreak)) ≤ numExts sbreakm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝: Bool
α✝: TypenumExts (L (L scont)) ≤ numExts sconttheoremGoals accomplished! 🐙Stmt.numExts_C_B [Stmt.numExts_C_B: ∀ {m : Type → Type u_1} {ω : Type} {Γ Δ : List Type} {b c : Bool} {β : Type} [inst : Monad m] (s : Stmt m ω Γ Δ b c β), numExts (C (B s)) ≤ numExts sMonadMonad: (Type ?u.342450 → Type ?u.342449) → Type (max (?u.342450 + 1) ?u.342449)m] (m: Type → Type u_1s :s: Stmt m ω Γ Δ b c βStmtStmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolβ) :β: TypenumExts (numExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatC (C: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false αBB: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c αs)) ≤s: Stmt m ω Γ Δ b c βnumExtsnumExts: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → Nats :=s: Stmt m ω Γ Δ b c βm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
s: Stmt m ω Γ Δ b c βnumExts (C (B s)) ≤ numExts sm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → m α✝
exprnumExts (C (B (expr e✝))) ≤ numExts (expr e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝numExts (C (B (bind s✝ s'✝))) ≤ numExts (bind s✝ s'✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝numExts (C (B (letmut e✝ s✝))) ≤ numExts (letmut e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝numExts (C (B (assg x✝ e✝))) ≤ numExts (assg x✝ e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝numExts (C (B (ite e✝ s₁✝ s₂✝))) ≤ numExts (ite e✝ s₁✝ s₂✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → ωnumExts (C (B (ret e✝))) ≤ numExts (ret e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true UnitnumExts (C (B (sfor e✝ s✝))) ≤ numExts (sfor e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
c✝: Bool
α✝: TypenumExts (C (B sbreak)) ≤ numExts sbreakm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝: Bool
α✝: TypenumExts (C (B scont)) ≤ numExts scontm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → m α✝
exprnumExts (C (B (expr e✝))) ≤ numExts (expr e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝numExts (C (B (bind s✝ s'✝))) ≤ numExts (bind s✝ s'✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝numExts (C (B (letmut e✝ s✝))) ≤ numExts (letmut e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝numExts (C (B (assg x✝ e✝))) ≤ numExts (assg x✝ e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝numExts (C (B (ite e✝ s₁✝ s₂✝))) ≤ numExts (ite e✝ s₁✝ s₂✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → ωnumExts (C (B (ret e✝))) ≤ numExts (ret e✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e✝: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true UnitnumExts (C (B (sfor e✝ s✝))) ≤ numExts (sfor e✝ s✝)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
c✝: Bool
α✝: TypenumExts (C (B sbreak)) ≤ numExts sbreakm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
β: Type
inst✝: Monad m
Γ✝, Δ✝: List Type
b✝: Bool
α✝: TypenumExts (C (B scont)) ≤ numExts scont-- Auxiliary tactic for showing that `D` terminates macro "D_tac" : tactic => `({simp_wf solve | apply Prod.Lex.left; assumption | apply Prod.Lex.right' <;> simp_arith }) @[simp] defGoals accomplished! 🐙D [D: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αMonadMonad: (Type ?u.348150 → Type ?u.348149) → Type (max (?u.348150 + 1) ?u.348149)m] :m: Type → TypeStmtStmt: (Type → Type) → Type → List Type → List Type → Bool → Bool → Type → Type 1mm: Type → TypeEmptyEmpty: TypeΓΓ: List Type∅∅: List Typefalsefalse: Boolfalsefalse: Boolα → (α: TypeΓ ⊢Γ: List Typemm: Type → Typeα) |α: TypeStmt.exprStmt.expr: {m : Type → Type ?u.349536} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c αe => (e: Assg Γ → Assg ∅ → m αe[·][e: Assg Γ → Assg ∅ → m α∅]) |∅: Assg ∅Stmt.bindStmt.bind: {m : Type → Type ?u.349597} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βss: Stmt m Empty Γ ∅ false false α✝s' => (funs': Stmt m Empty (α✝ :: Γ) ∅ false false αρ =>ρ: Assg ΓDD: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αss: Stmt m Empty Γ ∅ false false α✝ρ >>= funρ: Assg Γx =>x: α✝DD: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αs' (s': Stmt m Empty (α✝ :: Γ) ∅ false false αx ::x: α✝ρ)) |ρ: Assg ΓStmt.letmutStmt.letmut: {m : Type → Type ?u.349872} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c βee: Assg Γ → Assg ∅ → α✝s => have :=s: Stmt m Empty Γ (α✝ :: ∅) false false αNat.lt_succ_of_le <|Nat.lt_succ_of_le: ∀ {n m : Nat}, n ≤ m → n < Nat.succ mStmt.numExts_S (Δ :=Stmt.numExts_S: ∀ {m : Type → Type} {ω : Type} {Γ Δ : List Type} {α : Type} {b c : Bool} {β : Type} [inst : Monad m] (s : Stmt m ω Γ (List.append Δ [α]) b c β), Stmt.numExts (S s) ≤ Stmt.numExts s[])[]: List Types -- for termination funs: Stmt m Empty Γ (α✝ :: ∅) false false αρ => letρ: Assg Γx :=x: α✝e[e: Assg Γ → Assg ∅ → α✝ρ][ρ: Assg Γ∅]∅: Assg ∅StateT.run' (StateT.run': {σ : Type} → {m : Type → Type} → [inst : Functor m] → {α : Type} → StateT σ m α → σ → m αD (D: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αSS: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c βs) (s: Stmt m Empty Γ (α✝ :: ∅) false false αx ::x: α✝ρ))ρ: Assg Γx |x: α✝Stmt.iteStmt.ite: {m : Type → Type ?u.350351} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c αee: Assg Γ → Assg ∅ → Bools₁s₁: Stmt m Empty Γ ∅ false false αs₂ => (funs₂: Stmt m Empty Γ ∅ false false αρ => ifρ: Assg Γe[e: Assg Γ → Assg ∅ → Boolρ][ρ: Assg Γ∅] then∅: Assg ∅DD: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αs₁s₁: Stmt m Empty Γ ∅ false false αρ elseρ: Assg ΓDD: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αs₂s₂: Stmt m Empty Γ ∅ false false αρ) |ρ: Assg ΓStmt.sforStmt.sfor: {m : Type → Type ?u.350515} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unitee: Assg Γ → Assg ∅ → List α✝s => have :=s: Stmt m Empty (α✝ :: Γ) ∅ true true UnitNat.lt_succ_of_le <|Nat.lt_succ_of_le: ∀ {n m : Nat}, n ≤ m → n < Nat.succ mStmt.numExts_C_B (Δ :=Stmt.numExts_C_B: ∀ {m : Type → Type} {ω : Type} {Γ Δ : List Type} {b c : Bool} {β : Type} [inst : Monad m] (s : Stmt m ω Γ Δ b c β), Stmt.numExts (C (B s)) ≤ Stmt.numExts s[])[]: List Types -- for termination funs: Stmt m Empty (α✝ :: Γ) ∅ true true Unitρ =>ρ: Assg ΓrunCatch (runCatch: {m : Type → Type} → {α : Type} → [inst : Monad m] → ExceptT α m α → m αforMforM: {m : Type → Type} → {γ α : Type} → [self : ForM m γ α] → [inst : Monad m] → γ → (α → m PUnit) → m PUnite[e: Assg Γ → Assg ∅ → List α✝ρ][ρ: Assg Γ∅] (fun∅: Assg ∅x =>x: α✝runCatch (runCatch: {m : Type → Type} → {α : Type} → [inst : Monad m] → ExceptT α m α → m αD (D: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αC (C: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false αBB: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c αs)) (s: Stmt m Empty (α✝ :: Γ) ∅ true true Unitx ::x: α✝ρ)))) |ρ: Assg ΓStmt.retStmt.ret: {m : Type → Type ?u.351104} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c αe => (nomatche: Assg Γ → Assg ∅ → Emptye[·][e: Assg Γ → Assg ∅ → Empty∅]) termination_by _ s => (∅: Assg ∅s.s: Stmt m Empty Γ ∅ false false αnumExts,numExts: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatsizeOfsizeOf: {α : Type 1} → [self : SizeOf α] → α → Nats) decreasing_bys: Stmt m Empty Γ ∅ false false αGoals accomplished! 🐙
Finally we compose D
and R
into the translation rule for a top-level statement (1').
def Do.trans: {m : Type → Type} → {α : Type} → [inst : Monad m] → Do m α → m α
Do.trans [Monad: (Type → Type) → Type 1
Monad m: Type → Type
m] (s: Do m α
s : Do: (Type → Type) → Type → Type 1
Do m: Type → Type
m α: Type
α) : m: Type → Type
m α: Type
α := runCatch: {m : Type → Type} → {α : Type} → [inst : Monad m] → ExceptT α m α → m α
runCatch (D: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m α
D (R: {m : Type → Type} →
{ω : Type} →
{Γ Δ : List Type} →
{b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c α
R s: Do m α
s) ∅: Assg ∅
∅)
Equivalence Proof
Using the monadic dynamic semantics, we can modularly prove for each individual translation function that evaluating its output is equivalent to directly evaluating the input, modulo some lifting and adjustment of resulting values. After induction on the statement, the proofs are mostly concerned with case splitting, application of congruence theorems, and simplification. We can mostly offload these tasks onto Aesop.
attribute [local simp]map_eq_pure_bindmap_eq_pure_bind: ∀ {m : Type u_1 → Type u_2} {α β : Type u_1} [inst : Monad m] [inst_1 : LawfulMonad m] (f : α → β) (x : m α), f <$> x = do let a ← x pure (f a)ExceptT.run_bind attribute [aesop safe apply]ExceptT.run_bind: ∀ {m : Type u_1 → Type u_2} {ε α β : Type u_1} {f : α → ExceptT ε m β} [inst : Monad m] (x : ExceptT ε m α), ExceptT.run (x >>= f) = do let x ← ExceptT.run x match x with | Except.ok x => ExceptT.run (f x) | Except.error e => pure (Except.error e)bind_congr theorembind_congr: ∀ {m : Type u_1 → Type u_2} {α β : Type u_1} [inst : Bind m] {x : m α} {f g : α → m β}, (∀ (a : α), f a = g a) → x >>= f = x >>= geval_R [eval_R: ∀ {m : Type → Type u_1} {ω : Type} {Γ Δ : List Type} {b c : Bool} {α : Type} {ρ : Assg Γ} {σ : Assg Δ} [inst : Monad m] [inst_1 : LawfulMonad m] (s : Stmt m ω Γ Δ b c α), Stmt.eval ρ (R s) σ = do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)MonadMonad: (Type ?u.373143 → Type ?u.373142) → Type (max (?u.373143 + 1) ?u.373142)m] [m: Type → Type u_1LawfulMonadLawfulMonad: (m : Type ?u.373172 → Type ?u.373171) → [inst : Monad m] → Propm] (m: Type → Type u_1s :s: Stmt m ω Γ Δ b c αStmtStmt: (Type → Type ?u.373206) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 ?u.373206)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolα) : (α: TypeRR: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT ω m) Empty Γ Δ b c αs).s: Stmt m ω Γ Δ b c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ = (σ: Assg ΔExceptT.lift (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m αs.s: Stmt m ω Γ Δ b c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ) >>= funσ: Assg Δx => match (generalizing := false)x: Neut ω α b c × Assg Δx with | (x: Neut ω α b c × Assg ΔNeut.retNeut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b co, _) =>o: ωthrowthrow: {ε : Type} → {m : Type → Type u_1} → [self : MonadExcept ε m] → {α : Type} → ε → m αo | (o: ωNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca,a: ασ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca,a: ασ) | (σ: Assg ΔNeut.rcont,Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b trueσ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.rcont,Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b trueσ) | (σ: Assg ΔNeut.rbreak,Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true cσ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.rbreak,Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true cσ) :σ: Assg ΔExceptTExceptT: Type → (Type → Type u_1) → Type → Type u_1ωω: Typem (m: Type → Type u_1NeutNeut: Type → Type → Bool → Bool → TypeEmptyEmpty: Typeαα: Typebb: Boolc ×c: BoolAssgAssg: List Type → TypeΔ)) :=Δ: List Typem: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c αStmt.eval ρ (R s) σ = do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c α
hExceptT.run (Stmt.eval ρ (R s) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c α
hExceptT.run (Stmt.eval ρ (R s) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sforExceptT.run (Stmt.eval ρ (R (Stmt.sfor e s✝)) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ (Stmt.sfor e s✝) σ) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sforExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (R s✝) σ (e ρ σ)) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (e ρ σ)) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sfor.nilExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (R s✝) σ []) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ []) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝ExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (R s✝) σ (head✝ :: tail✝)) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (head✝ :: tail✝)) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sfor.nilExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (R s✝) σ []) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ []) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝ExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (R s✝) σ (head✝ :: tail✝)) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (head✝ :: tail✝)) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)Goals accomplished! 🐙m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝
ρ: Assg Γ✝
σ: Assg Δ✝
h.letmutExceptT.run (Stmt.eval ρ (R (Stmt.letmut e✝ s✝)) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ (Stmt.letmut e✝ s✝) σ) match b✝, c✝, x with | b, c, (Neut.ret o, snd) => throw o | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, σ) => pure (Neut.rbreak, σ)@[simp] theoremGoals accomplished! 🐙eval_mapAssg [eval_mapAssg: ∀ {m : Type → Type u_1} {Γ' Γ : List Type} {ω : Type} {Δ : List Type} {b c : Bool} {β : Type} {ρ : Assg Γ'} {σ : Assg Δ} [inst : Monad m] [inst_1 : LawfulMonad m] (f : Assg Γ' → Assg Γ) (s : Stmt m ω Γ Δ b c β), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σMonadMonad: (Type ?u.513583 → Type ?u.513582) → Type (max (?u.513583 + 1) ?u.513582)m] [m: Type → Type u_1LawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] (m: Type → Type u_1f :f: Assg Γ' → Assg ΓAssgAssg: List (Type ?u.513856) → Type ?u.513856Γ' →Γ': List TypeAssgAssg: List (Type ?u.513712) → Type ?u.513712Γ) : ∀ (Γ: List Types :s: Stmt m ω Γ Δ b c βStmtStmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolβ),β: TypeStmt.evalStmt.eval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρ (ρ: Assg Γ'Stmt.mapAssgStmt.mapAssg: {Γ' Γ : List Type} → {m : Type → Type u_1} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {β : Type} → (Assg Γ' → Assg Γ) → Stmt m ω Γ Δ b c β → Stmt m ω Γ' Δ b c βff: Assg Γ' → Assg Γs)s: Stmt m ω Γ Δ b c βσ =σ: Assg ΔStmt.eval (Stmt.eval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ff: Assg Γ' → Assg Γρ)ρ: Assg Γ'ss: Stmt m ω Γ Δ b c βσ :=σ: Assg Δm: Type → Type u_1
Γ', Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
ρ: Assg Γ'
σ: Assg Δ
inst✝¹: Monad m
f: Assg Γ' → Assg Γ∀ (s : Stmt m ω Γ Δ b c β), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σm: Type → Type u_1
Γ', Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
ρ: Assg Γ'
σ: Assg Δ
inst✝¹: Monad m
f: Assg Γ' → Assg Γ
s: Stmt m ω Γ Δ b c βStmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σm: Type → Type u_1
Γ', Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
ρ: Assg Γ'
σ: Assg Δ
inst✝¹: Monad m
f: Assg Γ' → Assg Γ
s: Stmt m ω Γ Δ b c βStmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σm: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ih: ∀ {Γ' : List Type} {ρ : Assg Γ'} {σ : Assg Δ✝} (f : Assg Γ' → Assg (α✝ :: Γ✝)), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σ
Γ': List Type
ρ: Assg Γ'
σ: Assg Δ✝
f: Assg Γ' → Assg Γ✝
sforStmt.eval ρ (Stmt.mapAssg f (Stmt.sfor e s)) σ = Stmt.eval (f ρ) (Stmt.sfor e s) σm: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ih: ∀ {Γ' : List Type} {ρ : Assg Γ'} {σ : Assg Δ✝} (f : Assg Γ' → Assg (α✝ :: Γ✝)), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σ
Γ': List Type
ρ: Assg Γ'
σ: Assg Δ✝
f: Assg Γ' → Assg Γ✝
sforStmt.eval.go ρ c✝ b✝ α✝ (Stmt.mapAssg (fun x => match x with | (a, as) => a :: f as) s) σ (e (f ρ) σ) = Stmt.eval.go (f ρ) c✝ b✝ α✝ s σ (e (f ρ) σ)m: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ih: ∀ {Γ' : List Type} {ρ : Assg Γ'} {σ : Assg Δ✝} (f : Assg Γ' → Assg (α✝ :: Γ✝)), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σ
Γ': List Type
ρ: Assg Γ'
f: Assg Γ' → Assg Γ✝
σ: Assg Δ✝
sfor.nilStmt.eval.go ρ c✝ b✝ α✝ (Stmt.mapAssg (fun x => match x with | (a, as) => a :: f as) s) σ [] = Stmt.eval.go (f ρ) c✝ b✝ α✝ s σ []m: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ih: ∀ {Γ' : List Type} {ρ : Assg Γ'} {σ : Assg Δ✝} (f : Assg Γ' → Assg (α✝ :: Γ✝)), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σ
Γ': List Type
ρ: Assg Γ'
f: Assg Γ' → Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝Stmt.eval.go ρ c✝ b✝ α✝ (Stmt.mapAssg (fun x => match x with | (a, as) => a :: f as) s) σ (head✝ :: tail✝) = Stmt.eval.go (f ρ) c✝ b✝ α✝ s σ (head✝ :: tail✝)m: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ih: ∀ {Γ' : List Type} {ρ : Assg Γ'} {σ : Assg Δ✝} (f : Assg Γ' → Assg (α✝ :: Γ✝)), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σ
Γ': List Type
ρ: Assg Γ'
f: Assg Γ' → Assg Γ✝
σ: Assg Δ✝
sfor.nilStmt.eval.go ρ c✝ b✝ α✝ (Stmt.mapAssg (fun x => match x with | (a, as) => a :: f as) s) σ [] = Stmt.eval.go (f ρ) c✝ b✝ α✝ s σ []m: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ih: ∀ {Γ' : List Type} {ρ : Assg Γ'} {σ : Assg Δ✝} (f : Assg Γ' → Assg (α✝ :: Γ✝)), Stmt.eval ρ (Stmt.mapAssg f s) σ = Stmt.eval (f ρ) s σ
Γ': List Type
ρ: Assg Γ'
f: Assg Γ' → Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝Stmt.eval.go ρ c✝ b✝ α✝ (Stmt.mapAssg (fun x => match x with | (a, as) => a :: f as) s) σ (head✝ :: tail✝) = Stmt.eval.go (f ρ) c✝ b✝ α✝ s σ (head✝ :: tail✝)Goals accomplished! 🐙m: Type → Type u_1
Γ: List Type
ω: Type
Δ: List Type
b, c: Bool
β: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝
Γ': List Type
ρ: Assg Γ'
σ: Assg Δ✝
f: Assg Γ' → Assg Γ✝
letmutStmt.eval ρ (Stmt.mapAssg f (Stmt.letmut e✝ s✝)) σ = Stmt.eval (f ρ) (Stmt.letmut e✝ s✝) σGoals accomplished! 🐙
We need one last helper function on context bottoms to be able to state the invariant of S
, and then
prove various lemmas about their interactions.
defAssg.bot : {Assg.bot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → αΓ :Γ: List (Type u_1)_} →_: Type (u_1 + 1)Assg (Assg: List (Type u_1) → Type u_1Γ ++ [Γ: List (Type u_1)α]) →α: Type u_1α | [], [α: Type u_1a] =>a: αa | _ ::a: α_, _ ::_: List (Type u_1)as =>as: HList (List.append tail✝ [α])botbot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → αas @[simp] theoremas: HList (List.append tail✝ [α])Assg.dropBot_extendBot (Assg.dropBot_extendBot: ∀ {α : Type u_1} {Γ : List (Type u_1)} (a : α) (σ : Assg Γ), dropBot (extendBot a σ) = σa :a: αα) (α: Type u_1σ :σ: Assg ΓAssgAssg: List (Type u_1) → Type u_1Γ) :Γ: List (Type u_1)Assg.dropBot (Assg.dropBot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → Assg ΓAssg.extendBotAssg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])aa: ασ) =σ: Assg Γσ :=σ: Assg Γα: Type u_1
Γ: List (Type u_1)
a: α
σ: Assg ΓdropBot (extendBot a σ) = σα: Type u_1
a: α
σ: Assg []
nildropBot (extendBot a σ) = σα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
σ: Assg (head✝ :: tail✝)dropBot (extendBot a σ) = σα: Type u_1
a: α
σ: Assg []
nildropBot (extendBot a σ) = σα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
σ: Assg (head✝ :: tail✝)dropBot (extendBot a σ) = σα: Type u_1
a: α
nil.unitdropBot (extendBot a PUnit.unit) = PUnit.unitα: Type u_1
a: α
nil.unitdropBot (extendBot a PUnit.unit) = PUnit.unit@[simp] theoremGoals accomplished! 🐙Assg.bot_extendBot (Assg.bot_extendBot: ∀ {α : Type u_1} {Γ : List (Type u_1)} (a : α) (σ : Assg Γ), bot (extendBot a σ) = aa :a: αα) (α: Type u_1σ :σ: Assg ΓAssgAssg: List (Type u_1) → Type u_1Γ) :Γ: List (Type u_1)Assg.bot (Assg.bot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → αAssg.extendBotAssg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])aa: ασ) =σ: Assg Γa :=a: αα: Type u_1
Γ: List (Type u_1)
a: α
σ: Assg Γbot (extendBot a σ) = aα: Type u_1
a: α
σ: Assg []
nilbot (extendBot a σ) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
σ: Assg (head✝ :: tail✝)bot (extendBot a σ) = aα: Type u_1
a: α
σ: Assg []
nilbot (extendBot a σ) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
σ: Assg (head✝ :: tail✝)bot (extendBot a σ) = aα: Type u_1
a: α
nil.unitbot (extendBot a PUnit.unit) = aα: Type u_1
a: α
nil.unitbot (extendBot a PUnit.unit) = a@[simp] theoremGoals accomplished! 🐙Assg.extendBot_bot_dropBot (Assg.extendBot_bot_dropBot: ∀ {Γ : List (Type u_1)} {α : Type u_1} (σ : Assg (List.append Γ [α])), extendBot (bot σ) (dropBot σ) = σσ :σ: Assg (List.append Γ [α])Assg (Assg: List (Type u_1) → Type u_1Γ ++ [Γ: List (Type u_1)α])) :α: Type u_1Assg.extendBot (Assg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])Assg.botAssg.bot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → ασ) (σ: Assg (List.append Γ [α])Assg.dropBotAssg.dropBot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → Assg Γσ) =σ: Assg (List.append Γ [α])σ :=σ: Assg (List.append Γ [α])Γ: List (Type u_1)
α: Type u_1
σ: Assg (List.append Γ [α])extendBot (bot σ) (dropBot σ) = σα: Type u_1
σ: Assg (List.append [] [α])
nilextendBot (bot σ) (dropBot σ) = σα, head✝: Type u_1
tail✝: List (Type u_1)
σ: Assg (List.append (head✝ :: tail✝) [α])extendBot (bot σ) (dropBot σ) = σα: Type u_1
σ: Assg (List.append [] [α])
nilextendBot (bot σ) (dropBot σ) = σα, head✝: Type u_1
tail✝: List (Type u_1)
σ: Assg (List.append (head✝ :: tail✝) [α])extendBot (bot σ) (dropBot σ) = σα: Type u_1
fst✝: α
snd✝: HList []
nil.mkextendBot (bot (fst✝, snd✝)) (dropBot (fst✝, snd✝)) = (fst✝, snd✝)α: Type u_1
fst✝: α
snd✝: HList []
nil.mkextendBot (bot (fst✝, snd✝)) (dropBot (fst✝, snd✝)) = (fst✝, snd✝)Goals accomplished! 🐙Goals accomplished! 🐙@[simp] theoremGoals accomplished! 🐙Assg.dropBot_set_extendBot_init (Assg.dropBot_set_extendBot_init: ∀ {α : Type u_1} {Γ : List (Type u_1)} {i : Fin (List.length (List.append Γ [α]))} (a : α) (σ : Assg Γ) (h : i.val < List.length Γ) {b : List.get (List.append Γ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (Γ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (Γ ++ [α])) } = List.get Γ { val := i.val, isLt := h }) ▸ b)a :a: αα) (α: Type u_1σ :σ: Assg ΓAssgAssg: List (Type u_1) → Type u_1Γ) (Γ: List (Type u_1)h :h: i.val < List.length Γi.i: Fin (List.length (List.append Γ [α]))1 <1: {n : Nat} → Fin n → NatΓ.Γ: List (Type u_1)length) {length: {α : Type (u_1 + 1)} → List α → Natb} :b: List.get (List.append Γ [α]) iAssg.dropBot ((Assg.dropBot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → Assg ΓAssg.extendBotAssg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])aa: ασ).σ: Assg Γsetset: {αs : List (Type u_1)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αsii: Fin (List.length (List.append Γ [α]))b) =b: List.get (List.append Γ [α]) iσ.σ: Assg Γset ⟨set: {αs : List (Type u_1)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αsi.i: Fin (List.length (List.append Γ [α]))1,1: {n : Nat} → Fin n → Nath⟩ (h: i.val < List.length ΓList.get_append_left .. ▸List.get_append_left: ∀ {α : Type (u_1 + 1)} {i : Nat} (as bs : List α) (h : i < List.length as) {h' : i < List.length (as ++ bs)}, List.get (as ++ bs) { val := i, isLt := h' } = List.get as { val := i, isLt := h }b) :=b: List.get (List.append Γ [α]) iα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: i.val < List.length Γ
b: List.get (List.append Γ [α]) idropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (Γ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (Γ ++ [α])) } = List.get Γ { val := i.val, isLt := h }) ▸ b)α: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: i.val < List.length Γ
b: List.get (List.append Γ [α]) idropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (Γ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (Γ ++ [α])) } = List.get Γ { val := i.val, isLt := h }) ▸ b)α: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h: i.val < List.length []
b: List.get (List.append [] [α]) i
nildropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get ([] ++ [α]) { val := i.val, isLt := (_ : i.val < List.length ([] ++ [α])) } = List.get [] { val := i.val, isLt := h }) ▸ b)Goals accomplished! 🐙α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
σ: Assg (head✝ :: tail✝)
h: i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
consdropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := i.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
h: i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
fst✝: head✝
snd✝: HList tail✝
cons.mkdropBot (HList.set (extendBot a (fst✝, snd✝)) i b) = HList.set (fst✝, snd✝) { val := i.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := i.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i✝: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
i: Nat
h': i < List.length (List.append (head✝ :: tail✝) [α])
h: { val := i, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := i, isLt := h' }
cons.mkdropBot (HList.set (extendBot a (fst✝, snd✝)) { val := i, isLt := h' } b) = HList.set (fst✝, snd✝) { val := { val := i, isLt := h' }.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := i, isLt := h' }.val, isLt := (_ : { val := i, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := i, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerodropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = HList.set (fst✝, snd✝) { val := { val := Nat.zero, isLt := h' }.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.zero, isLt := h' }.val, isLt := (_ : { val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.zero, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }dropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = HList.set (fst✝, snd✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := (_ : { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerodropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = HList.set (fst✝, snd✝) { val := { val := Nat.zero, isLt := h' }.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.zero, isLt := h' }.val, isLt := (_ : { val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.zero, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }dropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = HList.set (fst✝, snd✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := (_ : { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succfst✝ :: dropBot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = fst✝ :: HList.set snd✝ { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length tail✝) } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := (_ : { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succfst✝ :: dropBot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = fst✝ :: HList.set snd✝ { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length tail✝) } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := (_ : { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succfst✝ :: HList.set snd✝ { val := { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val, isLt := ?cons.mk.succ.h } ((_ : List.get (tail✝ ++ [α]) { val := { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val, isLt := (_ : { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val, isLt := ?cons.mk.succ.h }) ▸ b) = fst✝ :: HList.set snd✝ { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length tail✝) } ((_ : List.get (head✝ :: tail✝ ++ [α]) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := (_ : { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝ ++ [α])) } = List.get (head✝ :: tail✝) { val := { val := Nat.succ n✝, isLt := h' }.val, isLt := h }) ▸ b)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝) (h : i.val < List.length tail✝) {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = HList.set σ { val := i.val, isLt := h } ((_ : List.get (tail✝ ++ [α]) { val := i.val, isLt := (_ : i.val < List.length (tail✝ ++ [α])) } = List.get tail✝ { val := i.val, isLt := h }) ▸ b)
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝@[simp] theoremGoals accomplished! 🐙Assg.bot_set_extendBot_init (Assg.bot_set_extendBot_init: ∀ {α : Type u_1} {Γ : List (Type u_1)} {i : Fin (List.length (List.append Γ [α]))} (a : α) (σ : Assg Γ), i.val < List.length Γ → ∀ {b : List.get (List.append Γ [α]) i}, bot (HList.set (extendBot a σ) i b) = aa :a: αα) (α: Type u_1σ :σ: Assg ΓAssgAssg: List (Type u_1) → Type u_1Γ) (Γ: List (Type u_1)h :h: i.val < List.length Γi.i: Fin (List.length (List.append Γ [α]))1 <1: {n : Nat} → Fin n → NatΓ.Γ: List (Type u_1)length) {length: {α : Type (u_1 + 1)} → List α → Natb} :b: List.get (List.append Γ [α]) iAssg.bot ((Assg.bot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → αAssg.extendBotAssg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])aa: ασ).σ: Assg Γsetset: {αs : List (Type u_1)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αsii: Fin (List.length (List.append Γ [α]))b) =b: List.get (List.append Γ [α]) ia :=a: αα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: i.val < List.length Γ
b: List.get (List.append Γ [α]) ibot (HList.set (extendBot a σ) i b) = aα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: i.val < List.length Γ
b: List.get (List.append Γ [α]) ibot (HList.set (extendBot a σ) i b) = aα: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h: i.val < List.length []
b: List.get (List.append [] [α]) i
nilbot (HList.set (extendBot a σ) i b) = aGoals accomplished! 🐙α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
σ: Assg (head✝ :: tail✝)
h: i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
consbot (HList.set (extendBot a σ) i b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
h: i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
fst✝: head✝
snd✝: HList tail✝
cons.mkbot (HList.set (extendBot a (fst✝, snd✝)) i b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i✝: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
i: Nat
h': i < List.length (List.append (head✝ :: tail✝) [α])
h: { val := i, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := i, isLt := h' }
cons.mkbot (HList.set (extendBot a (fst✝, snd✝)) { val := i, isLt := h' } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerobot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }bot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerobot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }bot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succbot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succbot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succa = aα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝;α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = a
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: { val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succ.h{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝@[simp] theoremGoals accomplished! 🐙Assg.dropBot_set_extendBot_bottom (Assg.dropBot_set_extendBot_bottom: ∀ {α : Type u_1} {Γ : List (Type u_1)} {i : Fin (List.length (List.append Γ [α]))} (a : α) (σ : Assg Γ), ¬i.val < List.length Γ → ∀ {b : List.get (List.append Γ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σa :a: αα) (α: Type u_1σ :σ: Assg ΓAssgAssg: List (Type ?u.548037) → Type ?u.548037Γ) (Γ: List (Type u_1)h : ¬h: ¬i.val < List.length Γi.i: Fin (List.length (List.append Γ [α]))1 <1: {n : Nat} → Fin n → NatΓ.Γ: List (Type u_1)length) {length: {α : Type (u_1 + 1)} → List α → Natb} :b: List.get (List.append Γ [α]) iAssg.dropBot ((Assg.dropBot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → Assg ΓAssg.extendBotAssg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])aa: ασ).σ: Assg Γsetset: {αs : List (Type u_1)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αsii: Fin (List.length (List.append Γ [α]))b) =b: List.get (List.append Γ [α]) iσ :=σ: Assg Γα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: ¬i.val < List.length Γ
b: List.get (List.append Γ [α]) idropBot (HList.set (extendBot a σ) i b) = σα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: ¬i.val < List.length Γ
b: List.get (List.append Γ [α]) idropBot (HList.set (extendBot a σ) i b) = σα: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h: ¬i.val < List.length []
b: List.get (List.append [] [α]) i
nildropBot (HList.set (extendBot a σ) i b) = σGoals accomplished! 🐙α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
σ: Assg (head✝ :: tail✝)
h: ¬i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
consdropBot (HList.set (extendBot a σ) i b) = σα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
h: ¬i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
fst✝: head✝
snd✝: HList tail✝
cons.mkdropBot (HList.set (extendBot a (fst✝, snd✝)) i b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i✝: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
i: Nat
h': i < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := i, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := i, isLt := h' }
cons.mkdropBot (HList.set (extendBot a (fst✝, snd✝)) { val := i, isLt := h' } b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerodropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }dropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerodropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = (fst✝, snd✝)Goals accomplished! 🐙α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succdropBot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succfst✝ :: dropBot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succfst✝ :: dropBot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succfst✝ :: snd✝ = (fst✝, snd✝)α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }¬{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succ.h¬{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, dropBot (HList.set (extendBot a σ) i b) = σ
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
h'': { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝
cons.mk.succ.hFalse@[simp] theoremGoals accomplished! 🐙Assg.bot_set_extendBot_bottom (Assg.bot_set_extendBot_bottom: ∀ {α : Type u_1} {Γ : List (Type u_1)} {i : Fin (List.length (List.append Γ [α]))} (a : α) (σ : Assg Γ), ¬i.val < List.length Γ → ∀ {b : List.get (List.append Γ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (Γ ++ [α]) i = α) ba :a: αα) (α: Type u_1σ :σ: Assg ΓAssgAssg: List (Type u_1) → Type u_1Γ) (Γ: List (Type u_1)h : ¬h: ¬i.val < List.length Γi.i: Fin (List.length (List.append Γ [α]))1 <1: {n : Nat} → Fin n → NatΓ.Γ: List (Type u_1)length) {length: {α : Type (u_1 + 1)} → List α → Natb} :b: List.get (List.append Γ [α]) iAssg.bot ((Assg.bot: {α : Type u_1} → {Γ : List (Type u_1)} → Assg (List.append Γ [α]) → αAssg.extendBotAssg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])aa: ασ).σ: Assg Γsetset: {αs : List (Type u_1)} → HList αs → (i : Fin (List.length αs)) → List.get αs i → HList αsii: Fin (List.length (List.append Γ [α]))b) =b: List.get (List.append Γ [α]) icast (cast: {α β : Type u_1} → α = β → α → βList.get_lastList.get_last: ∀ {α : Type (u_1 + 1)} {a : α} {as : List α} {i : Fin (List.length (as ++ [a]))}, ¬i.val < List.length as → List.get (as ++ [a]) i = ah)h: ¬i.val < List.length Γb :=b: List.get (List.append Γ [α]) iα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: ¬i.val < List.length Γ
b: List.get (List.append Γ [α]) ibot (HList.set (extendBot a σ) i b) = cast (_ : List.get (Γ ++ [α]) i = α) bα: Type u_1
Γ: List (Type u_1)
i: Fin (List.length (List.append Γ [α]))
a: α
σ: Assg Γ
h: ¬i.val < List.length Γ
b: List.get (List.append Γ [α]) ibot (HList.set (extendBot a σ) i b) = cast (_ : List.get (Γ ++ [α]) i = α) bα: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h: ¬i.val < List.length []
b: List.get (List.append [] [α]) i
nilbot (HList.set (extendBot a σ) i b) = cast (_ : List.get ([] ++ [α]) i = α) bα: Type u_1
a: α
i✝: Fin (List.length (List.append [] [α]))
σ: Assg []
i: Nat
h': i < List.length (List.append [] [α])
h: ¬{ val := i, isLt := h' }.val < List.length []
b: List.get (List.append [] [α]) { val := i, isLt := h' }
nilbot (HList.set (extendBot a σ) { val := i, isLt := h' } b) = cast (_ : List.get ([] ++ [α]) { val := i, isLt := h' } = α) bα: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h': Nat.zero < List.length (List.append [] [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length []
b: List.get (List.append [] [α]) { val := Nat.zero, isLt := h' }
nil.zerobot (HList.set (extendBot a σ) { val := Nat.zero, isLt := h' } b) = cast (_ : List.get ([] ++ [α]) { val := Nat.zero, isLt := h' } = α) bα: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
n✝: Nat
h': Nat.succ n✝ < List.length (List.append [] [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length []
b: List.get (List.append [] [α]) { val := Nat.succ n✝, isLt := h' }bot (HList.set (extendBot a σ) { val := Nat.succ n✝, isLt := h' } b) = cast (_ : List.get ([] ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bα: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h': Nat.zero < List.length (List.append [] [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length []
b: List.get (List.append [] [α]) { val := Nat.zero, isLt := h' }
nil.zerobot (HList.set (extendBot a σ) { val := Nat.zero, isLt := h' } b) = cast (_ : List.get ([] ++ [α]) { val := Nat.zero, isLt := h' } = α) b;α: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
h': Nat.zero < List.length (List.append [] [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length []
b: List.get (List.append [] [α]) { val := Nat.zero, isLt := h' }
nil.zerob = cast (_ : List.get ([] ++ [α]) { val := Nat.zero, isLt := h' } = α) bGoals accomplished! 🐙α: Type u_1
a: α
i: Fin (List.length (List.append [] [α]))
σ: Assg []
n✝: Nat
h': Nat.succ n✝ < List.length (List.append [] [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length []
b: List.get (List.append [] [α]) { val := Nat.succ n✝, isLt := h' }
nil.succbot (HList.set (extendBot a σ) { val := Nat.succ n✝, isLt := h' } b) = cast (_ : List.get ([] ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bGoals accomplished! 🐙α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
σ: Assg (head✝ :: tail✝)
h: ¬i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
consbot (HList.set (extendBot a σ) i b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) i = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
h: ¬i.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) i
fst✝: head✝
snd✝: HList tail✝
cons.mkbot (HList.set (extendBot a (fst✝, snd✝)) i b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) i = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i✝: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
i: Nat
h': i < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := i, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := i, isLt := h' }
cons.mkbot (HList.set (extendBot a (fst✝, snd✝)) { val := i, isLt := h' } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := i, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerobot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.zero, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }bot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
h': Nat.zero < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.zero, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.zero, isLt := h' }
cons.mk.zerobot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.zero, isLt := h' } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.zero, isLt := h' } = α) bGoals accomplished! 🐙α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succbot (HList.set (extendBot a (fst✝, snd✝)) { val := Nat.succ n✝, isLt := h' } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succbot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succbot (HList.set (extendBot a snd✝) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } b) = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succcast (_ : List.get (tail✝ ++ [α]) { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) } = α) b = cast (_ : List.get (head✝ :: tail✝ ++ [α]) { val := Nat.succ n✝, isLt := h' } = α) bα: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }¬{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
cons.mk.succ.h¬{ val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝α: Type u_1
a: α
head✝: Type u_1
tail✝: List (Type u_1)
ih: ∀ {i : Fin (List.length (List.append tail✝ [α]))} (σ : Assg tail✝), ¬i.val < List.length tail✝ → ∀ {b : List.get (List.append tail✝ [α]) i}, bot (HList.set (extendBot a σ) i b) = cast (_ : List.get (tail✝ ++ [α]) i = α) b
i: Fin (List.length (List.append (head✝ :: tail✝) [α]))
fst✝: head✝
snd✝: HList tail✝
n✝: Nat
h': Nat.succ n✝ < List.length (List.append (head✝ :: tail✝) [α])
h: ¬{ val := Nat.succ n✝, isLt := h' }.val < List.length (head✝ :: tail✝)
b: List.get (List.append (head✝ :: tail✝) [α]) { val := Nat.succ n✝, isLt := h' }
h'': { val := n✝, isLt := (_ : Nat.succ n✝ ≤ List.length (tail✝ ++ [α])) }.val < List.length tail✝
cons.mk.succ.hFalsetheoremGoals accomplished! 🐙eval_S [eval_S: ∀ {m : Type → Type} {ω : Type} {Γ Δ : List Type} {α : Type} {b c : Bool} {β : Type} {a : α} {ρ : HList Γ} {σ : Assg Δ} [inst : Monad m] [inst_1 : LawfulMonad m] (s : Stmt m ω Γ (List.append Δ [α]) b c β), StateT.run (Stmt.eval (a :: ρ) (S s) σ) a = do let x ← Stmt.eval ρ s (Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot σ, Assg.bot σ)MonadMonad: (Type ?u.552273 → Type ?u.552272) → Type (max (?u.552273 + 1) ?u.552272)m] [m: Type → TypeLawfulMonadLawfulMonad: (m : Type → Type) → [inst : Monad m] → Propm] : ∀ (m: Type → Types :s: Stmt m ω Γ (List.append Δ [α]) b c βStmtStmt: (Type → Type) → Type → List Type → List Type → Bool → Bool → Type → Type 1mm: Type → Typeωω: TypeΓ (Γ: List TypeΔ ++ [Δ: List Typeα])α: Typebb: Boolcc: Boolβ),β: TypeStateT.run ((StateT.run: {σ : Type} → {m : Type → Type} → {α : Type} → StateT σ m α → σ → m (α × σ)SS: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → [inst : Monad m] → Stmt m ω Γ (List.append Δ [α]) b c β → Stmt (StateT α m) ω (α :: Γ) Δ b c βs).s: Stmt m ω Γ (List.append Δ [α]) b c βeval (eval: {m : Type → Type} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)a ::a: αρ)ρ: HList Γσ)σ: Assg Δa =a: αs.s: Stmt m ω Γ (List.append Δ [α]) b c βevaleval: {m : Type → Type} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρ (ρ: HList ΓAssg.extendBotAssg.extendBot: {α : Type} → α → {Γ : List Type} → Assg Γ → Assg (List.append Γ [α])aa: ασ) >>= fun |σ: Assg Δr ::r: Neut ω β b cσ =>σ: HList (List.append Δ [α])pure ((pure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αr ::r: Neut ω β b cAssg.dropBotAssg.dropBot: {α : Type} → {Γ : List Type} → Assg (List.append Γ [α]) → Assg Γσ),σ: HList (List.append Δ [α])Assg.botAssg.bot: {α : Type} → {Γ : List Type} → Assg (List.append Γ [α]) → ασ) :=σ: HList (List.append Δ [α])m: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
a: α
ρ: HList Γ
σ: Assg Δ
inst✝¹: Monad m∀ (s : Stmt m ω Γ (List.append Δ [α]) b c β), StateT.run (Stmt.eval (a :: ρ) (S s) σ) a = do let x ← Stmt.eval ρ s (Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot σ, Assg.bot σ)m: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
a: α
ρ: HList Γ
σ: Assg Δ
inst✝¹: Monad m∀ {Δ' : List Type} (s : Stmt m ω Γ Δ' b c β) (h : Δ' = List.append Δ [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = Δ') ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))m: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
a: α
ρ: HList Γ
σ: Assg Δ
inst✝¹: Monad m
Δ': List Type
s: Stmt m ω Γ Δ' b c β
h: Δ' = List.append Δ [α]StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = Δ') ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))m: Type → Type
ω: Type
Γ, Δ: List Type
α: Type
b, c: Bool
β: Type
a: α
ρ: HList Γ
σ: Assg Δ
inst✝¹: Monad m
Δ': List Type
s: Stmt m ω Γ Δ' b c β
h: Δ' = List.append Δ [α]StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = Δ') ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
iteStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.ite e✝ s₁✝ s₂✝)) σ) a = do let x ← Stmt.eval ρ (Stmt.ite e✝ s₁✝ s₂✝) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
s₁: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
s₂: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) b✝ c✝ β✝
ih₁: ∀ {Δ_1 : List Type} {a : α} {ρ : HList Γ✝} {σ : Assg Δ_1} (h : List.append Δ [α] = List.append Δ_1 [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s₁)) σ) a = do let x ← Stmt.eval ρ s₁ ((_ : List.append Δ_1 [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))
ih₂: ∀ {Δ_1 : List Type} {a : α} {ρ : HList (α✝ :: Γ✝)} {σ : Assg Δ_1} (h : List.append Δ [α] = List.append Δ_1 [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s₂)) σ) a = do let x ← Stmt.eval ρ s₂ ((_ : List.append Δ_1 [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))
bindStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.bind s₁ s₂)) σ) a = do let x ← Stmt.eval ρ (Stmt.bind s₁ s₂) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
s₁: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
s₂: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) b✝ c✝ β✝
ih₂: ∀ {Δ_1 : List Type} {a : α} {ρ : HList (α✝ :: Γ✝)} {σ : Assg Δ_1} (h : List.append Δ [α] = List.append Δ_1 [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s₂)) σ) a = do let x ← Stmt.eval ρ s₂ ((_ : List.append Δ_1 [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))
ih₁: ∀ (a : α) (ρ : HList Γ✝) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s₁)) σ) a = do let x ← Stmt.eval ρ s₁ ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
bindStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.bind s₁ s₂)) σ) a = do let x ← Stmt.eval ρ (Stmt.bind s₁ s₂) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
s₁: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
s₂: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) b✝ c✝ β✝
ih₁: ∀ (a : α) (ρ : HList Γ✝) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s₁)) σ) a = do let x ← Stmt.eval ρ s₁ ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
ih₂: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s₂)) σ) a = do let x ← Stmt.eval ρ s₂ ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
bindStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.bind s₁ s₂)) σ) a = do let x ← Stmt.eval ρ (Stmt.bind s₁ s₂) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → α✝
s: Stmt m ω Γ✝ (α✝ :: List.append Δ [α]) b✝ c✝ β✝
ih: ∀ {Δ_1 : List Type} {a : α} {ρ : HList Γ✝} {σ : Assg Δ_1} (h : α✝ :: List.append Δ [α] = List.append Δ_1 [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ_1 [α] = α✝ :: List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))
letmutStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.letmut e s)) σ) a = do let x ← Stmt.eval ρ (Stmt.letmut e s) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → α✝
s: Stmt m ω Γ✝ (α✝ :: List.append Δ [α]) b✝ c✝ β✝
ih: ∀ (a : α) (ρ : HList Γ✝) (σ : Assg (α✝ :: Δ)), StateT.run (Stmt.eval (a :: ρ) (S ((_ : α✝ :: List.append Δ [α] = α✝ :: List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append (α✝ :: Δ) [α] = α✝ :: List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : α✝ :: List.append Δ [α] = α✝ :: List.append Δ [α]) ▸ σ), Assg.bot ((_ : α✝ :: List.append Δ [α] = α✝ :: List.append Δ [α]) ▸ σ))
letmutStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.letmut e s)) σ) a = do let x ← Stmt.eval ρ (Stmt.letmut e s) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ {Δ_1 : List Type} {a : α} {ρ : HList (α✝ :: Γ✝)} {σ : Assg Δ_1} (h : List.append Δ [α] = List.append Δ_1 [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ_1 [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))
sforStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.sfor e s)) σ) a = do let x ← Stmt.eval ρ (Stmt.sfor e s) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
sforStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.sfor e s)) σ) a = do let x ← Stmt.eval ρ (Stmt.sfor e s) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
sforStateT.run (Stmt.eval.go (a :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ (e ρ (Assg.extendBot a σ))) a = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a σ) (e ρ (Assg.extendBot a σ)) pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ {Δ_1 : List Type} {a : α} {ρ : HList (α✝ :: Γ✝)} {σ : Assg Δ_1} (h : List.append Δ [α] = List.append Δ_1 [α]), StateT.run (Stmt.eval (a :: ρ) (S (h ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ_1 [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot (h ▸ σ), Assg.bot (h ▸ σ))
sforStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.sfor e s)) σ) a = do let x ← Stmt.eval ρ (Stmt.sfor e s) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
h: a = a'
sforStateT.run (Stmt.eval.go (a' :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ (e ρ (Assg.extendBot a' σ))) a' = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a' σ) (e ρ (Assg.extendBot a' σ)) pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
h: a = a'a :: ρm: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
h: a = a'a' :: ρm: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
h: a = a'a' :: ρm: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
h: a = a'a :: ρm: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
h: a = a'a :: ρm: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
a': α
sforStateT.run (Stmt.eval.go (a :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ (e ρ (Assg.extendBot a' σ))) a' = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a' σ) (e ρ (Assg.extendBot a' σ)) pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
σ: Assg Δ
a': α
sfor.nilStateT.run (Stmt.eval.go (a :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ []) a' = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a' σ) [] pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
head✝: α✝
tail✝: List α✝
σ: Assg Δ
a': αStateT.run (Stmt.eval.go (a :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ (head✝ :: tail✝)) a' = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a' σ) (head✝ :: tail✝) pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
σ: Assg Δ
a': α
sfor.nilStateT.run (Stmt.eval.go (a :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ []) a' = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a' σ) [] pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
α✝: Type
b✝, c✝: Bool
Δ: List Type
a: α
ρ: HList Γ✝
e: Assg Γ✝ → Assg (List.append Δ [α]) → List α✝
s: Stmt m ω (α✝ :: Γ✝) (List.append Δ [α]) true true Unit
ih: ∀ (a : α) (ρ : HList (α✝ :: Γ✝)) (σ : Assg Δ), StateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ s)) σ) a = do let x ← Stmt.eval ρ s ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))
head✝: α✝
tail✝: List α✝
σ: Assg Δ
a': αStateT.run (Stmt.eval.go (a :: ρ) c✝ b✝ α✝ (Stmt.bind (Stmt.expr fun x x => get) (Stmt.mapAssg S.shadowSnd (S s))) σ (head✝ :: tail✝)) a' = do let x ← Stmt.eval.go ρ c✝ b✝ α✝ s (Assg.extendBot a' σ) (head✝ :: tail✝) pure (x.fst :: Assg.dropBot x.snd, Assg.bot x.snd)Goals accomplished! 🐙m: Type → Type
ω: Type
Γ: List Type
α: Type
b, c: Bool
β: Type
inst✝¹: Monad m
Δ', Γ✝: List Type
b✝, c✝: Bool
α✝: Type
Δ: List Type
a: α
ρ: HList Γ✝
σ: Assg Δ
e✝: Assg Γ✝ → Assg (List.append Δ [α]) → Bool
s₁✝, s₂✝: Stmt m ω Γ✝ (List.append Δ [α]) b✝ c✝ α✝
iteStateT.run (Stmt.eval (a :: ρ) (S ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Stmt.ite e✝ s₁✝ s₂✝)) σ) a = do let x ← Stmt.eval ρ (Stmt.ite e✝ s₁✝ s₂✝) ((_ : List.append Δ [α] = List.append Δ [α]) ▸ Assg.extendBot a σ) match x with | (r, σ) => pure (r :: Assg.dropBot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ), Assg.bot ((_ : List.append Δ [α] = List.append Δ [α]) ▸ σ))theoremGoals accomplished! 🐙HList.eq_nil (HList.eq_nil: ∀ (as : HList ∅), as = ∅as :as: HList ∅HListHList: List (Type u_1) → Type u_1∅) :∅: List (Type u_1)as = ∅ :=as: HList ∅rfl attribute [local simp]rfl: ∀ {α : Type u_1} {a : α}, a = aExceptT.run_bind theoremExceptT.run_bind: ∀ {m : Type u_1 → Type u_2} {ε α β : Type u_1} {f : α → ExceptT ε m β} [inst : Monad m] (x : ExceptT ε m α), ExceptT.run (x >>= f) = do let x ← ExceptT.run x match x with | Except.ok x => ExceptT.run (f x) | Except.error e => pure (Except.error e)eval_L [eval_L: ∀ {m : Type → Type u_1} {ω : Type} {Γ Δ : List Type} {b c : Bool} {α : Type} {ρ : Assg Γ} {σ : Assg Δ} [inst : Monad m] [inst_1 : LawfulMonad m] (s : Stmt m ω Γ Δ b c α), Stmt.eval ρ (L s) σ = ExceptT.lift (Stmt.eval ρ s σ)MonadMonad: (Type ?u.632180 → Type ?u.632179) → Type (max (?u.632180 + 1) ?u.632179)m] [m: Type → Type u_1LawfulMonadLawfulMonad: (m : Type → Type u_1) → [inst : Monad m] → Propm] (m: Type → Type u_1s :s: Stmt m ω Γ Δ b c αStmtStmt: (Type → Type u_1) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 u_1)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolα) : (α: TypeLL: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ b c αs).s: Stmt m ω Γ Δ b c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ =σ: Assg ΔExceptT.lift (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m αs.s: Stmt m ω Γ Δ b c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ) :=σ: Assg Δm: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c αStmt.eval ρ (L s) σ = ExceptT.lift (Stmt.eval ρ s σ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c α
hExceptT.run (Stmt.eval ρ (L s) σ) = ExceptT.run (ExceptT.lift (Stmt.eval ρ s σ))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c α
hExceptT.run (Stmt.eval ρ (L s) σ) = ExceptT.run (ExceptT.lift (Stmt.eval ρ s σ))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sforExceptT.run (Stmt.eval ρ (L (Stmt.sfor e s✝)) σ) = ExceptT.run (ExceptT.lift (Stmt.eval ρ (Stmt.sfor e s✝) σ))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sforExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (L s✝) σ (e ρ σ)) = ExceptT.run (ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (e ρ σ)))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sfor.nilExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (L s✝) σ []) = ExceptT.run (ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ []))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝ExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (L s✝) σ (head✝ :: tail✝)) = ExceptT.run (ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (head✝ :: tail✝)))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sfor.nilExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (L s✝) σ []) = ExceptT.run (ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ []))m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝ExceptT.run (Stmt.eval.go ρ c✝ b✝ α✝ (L s✝) σ (head✝ :: tail✝)) = ExceptT.run (ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (head✝ :: tail✝)))Goals accomplished! 🐙m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝
ρ: Assg Γ✝
σ: Assg Δ✝
h.assgExceptT.run (Stmt.eval ρ (L (Stmt.assg x✝ e✝)) σ) = ExceptT.run (ExceptT.lift (Stmt.eval ρ (Stmt.assg x✝ e✝) σ))theoremGoals accomplished! 🐙eval_B [eval_B: ∀ {m : Type → Type u_1} {ω : Type} {Γ Δ : List Type} {b c : Bool} {α : Type} {ρ : Assg Γ} {σ : Assg Δ} [inst : Monad m] [inst_1 : LawfulMonad m] (s : Stmt m ω Γ Δ b c α), Stmt.eval ρ (B s) σ = do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()MonadMonad: (Type ?u.666038 → Type ?u.666037) → Type (max (?u.666038 + 1) ?u.666037)m] [m: Type → Type u_1LawfulMonadLawfulMonad: (m : Type ?u.665935 → Type ?u.665934) → [inst : Monad m] → Propm] (m: Type → Type u_1s :s: Stmt m ω Γ Δ b c αStmtStmt: (Type → Type ?u.665969) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 ?u.665969)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typebb: Boolcc: Boolα) : (α: TypeBB: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ b c α → Stmt (ExceptT Unit m) ω Γ Δ false c αs).s: Stmt m ω Γ Δ b c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ = (σ: Assg ΔExceptT.lift (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m αs.s: Stmt m ω Γ Δ b c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ) >>= funσ: Assg Δx => match (generalizing := false)x: Neut ω α b c × Assg Δx with | (x: Neut ω α b c × Assg ΔNeut.retNeut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b co,o: ωσ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.retNeut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b co,o: ωσ) | (σ: Assg ΔNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca,a: ασ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca,a: ασ) | (σ: Assg ΔNeut.rcont,Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b trueσ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.rcont,Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b trueσ) | (σ: Assg ΔNeut.rbreak, _) =>Neut.rbreak: {ω α : Type} → {c : Bool} → Neut ω α true cthrow () :throw: {ε : Type} → {m : Type → Type u_1} → [self : MonadExcept ε m] → {α : Type} → ε → m αExceptTExceptT: Type → (Type → Type u_1) → Type → Type u_1UnitUnit: Typem (m: Type → Type u_1NeutNeut: Type → Type → Bool → Bool → Typeωω: Typeαα: Typefalsefalse: Boolc ×c: BoolAssgAssg: List Type → TypeΔ)) :=Δ: List Typem: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c αStmt.eval ρ (B s) σ = do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c α
hExceptT.run (Stmt.eval ρ (B s) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ b c α
hExceptT.run (Stmt.eval ρ (B s) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ s σ) match b, c, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sforExceptT.run (Stmt.eval ρ (B (Stmt.sfor e s✝)) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ (Stmt.sfor e s✝) σ) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sforExceptT.run (Stmt.eval.go ρ c✝ false α✝ (L s✝) σ (e ρ σ)) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (e ρ σ)) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sfor.nilExceptT.run (Stmt.eval.go ρ c✝ false α✝ (L s✝) σ []) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ []) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝ExceptT.run (Stmt.eval.go ρ c✝ false α✝ (L s✝) σ (head✝ :: tail✝)) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (head✝ :: tail✝)) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
h.sfor.nilExceptT.run (Stmt.eval.go ρ c✝ false α✝ (L s✝) σ []) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ []) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝ExceptT.run (Stmt.eval.go ρ c✝ false α✝ (L s✝) σ (head✝ :: tail✝)) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval.go ρ c✝ b✝ α✝ s✝ σ (head✝ :: tail✝)) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()Goals accomplished! 🐙m: Type → Type u_1
ω: Type
Γ, Δ: List Type
b, c: Bool
α: Type
inst✝¹: Monad m
Γ✝, Δ✝: List Type
b✝, c✝: Bool
x✝: Fin (List.length Δ✝)
e✝: Assg Γ✝ → Assg Δ✝ → List.get Δ✝ x✝
ρ: Assg Γ✝
σ: Assg Δ✝
h.assgExceptT.run (Stmt.eval ρ (B (Stmt.assg x✝ e✝)) σ) = ExceptT.run do let x ← ExceptT.lift (Stmt.eval ρ (Stmt.assg x✝ e✝) σ) match b✝, c✝, x with | b, c, (Neut.ret o, σ) => pure (Neut.ret o, σ) | b, c, (Neut.val a, σ) => pure (Neut.val a, σ) | b, .(true), (Neut.rcont, σ) => pure (Neut.rcont, σ) | .(true), c, (Neut.rbreak, snd) => throw ()@[simp] defGoals accomplished! 🐙throwOnContinue [throwOnContinue: {m : Type → Type u_1} → {ω α : Type} → {c : Bool} → {Δ : List Type} → [inst : Monad m] → Neut ω α false c × Assg Δ → ExceptT Unit m (Neut ω α false false × Assg Δ)MonadMonad: (Type ?u.788677 → Type ?u.788676) → Type (max (?u.788677 + 1) ?u.788676)m] : (m: Type → Type u_1NeutNeut: Type → Type → Bool → Bool → Typeωω: Typeαα: Typefalsefalse: Boolc ×c: BoolAssgAssg: List Type → TypeΔ) →Δ: List TypeExceptTExceptT: Type → (Type → Type u_1) → Type → Type u_1UnitUnit: Typem (m: Type → Type u_1NeutNeut: Type → Type → Bool → Bool → Typeωω: Typeαα: Typefalsefalse: Boolfalse ×false: BoolAssgAssg: List Type → TypeΔ) | (Δ: List TypeNeut.retNeut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b co,o: ωσ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.retNeut.ret: {ω α : Type} → {b c : Bool} → ω → Neut ω α b co,o: ωσ) | (σ: Assg ΔNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca,a: ασ) =>σ: Assg Δpure (pure: {f : Type → Type u_1} → [self : Pure f] → {α : Type} → α → f αNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca,a: ασ) | (σ: Assg ΔNeut.rcont, _) =>Neut.rcont: {ω α : Type} → {b : Bool} → Neut ω α b truethrowthrow: {ε : Type} → {m : Type → Type u_1} → [self : MonadExcept ε m] → {α : Type} → ε → m α() theorem(): Uniteval_C [eval_C: ∀ {m : Type → Type u_1} {ω : Type} {Γ Δ : List Type} {c : Bool} {α : Type} {ρ : Assg Γ} {σ : Assg Δ} [inst : Monad m] [inst_1 : LawfulMonad m] (s : Stmt m ω Γ Δ false c α), Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinueMonadMonad: (Type ?u.790186 → Type ?u.790185) → Type (max (?u.790186 + 1) ?u.790185)m] [m: Type → Type u_1LawfulMonadLawfulMonad: (m : Type ?u.790060 → Type ?u.790059) → [inst : Monad m] → Propm] (m: Type → Type u_1s :s: Stmt m ω Γ Δ false c αStmtStmt: (Type → Type ?u.790118) → Type → List Type → List Type → Bool → Bool → Type → Type (max 1 ?u.790118)mm: Type → Type u_1ωω: TypeΓΓ: List TypeΔΔ: List Typefalsefalse: Boolcc: Boolα) : (α: TypeCC: {m : Type → Type u_1} → {ω : Type} → {Γ Δ : List Type} → {c : Bool} → {α : Type} → [inst : Monad m] → Stmt m ω Γ Δ false c α → Stmt (ExceptT Unit m) ω Γ Δ false false αs).s: Stmt m ω Γ Δ false c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ =σ: Assg ΔExceptT.lift (ExceptT.lift: {ε : Type} → {m : Type → Type u_1} → [inst : Monad m] → {α : Type} → m α → ExceptT ε m αs.s: Stmt m ω Γ Δ false c αevaleval: {m : Type → Type u_1} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρρ: Assg Γσ) >>=σ: Assg ΔthrowOnContinue :=throwOnContinue: {m : Type → Type u_1} → {ω α : Type} → {c : Bool} → {Δ : List Type} → [inst : Monad m] → Neut ω α false c × Assg Δ → ExceptT Unit m (Neut ω α false false × Assg Δ)m: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
s: Stmt m ω Γ Δ false c αStmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m∀ (s : Stmt m ω Γ Δ false c α), Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m∀ {b : Bool} (s' : Stmt m ω Γ Δ b c α) (h : b = false), let s := h ▸ s'; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
b': Bool
s: Stmt m ω Γ Δ b' c α
h: b' = falselet s := h ▸ s; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
ρ: Assg Γ
σ: Assg Δ
inst✝¹: Monad m
b': Bool
s: Stmt m ω Γ Δ b' c α
h: b' = falselet s := h ▸ s; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
b✝, c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) b✝ c✝ β✝
ρ: Assg Γ✝
σ: Assg Δ✝
h: b✝ = false
letmutlet s := h ▸ Stmt.letmut e✝ s✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝
ρ: Assg Γ✝
σ: Assg Δ✝
h: b✝ = false
bindlet s := h ▸ Stmt.bind s✝ s'✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
c✝: Bool
α✝, β✝: Type
ρ: Assg Γ✝
σ: Assg Δ✝
s✝: Stmt m ω Γ✝ Δ✝ false c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ false c✝ β✝
bindlet s := (_ : false = false) ▸ Stmt.bind s✝ s'✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
b✝, c✝: Bool
α✝, β✝: Type
s✝: Stmt m ω Γ✝ Δ✝ b✝ c✝ α✝
s'✝: Stmt m ω (α✝ :: Γ✝) Δ✝ b✝ c✝ β✝
ρ: Assg Γ✝
σ: Assg Δ✝
h: b✝ = false
bindlet s := h ▸ Stmt.bind s✝ s'✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
c✝: Bool
α✝: Type
ρ: Assg Γ✝
σ: Assg Δ✝
h: true = false
sbreaklet s := h ▸ Stmt.sbreak; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
ρ: Assg Γ✝
σ: Assg Δ✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) false c✝ β✝
letmutlet s := (_ : false = false) ▸ Stmt.letmut e✝ s✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
sforlet s := (_ : false = false) ▸ Stmt.sfor e s✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
sforStmt.eval.go ρ false false α✝ (L s✝) σ (e ρ σ) = ExceptT.lift (Stmt.eval.go ρ c✝ false α✝ s✝ σ (e ρ σ)) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
sfor.nilStmt.eval.go ρ false false α✝ (L s✝) σ [] = ExceptT.lift (Stmt.eval.go ρ c✝ false α✝ s✝ σ []) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝Stmt.eval.go ρ false false α✝ (L s✝) σ (head✝ :: tail✝) = ExceptT.lift (Stmt.eval.go ρ c✝ false α✝ s✝ σ (head✝ :: tail✝)) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
σ: Assg Δ✝
sfor.nilStmt.eval.go ρ false false α✝ (L s✝) σ [] = ExceptT.lift (Stmt.eval.go ρ c✝ false α✝ s✝ σ []) >>= throwOnContinuem: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
e: Assg Γ✝ → Assg Δ✝ → List α✝
s✝: Stmt m ω (α✝ :: Γ✝) Δ✝ true true Unit
ρ: Assg Γ✝
head✝: α✝
tail✝: List α✝
σ: Assg Δ✝Stmt.eval.go ρ false false α✝ (L s✝) σ (head✝ :: tail✝) = ExceptT.lift (Stmt.eval.go ρ c✝ false α✝ s✝ σ (head✝ :: tail✝)) >>= throwOnContinueGoals accomplished! 🐙m: Type → Type u_1
ω: Type
Γ, Δ: List Type
c: Bool
α: Type
inst✝¹: Monad m
b': Bool
Γ✝, Δ✝: List Type
α✝: Type
c✝: Bool
β✝: Type
e✝: Assg Γ✝ → Assg Δ✝ → α✝
ρ: Assg Γ✝
σ: Assg Δ✝
s✝: Stmt m ω Γ✝ (α✝ :: Δ✝) false c✝ β✝
letmutlet s := (_ : false = false) ▸ Stmt.letmut e✝ s✝; Stmt.eval ρ (C s) σ = ExceptT.lift (Stmt.eval ρ s σ) >>= throwOnContinuetheoremGoals accomplished! 🐙D_eq [D_eq: ∀ (_x : (m : Type → Type) ×' (Γ : List Type) ×' (α : Type) ×' (_ : Assg Γ) ×' (inst : Monad m) ×' (_ : LawfulMonad m) ×' Stmt m Empty Γ ∅ false false α), D _x.2.2.2.2.2.2 _x.2.2.2.1 = do let x ← Stmt.eval _x.2.2.2.1 _x.2.2.2.2.2.2 ∅ match x with | (Neut.val a, snd) => pure aMonadMonad: (Type ?u.924916 → Type ?u.924915) → Type (max (?u.924916 + 1) ?u.924915)m] [m: Type → TypeLawfulMonadLawfulMonad: (m : Type ?u.924921 → Type ?u.924920) → [inst : Monad m] → Propm] : (m: Type → Types :s: Stmt m Empty Γ ∅ false false αStmtStmt: (Type → Type) → Type → List Type → List Type → Bool → Bool → Type → Type 1mm: Type → TypeEmptyEmpty: TypeΓΓ: List Type∅∅: List Typefalsefalse: Boolfalsefalse: Boolα) →α: TypeDD: {m : Type → Type} → {Γ : List Type} → {α : Type} → [inst : Monad m] → Stmt m Empty Γ ∅ false false α → Assg Γ → m αss: Stmt m Empty Γ ∅ false false αρ =ρ: Assg Γs.s: Stmt m Empty Γ ∅ false false αevaleval: {m : Type → Type} → {Γ : List Type} → {ω : Type} → {Δ : List Type} → {b c : Bool} → {α : Type} → [inst : Monad m] → Assg Γ → Stmt m ω Γ Δ b c α → Assg Δ → m (Neut ω α b c × Assg Δ)ρ ∅ >>= fun (ρ: Assg ΓNeut.valNeut.val: {ω α : Type} → {b c : Bool} → α → Neut ω α b ca, _) =>a: αpurepure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αa |a: αStmt.exprStmt.expr: {m : Type → Type ?u.926133} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c αe =>e: Assg Γ → Assg ∅ → m αm: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → m αD (Stmt.expr e) ρ = do let x ← Stmt.eval ρ (Stmt.expr e) ∅ match x with | (Neut.val a, snd) => pure a|Goals accomplished! 🐙Stmt.bindStmt.bind: {m : Type → Type ?u.926201} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βs₁s₁: Stmt m Empty Γ ∅ false false α✝s₂ =>s₂: Stmt m Empty (α✝ :: Γ) ∅ false false αm: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
s₁: Stmt m Empty Γ ∅ false false α✝
s₂: Stmt m Empty (α✝ :: Γ) ∅ false false αD (Stmt.bind s₁ s₂) ρ = do let x ← Stmt.eval ρ (Stmt.bind s₁ s₂) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
s₁: Stmt m Empty Γ ∅ false false α✝
s₂: Stmt m Empty (α✝ :: Γ) ∅ false false α
ih₁: ∀ (ρ : Assg Γ), Monad m → LawfulMonad m → D s₁ ρ = do let x ← Stmt.eval ρ s₁ ∅ match x with | (Neut.val a, snd) => pure aD (Stmt.bind s₁ s₂) ρ = do let x ← Stmt.eval ρ (Stmt.bind s₁ s₂) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
s₁: Stmt m Empty Γ ∅ false false α✝
s₂: Stmt m Empty (α✝ :: Γ) ∅ false false α
ih₁: ∀ (ρ : Assg Γ), Monad m → LawfulMonad m → D s₁ ρ = do let x ← Stmt.eval ρ s₁ ∅ match x with | (Neut.val a, snd) => pure a
ih₂: ∀ (ρ : Assg (α✝ :: Γ)), Monad m → LawfulMonad m → D s₂ ρ = do let x ← Stmt.eval ρ s₂ ∅ match x with | (Neut.val a, snd) => pure aD (Stmt.bind s₁ s₂) ρ = do let x ← Stmt.eval ρ (Stmt.bind s₁ s₂) ∅ match x with | (Neut.val a, snd) => pure a|Goals accomplished! 🐙Stmt.letmutStmt.letmut: {m : Type → Type ?u.926267} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c βee: Assg Γ → Assg ∅ → α✝s =>s: Stmt m Empty Γ (α✝ :: ∅) false false αm: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
e: Assg Γ → Assg ∅ → α✝
s: Stmt m Empty Γ (α✝ :: ∅) false false αD (Stmt.letmut e s) ρ = do let x ← Stmt.eval ρ (Stmt.letmut e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
e: Assg Γ → Assg ∅ → α✝
s: Stmt m Empty Γ (α✝ :: ∅) false false α
this: Stmt.numExts (S s) < Nat.succ (Stmt.numExts s)D (Stmt.letmut e s) ρ = do let x ← Stmt.eval ρ (Stmt.letmut e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
e: Assg Γ → Assg ∅ → α✝
s: Stmt m Empty Γ (α✝ :: ∅) false false αD (Stmt.letmut e s) ρ = do let x ← Stmt.eval ρ (Stmt.letmut e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α, α✝: Type
e: Assg Γ → Assg ∅ → α✝
s: Stmt m Empty Γ (α✝ :: ∅) false false α
this: Stmt.numExts (S s) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (S s) a = do let x ← Stmt.eval a (S s) ∅ match x with | (Neut.val a, snd) => pure aD (Stmt.letmut e s) ρ = do let x ← Stmt.eval ρ (Stmt.letmut e s) ∅ match x with | (Neut.val a, snd) => pure a|Goals accomplished! 🐙Stmt.iteStmt.ite: {m : Type → Type ?u.926338} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c αee: Assg Γ → Assg ∅ → Bools₁s₁: Stmt m Empty Γ ∅ false false αs₂ =>s₂: Stmt m Empty Γ ∅ false false αm: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → Bool
s₁, s₂: Stmt m Empty Γ ∅ false false αD (Stmt.ite e s₁ s₂) ρ = do let x ← Stmt.eval ρ (Stmt.ite e s₁ s₂) ∅ match x with | (Neut.val a, snd) => pure a;m: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → Bool
s₁, s₂: Stmt m Empty Γ ∅ false false α(if e ρ ∅ = true then D s₁ ρ else D s₂ ρ) = do let x ← if e ρ ∅ = true then Stmt.eval ρ s₁ ∅ else Stmt.eval ρ s₂ ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → Bool
s₁, s₂: Stmt m Empty Γ ∅ false false α
inlD s₁ ρ = do let x ← Stmt.eval ρ s₁ ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → Bool
s₁, s₂: Stmt m Empty Γ ∅ false false αD s₂ ρ = do let x ← Stmt.eval ρ s₂ ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → Bool
s₁, s₂: Stmt m Empty Γ ∅ false false α
inlD s₁ ρ = do let x ← Stmt.eval ρ s₁ ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α: Type
e: Assg Γ → Assg ∅ → Bool
s₁, s₂: Stmt m Empty Γ ∅ false false αD s₂ ρ = do let x ← Stmt.eval ρ s₂ ∅ match x with | (Neut.val a, snd) => pure a|Goals accomplished! 🐙Stmt.retStmt.ret: {m : Type → Type ?u.926403} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c αe => nomatche: Assg Γ → Assg ∅ → Emptyee: Assg Γ → Assg ∅ → Emptyρρ: Assg Γ∅ |∅: Assg ∅Stmt.sforStmt.sfor: {m : Type → Type ?u.926500} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unitee: Assg Γ → Assg ∅ → List α✝s =>s: Stmt m Empty (α✝ :: Γ) ∅ true true Unitm: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true UnitD (Stmt.sfor e s) ρ = do let x ← Stmt.eval ρ (Stmt.sfor e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)D (Stmt.sfor e s) ρ = do let x ← Stmt.eval ρ (Stmt.sfor e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true UnitD (Stmt.sfor e s) ρ = do let x ← Stmt.eval ρ (Stmt.sfor e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (C (B s)) a = do let x ← Stmt.eval a (C (B s)) ∅ match x with | (Neut.val a, snd) => pure aD (Stmt.sfor e s) ρ = do let x ← Stmt.eval ρ (Stmt.sfor e s) ∅ match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (C (B s)) a = do let x ← Stmt.eval a (C (B s)) ∅ match x with | (Neut.val a, snd) => pure arunCatch (forM (e ρ ∅) fun x => runCatch (D (C (B s)) (x :: ρ))) = do let x ← Stmt.eval.go ρ false false α✝ s ∅ (e ρ ∅) match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (C (B s)) a = do let x ← Stmt.eval a (C (B s)) ∅ match x with | (Neut.val a, snd) => pure a
nilrunCatch (forM [] fun x => runCatch (D (C (B s)) (x :: ρ))) = do let x ← Stmt.eval.go ρ false false α✝ s ∅ [] match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (C (B s)) a = do let x ← Stmt.eval a (C (B s)) ∅ match x with | (Neut.val a, snd) => pure a
head✝: α✝
tail✝: List α✝runCatch (forM (head✝ :: tail✝) fun x => runCatch (D (C (B s)) (x :: ρ))) = do let x ← Stmt.eval.go ρ false false α✝ s ∅ (head✝ :: tail✝) match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (C (B s)) a = do let x ← Stmt.eval a (C (B s)) ∅ match x with | (Neut.val a, snd) => pure a
nilrunCatch (forM [] fun x => runCatch (D (C (B s)) (x :: ρ))) = do let x ← Stmt.eval.go ρ false false α✝ s ∅ [] match x with | (Neut.val a, snd) => pure am: Type → Type
Γ: List Type
ρ: Assg Γ
inst✝¹: Monad m
α✝: Type
e: Assg Γ → Assg ∅ → List α✝
s: Stmt m Empty (α✝ :: Γ) ∅ true true Unit
this: Stmt.numExts (C (B s)) < Nat.succ (Stmt.numExts s)
ih: ∀ (a : Assg (α✝ :: Γ)), D (C (B s)) a = do let x ← Stmt.eval a (C (B s)) ∅ match x with | (Neut.val a, snd) => pure a
head✝: α✝
tail✝: List α✝runCatch (forM (head✝ :: tail✝) fun x => runCatch (D (C (B s)) (x :: ρ))) = do let x ← Stmt.eval.go ρ false false α✝ s ∅ (head✝ :: tail✝) match x with | (Neut.val a, snd) => pure atermination_by _ s => (Goals accomplished! 🐙s.s: Stmt m Empty Γ ∅ false false αnumExts,numExts: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → Stmt m ω Γ Δ b c α → NatsizeOfsizeOf: {α : Type 1} → [self : SizeOf α] → α → Nats) decreasing_bys: Stmt m Empty Γ ∅ false false αGoals accomplished! 🐙
The equivalence proof cited in the paper follows from the invariants of D
and R
.
theoremDo.trans_eq_eval [Do.trans_eq_eval: ∀ {m : Type → Type} {α : Type} [inst : Monad m] [inst_1 : LawfulMonad m] (s : Do m α), trans s = ⟦s⟧MonadMonad: (Type → Type) → Type 1m] [m: Type → TypeLawfulMonadLawfulMonad: (m : Type ?u.1069260 → Type ?u.1069259) → [inst : Monad m] → Propm] : ∀m: Type → Types :s: Do m αDoDo: (Type → Type) → Type → Type 1mm: Type → Typeα,α: TypeDo.transDo.trans: {m : Type → Type} → {α : Type} → [inst : Monad m] → Do m α → m αs = ⟦s: Do m αs⟧ :=s: Do m αm: Type → Type
α: Type
inst✝¹: Monad m∀ (s : Do m α), trans s = ⟦s⟧Goals accomplished! 🐙
Partial Evaluation
We define a new term notation simp [...] in e
that rewrites the term e using the given
simplification theorems.
open Lean in
open Lean.Parser.Tactic in
open Lean.Meta in
open Lean.Elab in
elab "simp" "[" simps: Syntax.TSepArray `Lean.Parser.Tactic.simpLemma ","
simps:simpLemma: ParserDescr
simpLemma,* "]" "in" e: TSyntax `term
e:term : term => do
-- construct goal `⊢ e = ?x` with fresh metavariable `?x`, simplify, solve by reflexivity,
-- and return assigned value of `?x`
let e: Expr
e ← Term.elabTermAndSynthesize: Syntax → Option Expr → TermElabM Expr
Term.elabTermAndSynthesize e: TSyntax `term
e none: {α : Type} → Option α
none
let x: Expr
x ← mkFreshExprMVar: Option Expr → optParam MetavarKind MetavarKind.natural → optParam Name Name.anonymous → MetaM Expr
mkFreshExprMVar (← inferType e): Expr
(← inferType: Expr → MetaM Expr
inferType(← inferType e): Expr
e: Expr
e(← inferType e): Expr
)
let goal: Expr
goal ← mkFreshExprMVar: Option Expr → optParam MetavarKind MetavarKind.natural → optParam Name Name.anonymous → MetaM Expr
mkFreshExprMVar (← mkEq e x): Expr
(← mkEq: Expr → Expr → MetaM Expr
mkEq(← mkEq e x): Expr
e: Expr
e(← mkEq e x): Expr
x: Expr
x(← mkEq e x): Expr
)
-- disable ζ-reduction to preserve `let`s
Term.runTactic: MVarId → Syntax → TermElabM Unit
Term.runTactic goal: Expr
goal.mvarId!: Expr → MVarId
mvarId! (← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
(← `(tactic| ((← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
simp(← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
((← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
config(← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
:= { zeta := false }) [$simps: Syntax.TSepArray `Lean.Parser.Tactic.simpLemma ","
simps(← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
:simpLemma,*]; (← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
rfl(← `(tactic| (simp (config := { zeta := false }) [$simps:simpLemma,*]; rfl))): TSyntax `tactic
)))
instantiateMVars: {m : Type → Type} → [inst : Monad m] → [inst : MonadMCtx m] → Expr → m Expr
instantiateMVars x: Expr
x
-- further clean up generated programs
attribute [local simp] Assg.extendBot: {α : Type u_1} → α → {Γ : List (Type u_1)} → Assg Γ → Assg (List.append Γ [α])
Assg.extendBot cast: {α β : Sort u} → α = β → α → β
cast
attribute [-simp] StateT.run'_eq: ∀ {m : Type u_1 → Type u_2} {σ α : Type u_1} [inst : Monad m] (x : StateT σ m α) (s : σ),
StateT.run' x s = (fun a => a.fst) <$> StateT.run x s
StateT.run'_eq
We can now use this new notation to completely erase the translation functions
from an invocation on the example ex2
from For.lean
(manually translated to Stmt
).
/- let mut y := init; for x in xs do' { y ← f y x }; return y -/ defex2' [ex2': {m : Type → Type} → {β α : Type} → [inst : Monad m] → (β → α → m β) → β → List α → m βMonadMonad: (Type ?u.1085514 → Type ?u.1085513) → Type (max (?u.1085514 + 1) ?u.1085513)m] (m: Type → Typef :f: β → α → m ββ →β: Typeα →α: Typemm: Type → Typeβ) (β: Typeinit :init: ββ) (β: Typexs :xs: List αListList: Type → Typeα) :α: Typemm: Type → Typeβ := simp [Do.trans] inβ: TypeDo.trans (Do.trans: {m : Type → Type} → {α : Type} → [inst : Monad m] → Do m α → m αStmt.letmut (fun _ _ =>Stmt.letmut: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → {β : Type} → (Assg Γ → Assg Δ → α) → Stmt m ω Γ (α :: Δ) b c β → Stmt m ω Γ Δ b c βinit) <|init: βStmt.bind (Stmt.bind: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βStmt.sfor (fun _ _ =>Stmt.sfor: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unitxs) <| -- `y ← f y x` unfolded to `let z ← f y x; y := z` (A4)xs: List αStmt.bind (Stmt.bind: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βStmt.expr (fun ([Stmt.expr: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c αx]) ([x: αy]) =>y: βff: β → α → m βyy: βx)) (x: αStmt.assg ⟨Stmt.assg: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → (x : Fin (List.length Δ)) → (Assg Γ → Assg Δ → List.get Δ x) → Stmt m ω Γ Δ b c Unit0,0: Natm: Type → Type
β, α: Type
inst✝: Monad m
f: β → α → m β
init: β
xs: List α0 < List.length (β :: ∅)⟩ (fun ([Goals accomplished! 🐙z,z: β]) _ =>z))) <|z: βStmt.ret (fun _ ([Stmt.ret: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c αy]) =>y: βy))y: β
Compare the output of the two versions - the structure is identical except for unused monadic layers in the formal translation, which would be harder to avoid in this typed approach.
ex2ex2: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → {β : Type} → (β → α → m β) → β → List α → m βex2'ex2': {m : Type → Type} → {β α : Type} → [inst : Monad m] → (β → α → m β) → β → List α → m β
We can evaluate the generated program like any other Lean program, and prove that both versions are equivalent.
ex2' (m :=ex2': {m : Type → Type} → {β α : Type} → [inst : Monad m] → (β → α → m β) → β → List α → m βId) (funId: Type → Typeaa: Natb =>b: Natpure (pure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αa +a: Natb))b: Nat0 [0: Nat1,1: Nat2]2: Natexample [example: ∀ {m : Type → Type} {β α : Type} {init : β} {xs : List α} [inst : Monad m] [inst_1 : LawfulMonad m] (f : β → α → m β), ex2' f init xs = ex2 f init xsMonadMonad: (Type → Type) → Type 1m] [m: Type → TypeLawfulMonadLawfulMonad: (m : Type → Type) → [inst : Monad m] → Propm] (m: Type → Typef :f: β → α → m ββ →β: Typeα →α: Typemm: Type → Typeβ) :β: Typeex2'ex2': {m : Type → Type} → {β α : Type} → [inst : Monad m] → (β → α → m β) → β → List α → m βff: β → α → m βinitinit: βxs =xs: List αex2ex2: {m : Type → Type} → {α : Type} → [inst : Monad m] → {β : Type} → (β → α → m β) → β → List α → m βff: β → α → m βinitinit: βxs :=xs: List αm: Type → Type
β, α: Type
init: β
xs: List α
inst✝¹: Monad m
f: β → α → m βex2' f init xs = ex2 f init xsm: Type → Type
β, α: Type
init: β
xs: List α
inst✝¹: Monad m
f: β → α → m βex2' f init xs = ex2 f init xsm: Type → Type
β, α: Type
init: β
xs: List α
inst✝¹: Monad m
f: β → α → m βex2' f init xs = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM xs fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y)m: Type → Type
β, α: Type
init: β
xs: List α
inst✝¹: Monad m
f: β → α → m βrunCatch (let x := init; StateT.run' (do runCatch (forM xs fun x => runCatch do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x))) let x ← get StateT.lift (throw x)) x) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM xs fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y);m: Type → Type
β, α: Type
init: β
xs: List α
inst✝¹: Monad m
f: β → α → m βrunCatch (let x := init; StateT.run' (do runCatch (forM xs fun x => runCatch do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x))) let x ← get StateT.lift (throw x)) x) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM xs fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y);m: Type → Type
β, α: Type
init: β
xs: List α
inst✝¹: Monad m
f: β → α → m β(do let x ← ExceptT.run (let x := init; StateT.run' (do do let x ← ExceptT.run (forM xs fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x)) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e let x ← get StateT.lift (throw x)) x) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM xs fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y)m: Type → Type
β, α: Type
inst✝¹: Monad m
f: β → α → m β
init: β
nil(do let x ← ExceptT.run (let x := init; StateT.run' (do do let x ← ExceptT.run (forM [] fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x)) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e let x ← get StateT.lift (throw x)) x) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM [] fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y)m: Type → Type
β, α: Type
inst✝¹: Monad m
f: β → α → m β
head✝: α
tail✝: List α
init: β(do let x ← ExceptT.run (let x := init; StateT.run' (do do let x ← ExceptT.run (forM (head✝ :: tail✝) fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x)) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e let x ← get StateT.lift (throw x)) x) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM (head✝ :: tail✝) fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y)m: Type → Type
β, α: Type
inst✝¹: Monad m
f: β → α → m β
init: β
nil(do let x ← ExceptT.run (let x := init; StateT.run' (do do let x ← ExceptT.run (forM [] fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x)) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e let x ← get StateT.lift (throw x)) x) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM [] fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y)m: Type → Type
β, α: Type
inst✝¹: Monad m
f: β → α → m β
head✝: α
tail✝: List α
init: β(do let x ← ExceptT.run (let x := init; StateT.run' (do do let x ← ExceptT.run (forM (head✝ :: tail✝) fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift get) let x ← ExceptT.lift (ExceptT.lift (StateT.lift (ExceptT.lift (f x_1 x)))) let _ ← ExceptT.lift (ExceptT.lift get) ExceptT.lift (ExceptT.lift (set x)) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e let x ← get StateT.lift (throw x)) x) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch (let y := init; StateT.run' (do forM (head✝ :: tail✝) fun x => do let y ← get let y ← StateT.lift (ExceptCpsT.lift (f y x)) let _ ← get set y let y ← get StateT.lift (throw y)) y)Goals accomplished! 🐙
For one more example, consider ex3
from For.lean
.
/- for xs in xss do' { for x in xs do' { let b ← p x; if b then { return some x } } }; pure none -/ defex3' [ex3': {m : Type → Type} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)MonadMonad: (Type → Type) → Type 1m] (m: Type → Typep :p: α → m Boolα →α: Typemm: Type → TypeBool) (Bool: Typexss :xss: List (List α)List (List: Type → TypeListList: Type → Typeα)) :α: Typem (m: Type → TypeOptionOption: Type → Typeα) := simp [Do.trans] inα: TypeDo.trans (Do.trans: {m : Type → Type} → {α : Type} → [inst : Monad m] → Do m α → m αStmt.bind (Stmt.bind: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βStmt.sfor (fun _ _ =>Stmt.sfor: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unitxss) <|xss: List (List α)Stmt.sfor (fun ([Stmt.sfor: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → List α) → Stmt m ω (α :: Γ) Δ true true Unit → Stmt m ω Γ Δ b c Unitxs]) _ =>xs: List αxs) <|xs: List αStmt.bind (Stmt.bind: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α β : Type} → Stmt m ω Γ Δ b c α → Stmt m ω (α :: Γ) Δ b c β → Stmt m ω Γ Δ b c βStmt.expr (fun ([Stmt.expr: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c αx,x: α]) _ =>pp: α → m Boolx)) (x: αStmt.ite (fun ([Stmt.ite: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → Bool) → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c α → Stmt m ω Γ Δ b c αb,b: Bool,]) _ =>b) (b: BoolStmt.ret (fun ([Stmt.ret: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {b c : Bool} → {α : Type} → (Assg Γ → Assg Δ → ω) → Stmt m ω Γ Δ b c α,x,x: α]) _ =>somesome: {α : Type} → α → Option αx)) (x: αStmt.expr (fun _ _ =>Stmt.expr: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c αpurepure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f α())))) ((): UnitStmt.expr (fun _ _ =>Stmt.expr: {m : Type → Type} → {ω : Type} → {Γ Δ : List Type} → {α : Type} → {b c : Bool} → (Assg Γ → Assg Δ → m α) → Stmt m ω Γ Δ b c αpurepure: {f : Type → Type} → [self : Pure f] → {α : Type} → α → f αnone)))none: {α : Type} → Option αex3ex3: {m : Type → Type u_1} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)ex3'ex3': {m : Type → Type} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)ex3' (m :=ex3': {m : Type → Type} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)Id) (funId: Type → Typen =>n: Natn %n: Nat2 ==2: Nat0) [[0: Nat1,1: Nat3], [3: Nat2,2: Nat4]]4: Natexample [example: ∀ {m : Type → Type} {α : Type} [inst : Monad m] [inst_1 : LawfulMonad m] (p : α → m Bool) (xss : List (List α)), ex3' p xss = ex3 p xssMonadMonad: (Type → Type) → Type 1m] [m: Type → TypeLawfulMonadLawfulMonad: (m : Type ?u.1130706 → Type ?u.1130705) → [inst : Monad m] → Propm] (m: Type → Typep :p: α → m Boolα →α: Typemm: Type → TypeBool) (Bool: Typexss :xss: List (List α)List (List: Type → TypeListList: Type → Typeα)) :α: Typeex3'ex3': {m : Type → Type} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)pp: α → m Boolxss =xss: List (List α)ex3ex3: {m : Type → Type} → {α : Type} → [inst : Monad m] → (α → m Bool) → List (List α) → m (Option α)pp: α → m Boolxss :=xss: List (List α)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)ex3' p xss = ex3 p xssm: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)ex3' p xss = ex3 p xssm: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)ex3' p xss = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)(runCatch do runCatch (forM xss fun x => runCatch (runCatch (forM x fun x => runCatch do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ())))))))) ExceptT.lift (pure none)) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)(runCatch do runCatch (forM xss fun x => runCatch (runCatch (forM x fun x => runCatch do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ())))))))) ExceptT.lift (pure none)) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)(do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)(do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
nil(do let x ← ExceptT.run do do let x ← ExceptT.run (forM [] fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM [] fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)Goals accomplished! 🐙m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xs: List α
xss: List (List α)
ih: (do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons(do let x ← ExceptT.run do do let x ← ExceptT.run (forM (xs :: xss) fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM (xs :: xss) fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xs: List α
xss: List (List α)
ih: (do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons(do let x ← ExceptT.run (ExceptT.run (ExceptT.run (ExceptT.run (forM xs fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)))) let x ← match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => ExceptT.run (forM xss fun x => do let x ← ExceptT.run (ExceptT.run (forM x fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)) let x ← match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => pure (Except.ok none) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) = ExceptCpsT.runCatch do forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)
ih: (do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons.nil(do let x ← ExceptT.run (ExceptT.run (ExceptT.run (ExceptT.run (forM [] fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)))) let x ← match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => ExceptT.run (forM xss fun x => do let x ← ExceptT.run (ExceptT.run (forM x fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)) let x ← match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => pure (Except.ok none) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) = ExceptCpsT.runCatch do forM [] fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)
ih: (do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
head✝: α
tail✝: List α(do let x ← ExceptT.run (ExceptT.run (ExceptT.run (ExceptT.run (forM (head✝ :: tail✝) fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)))) let x ← match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => ExceptT.run (forM xss fun x => do let x ← ExceptT.run (ExceptT.run (forM x fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)) let x ← match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => pure (Except.ok none) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) = ExceptCpsT.runCatch do forM (head✝ :: tail✝) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)
ih: (do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
cons.nil(do let x ← ExceptT.run (ExceptT.run (ExceptT.run (ExceptT.run (forM [] fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)))) let x ← match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => ExceptT.run (forM xss fun x => do let x ← ExceptT.run (ExceptT.run (forM x fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)) let x ← match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => pure (Except.ok none) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) = ExceptCpsT.runCatch do forM [] fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)m: Type → Type
α: Type
inst✝¹: Monad m
p: α → m Bool
xss: List (List α)
ih: (do let x ← ExceptT.run do do let x ← ExceptT.run (forM xss fun x => do let x ← ExceptT.run do let x ← ExceptT.run (forM x fun x => do let x ← ExceptT.run do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x))))) if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (pure ()))))) match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e match x with | Except.ok x => pure x | Except.error e => pure e) match x with | Except.ok x => pure x | Except.error e => pure e ExceptT.lift (pure none) match x with | Except.ok x => pure x | Except.error e => pure e) = ExceptCpsT.runCatch do forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)
head✝: α
tail✝: List α(do let x ← ExceptT.run (ExceptT.run (ExceptT.run (ExceptT.run (forM (head✝ :: tail✝) fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)))) let x ← match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => ExceptT.run (forM xss fun x => do let x ← ExceptT.run (ExceptT.run (forM x fun x => do let x_1 ← ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (p x)))) let x ← ExceptT.run (if x_1 = true then ExceptT.lift (ExceptT.lift (ExceptT.lift (ExceptT.lift (throw (some x))))) else pure ()) match x with | Except.ok x => pure x | Except.error x => pure x)) let x ← match x with | Except.ok x => ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e)) match x with | Except.ok x => do let x ← ExceptT.run (match x with | Except.ok x => pure x | Except.error x => pure x) match x with | Except.ok x => pure (Except.ok none) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) | Except.error e => pure (Except.error e) match x with | Except.ok x => pure x | Except.error x => pure x) = ExceptCpsT.runCatch do forM (head✝ :: tail✝) fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) forM xss fun xs => forM xs fun x => do let b ← ExceptCpsT.lift (p x) if b = true then throw (some x) else ExceptCpsT.lift (pure ()) ExceptCpsT.lift (pure none)Goals accomplished! 🐙
While it would be possible to override our do'
notation such that its named syntax
is first translated to nameless Stmt
constructors and then applied to simp [Do.trans] in
,
for demonstration purposes we decided to encode these examples manually. In practice, the
macro implementation remains more desirable as mentioned in the paper.