1{- | Support for checked exceptions.
3 The `Error` effect provided by this module is a suitable replacement for the
4 `Control.Monad.Except.ExceptT` monad transformer found in the mtl library.
5 It is __not__ intended to be a general mechanism for catching errors like
6 the functions of the 'exceptions' package. For example, if you want to catch
7 an unchecked exception like `Control.Exception.SomeException` or
8 `Control.Exception.ErrorCall` you could rely on `Control.Monad.catch`:
11 let boom :: Eff '[IOE] String
14 runIOE $ boom `Control.Monad.Catch.catch` \(e :: ErrorCall) ->
15 return "caught some error"
30import Control.Exception
35import Effectful.Internal.Effect
36import Effectful.Internal.Env
37import Effectful.Internal.Monad
40-- >>> import Control.Monad.Catch
41-- >>> import Control.Monad.IO.Class
42-- >>> import Effectful.Interpreter
44data Error e :: Effect where
45 Error :: Unique -> Error e m r
47-- | TODO: write about possibility of an error escaping the scope of 'runError'
48-- when misused with 'AsyncE'.
50 :: forall e es a. Typeable e
51 => Eff (Error e : es) a
52 -> Eff es (Either (CallStack, e) a)
53runError m = unsafeEff $ \es0 -> mask $ \release -> do
54 -- A unique tag is picked so that different runError handlers for the same
55 -- type don't catch each other's exceptions.
58 es <- unsafeConsEnv (IdE (Error @e tag)) noRelinker es0
59 r <- tryErrorIO tag (release $ unEff m es) `onException` unsafeTailEnv size0 es
60 _ <- unsafeTailEnv size0 es
64 :: forall e es a. (HasCallStack, Typeable e, Error e :> es)
67throwError e = readerEffectM @(Error e) $ \(IdE (Error tag)) -> unsafeEff_ $ do
68 throwIO $ WrapErr tag callStack e
71 :: forall e es a. (Typeable e, Error e :> es)
73 -> (CallStack -> e -> Eff es a)
75catchError m handler = do
76 readerEffectM @(Error e) $ \(IdE (Error tag)) -> unsafeEff $ \es -> do
78 catchErrorIO tag (unEff m es) $ \cs e -> do
80 unEff (handler cs e) es
83 :: forall e es a. (Typeable e, Error e :> es)
85 -> Eff es (Either (CallStack, e) a)
86tryError m = (Right <$> m) `catchError` \es e -> pure $ Left (es, e)
88----------------------------------------
91data WrapErr e = WrapErr Unique CallStack e
93instance Typeable e => Show (WrapErr e) where
94 showsPrec p (WrapErr _ cs e)
95 = showsPrec p "Effectful.Error.WrapErr ("
96 . showsPrec p (typeOf e)
99instance Typeable e => Exception (WrapErr e)
101catchErrorIO :: Typeable e => Unique -> IO a -> (CallStack -> e -> IO a) -> IO a
102catchErrorIO tag m handler = do
103 m `catch` \err@(WrapErr etag e cs) -> do
108tryErrorIO :: Typeable e => Unique -> IO a -> IO (Either (CallStack, e) a)
109tryErrorIO tag m = catchErrorIO tag (Right <$> m) $ \es e -> pure $ Left (es, e)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list