Qual è la differenza tra ADT, GADT e tipi induttivi?


21

Qualcuno potrebbe essere in grado di spiegare la differenza tra:

  • Tipi di dati algebrici (con cui ho abbastanza familiarità)
  • Tipi di dati algebrici generalizzati (cosa li rende generalizzati?)
  • Tipi induttivi (ad es. Coq)

(Soprattutto tipi induttivi.) Grazie.

Risposte:


21

I tipi di dati algebrici consentono di definire i tipi in modo ricorsivo. Concretamente, supponiamo di avere il tipo di dati

datalist=Nil|ConsofN×list

Ciò significa che è l'insieme più piccolo generato dal N i L e C o n s operatori. Possiamo formalizzare ciò definendo l'operatore F ( X )listNilConsF(X)

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

e quindi definire aslist

list=iNFi()

Un ADT generalizzato è ciò che otteniamo quando definiamo un operatore di tipo in modo ricorsivo. Ad esempio, potremmo definire il seguente tipo di costruttore:

busha=Leafofa|Nestofbush(a×a)

Questo tipo significa che un elemento di è una tupla di una s di lunghezza 2 n per qualche n , poiché ogni volta che entriamo nelcostruttore N e s t l'argomento type è accoppiato con se stesso. Quindi possiamo definire l'operatore di cui vogliamo prendere un punto fisso come:bushaa2nnNest

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

Un tipo induttivo in Coq è essenzialmente un GADT, in cui gli indici dell'operatore tipo non sono limitati ad altri tipi (come ad esempio Haskell), ma possono anche essere indicizzati da valori della teoria dei tipi. Ciò consente di fornire tipi per elenchi indicizzati per lunghezza e così via.


1
Grazie. Ciò non significherebbe, tuttavia, che "tipo induttivo" è completamente sinonimo di "tipo dipendente"?
ninjagecko

4
@Neel: non ho mai visto tipi come i bushGADT. Li ho visti chiamati tipi nidificati o non regolari.
jbapple

3
I tipi nidificati sono un caso speciale di GADT. La caratteristica fondamentale di un GADT è semplicemente che si tratta di una definizione ricorsiva di tipo superiore. (Le modifiche al rhs sono fondamentalmente zucchero sintattico per l'aggiunta di un tipo di uguaglianza come componente del costruttore.)
Neel Krishnaswami

4
@ninjagecko: "Tipi induttivi" sono tipi dati semantici come il punto meno fisso di un costruttore. Non tutti i tipi possono essere descritti in questo modo (le funzioni non possono, e neppure i tipi infiniti come i flussi). I tipi dipendenti descrivono i tipi che consentono che si verifichino termini del programma (ovvero, i tipi possono "dipendere da" termini). Poiché Coq è una teoria dei tipi dipendenti, anche i tipi induttivi che consente di definire dipendono. Ma anche le teorie dei tipi non dipendenti possono supportare i tipi induttivi e quei tipi induttivi non dipenderanno.
Neel Krishnaswami l'

2
@NeelKrishnaswami: Saresti così gentile da chiarire la tua risposta elencando i "primi pochi elementi" dei tipi di bush a? In questo esempio, è Nest Leaf(a) Leaf(a) Leaf(a) Leaf(a)o Nest ((Nest Leaf(a) Leaf(a)) (Nest Leaf(a) Leaf(a)))come esempio del set?
ninjagecko,

19

Prendi in considerazione tipi di dati algebrici come:

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

I tipi di ritorno di ciascun costruttore in un tipo di dati sono tutti uguali: Niled Consentrambi restituiscono List a. Se permettiamo ai costruttori di restituire tipi diversi, abbiamo un 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

Occupiedha il tipo a -> NullableList a b -> NullableList a NonEmpty, mentre Consha il tipo a -> List a -> List a. È importante notare che NonEmptyè un tipo, non un termine. Un altro esempio:

data Zero
data Succ n

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

I tipi induttivi nei linguaggi di programmazione che hanno tipi dipendenti consentono ai tipi restituiti dai costruttori di dipendere dai valori (non solo dai tipi) degli argomenti.

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).

Una nota a margine : GHC ha un meccanismo per trattare i costruttori di valori come costruttori di tipi . Questo non è lo stesso dei tipi induttivi dipendenti di Coq, ma riduce in qualche modo il carico sintattico dei GADT e può portare a migliori messaggi di errore.


Grazie. "Tipi induttivi in ​​linguaggi di programmazione che hanno tipi dipendenti" Come sarebbe un tipo induttivo in un linguaggio senza tipi dipendenti e si possono avere tipi dipendenti non induttivi (ma simili a GADT)?
ninjagecko
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.