/- Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ prelude import init.monad init.meta.format /- Remark: we use a function that produces a format object as the exception information. Motivation: the formatting object may be big, and we may create it on demand. -/ inductive exceptional (A : Type) := | success : A → exceptional A | exception : (options → format) → exceptional A section open exceptional variables {A : Type} variables [has_to_string A] protected meta_definition exceptional.to_string : exceptional A → string | (success a) := to_string a | (exception A e) := "Exception: " + to_string (e options.mk) protected meta_definition exceptional.has_to_string [instance] : has_to_string (exceptional A) := has_to_string.mk exceptional.to_string end namespace exceptional variables {A B : Type} inline protected meta_definition fmap (f : A → B) (e : exceptional A) : exceptional B := exceptional.cases_on e (λ a, success (f a)) (λ f, !exception f) inline protected meta_definition bind (e₁ : exceptional A) (e₂ : A → exceptional B) : exceptional B := exceptional.cases_on e₁ (λ a, e₂ a) (λ f, !exception f) inline protected meta_definition return (a : A) : exceptional A := success a inline meta_definition fail (f : format) : exceptional A := !exception (λ u, f) end exceptional meta_definition exceptional.is_monad [instance] : monad exceptional := monad.mk @exceptional.fmap @exceptional.return @exceptional.bind