如何创建将在Servant中的任何路径上触发的路由?

时间:2019-03-14 05:51:00

标签: haskell type-level-computation servant

我在Haskell Servant App中具有类型级别功能(又称类型族),该应用程序接受一个Symbol并产生一个Type(路由),即

type family AppRoute (x :: Symbol) where
    AppRoute x = x :> Get '[HTML] RawHtml

这有望在API中使用:

type ServerAPI = 
    Get '[HTML] RawHtml 
    :<|> UserAPI
    :<|> AdminAPI
    :<|> AppRoute "about" 
    :<|> AppRoute "contact" 
    :<|> AppRoute "services"
    :<|> AppRoute "blog"
    :<|> AppRoute "products"

相应的服务器功能是

server :: Server ServerAPI
server = 
    html
    :<|> userServer
    :<|> adminServer
    :<|> html
    :<|> html
    :<|> html
    :<|> html
    :<|> html

基本上,所有AppRoute都到达相同的端点(原始html文件)。有没有办法通过编写类似(不会编译)的东西来消除重复(参考最后五个路由)

type family AppRoute where
    AppRoute = String :> Get '[HTML] RawHtml

type ServerAPI =
    Get '[HTML] RawHtml
    :<|> UserAPI
    :<|> AdminAPI
    :<|> AppRoute _  -- * the problem is here. One function is needed here

使用相应的服务器

server :: Server ServerAPI
server = 
    html
    :<|> userServer
    :<|> adminServer
    :<|> html

实际上,AppRoutes是一个类型级别的函数,它接受任何字符串并返回路由。

总之,而不是写作

:<|> AppRoute "about" :<|> AppRoute "contact" :<|> AppRoute "services" :<|> AppRoute "products"

我只想写     :<|> AppRoute _

2 个答案:

答案 0 :(得分:1)

您可以使用Capture捕获任何路径。但是,必须在其前加上: char。例如

type AppRoute = Capture "routePath" String :> Get '[HTML] RawHtml

type ServerAPI =
    Get '[HTML] RawHtml
    :<|> UserAPI
    :<|> AdminAPI
    :<|> AppRoute

现在,AppRoute将在yourserver.com/:thisIsMyPath/上触发,并将"thisIsMyPath"作为端点的参数传递。我目前不知道如何绕过此:。假设html是目前不依赖于给定路径的端点,则可以将整个服务器定义为

server :: Server ServerAPI
server = html
  :<|> userServer
  :<|> adminServer
  :<|> const html

您可能会读到here


顺便说一句,为什么不使用type别名而不是tank类型的族?通常在我的Servant应用中

type AppRoute (x :: Symbol) = x :> Get '[HTML] RawHtml

哪个效果很好。

答案 1 :(得分:0)

如果有人仍在寻找应答者,则还有另一种捕获任何路线的方法。看看CaptureAll类型