【发布时间】:2019-05-26 23:11:22
【问题描述】:
Servant 使用 Servant.API.safeLink 生成相对 URL,但我遇到了一个问题,让我觉得我误解了一些关于如何使用它或如何定义 Servant API 的基本知识。
我构建的最小示例包含两个端点。一个旨在成为(相对 URL)/foo 的“前门”端点,另一个位于 /foo/1:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import Servant
data HTML
type Foo = "foo" :> (Foo0 :<|> Foo1)
type Foo0 = Get '[HTML] String
type Foo1 = "1" :> Get '[HTML] String
slFoo :: Link
slFoo = safeLink (Proxy :: Proxy Foo) (Proxy :: Proxy Foo1)
上面slFoo的定义给了我错误
Could not deduce: IsElem' ("1" :> Get '[HTML] String) ("foo" :> (Foo0 :<|> Foo1))
...这正是我在要求 safeLink 生成不在其第一个参数定义的 API 中的链接时遇到的错误。当safeLink 的第二个参数改为Proxy :: Foo0 时,错误类似。
我已经尝试了很多很多这种排列方式,但使用我找到的文档似乎无法自己弄清楚。我会很感激一些指示,让我找出我的误解在哪里。
【问题讨论】:
-
这是因为
Foo1不包含前导foo静态路径片段,所以当您要求servant 生成Foo1的链接(在FooAPI 内)时,它不会'找不到与Foo1完全匹配的端点并抱怨。 -
也许像
servant-flatten这样的东西在这里合适?就像那些文档中的客户端/服务器示例一样,您可以将FooAPI 类型的“扁平化”版本作为safeLink的第二个参数传递,而第一个参数也许可以在上述扁平化 API 上使用Nth键入以点击您想要的端点? -
关于servant-flatten的使用,令人惊讶的是我不是唯一的用户:-)参见here。
-
关于您的实际问题,我们的想法是不要将
apiProxy :: Proxy YourAPI传递给您正在使用的任何函数(serve、client、safeLink,...),而是d 通过flatten apiProxy,其类型为Proxy (Flat YourAPI)。您不必定义Nth的实例,您只需使用它来获取到正确端点的代理。Nth <some number> <some flattened API type>将为您提供<some number> + 1端点的 API 类型。第一个是Nth 0,第二个是Nth 1,等等。如果这还不够清楚,请给我发电子邮件,对于这些问题,我不是 SO 的忠实粉丝。 -
确实,
Nth似乎没有在公共存储库中使用。我很高兴合并一个补丁,该补丁将使用Nth的示例添加到它的黑线鳕中。 =) Re: github search,当我在寻找使用一些库/函数/的例子时,我总是先看那里,我绝对推荐它。