如何正确实现Haskell Servant中APIFor对应的serverFor函数?
解决Servant中
serverFor函数的实现错误问题 首先看给出的API定义:
type APIFor a i = Get '[JSON] [a] :<|> ReqBody '[JSON] a :> PostNoContent :<|> Capture "id" i :> ( Get '[JSON] a :<|> ReqBody '[JSON] a :> PutNoContent :<|> DeleteNoContent ) serverFor :: Handler [a] -> (a -> Handler NoContent) -> (i -> Handler a) -> (i -> a -> Handler NoContent) -> (i -> Handler NoContent) -> Server (APIFor a i) serverFor = error "..." -- What should be here?
你的错误实现没有正确处理serverFor的参数,也没有匹配嵌套API的结构,导致类型不匹配:
serverFor = listing :<|> ops where listing :: Handler [a] listing = error "" ops a i = creating a :<|> getById i :<|> updating i a :<|> deleting i where creating :: a -> Handler NoContent creating a = error "" getById :: i -> Handler a getById id = error "" updating :: i -> a -> Handler NoContent updating i a = error "" deleting :: i -> Handler NoContent deleting i = error ""
对应的错误提示:
• Couldn't match expected type ‘Handler [a]
-> (a -> Handler NoContent)
-> (i -> Handler a)
-> (i -> a -> Handler NoContent)
-> (i -> Handler NoContent)
-> Server (APIFor a i)’
with actual type ‘Handler [a0]
:<|> (a1
-> i0
-> Handler NoContent
:<|> (Handler a2
:<|> (Handler NoContent :<|> Handler NoContent)))’
• Possible cause: ‘(:<|>)’ is applied to too many arguments
In the expression: listing :<|> ops
正确实现方案
要解决这个问题,需要让serverFor正确接收所有参数,并按照API的嵌套结构组合对应的服务器逻辑:
serverFor list create get update delete = list :<|> create :<|> \i -> get i :<|> \a -> update i a :<|> delete i
实现解释
- 顶层API分支组合:用
:<|>把三个顶层API对应的服务器逻辑组合起来:list对应Get '[JSON] [a],直接返回资源列表的Handlercreate对应ReqBody '[JSON] a :> PostNoContent,接收请求体参数并处理创建逻辑- 第三个分支对应
Capture "id" i :> (...),需要写成\i -> ...来接收Capture的id参数
- 嵌套子API分支组合:在接收id参数后,再用
:<|>组合三个子分支:get i对应子API中的Get '[JSON] a,根据id获取单个资源\a -> update i a对应ReqBody '[JSON] a :> PutNoContent,接收请求体和id参数处理更新delete i对应DeleteNoContent,根据id处理删除逻辑
内容的提问来源于stack exchange,提问作者HuntressMain
相关产品推荐
相关产品推荐

