我正在阅读 Servant文档并遇到了这一行:
type UserAPI = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
该列表在'
做什么?
引号用于区分类型级构造函数与提升类型的术语级构造函数。
例如:
{-# LANGUAGE DataKinds #-}
data Which = One | Two
myPick :: Which -- Type
myPick = One
type MyPick :: Which -- Kind
type MyPick = 'One
顺便说一句,kind 注释type MyPick :: Which
不是有效的 Haskell,但它让您了解术语和类型级别之间的对应关系。最接近这一点需要打开另一个扩展:
{-# LANGUAGE TypeFamilies #-}
type family MyPick :: Which where
MyPick = 'One
这是DataKinds
在行动,其中:
然而,这会导致类型级别的混乱。现在,在类型中,[X]
可能是[X] :: *
,类型列表X
,或者我们可能[X] :: [T]
由于提升而拥有 - 即值[X]
(仅包含单个值的列表X
),X
类型为T
,在类型级别提升。
为了克服这种歧义,GHC 要求在提升值构造函数前加上引号。所以,我们有[X] :: *
和'[X] :: [T]
。
具体而言,在您的情况下,Get '[JSON] [User]
涉及[JSON]
提升到类型级别的列表值和列表类型[User]
。为了更好地理解差异,请注意没有 type 术语'[JSON]
,因为这不是列表类型。我们甚至可以有Get '[JSON,JSON,JSON] [User]
一个善意的表达,甚至Get '[] [User]
. 相反,我们不能有,Get '[JSON] [User,User]
因为[User,User]
它不是一个类型。
( type Get '[JSON,JSON,JSON] [User]
,即使它是有效的,也不能被 Servant 库有意义地使用。我不知道提升列表在 Servant 中的用途。)