Что означает апостроф перед списком ( '[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
Другие вопросы по тегам