Яка різниця між 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. Критична особливість GADT полягає в тому, що він є рекурсивним визначенням на вищому рівні. (Зміни в резус - це в основному синтаксичний цукор для додавання рівності типу як складової конструктора.)
Neel Krishnaswami

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)))як один із прикладів безлічі?
ninjagecko

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.