blob: 030f10b142b376a540e6fec2c09f9304698712e5 [file]
/-
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