Built with
doc-gen4 , running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+↑ Ctrl+↓ to navigate,
Ctrl+🖱️ to focus.
On Mac, use
Cmd instead of
Ctrl .
/-
Copyright (c) 2022 Mario Carneiro. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro
-/
import Std.Logic
/--
An alternative constructor for `LawfulMonad` which has more
defaultable fields in the common case.
-/
theorem LawfulMonad.mk' ( m : Type u → Type v ) [ Monad m ]
( id_map : ∀ { α } ( x : m α ), id : {α : Sort ?u.26} → α → α id <$> x = x )
( pure_bind : ∀ { α β } ( x : α ) ( f : α → m β ), pure : {f : Type ?u.86 → Type ?u.85 } → [self : Pure f ] → {α : Type ?u.86} → α → f α pure x >>= f = f x )
( bind_assoc : ∀ { α β γ } ( x : m α ) ( f : α → m β ) ( g : β → m γ ),
x >>= f >>= g = x >>= fun x => f x >>= g )
( map_const : ∀ { α β } ( x : α ) ( y : m β ),
Functor.mapConst : {f : Type ?u.384 → Type ?u.383 } → [self : Functor f ] → {α β : Type ?u.384} → α → f β → f α Functor.mapConst x y = Function.const : {α : Sort ?u.397} → (β : Sort ?u.396) → α → β → α Function.const β x <$> y := by intros ; rfl )
( seqLeft_eq : ∀ { α β } ( x : m α ) ( y : m β ),
x <* y = ( x >>= fun a => y >>= fun _ => pure : {f : Type ?u.571 → Type ?u.570 } → [self : Pure f ] → {α : Type ?u.571} → α → f α pure a ) := by intros ; rfl )
( seqRight_eq : ∀ { α β } ( x : m α ) ( y : m β ), x *> y = ( x >>= fun _ => y ) := by intros ; rfl )
( bind_pure_comp : ∀ { α β } ( f : α → β ) ( x : m α ),
x >>= ( fun y => pure : {f : Type ?u.829 → Type ?u.828 } → [self : Pure f ] → {α : Type ?u.829} → α → f α pure ( f y )) = f <$> x := by intros ; rfl )
( bind_map : ∀ { α β } ( f : m ( α → β )) ( x : m α ), f >>= (. <$> x ) = f <*> x := by intros ; rfl )
: LawfulMonad m :=
have map_pure { α β } ( g : α → β ) ( x : α ) : g <$> ( pure : {f : Type ?u.1095 → Type ?u.1094 } → [self : Pure f ] → {α : Type ?u.1095} → α → f α pure x : m α ) = pure : {f : Type ?u.1153 → Type ?u.1152 } → [self : Pure f ] → {α : Type ?u.1153} → α → f α pure ( g x ) := by
rw [ ← bind_pure_comp ] ; simp [ pure_bind ]
{ id_map , bind_pure_comp , bind_map , pure_bind , bind_assoc , map_pure ,
comp_map := by simp [← bind_pure_comp , bind_assoc , pure_bind ]
pure_seq := by intros m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : α✝ → β✝ x✝ : m α✝ ; m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : α✝ → β✝ x✝ : m α✝ rw [ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : α✝ → β✝ x✝ : m α✝ ← bind_map m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : α✝ → β✝ x✝ : m α✝ ] m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : α✝ → β✝ x✝ : m α✝ ; m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : α✝ → β✝ x✝ : m α✝ simp [ pure_bind ]
seq_pure := by intros m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : m (α✝ → β✝ )x✝ : α✝ ; m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : m (α✝ → β✝ )x✝ : α✝ rw [ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : m (α✝ → β✝ )x✝ : α✝ ← bind_map m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : m (α✝ → β✝ )x✝ : α✝ ] m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : m (α✝ → β✝ )x✝ : α✝ ; m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ug✝ : m (α✝ → β✝ )x✝ : α✝ simp [ map_pure , bind_pure_comp ]
seq_assoc := by simp [← bind_pure_comp , ← bind_map , bind_assoc , pure_bind ]
map_const := funext : ∀ {α : Sort ?u.1235} {β : α → Sort ?u.1234 } {f g : (x : α ) → β x }, (∀ (x : α ), f x = g x ) → f = g funext fun x => funext : ∀ {α : Sort ?u.1253} {β : α → Sort ?u.1252 } {f g : (x : α ) → β x }, (∀ (x : α ), f x = g x ) → f = g funext ( map_const x )
seqLeft_eq := by simp [ seqLeft_eq , ← bind_map , ← bind_pure_comp , pure_bind , bind_assoc ]
seqRight_eq := fun x y => by
m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ rw [ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ seqRight_eq , m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ ← bind_map , m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ ← bind_pure_comp , m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ bind_assoc m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ ] m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ ; m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ m : Type u → Type vinst✝ : Monad m id_map : ∀ {α : Type u} (x : m α ), id <$> x = x pure_bind : ∀ {α β : Type u} (x : α ) (f : α → m β ), pure x >>= f = f x bind_assoc : ∀ {α β γ : Type u} (x : m α ) (f : α → m β ) (g : β → m γ ), x >>= f >>= g = x >>= fun x => f x >>= g map_const : autoParam (∀ {α β : Type u} (x : α ) (y : m β ), Functor.mapConst x y = Function.const β x <$> y ) _auto✝ seqLeft_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqLeft.seqLeft x fun x => y ) = do
let a ← x
let _ ← y
pure a )
_auto✝ seqRight_eq : autoParam
(∀ {α β : Type u} (x : m α ) (y : m β ),
(SeqRight.seqRight x fun x => y ) = do
let _ ← x
y )
_auto✝ bind_pure_comp : autoParam
(∀ {α β : Type u} (f : α → β ) (x : m α ),
(do
let y ← x
pure (f y ) ) = f <$> x )
_auto✝ bind_map : autoParam
(∀ {α β : Type u} (f : m (α → β ) ) (x : m α ),
(do
let x_1 ← f
x_1 <$> x ) = Seq.seq f fun x_1 => x )
_auto✝ map_pure : ∀ {α β : Type u} (g : α → β ) (x : α ), g <$> pure x = pure (g x ) α✝, β✝ : Type ux : m α✝ y : m β✝ simp [ pure_bind , id_map ] }
instance : LawfulMonad ( Except : Type ?u.11296 → Type ?u.11295 → Type (max?u.11296?u.11295) Except ε ) := LawfulMonad.mk'
(id_map := fun x => by cases x <;> rfl )
(pure_bind := fun a f => rfl : ∀ {α : Sort ?u.11397} {a : α }, a = a rfl)
(bind_assoc := fun a f g => by cases a <;> rfl )
instance : LawfulApplicative ( Except : Type ?u.11994 → Type ?u.11993 → Type (max?u.11994?u.11993) Except ε ) := inferInstance : ∀ {α : Sort ?u.12027} [i : α ], α inferInstance
instance : LawfulFunctor ( Except : Type ?u.12080 → Type ?u.12079 → Type (max?u.12080?u.12079) Except ε ) := inferInstance : ∀ {α : Sort ?u.12123} [i : α ], α inferInstance
instance : LawfulMonad Option := LawfulMonad.mk'
(id_map := fun x => by cases x none α✝ : Type ?u.12181val✝ : α✝ some <;> none α✝ : Type ?u.12181val✝ : α✝ some rfl )
(pure_bind := fun x f => rfl : ∀ {α : Sort ?u.12276} {a : α }, a = a rfl)
(bind_assoc := fun x f g => by cases x <;> rfl )
(bind_pure_comp := fun f x => by cases x α✝, β✝ : Type ?u.12181f : α✝ → β✝ none α✝, β✝ : Type ?u.12181f : α✝ → β✝ val✝ : α✝ some <;> α✝, β✝ : Type ?u.12181f : α✝ → β✝ none α✝, β✝ : Type ?u.12181f : α✝ → β✝ val✝ : α✝ some rfl )
instance : LawfulApplicative Option := inferInstance : ∀ {α : Sort ?u.12958} [i : α ], α inferInstance
instance : LawfulFunctor Option := inferInstance : ∀ {α : Sort ?u.13007} [i : α ], α inferInstance
/-!
## SatisfiesM
The `SatisfiesM` predicate works over an arbitrary (lawful) monad / applicative / functor,
and enables Hoare-like reasoning over monadic expressions. For example, given a monadic
function `f : α → m β`, to say that the return value of `f` satisfies `Q` whenever
the input satisfies `P`, we write `∀ a, P a → SatisfiesM Q (f a)`.
-/
/--
`SatisfiesM p (x : m α)` lifts propositions over a monad. It asserts that `x` may as well
have the type `x : m {a // p a}`, because there exists some `m {a // p a}` whose image is `x`.
So `p` is the postcondition of the monadic value.
-/
def SatisfiesM { m : Type u → Type v } [ Functor : (Type ?u.13058 → Type ?u.13057 ) → Type (max(?u.13058+1)?u.13057) Functor m ] ( p : α → Prop ) ( x : m α ) : Prop :=
∃ x' : m { a // p a }, Subtype.val <$> x' = x
namespace SatisfiesM
/-- If `p` is always true, then every `x` satisfies it. -/
theorem of_true [ Applicative : (Type ?u.13156 → Type ?u.13155 ) → Type (max(?u.13156+1)?u.13155) Applicative m ] [ LawfulApplicative m ] { x : m α }
( h : ∀ (a : ?m.13232 ), ?m.13236 a
h : ∀ a , p a ) : SatisfiesM p x :=
⟨( fun a => ⟨ a , h a ⟩) <$> x , by Subtype.val <$> (fun a => { val := a , property := (_ : p a ) } ) <$> x = x simp [← comp_map , Function.comp : {α : Sort ?u.13394} → {β : Sort ?u.13393} → {δ : Sort ?u.13392} → (β → δ ) → (α → β ) → α → δ Function.comp] ⟩
/--
If `p` is always true, then every `x` satisfies it.
(This is the strongest postcondition version of `of_true`.)
-/
protected theorem trivial [ Applicative : (Type ?u.13890 → Type ?u.13889 ) → Type (max(?u.13890+1)?u.13889) Applicative m ] [ LawfulApplicative m ] { x : m α } :
SatisfiesM ( fun _ => True ) x := of_true fun _ => trivial
/-- The `SatisfiesM p x` predicate is monotonic in `p`. -/
theorem imp [ Functor : (Type ?u.14027 → Type ?u.14026 ) → Type (max(?u.14027+1)?u.14026) Functor m ] [ LawfulFunctor m ] { x : m α }
( h : SatisfiesM p x ) ( H : ∀ { a }, p a → q a ) : SatisfiesM q x :=
let ⟨ x , h ⟩ := h ; ⟨( fun ⟨ a , h ⟩ => ⟨ _ , H h ⟩) <$> x , by Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = x✝ rw [ Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = x✝ ← h , Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = Subtype.val <$> x Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = x✝ ← comp_map (Subtype.val ∘ fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = Subtype.val <$> x ] (Subtype.val ∘ fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = Subtype.val <$> x ; (Subtype.val ∘ fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = Subtype.val <$> x Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := a , property := (_ : q a ) } ) <$> x = x✝ rfl ⟩
/-- `SatisfiesM` distributes over `<$>`, general version. -/
protected theorem map [ Functor : (Type ?u.14764 → Type ?u.14763 ) → Type (max(?u.14764+1)?u.14763) Functor m ] [ LawfulFunctor m ] { x : m α }
( hx : SatisfiesM p x ) ( hf : ∀ {a : α }, p a → ?m.14904
hf : ∀ { a }, p a : unknown metavariable '?_uniq.14807'
a → q ( f a )) : SatisfiesM q ( f <$> x ) := by
let ⟨ x' , hx ⟩ := hx
refine ⟨( fun ⟨ a , h ⟩ => ⟨ f a , hf : ∀ {a : α }, p a → q (f a )
hf h ⟩) <$> x' , ?_ : ?m.15081 ((fun x => ?m.15104 x ) <$> x' ) ?_⟩ Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := f a , property := (_ : q (f a ) ) } ) <$> x' = f <$> x
rw [ Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := f a , property := (_ : q (f a ) ) } ) <$> x' = f <$> x ← hx Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := f a , property := (_ : q (f a ) ) } ) <$> x' = f <$> Subtype.val <$> x' ] Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := f a , property := (_ : q (f a ) ) } ) <$> x' = f <$> Subtype.val <$> x' ; Subtype.val <$> (fun x =>
match x with
| { val := a , property := h } => { val := f a , property := (_ : q (f a ) ) } ) <$> x' = f <$> Subtype.val <$> x' simp [← comp_map , Function.comp : {α : Sort ?u.15278} → {β : Sort ?u.15277} → {δ : Sort ?u.15276} → (β → δ ) → (α → β ) → α → δ Function.comp]
/--
`SatisfiesM` distributes over `<$>`, strongest postcondition version.
(Use this for reasoning forward from assumptions.)
-/
theorem map_post [ Functor : (Type ?u.16250 → Type ?u.16249 ) → Type (max(?u.16250+1)?u.16249) Functor m ] [ LawfulFunctor m ] { x : m α }
( hx : SatisfiesM p x ) : SatisfiesM ( fun b => ∃ a , p a ∧ b = f a ) ( f <$> x ) :=
hx . map fun h => ⟨ _ , h , rfl : ∀ {α : Sort ?u.16582} {a : α }, a = a rfl⟩
/--
`SatisfiesM` distributes over `<$>`, weakest precondition version.
(Use this for reasoning backward from the goal.)
-/
theorem map_pre [ Functor : (Type ?u.16682 → Type ?u.16681 ) → Type (max(?u.16682+1)?u.16681) Functor m ] [ LawfulFunctor m ] { x : m α }
( hx : SatisfiesM ( fun a => p ( f a )) x ) : SatisfiesM p ( f <$> x ) :=
hx . map fun h => h
/-- `SatisfiesM` distributes over `mapConst`, general version. -/
protected theorem mapConst [ Functor : (Type ?u.17073 → Type ?u.17072 ) → Type (max(?u.17073+1)?u.17072) Functor m ] [ LawfulFunctor m ] { x : m α }
( hx : SatisfiesM q x ) ( ha : ∀ {b : α }, q b → ?m.17213
ha : ∀ { b }, q b : unknown metavariable '?_uniq.17116'
b → p a ) : SatisfiesM p ( Functor.mapConst : {f : Type ?u.17234 → Type ?u.17233 } → [self : Functor f ] → {α β : Type ?u.17234} → α → f β → f α Functor.mapConst a x ) :=
map_const (f := m ) ▸ hx . map ha
/-- `SatisfiesM` distributes over `pure`, general version / weakest precondition version. -/
protected theorem pure [ Applicative : (Type ?u.17498 → Type ?u.17497 ) → Type (max(?u.17498+1)?u.17497) Applicative m ] [ LawfulApplicative m ]
( h : unknown metavariable '?_uniq.17458'
h : p a ) : SatisfiesM (m := m ) p ( pure : {f : Type ?u.17531 → Type ?u.17530 } → [self : Pure f ] → {α : Type ?u.17531} → α → f α pure a ) := ⟨ pure : {f : Type ?u.17615 → Type ?u.17614 } → [self : Pure f ] → {α : Type ?u.17615} → α → f α pure ⟨ _ , h ⟩, by simp ⟩
/-- `SatisfiesM` distributes over `<*>`, general version. -/
protected theorem seq [ Applicative : (Type ?u.18028 → Type ?u.18027 ) → Type (max(?u.18028+1)?u.18027) Applicative m ] [ LawfulApplicative m ] { x : m α }
( hf : SatisfiesM p₁ f ) ( hx : SatisfiesM p₂ x )
( H : ∀ {f : ?m.18309 } {a : α }, p₁ f → p₂ a → ?m.18314
H : ∀ { f a }, p₁ f → p₂ a → q ( f a )) : SatisfiesM q ( f <*> x ) := by
match f , x , hf , hx with | _, _, ⟨ f , rfl : ∀ {α : Sort ?u.18428} {a : α }, a = a rfl⟩, ⟨ x , rfl : ∀ {α : Sort ?u.18432} {a : α }, a = a rfl⟩ => ?_
refine ⟨( fun ⟨ a , h₁ ⟩ ⟨ b , h₂ ⟩ => ⟨ a b , H : ∀ {f : α → α✝ } {a : α }, p₁ f → p₂ a → q (f a )
H h₁ h₂ ⟩) <$> f <*> x , ?_ : ?m.18906 (Seq.seq ((fun x x_1 => ?m.18959 x x_1 ) <$> f ) fun x_1 => x ) ?_⟩ (Subtype.val <$> Seq.seq
((fun x x_1 =>
match x with
| { val := a , property := h₁ } =>
match x_1 with
| { val := b , property := h₂ } => { val := a b , property := (_ : q (a b ) ) } ) <$> f )
fun x_1 => x ) = Seq.seq (Subtype.val <$> f ) fun x_1 => Subtype.val <$> x
simp only [← pure_seq ] ; simp [ SatisfiesM , seq_assoc ]
simp only [← pure_seq ] ; simp [ seq_assoc , Function.comp : {α : Sort ?u.22112} → {β : Sort ?u.22111} → {δ : Sort ?u.22110} → (β → δ ) → (α → β ) → α → δ Function.comp]
/-- `SatisfiesM` distributes over `<*>`, strongest postcondition version. -/
protected theorem seq_post [ Applicative : (Type ?u.25708 → Type ?u.25707 ) → Type (max(?u.25708+1)?u.25707) Applicative m ] [ LawfulApplicative m ] { x : m α }
( hf : SatisfiesM p₁ f ) ( hx : SatisfiesM p₂ x ) :
SatisfiesM ( fun c => ∃ f a , p₁ f ∧ p₂ a ∧ c = f a ) ( f <*> x ) :=
hf . seq hx fun hf ha => ⟨ _ , _ , hf , ha , rfl : ∀ {α : Sort ?u.26107} {a : α }, a = a rfl⟩
/--
`SatisfiesM` distributes over `<*>`, weakest precondition version 1.
(Use this when `x` and the goal are known and `f` is a subgoal.)
-/
protected theorem seq_pre [ Applicative : (Type ?u.26159 → Type ?u.26158 ) → Type (max(?u.26159+1)?u.26158) Applicative m ] [ LawfulApplicative m ] { x : m α }
( hf : SatisfiesM (fun f => ∀ {a : ?m.26393 f }, ?m.26394 f → ?m.26395 f ) f hf : SatisfiesM ( fun f => ∀ { a }, p₂ a → q ( f a )) f ) ( hx : SatisfiesM p₂ x ) :
SatisfiesM q ( f <*> x ) :=
hf : SatisfiesM (fun f => ∀ {a : α }, p₂ a → q (f a ) ) f hf . seq hx fun hf ha => hf ha
/--
`SatisfiesM` distributes over `<*>`, weakest precondition version 2.
(Use this when `f` and the goal are known and `x` is a subgoal.)
-/
protected theorem seq_pre' [ Applicative : (Type ?u.26865 → Type ?u.26864 ) → Type (max(?u.26865+1)?u.26864) Applicative m ] [ LawfulApplicative m ] { x : m α }
( hf : SatisfiesM p₁ f ) ( hx : SatisfiesM (fun a => ∀ {f : ?m.26942 }, p₁ f → ?m.26948 a ) x hx : SatisfiesM ( fun a => ∀ { f },