为Haskell开发人员自动生成Servant-API文档

时间:2017-10-05 14:26:25

标签: haskell documentation-generation haddock servant

我使用越来越大的servant构建了一个Web-API。

我知道有两种方法可以自动为api创建文档。

首先,有黑线鳕。 Haddock将我的代码转换为超链接的HTML页面。整齐!这特别有用,因为我的api端点往往会延伸到几个模块,现在我可以浏览它们并找到相关的类型信息。

但是,haddock并没有完全正确地显示这些行的方法:

type Public =
       "new"    :> ReqBody '[JSON] UserNewRequest    :> Post '[JSON] UserNewResponse
  :<|> "exists" :> ReqBody '[JSON] UserExistsRequest :> Post '[JSON] Bool
  :<|> "login"  :> ReqBody '[JSON] LoginRequest      :> Post '[JSON] LoginResponse

Haddock把它变成这样的东西:

type Public = ("new" :> (ReqBody '[JSON] UserNewRequest :> Post '[JSON] UserNewResponse)) :<|> (("exists" :> (ReqBody '[JSON] UserExistsRequest :> Post '[JSON] Bool)) :<|> ("login" :> (ReqBody '[JSON] LoginRequest :> Post '[JSON] LoginResponse)))

...甚至添加括号。具有讽刺意味的是,代码中的格式更漂亮,仅仅是因为换行符。

其次,有servant-docs。但是,servant-docs非常一致地构建了端点的文档,并使用了很好的钩子来添加示例,例如在JSON中。 Servant-docs并非旨在提供haskell类型信息 - 这就是我所追求的。

所以,我找到了一种方法让haddock以漂亮的方式显示长类型,或者我找到一种方法来显示带有servant-docs的haskell类型。

在这两种情况下,它似乎都不符合他们的设计。我可能完全需要别的东西。

我在haddock尝试的内容:

type Public =

  -- create new user
       "new"    :> ReqBody '[JSON] UserNewRequest    :> Post '[JSON] UserNewResponse

  -- check if user exists
  :<|> "exists" :> ReqBody '[JSON] UserExistsRequest :> Post '[JSON] Bool

  -- user login
  :<|> "login"  :> ReqBody '[JSON] LoginRequest      :> Post '[JSON] LoginResponse

它是有效的haskell,但haddock忽略了注释。使用haddock标题语法--|-- *会导致haddock编译错误。

1 个答案:

答案 0 :(得分:1)

注释中提到了使用每个端点type的别名。但是,较新的servant具有Servant.API.Generic(更多信息请参见https://haskell-servant.readthedocs.io/en/stable/cookbook/generic/Generic.html),可让您以更加结构化的方式编写API:

data Public route = Public

  -- | create new user
   { routeNewUser :: route :- "new"    :> ReqBody '[JSON] UserNewRequest    :> Post '[JSON] UserNewResponse

  -- | check if user exists
  , routeExists   :: route :- "exists" :> ReqBody '[JSON] UserExistsRequest :> Post '[JSON] Bool

  -- | user login
  , routeLogin    :: route :- "login"  :> ReqBody '[JSON] LoginRequest      :> Post '[JSON] LoginResponse
  }

这种方法对于嵌套API来说比较棘手,但是在“线性” api中有很多好处。