0 | module Control.Monad.MErr
2 | import public Data.List.Quantifiers.Extra
10 | 0 Result : List Type -> Type -> Type
11 | Result es a = Either (HSum es) a
18 | interface MErr (0 m : List Type -> Type -> Type) where
19 | fail : HSum es -> m es a
20 | succeed : a -> m es a
21 | attempt : m es a -> m fs (Result es a)
22 | bind : m es a -> (a -> m es b) -> m es b
23 | mapImpl : (a -> b) -> m es a -> m es b
24 | appImpl : m es (a -> b) -> m es a -> m es b
26 | public export %inline
27 | MErr m => Functor (m es) where
30 | public export %inline
31 | MErr m => Applicative (m es) where
35 | public export %inline
36 | MErr m => Monad (m es) where
40 | fromResult : MErr m => Result es a -> m es a
41 | fromResult = either fail succeed
47 | parameters {auto merr : MErr m}
51 | throw : Has x es => x -> m es a
52 | throw = fail . inject
57 | injectEither : Has x es => Either x a -> m es a
58 | injectEither (Left v) = throw v
59 | injectEither (Right v) = succeed v
63 | handleErrors : (HSum es -> m fs a) -> m es a -> m fs a
64 | handleErrors f act = attempt act >>= either f pure
69 | handleError : (0 e : Type) -> Has e es => (e -> m es a) -> m es a -> m es a
71 | handleErrors $
\x => case project e x of
78 | catch : (0 e : Type) -> Has e es => m es a -> m es (Either e a)
81 | Right v => pure $
Right v
82 | Left errs => case project e errs of
83 | Nothing => fail errs
84 | Just err => pure $
Left err
92 | extractErr : (0 e : Type) -> (p : Has e es) => m es a -> m (es - e) (Either e a)
94 | attempt {fs = es - e} m >>= \case
95 | Right v => pure $
Right v
96 | Left errs => case decomp @{p} errs of
98 | Right x => pure $
Left x
101 | mapErrors : (HSum es -> HSum fs) -> m es a -> m fs a
102 | mapErrors f = handleErrors (fail . f)
105 | mapErr : (h : Has e es) => (e -> f) -> m es a -> m (Replaced es h f) a
106 | mapErr fun = mapErrors (update fun)
108 | widen_ : All (`Elem` es) fs => HSum fs -> HSum es
109 | widen_ @{_::_} (Here v) = inject v
110 | widen_ @{_::_} (There v) = widen_ v
113 | widenErrors : All (`Elem` es) fs => m fs a -> m es a
114 | widenErrors = mapErrors widen_
117 | weakenErrors : m [] a -> m fs a
118 | weakenErrors = handleErrors absurd
121 | dropErrs : m es () -> m [] ()
122 | dropErrs = handleErrors (const $
succeed ())
125 | liftError : m [e] a -> m fs (Either e a)
126 | liftError = handleErrors (pure . Left . project1) . map Right
129 | handle : All (\e => e -> m [] a) es -> m es a -> m [] a
130 | handle hs = handleErrors (collapse' . hzipWith id hs)
134 | bindResult : m es a -> (Result es a -> m fs b) -> m fs b
135 | bindResult act f = attempt act >>= f
140 | onError : m es a -> (HSum es -> m [] ()) -> m es a
141 | onError act f = handleErrors (\x => weakenErrors (f x) >> fail x) act
147 | ifError : Has e es => Eq e => (err : e) -> Lazy a -> m es a -> m es a
149 | handleErrors $
\x => case project e x of
151 | Just y => if err == y then pure v else fail x