| /- | |
| Copyright (c) 2019 Microsoft Corporation. All rights reserved. | |
| Released under Apache 2.0 license as described in the file LICENSE. | |
| Authors: Leonardo de Moura | |
| -/ | |
| prelude | |
| import Init.Control.State | |
| import Init.Control.Except | |
| import Init.Data.ToString.Basic | |
| universe u v | |
| namespace EStateM | |
| variable {ε σ α : Type u} | |
| instance [ToString ε] [ToString α] : ToString (Result ε σ α) where | |
| toString | |
| | Result.ok a _ => "ok: " ++ toString a | |
| | Result.error e _ => "error: " ++ toString e | |
| instance [Repr ε] [Repr α] : Repr (Result ε σ α) where | |
| reprPrec | |
| | Result.error e _, prec => Repr.addAppParen ("EStateM.Result.error " ++ reprArg e) prec | |
| | Result.ok a _, prec => Repr.addAppParen ("EStateM.Result.ok " ++ reprArg a) prec | |
| end EStateM | |
| namespace EStateM | |
| variable {ε σ α β : Type u} | |
| /-- Alternative orElse operator that allows to select which exception should be used. | |
| The default is to use the first exception since the standard `orElse` uses the second. -/ | |
| @[always_inline, inline] | |
| protected def orElse' {δ} [Backtrackable δ σ] (x₁ x₂ : EStateM ε σ α) (useFirstEx := true) : EStateM ε σ α := fun s => | |
| let d := Backtrackable.save s; | |
| match x₁ s with | |
| | Result.error e₁ s₁ => | |
| match x₂ (Backtrackable.restore s₁ d) with | |
| | Result.error e₂ s₂ => Result.error (if useFirstEx then e₁ else e₂) s₂ | |
| | ok => ok | |
| | ok => ok | |
| @[always_inline] | |
| instance : MonadFinally (EStateM ε σ) := { | |
| tryFinally' := fun x h s => | |
| let r := x s | |
| match r with | |
| | Result.ok a s => match h (some a) s with | |
| | Result.ok b s => Result.ok (a, b) s | |
| | Result.error e s => Result.error e s | |
| | Result.error e₁ s => match h none s with | |
| | Result.ok _ s => Result.error e₁ s | |
| | Result.error e₂ s => Result.error e₂ s | |
| } | |
| @[always_inline, inline] def fromStateM {ε σ α : Type} (x : StateM σ α) : EStateM ε σ α := fun s => | |
| match x.run s with | |
| | (a, s') => EStateM.Result.ok a s' | |
| end EStateM |