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
49 | throw : MErr m => Has x es => x -> m es a
50 | throw = fail . inject
55 | injectEither : MErr m => Has x es => Either x a -> m es a
56 | injectEither (Left v) = throw v
57 | injectEither (Right v) = succeed v
61 | handleErrors : MErr m => (HSum es -> m fs a) -> m es a -> m fs a
62 | handleErrors f act = attempt act >>= either f pure
67 | catch : MErr m => (0 e : Type) -> Has e es => m es a -> m es (Either e a)
70 | Right v => pure $
Right v
71 | Left errs => case project e errs of
72 | Nothing => fail errs
73 | Just err => pure $
Left err
81 | extractErr : MErr m => (0 e : Type) -> (p : Has e es) => m es a -> m (es - e) (Either e a)
83 | attempt {fs = es - e} m >>= \case
84 | Right v => pure $
Right v
85 | Left errs => case decomp @{p} errs of
87 | Right x => pure $
Left x
90 | mapErrors : MErr m => (HSum es -> HSum fs) -> m es a -> m fs a
91 | mapErrors f = handleErrors (fail . f)
93 | widen_ : All (`Elem` es) fs => HSum fs -> HSum es
94 | widen_ @{_::_} (Here v) = inject v
95 | widen_ @{_::_} (There v) = widen_ v
98 | widenErrors : MErr m => All (`Elem` es) fs => m fs a -> m es a
99 | widenErrors = mapErrors widen_
102 | weakenErrors : MErr m => m [] a -> m fs a
103 | weakenErrors = handleErrors absurd
106 | dropErrs : MErr m => m es () -> m [] ()
107 | dropErrs = handleErrors (const $
succeed ())
110 | liftError : MErr m => m [e] a -> m fs (Either e a)
111 | liftError = handleErrors (pure . Left . project1) . map Right
114 | handle : MErr m => All (\e => e -> m [] a) es -> m es a -> m [] a
115 | handle hs = handleErrors (collapse' . hzipWith id hs)
119 | bindResult : MErr m => m es a -> (Result es a -> m fs b) -> m fs b
120 | bindResult act f = attempt act >>= f
125 | onError : MErr m => m es a -> (HSum es -> m [] ()) -> m es a
126 | onError act f = handleErrors (\x => weakenErrors (f x) >> fail x) act
132 | ifError : MErr m => Has e es => Eq e => (err : e) -> Lazy a -> m es a -> m es a
134 | handleErrors $
\x => case project e x of
136 | Just y => if err == y then pure v else fail x