/- Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Jared Roesch -/ /- FIXME(@jroesch): remove this after the native compiler branch is merged. -/ universes u v inductive except (ε α : Type u) | error {} : ε → except | ok {} : α → except def except.return {ε α : Type u} (a : α) : except ε α := except.ok a def except.map {ε α β : Type u} (f : α → β) : except ε α → except ε β | (except.error err) := except.error err | (except.ok v) := except.ok $ f v def except.bind {ε α β : Type u} (ma : except ε α) (f : α → except ε β) : except ε β := match ma with | (except.error err) := except.error err | (except.ok v) := f v end lemma except.id_map {ε α : Type u} (x : except ε α) : except.map id x = x := begin intros, cases x; dsimp [except.map]; reflexivity, end lemma except.pure_bind {ε α β : Type u} (x : α) (f : α → except ε β) : except.bind (except.return x) f = f x := begin intros, dsimp [except.return, except.bind], reflexivity end lemma except.bind_pure_comp_eq_map {ε α β : Type u} (f : α → β) (x : except ε α) : (except.bind x) (except.return ∘ f) = except.map f x := begin intros, cases x; dunfold except.bind except.return except.map, dunfold except.bind._match_1, simp, reflexivity, end instance except_monad (ε : Type u) : monad (except ε) := { pure := @except.return ε, map := @except.map ε, bind := @except.bind ε, id_map := @except.id_map ε, pure_bind := @except.pure_bind ε, bind_pure_comp_eq_map := @except.bind_pure_comp_eq_map ε, bind_assoc := begin intros, cases x; dsimp [except.bind]; reflexivity end } @[reducible] def except_t (m : Type u → Type v) (ε α : Type u) := m (except ε α) section except_t parameter (m : Type u → Type v) parameter [monad_m : monad m] parameter ε : Type u def except_t.return {α : Type u} (a : α) : except_t m ε α := @return m monad_m _ (except.ok a) -- WHy doesn't this work anymore, this seems super annoying ... -- Overall if we lost the ability for these types of projections working it seems like -- a massive lose compared to the old style. -- -- def except_t.map {α β : Type u} (f : α → β) (ma : except_t m ε α) : except_t m ε β := -- (@has_map.map m _ _ _) (except.map f) ma -- This is super annoying ... def except_t.map {α β : Type u} (f : α → β) (ma : except_t m ε α) : except_t m ε β := (@has_map.map m (monad_m.to_applicative.to_functor.to_has_map) _) _ (except.map f) ma def except_t.bind {α β : Type u} (ma : except_t m ε α) (f : α → except_t m ε β) : except_t m ε β := (@has_bind.bind m monad_m.to_has_bind _ _) ma $ λ res, match res with | (except.error err) := return $ except.error err | (except.ok v) := f v end lemma except_t.id_map {α : Type u} (x : except_t m ε α) : except_t.map id x = x := begin intros, unfold except_t at x, dunfold except_t.map, have P : @except.map ε α α id = id, apply funext, intros, rewrite except.id_map, simp, rewrite P, rw functor.id_map, end lemma except_t.pure_bind {α β : Type u} (x : α) (f : α → except_t m ε β) : except_t.bind (except_t.return x) f = f x := begin dunfold except_t.return except_t.bind, have pb := @monad.pure_bind, rewrite pb, dunfold except_t.bind._match_1, reflexivity end lemma except_t.bind_assoc {α β γ : Type u} (x : except_t m ε α) (f : α → except_t m ε β) (g : β → except_t m ε γ): except_t.bind (except_t.bind x f) g = except_t.bind x (λ (x : α), except_t.bind (f x) g) := begin dunfold except_t.bind, rewrite monad.bind_assoc, apply congr, simp, apply funext, intros, cases x_1; simp; dunfold except_t.bind._match_1, unfold return pure, rewrite @monad.pure_bind, dunfold except_t.bind._match_1 has_pure.pure, dsimp, reflexivity, reflexivity, end lemma except_t.bind_pure_comp_eq_map {α β : Type u} (f : α → β) (x : except_t m ε α) : (except_t.bind x) (except_t.return ∘ f) = except_t.map f x := begin intros, unfold except_t at x, dunfold except_t.bind except_t.map, rewrite [← monad.bind_pure_comp_eq_map], apply congr ; simp, apply funext, intros, cases x_1, dunfold except_t.bind._match_1, unfold function.comp, simp [except.map], unfold function.comp, dunfold except_t.bind._match_1, simp [except.map], dunfold except_t.return, reflexivity, end end except_t instance except_t.monad (m : Type u → Type v) [monad m] (ε : Type u) : monad (except_t m ε) := { pure := @except_t.return m _ ε , map := @except_t.map m _ ε, bind := @except_t.bind m _ ε, id_map := @except_t.id_map m _ ε, pure_bind := @except_t.pure_bind m _ ε, bind_assoc := @except_t.bind_assoc m _ ε, bind_pure_comp_eq_map := @except_t.bind_pure_comp_eq_map m _ ε }