无法在 Snap 处理程序中推断 (CI.MonadCatchIO (Handler App (AuthManager App)))

Could not deduce (CI.MonadCatchIO (Handler App (AuthManager App))) in Snap handler

我在处理程序中使用基于 openapi 的库;不幸的是,它抛出了很多网络或 http 异常,所以我试图将 Control.Monad.CatchIO 与它一起使用,但我的头撞到了类型。

这是我所在的位置:

{-# LANGUAGE ScopedTypeVariables #-}

import qualified Control.Exception as E
import qualified Control.Monad.CatchIO as CI (try,MonadCatchIO)
import           Control.Monad.State

import           Snap
import           Application
import           Services
import qualified Helper.Heist as H
import           Snap.AzureAdAuth

-- this is the function that throws the exceptions
runQuery :: (Produces req accept, MimeUnrender accept b1, Show b1, MimeType contentType) => ServicesRequest req contentType b1 accept -> Handler App (AuthManager App) (Either MimeError b1)
runQuery r = ...


runQuery' :: forall req accept contentType b1. (Produces req accept, MimeUnrender accept b1, Show b1, MimeType contentType)
                       => ServicesRequest req contentType b1 accept
                       -> Handler App (AuthManager App) (Either E.SomeException (Either MimeError b1))
runQuery' req = 
  CI.try $ runQuery req :: Handler App (AuthManager App) (Either E.SomeException (Either MimeError b1))

编译给出这个错误信息:

    * Could not deduce (CI.MonadCatchIO
                          (Handler App (AuthManager App)))
        arising from a use of `CI.try'
      from the context: (Produces req accept, MimeUnrender accept b1,
                         Show b1, MimeType contentType)
        bound by the type signature for:
                   runQuery' :: forall req accept contentType b1.
                                       (Produces req accept, MimeUnrender accept b1, Show b1,
                                        MimeType contentType) =>
                                       ServicesRequest req contentType b1 accept
                                       -> Handler
                                            App
                                            (AuthManager App)
                                            (Either E.SomeException (Either MimeError b1))
        at src/Helper/API.hs:(96,1)-(99,102)
    * In the expression: CI.try $ runQuery req
      In an equation for runQuery':
          runQuery' req = CI.try $ runQuery req

对如何排列类型有什么想法吗?

我无法准确重现您的示例,因为还有很多类型我不知道它们来自哪里。

Snap 框架的 Handler monad 使用 MonadBaseControl 嵌入 IO monad,而不是更传统的 mtl 风格 MonadIOMonadCatchIO MonadCatchIO-mtl 使用。

相反,lifted-base 包为这些嵌入提供了原语,例如 try(在 Control.Exception.Lifted 中)。

以下代码为我编译:

import Snap.Snaplet
import Control.Exception.Lifted hiding (Handler)

runQuery :: Handler a b c
runQuery = undefined

runQuery' :: (Exception e) => Handler a b (Either e a1)
runQuery' = try runQuery

Haskelling 快乐!