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

如何正确实现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

实现解释

  1. 顶层API分支组合:用:<|>把三个顶层API对应的服务器逻辑组合起来:
    • list 对应 Get '[JSON] [a],直接返回资源列表的Handler
    • create 对应 ReqBody '[JSON] a :> PostNoContent,接收请求体参数并处理创建逻辑
    • 第三个分支对应Capture "id" i :> (...),需要写成\i -> ...来接收Capture的id参数
  2. 嵌套子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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:40:29