|
9 | 9 | public import Init.Control.Lawful.Basic |
10 | 10 | public import Init.Control.Except |
11 | 11 | import all Init.Control.Except |
| 12 | +public import Init.Control.Option |
| 13 | +import all Init.Control.Option |
12 | 14 | public import Init.Control.State |
13 | 15 | import all Init.Control.State |
14 | 16 | public import Init.Control.StateRef |
@@ -110,6 +112,118 @@ instance : LawfulMonad (Except ε) := LawfulMonad.mk' |
110 | 112 | instance : LawfulApplicative (Except ε) := inferInstance |
111 | 113 | instance : LawfulFunctor (Except ε) := inferInstance |
112 | 114 |
|
| 115 | +/-! # OptionT -/ |
| 116 | + |
| 117 | +namespace OptionT |
| 118 | + |
| 119 | +@[ext] theorem ext {x y : OptionT m α} (h : x.run = y.run) : x = y := by |
| 120 | + simp [run] at h |
| 121 | + assumption |
| 122 | + |
| 123 | +@[simp, grind =] theorem run_pure [Monad m] (x : α) : run (pure x : OptionT m α) = pure (some x) := by |
| 124 | + simp [run, pure, OptionT.pure, OptionT.mk] |
| 125 | + |
| 126 | +@[simp, grind =] theorem run_lift [Monad.{u, v} m] (x : m α) : run (OptionT.lift x : OptionT m α) = (return some (← x) : m (Option α)) := by |
| 127 | + simp [run, OptionT.lift, OptionT.mk] |
| 128 | + |
| 129 | +@[simp, grind =] theorem run_throw [Monad m] : run (throw e : OptionT m β) = pure none := by |
| 130 | + simp [run, throw, throwThe, MonadExceptOf.throw, OptionT.fail, OptionT.mk] |
| 131 | + |
| 132 | +@[simp, grind =] theorem run_bind_lift [Monad m] [LawfulMonad m] (x : m α) (f : α → OptionT m β) : run (OptionT.lift x >>= f : OptionT m β) = x >>= fun a => run (f a) := by |
| 133 | + simp [OptionT.run, OptionT.lift, bind, OptionT.bind, OptionT.mk] |
| 134 | + |
| 135 | +@[simp, grind =] theorem bind_throw [Monad m] [LawfulMonad m] (f : α → OptionT m β) : (throw e >>= f) = throw e := by |
| 136 | + simp [throw, throwThe, MonadExceptOf.throw, bind, OptionT.bind, OptionT.mk, OptionT.fail] |
| 137 | + |
| 138 | +@[simp, grind =] theorem run_bind (f : α → OptionT m β) [Monad m] : |
| 139 | + (x >>= f).run = Option.elimM x.run (pure none) (fun x => (f x).run) := by |
| 140 | + change x.run >>= _ = _ |
| 141 | + simp [Option.elimM] |
| 142 | + exact bind_congr fun |some _ => rfl | none => rfl |
| 143 | + |
| 144 | +@[simp, grind =] theorem lift_pure [Monad m] [LawfulMonad m] {α : Type u} (a : α) : OptionT.lift (pure a : m α) = pure a := by |
| 145 | + simp only [OptionT.lift, OptionT.mk, bind_pure_comp, map_pure, pure, OptionT.pure] |
| 146 | + |
| 147 | +@[simp, grind =] theorem run_map [Monad m] [LawfulMonad m] (f : α → β) (x : OptionT m α) |
| 148 | + : (f <$> x).run = Option.map f <$> x.run := by |
| 149 | + simp [Functor.map, Option.map, ←bind_pure_comp] |
| 150 | + apply bind_congr |
| 151 | + intro a; cases a <;> simp [OptionT.pure, OptionT.mk] |
| 152 | + |
| 153 | +protected theorem seq_eq {α β : Type u} [Monad m] (mf : OptionT m (α → β)) (x : OptionT m α) : mf <*> x = mf >>= fun f => f <$> x := |
| 154 | + rfl |
| 155 | + |
| 156 | +protected theorem bind_pure_comp [Monad m] (f : α → β) (x : OptionT m α) : x >>= pure ∘ f = f <$> x := by |
| 157 | + intros; rfl |
| 158 | + |
| 159 | +protected theorem seqLeft_eq {α β : Type u} {m : Type u → Type v} [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) : x <* y = const β <$> x <*> y := by |
| 160 | + change (x >>= fun a => y >>= fun _ => pure a) = (const (α := α) β <$> x) >>= fun f => f <$> y |
| 161 | + rw [← OptionT.bind_pure_comp] |
| 162 | + apply ext |
| 163 | + simp [Option.elimM, Option.elim] |
| 164 | + apply bind_congr |
| 165 | + intro |
| 166 | + | none => simp |
| 167 | + | some _ => |
| 168 | + simp [←bind_pure_comp]; apply bind_congr; intro b; |
| 169 | + cases b <;> simp [const] |
| 170 | + |
| 171 | +protected theorem seqRight_eq [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) : x *> y = const α id <$> x <*> y := by |
| 172 | + change (x >>= fun _ => y) = (const α id <$> x) >>= fun f => f <$> y |
| 173 | + rw [← OptionT.bind_pure_comp] |
| 174 | + apply ext |
| 175 | + simp [Option.elimM, Option.elim] |
| 176 | + apply bind_congr |
| 177 | + intro a; cases a <;> simp |
| 178 | + |
| 179 | +instance [Monad m] [LawfulMonad m] : LawfulMonad (OptionT m) where |
| 180 | + id_map := by intros; apply ext; simp |
| 181 | + map_const := by intros; rfl |
| 182 | + seqLeft_eq := OptionT.seqLeft_eq |
| 183 | + seqRight_eq := OptionT.seqRight_eq |
| 184 | + pure_seq := by intros; apply ext; simp [OptionT.seq_eq, Option.elimM, Option.elim] |
| 185 | + bind_pure_comp := OptionT.bind_pure_comp |
| 186 | + bind_map := by intros; rfl |
| 187 | + pure_bind := by intros; apply ext; simp [Option.elimM, Option.elim] |
| 188 | + bind_assoc := by intros; apply ext; simp [Option.elimM, Option.elim]; apply bind_congr; intro a; cases a <;> simp |
| 189 | + |
| 190 | +@[simp] theorem run_seq [Monad m] [LawfulMonad m] (f : OptionT m (α → β)) (x : OptionT m α) : |
| 191 | + (f <*> x).run = Option.elimM f.run (pure none) (fun f => Option.map f <$> x.run) := by |
| 192 | + simp [seq_eq_bind, Option.elimM, Option.elim] |
| 193 | + |
| 194 | +@[simp] theorem run_seqLeft [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) : |
| 195 | + (x <* y).run = Option.elimM x.run (pure none) |
| 196 | + (fun x => Option.map (Function.const β x) <$> y.run) := by |
| 197 | + simp [seqLeft_eq, seq_eq_bind, Option.elimM, OptionT.run_bind] |
| 198 | + |
| 199 | +@[simp] theorem run_seqRight [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) : |
| 200 | + (x *> y).run = Option.elimM x.run (pure none) (Function.const α y.run) := by |
| 201 | + simp only [seqRight_eq, run_seq, Option.elimM, run_map, Option.elim, bind_map_left] |
| 202 | + refine bind_congr (fun | some _ => by simp | none => by simp) |
| 203 | + |
| 204 | +@[simp, grind =] theorem run_failure [Monad m] : (failure : OptionT m α).run = pure none := by rfl |
| 205 | + |
| 206 | +@[simp] theorem map_failure [Monad m] [LawfulMonad m] {α β : Type _} (f : α → β) : |
| 207 | + f <$> (failure : OptionT m α) = (failure : OptionT m β) := by |
| 208 | + simp [OptionT.mk, Functor.map, Alternative.failure, OptionT.fail, OptionT.bind] |
| 209 | + |
| 210 | +@[simp] theorem run_orElse [Monad m] (x : OptionT m α) (y : OptionT m α) : |
| 211 | + (x <|> y).run = Option.elimM x.run y.run (fun x => pure (some x)) := |
| 212 | + bind_congr fun | some _ => by rfl | none => by rfl |
| 213 | + |
| 214 | +end OptionT |
| 215 | + |
| 216 | +/-! # Option -/ |
| 217 | + |
| 218 | +instance : LawfulMonad Option := LawfulMonad.mk' |
| 219 | + (id_map := fun x => by cases x <;> rfl) |
| 220 | + (pure_bind := fun _ _ => by rfl) |
| 221 | + (bind_assoc := fun a _ _ => by cases a <;> rfl) |
| 222 | + (bind_pure_comp := bind_pure_comp) |
| 223 | + |
| 224 | +instance : LawfulApplicative Option := inferInstance |
| 225 | +instance : LawfulFunctor Option := inferInstance |
| 226 | + |
113 | 227 | /-! # ReaderT -/ |
114 | 228 |
|
115 | 229 | namespace ReaderT |
|
0 commit comments