haskell - 使用仆人-客户模式匹配的问题

标签 haskell servant

Servant docs ,我们有以下 api:

type API = "position" :> Capture "x" Int :> Capture "y" Int :> Get '[JSON] Position
      :<|> "hello" :> QueryParam "name" String :> Get '[JSON] HelloMessage
      :<|> "marketing" :> ReqBody '[JSON] ClientInfo :> Post '[JSON] Email

我们可以像这样定义客户端函数:

api :: Proxy API
api = Proxy

position :<|> hello :<|> marketing = client api

如果我们的 api 类型看起来像:

type API = QueryParam "test" Int :> (
    "position" :> Capture "x" Int :> Capture "y" Int :> Get '[JSON] Position
      :<|> "hello" :> QueryParam "name" String :> Get '[JSON] HelloMessage
      :<|> "marketing" :> ReqBody '[JSON] ClientInfo :> Post '[JSON] Email)

与原始 api 相同,但为所有端点添加了一个额外的“test”查询参数,我们如何获取客户端函数?我尝试了几种模式匹配的变体,但没有成功。

如果所有其他方法都失败,则可以在每个端点的 api 类型中重复“test”查询参数,但这是 Haskell,我们尽量避免重复。

最佳答案

Servant API 定义存在于类型级别。如果我们想操纵它们,我们需要类似函数之类的东西,将类型(不是值,类型本身)转换为其他类型。

Haskell 中与此类类型级函数最接近的称为 closed type family :

{-# LANGUAGE TypeFamilies #-}

type family PrependParam api where
    PrependParam (a :<|> b) = PrependParam a :<|> PrependParam b
    PrependParam leaf = QueryParam "test" Int :> leaf

type API' = PrependParam API

:<|>分隔路线,而 :>分隔路线内的组件。我们正在映射路由树并为每个路由添加一个前缀。

我们可以使用 kind!ghci 检查它是否有效。命令:

ghci> :kind! API'
API' :: *
= (QueryParam "test" Int
   :> ("position"
       :> (Capture "x" Int :> (Capture "y" Int :> Get '[JSON] Position))))
  :<|> ((QueryParam "test" Int
         :> ("hello"
             :> (QueryParam "name" String :> Get '[JSON] HelloMessage)))
        :<|> (QueryParam "test" Int
              :> ("marketing"
                  :> (ReqBody '[JSON] ClientInfo :> Post '[JSON] Email))))

关于haskell - 使用仆人-客户模式匹配的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44007111/

相关文章:

haskell - 声明式编程中的实习字符串

haskell - 无法推导出前身 Nat 的 SingI

haskell - 使用当前范围在模板 haskell 中生成动态名称

haskell - 类型 家庭 类型 黑客

haskell - :~> operator do in haskell 是什么意思

haskell - 如何在仆人处理程序 monad 中处理异常?

haskell - 如何使用 Esqueleto 执行 "SELECT ... IN (SELECT ...)"?

haskell - Servant 总是在 ReaderT Monad 中给我一个初始值

haskell - 如何在自定义servant处理程序中响应HTTP状态?

haskell - Text.ParserCombinators.Parsec 和 Text.Parsec 有什么区别