12

我正在阅读 Servant文档并遇到了这一行:

type UserAPI = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]

该列表在'做什么?

4

2 回答 2

12

引号用于区分类型级构造函数与提升类型的术语级构造函数。

例如:

{-# 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
于 2017-07-01T20:19:29.020 回答
8

这是DataKinds在行动,其中:

  • 在类型级别提升值,并且
  • 将类型提升到 kind 级别

然而,这会导致类型级别的混乱。现在,在类型中,[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 中的用途。)

于 2017-07-01T20:19:31.930 回答