| import Init.Control.Option | |
| set_option warn.classDefReducibility false | |
| universe u v | |
| def OptionT2 (m : Type u → Type v) (α : Type u) : Type v := | |
| m (Option α) | |
| namespace OptionT2 | |
| variable {m : Type u → Type v} [Monad m] {α β : Type u} | |
| @[inline] protected def bind (ma : OptionT2 m α) (f : α → OptionT2 m β) : OptionT2 m β := | |
| (do { | |
| let a? ← ma; | |
| (match a? with | |
| | some a => f a | |
| | none => pure none) | |
| } : m (Option β)) | |
| @[inline] protected def pure (a : α) : OptionT2 m α := | |
| (Pure.pure (some a) : m (Option α)) | |
| @[inline] protected def orelse (ma : OptionT2 m α) (mb : Unit → OptionT2 m α) : OptionT2 m α := | |
| (do { let a? ← ma; | |
| (match a? with | |
| | some a => pure (some a) | |
| | _ => mb ()) } : m (Option α)) | |
| @[inline] protected def fail : OptionT2 m α := | |
| (pure none : m (Option α)) | |
| end OptionT2 | |
| instance optMonad1 {m} [Monad m] : Monad (OptionT2 m) := | |
| { pure := OptionT2.pure, bind := OptionT2.bind } | |
| def optMonad2 {m} [Monad m] : Monad (OptionT m) := | |
| { pure := OptionT.pure, bind := OptionT.bind } | |
| def optAlt1 {m} [Monad m] : Alternative (OptionT m) := | |
| { failure := OptionT.fail, | |
| orElse := OptionT.orElse, | |
| toApplicative := Monad.toApplicative } | |
| def optAlt2 {m} [Monad m] : Alternative (OptionT m) := | |
| ⟨OptionT.fail, OptionT.orElse⟩ -- it works because it treats `toApplicative` as an instance implicit argument | |
| def optAlt3 {m} [Monad m] : Alternative (OptionT2 m) := | |
| { failure := OptionT2.fail, | |
| orElse := OptionT2.orelse, | |
| toApplicative := Monad.toApplicative } |