Differenza tra `data` e` newtype` in Haskell


191

Qual è la differenza quando scrivo questo?

data Book = Book Int Int

contro

newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid

Dovresti fare qualche ricerca in giro, a questa domanda è già stata data una risposta. stackoverflow.com/questions/2649305/...
tehman


Anche correlati: usi per newtype: stackoverflow.com/questions/991467/…
Don Stewart

25
Nota che newtype Book = Book Int Intnon è valido. Tuttavia, è possibile, newtype Book = Book (Int, Int)come notato da dons sotto.
Edward KMETT,

Risposte:


241

Ottima domanda!

Esistono diverse differenze chiave.

Rappresentazione

  • A newtypegarantisce che i tuoi dati avranno esattamente la stessa rappresentazione in fase di esecuzione, come il tipo che avvolgi.
  • Mentre datadichiara una nuova struttura di dati in fase di esecuzione.

Quindi il punto chiave qui è che il costrutto per il newtypeè garantito per essere cancellato al momento della compilazione.

Esempi:

  • data Book = Book Int Int

dati

  • newtype Book = Book (Int, Int)

nuovo tipo

Nota come ha esattamente la stessa rappresentazione di a (Int,Int), poiché il Bookcostruttore viene cancellato.

  • data Book = Book (Int, Int)

tupla di dati

Ha un Bookcostruttore aggiuntivo non presente in newtype.

  • data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int

inserisci qui la descrizione dell'immagine

Nessun puntatore! I due Intcampi sono campi di dimensioni di parola senza riquadro nel Bookcostruttore.

Tipi di dati algebrici

A causa di questa necessità di cancellare il costruttore, newtypefunziona solo quando si avvolge un tipo di dati con un solo costruttore . Non c'è idea di newtypes "algebrici". Cioè, non puoi scrivere un equivalente newtype di, diciamo,

data Maybe a = Nothing
             | Just a

poiché ha più di un costruttore. Né puoi scrivere

newtype Book = Book Int Int

Rigore

Il fatto che il costruttore venga cancellato porta ad alcune sottili differenze di rigore tra datae newtype. In particolare, dataintroduce un tipo che viene "sollevato", il che significa essenzialmente che ha un modo aggiuntivo di valutare un valore inferiore. Poiché non è disponibile alcun costruttore aggiuntivo in fase di runtime newtype, questa proprietà non è valida.

Quel puntatore in più Booknel (,)costruttore to ci consente di inserire un valore inferiore.

Di conseguenza, newtypee datahanno proprietà di rigidezza leggermente diverse, come spiegato nell'articolo wiki di Haskell .

Spacchettamento

Non ha senso decomprimere i componenti di a newtype, poiché non esiste alcun costruttore. Mentre è perfettamente ragionevole scrivere:

data T = T {-# UNPACK #-}!Int

producendo un oggetto runtime con un Tcostruttore e un Int#componente. Basta avere una nuda Intcon newtype.


Riferimenti :


2
Continuo a non pensare che mi mancherebbe qualcosa se non ci fosse un "nuovo tipo" in Haskell. Le sottili differenze aggiungono complessità al linguaggio che non mi sembrano utili ...
Martingw,

14
La differenza è molto utile per motivi di prestazioni. Poiché i costruttori newtype vengono cancellati al momento della compilazione, non impongono la penalità delle prestazioni di runtime che fa un costruttore di dati. Ma ti danno ancora tutti i vantaggi di un tipo completamente distinto e qualsiasi astrazione che vuoi associare ad esso. Ad esempio, ci sono due modi diversi in cui il tipo di dati dell'elenco può formare una monade. Uno è integrato nel linguaggio, ma se si desidera utilizzare l'altro, un nuovo tipo sarebbe la strada da percorrere.
mightybyte,

Grande spiegazione! Quello che non capisco è se newtypeviene cancellato dopo che la compilazione e il runtime usano la stessa rappresentazione per vecchi e nuovi tipi, come possiamo ancora essere in grado di definire le istanze sia per il vecchio che per il nuovo tipo? Come può il runtime capire quale istanza usare?
damluar,

3
@damluar Tutti i tipi vengono cancellati in fase di esecuzione, tutti sono completamente risolti in fase di compilazione e durante la compilazione non newtypeè ovviamente ancora cancellato.
punto

3
@damlaur Una volta ho avuto la tua stessa domanda. Quando le persone dicono che i tipi vengono cancellati, omettono di menzionare che una cosa NON viene cancellata, che è una parola di memoria che viene utilizzata per le ricerche nel dizionario per decidere quale metodo di istanza utilizzare per un dato dato. Le persone sostengono che questa parola non è un "tipo", che penso dipenda dalla tua prospettiva, ma ecco qua.
Gabriel L.,
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.