如何使用 Servant 库中的 Enter 解决类型错误?
How do I resolve a type error using Enter from the Servant library?
我正在尝试使用 enter
函数允许我 运行 我的 API 处理程序有一组异常,我将在高级别将其转换为 Servant ,但我在类型匹配方面遇到了问题。
给定这个最小的定义集:
-- server :: Config -> Server Routes
server :: Config -> ServerT Routes (ExceptT ServantErr IO)
server c = enter runApp (handlers c)
-- runApp :: AppM :~> Handler
runApp :: ExceptT AppErr IO :~> ExceptT ServantErr IO
runApp = Nat undefined
handlers :: Config -> ServerT Routes (ExceptT AppErr IO)
handlers = undefined
我遇到了这种类型的错误:
Couldn't match type `IO' with `ExceptT ServantErr IO'
arising from a functional dependency between:
constraint `servant-0.7.1:Servant.Utils.Enter.Enter
(IO ResponseReceived)
(ExceptT AppErr IO :~> ExceptT ServantErr IO)
(IO ResponseReceived)'
arising from a use of `enter'
instance `servant-0.7.1:Servant.Utils.Enter.Enter
(m a) (m :~> n) (n a)'
at <no location info>
In the expression: enter runApp (handlers c)
In an equation for `server': server c = enter runApp (handlers c)
异常来自调用 enter
的行。作为参考,enter
:
的声明
class Enter typ arg ret | typ arg -> ret, typ ret -> arg where
enter :: arg -> typ -> ret
instance Enter (m a) (m :~> n) (n a) where
-- enter :: (m :~> n) -> m a -> n a
所以,当我调用 enter runApp
时,我希望类型是这样的:
enter :: (m :~> n) -> m a -> n a
enter (runApp :: m ~ ExceptT AppErr IO :~> n ~ ExceptT ServantErr IO) :: ExceptT AppErr IO a -> ExceptT ServantErr IO a
(上面我使用 n ~ ExceptT ServantErr IO
来说明我的类型替换)
实际上,我从其他代码(我试图模仿,但我不明白我哪里出错了)知道 enter runApp
should/must 有这种类型:
enter runApp :: ServerT Routes (ExceptT AppErr IO a) -> ServerT Routes (ExceptT ServantErr IO a)
所以,问题很多:
enter runApp
的实际类型是什么(不是 ghci 会给我的,而是更具描述性的解释)?
- (IO ResponseReceived) 约束来自哪里?
- 如何调整上述代码才能使整个处理程序通过自然转换?
您不能在 Api 类型中有 Raw
端点。这样做的方法是从 handlers
中获取原始端点并调用它,例如
server c = enter runApp (handlers c) :<|> handleRaw
我正在尝试使用 enter
函数允许我 运行 我的 API 处理程序有一组异常,我将在高级别将其转换为 Servant ,但我在类型匹配方面遇到了问题。
给定这个最小的定义集:
-- server :: Config -> Server Routes
server :: Config -> ServerT Routes (ExceptT ServantErr IO)
server c = enter runApp (handlers c)
-- runApp :: AppM :~> Handler
runApp :: ExceptT AppErr IO :~> ExceptT ServantErr IO
runApp = Nat undefined
handlers :: Config -> ServerT Routes (ExceptT AppErr IO)
handlers = undefined
我遇到了这种类型的错误:
Couldn't match type `IO' with `ExceptT ServantErr IO'
arising from a functional dependency between:
constraint `servant-0.7.1:Servant.Utils.Enter.Enter
(IO ResponseReceived)
(ExceptT AppErr IO :~> ExceptT ServantErr IO)
(IO ResponseReceived)'
arising from a use of `enter'
instance `servant-0.7.1:Servant.Utils.Enter.Enter
(m a) (m :~> n) (n a)'
at <no location info>
In the expression: enter runApp (handlers c)
In an equation for `server': server c = enter runApp (handlers c)
异常来自调用 enter
的行。作为参考,enter
:
class Enter typ arg ret | typ arg -> ret, typ ret -> arg where
enter :: arg -> typ -> ret
instance Enter (m a) (m :~> n) (n a) where
-- enter :: (m :~> n) -> m a -> n a
所以,当我调用 enter runApp
时,我希望类型是这样的:
enter :: (m :~> n) -> m a -> n a
enter (runApp :: m ~ ExceptT AppErr IO :~> n ~ ExceptT ServantErr IO) :: ExceptT AppErr IO a -> ExceptT ServantErr IO a
(上面我使用 n ~ ExceptT ServantErr IO
来说明我的类型替换)
实际上,我从其他代码(我试图模仿,但我不明白我哪里出错了)知道 enter runApp
should/must 有这种类型:
enter runApp :: ServerT Routes (ExceptT AppErr IO a) -> ServerT Routes (ExceptT ServantErr IO a)
所以,问题很多:
enter runApp
的实际类型是什么(不是 ghci 会给我的,而是更具描述性的解释)?- (IO ResponseReceived) 约束来自哪里?
- 如何调整上述代码才能使整个处理程序通过自然转换?
您不能在 Api 类型中有 Raw
端点。这样做的方法是从 handlers
中获取原始端点并调用它,例如
server c = enter runApp (handlers c) :<|> handleRaw