Что означает апостроф перед списком ( '[Something]) в Haskell?
Я читал документацию Servant и наткнулся на эту строку:
type UserAPI = "users" :> QueryParam "sortby" SortBy :> Get '[JSON] [User]
Что '
делать с этим списком?
2 ответа
Это DataKinds
в действии, которое:
- поднимает значения на уровне типа, и
- поднимает типы на добрый уровень
Это, однако, вызывает путаницу на уровне типа. Теперь, в типах, [X]
может быть [X] :: *
СписокX
типа, или вместо этого мы могли бы иметь [X] :: [T]
из-за подъема - это ценность [X]
(список, содержащий только одно значение X
), с X
типа T
, поднял на уровне типа.
Чтобы преодолеть эту неоднозначность, GHC требует кавычки перед поднятыми конструкторами значений. Итак, мы имеем [X] :: *
, а также '[X] :: [T]
,
Конкретно, в вашем случае, Get '[JSON] [User]
включает в себя как значение списка [JSON]
поднял до уровня типа, и тип списка [User]
, Чтобы лучше оценить разницу, обратите внимание, что здесь нет терминов типа '[JSON]
, поскольку это не тип списка. Мы могли бы даже иметь Get '[JSON,JSON,JSON] [User]
как доброжелательное выражение, или даже Get '[] [User]
, Вместо этого мы не можем иметь Get '[JSON] [User,User]
поскольку [User,User]
это не тип.
(Тип Get '[JSON,JSON,JSON] [User]
даже если он действителен, не может быть осмысленно использован библиотекой Servant. Я понятия не имею, для чего этот поднятый список используется в Servant.)
Кавычки используются для различения конструкторов уровня типов от конструкторов уровня терминов продвигаемых типов.
Например:
{-# LANGUAGE DataKinds #-}
data Which = One | Two
myPick :: Which -- Type
myPick = One
type MyPick :: Which -- Kind
type MyPick = 'One
Кстати, добрая аннотация type MyPick :: Which
не является допустимым Haskell, но дает представление о соответствии между термином и уровнем типа. Самое близкое, что вы можете получить к этому, требует включения другого расширения:
{-# LANGUAGE TypeFamilies #-}
type family MyPick :: Which where
MyPick = 'One