仆人中的安全链接

safeLink in Servant

Servant 使用 Servant.API.safeLink 生成相对 URLs,但我 运行 陷入了一个问题,这让我觉得我误解了一些关于如何使用它或关于如何定义Servant APIs.

我构建的最小示例包含两个端点。一个旨在成为(相对 URL)/foo 的 "front door" 端点,另一个在 /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 中的 link 时遇到的错误类型。当 safeLink 的第二个参数改为 Proxy :: Foo0 时,错误类似。

我已经尝试了很多很多的排列组合,但似乎无法通过使用我找到的文档自行解决。如果能给我一些提示,让我找出我的误解所在,我将不胜感激。

该示例不起作用,因为您为端点定义的类型 Foo1 本身不包含相对于 Foo API.

解决这种情况的一种方法是使用 "flattened" API 代替:

safeLink (Proxy :: Proxy (Flat Foo)) (Proxy :: Proxy (Nth 1 (Flat Foo)))

(还需要 import Servant.API.Flatten

缺点是你必须知道Foo1Foo中的顺序位置。似乎没有办法通过使用问题中指定的类型来获得所需的答案。您可以首先定义扁平化 API,但代价是使结构清晰(IMO)。

感谢 Alp Mestanogullari 在上面的问题评论中向我解释了这一点。答案真的应该归功于他!