从runDb中捕获异常

时间:2015-07-11 17:30:18

标签: haskell persistent

这是我上一篇文章的后续内容。 MaybeT and Transactions in runDb

我认为这将是一件很简单的事情,但我一直试图解决这个问题超过一天,但仍然没有取得多大进展。所以以为我会放弃并问!

我刚刚添加了一个try函数(来自Control.Exception.Lifted)到我以前的代码,我无法获取代码进行类型检查。 catchhandle等变体也存在类似问题。

eauth <- LiftIO (
           try( runDb $ do
                ma <- runMaybeT $ do
                   valid <- ... 
                case ma of
                  Just a -> return a
                  Nothing -> liftIO $ throwIO MyException
            )  :: IO (Either MyException Auth) 
          )
case eauth of
    Right auth -> return auth
    Left _     -> lift $ left err400 { errBody = "Could not create user"}

我的runDb看起来像这样(我还尝试了删除liftIO的变体):

runDb query = do
    pool <- asks getPool
    liftIO $ runSqlPool query pool

我收到此错误:

No instance for (Control.Monad.Reader.Class.MonadReader Config IO)
  arising from a use of ‘runDb’
In the expression: runDb
In the first argument of ‘try’, namely
  ‘(runDb
    $ do { ma <- runMaybeT ... 

我在servant处理程序中运行,我的返回类型是AppM Auth其中

 type AppM = ReaderT Config (EitherT ServantErr IO)

我尝试了许多提升组合,但似乎并没有帮助。我想我会抓住这个机会从头开始弄清楚事情,我也碰到了一堵墙。如果有人能够建议你如何得出答案,那对我来说将是超级有益的。

这是我的思考过程:

  1. 我看到runSqlConn :: MonadBaseControl IO m => SqlPersistT m a -> Connection -> m a
  2. 所以这似乎意味着它会出现在IO monad中,这意味着try应该工作
  3. 我想检查MonadBaseControl的定义class MonadBase b m => MonadBaseControl b m | m -> b。此时我很困惑。这个函数依赖逻辑似乎是建议类型m指示b将是什么,但在前一个b中指定为IO
  4. 我检查MonadBase,这也没有给我任何线索。
  5. 我检查SqlPersistT并且也没有找到任何线索。
  6. 我将问题简化为像result <- liftIO (try (evaluate (5 `div` 0)) :: IO (Either SomeException Int))这样非常简单的问题,并且有效。所以此时我更加困惑。没有runDbIO中工作,所以不应该对我的原始代码起作用吗?
  7. 我认为我可以通过回溯来解决这个问题,但似乎我的Haskell知识水平还不足以解决问题的根源。感谢人们是否可以提供一步一步的指示,以便找到正确的解决方案。

    谢谢!

0 个答案:

没有答案