You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义Monad栈中使用Servant的throwError做错误处理?

问题:自定义Monad无法使用Servant的throwError

自定义的Monad定义如下:

newtype App a = App
  { runApp :: ReaderT AppEnv (LoggingT IO) a
  }
  deriving newtype
    ( Functor,
      Applicative,
      Monad,
      MonadIO, 
      MonadReader AppEnv,
      MonadLogger
    )

newtype AppEnv = AppEnv -- environment for the app

想要使用Servant标准错误处理机制的throwError,写出如下代码:

foo :: App ()
foo = throwError err404

但代码无法编译,报错信息:

• No instance for (Control.Monad.Error.Class.MonadError
                     ServerError App)
    arising from a use of ‘throwError’
• In the expression: throwError err404
  In an equation for ‘foo’: foo = throwError err404

疑问:是否可为App推导该实例,或是否需要修改Monad栈?另外不想使用throw,因为会改变servant-client的行为。


解决方法

  • 无法自动推导MonadError ServerError App实例:当前的Monad栈(ReaderT + LoggingT + IO)里没有任何支持MonadError的转换器,deriving newtype只能基于栈中已有的实例进行推导,所以自动推导此实例行不通。

  • 修改Monad栈,加入ExceptT ServerError:这是最直接的解决方案,调整栈结构,将ExceptT ServerError加入到IO层之上,这样就能通过deriving newtype自动获取MonadError实例。修改后的代码如下:

import Servant (ServerError)
import Control.Monad.Except (ExceptT, MonadError)

newtype App a = App
  { runApp :: ReaderT AppEnv (LoggingT (ExceptT ServerError IO)) a
  }
  deriving newtype
    ( Functor,
      Applicative,
      Monad,
      MonadIO, 
      MonadReader AppEnv,
      MonadLogger,
      MonadError ServerError  -- 现在可正常推导该实例
    )

newtype AppEnv = AppEnv -- environment for the app

调整后即可直接使用throwError err404,完全符合Servant的错误处理规范,不会影响servant-client的行为。

  • 基于Servant的Handler重构Monad:如果不想手动调整栈结构,可以让App包裹Servant自带的Handler类型(Handler已经内置了MonadError ServerError实例),再叠加ReaderT和LoggingT。示例代码:
import Servant (Handler, ServerError)

newtype App a = App
  { runApp :: ReaderT AppEnv (LoggingT Handler) a
  }
  deriving newtype
    ( Functor,
      Applicative,
      Monad,
      MonadIO, 
      MonadReader AppEnv,
      MonadLogger,
      MonadError ServerError
    )

这种方式更贴合Servant生态,后续将App转换为Servant的Server类型时会更便捷。


内容的提问来源于stack exchange,提问作者l7r7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:50:29