В чем разница между ADT, GADT и индуктивными типами?


21

Может ли кто-нибудь объяснить разницу между:

  • Алгебраические типы данных (с которыми я довольно хорошо знаком)
  • Обобщенные алгебраические типы данных (что делает их обобщенными?)
  • Индуктивные типы (например, Coq)

(Особенно индуктивные типы.) Спасибо.

Ответы:


21

Алгебраические типы данных позволяют определять типы рекурсивно. Конкретно, предположим, у нас есть тип данных

datalist=Nil|ConsofN×list

Это означает, что - это наименьшее множество, генерируемое операторами N i l и C o n s . Мы можем формализовать это, определив оператор F ( X )listNilConsF(X)

F(X)=={Nil}{Cons(n,x)|nNxX}

и затем определение вlist

list=iNFi()

Обобщен ADT является то , что мы получаем , когда определить тип оператора рекурсивно. Например, мы могли бы определить следующий конструктор типа:

busha=Leafofa|Nestofbush(a×a)

Этот тип означает, что элемент является кортежем через с длиной 2 п для некоторого п , таккаждый размы в N е с т конструктора типа аргументпаре с самим собой. Таким образом, мы можем определить оператор, для которого мы хотим взять фиксированную точку:bushaa2nnNest

F(R)=λX.{Leaf(x)|xX}{Nest(v)|vR(X)}

Индуктивный тип в Coq - это, по сути, GADT, где индексы оператора типа не ограничены другими типами (как, например, в Haskell), но могут также индексироваться значениями теории типов. Это позволяет вам задавать типы для списков с индексацией длины и так далее.


1
Спасибо. Разве это не означает, однако, что этот «индуктивный тип» полностью синонимичен «зависимому типу»?
ninjagecko

4
@Neel: я никогда не видел таких типов, как bushGADT. Я видел их, называемые вложенными или нерегулярными типами.
Jbapple

3
Вложенные типы являются частным случаем ГАДЦ. Критическая особенность GADT состоит в том, что это рекурсивное определение в более высоком виде. (Изменения в rhs в основном являются синтаксическим сахаром для добавления равенства типов в качестве компонента конструктора.)
Нил Кришнасвами

4
@ninjagecko: «Индуктивные типы» - это типы, которым дана семантика как наименее фиксированная точка конструктора. Не все типы могут быть описаны таким образом (функции не могут, и ни один не может бесконечные типы, такие как потоки). Зависимые типы описывают типы, которые позволяют программным терминам встречаться в них (то есть типы могут «зависеть от» терминов). Поскольку Coq является теорией зависимых типов, индуктивные типы, которые она позволяет вам определять, также являются зависимыми. Но теории независимых типов также могут поддерживать индуктивные типы, и эти индуктивные типы не будут зависимыми.
Нил Кришнасвами

2
@NeelKrishnaswami: Не могли бы вы прояснить свой ответ, перечислив «первые несколько наименьших» элементов типов bush a? В этом примере это Nest Leaf(a) Leaf(a) Leaf(a) Leaf(a)или Nest ((Nest Leaf(a) Leaf(a)) (Nest Leaf(a) Leaf(a)))как один из примеров набора?
Ниндзягецко

19

Рассмотрим алгебраические типы данных, такие как:

data List a = Nil | Cons a (List a)

Типы возврата каждого конструктора в типе данных все равно: Nilи Consкак возвращение List a. Если мы позволим конструкторам возвращать разные типы, у нас есть GADT :

data Empty -- this is an empty data declaration; Empty has no constructors
data NonEmpty

data NullableList a t where
    Vacant :: NullableList a Empty
    Occupied :: a -> NullableList a b -> NullableList a NonEmpty

Occupiedимеет тип a -> NullableList a b -> NullableList a NonEmpty, а Consимеет тип a -> List a -> List a. Важно отметить, что NonEmptyэто тип, а не термин. Другой пример:

data Zero
data Succ n

data SizedList a t where
    Alone :: SizedList a Zero
    WithFriends :: a -> SizedList a n -> SizedList a (Succ n)

Индуктивные типы в языках программирования, которые имеют зависимые типы, позволяют типам возвращаемых конструкторов зависеть от значений (а не только типов) аргументов.

Inductive Parity := Even | Odd.

Definition flipParity (x:Parity) : Parity :=
  match x with
    | Even => Odd
    | Odd => Even
  end.

Fixpoint getParity (x:nat) : Parity :=
  match x with
    | 0 => Even
    | S n => flipParity (getParity n)
  end.

(*
A ParityNatList (Some P) is a list in which each member
is a natural number with parity P.
*)

Inductive ParityNatList : option Parity -> Type :=
  Nil : forall P, ParityNatList P
| Cons : forall (x:nat) (P:option Parity), 
  ParityNatList P -> ParityNatList 
  (match P, getParity x with
     | Some Even, Even => Some Even
     | Some Odd, Odd => Some Odd
     | _, _ => None
   end).

Примечание: GHC имеет механизм для обработки конструкторов значений как конструкторов типов . Это не то же самое, что зависимые индуктивные типы, которые есть у Coq, но это несколько уменьшает синтаксическую нагрузку GADT и может привести к улучшению сообщений об ошибках.


Спасибо. «Индуктивные типы в языках программирования, которые имеют зависимые типы» Как бы выглядел индуктивный тип в языке без зависимых типов, и можете ли вы иметь неиндуктивные (но GADT-подобные) зависимые типы?
ninjagecko
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.