给定一个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
的行为,这是我希望避免的。
1条答案
按热度按时间kgqe7b3p1#
如果我们想要
ServerError
类型的throwError
值,我们的monad需要是MonadError ServerError
的示例。看看available instances,我们可以知道我们需要向monad堆栈添加什么。这些示例将无法工作,因为它们用于与
ServerError
不同的特定错误类型:这个示例将迫使我们使用
Either
作为我们的基本monad:然后有一大堆“passthrough”示例从基本monad传播
MonadError
约束,但不引入它:这是我们需要的示例:
我们需要在monad堆栈中的某个地方添加一个
ExceptT ServerError
转换器,并通过newtype派生MonadError ServerError
。这种解决方案的一个缺点是,引入
ExceptT
可能会使像catch
(用于运行时异常)这样的操作更难执行。