Excellente question!
Il existe plusieurs différences clés.
Représentation
- A 
newtypegarantit que vos données auront exactement la même représentation au moment de l'exécution, que le type que vous encapsulez. 
- While 
datadéclare une toute nouvelle structure de données au moment de l'exécution. 
Donc, le point clé ici est que la construction pour le newtypeest garantie d'être effacée au moment de la compilation.
Exemples:

newtype Book = Book (Int, Int) 

Notez comment il a exactement la même représentation que a (Int,Int), puisque le Bookconstructeur est effacé.
data Book = Book (Int, Int) 

Possède un Bookconstructeur supplémentaire non présent dans le newtype.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int 

Pas de pointeurs! Les deux Intchamps sont des champs de la taille d'un mot sans boîte dans le Bookconstructeur.
Types de données algébriques
En raison de ce besoin d'effacer le constructeur, a newtypene fonctionne que lors de l'encapsulation d'un type de données avec un seul constructeur . Il n'y a pas de notion de newtypes "algébriques". Autrement dit, vous ne pouvez pas écrire un équivalent newtype de, disons,
data Maybe a = Nothing
             | Just a
car il a plus d'un constructeur. Tu ne peux pas non plus écrire
newtype Book = Book Int Int
Rigueur
Le fait que le constructeur soit effacé conduit à des différences très subtiles de rigueur entre dataet newtype. En particulier, dataintroduit un type qui est "soulevé", ce qui signifie, essentiellement, qu'il a un moyen supplémentaire d'évaluer à une valeur inférieure. Comme il n'y a pas de constructeur supplémentaire au moment de l'exécution avec newtype, cette propriété ne tient pas.
Ce pointeur supplémentaire dans le Bookau (,)constructeur nous permet de mettre une valeur inférieure à.
En conséquence, newtypeet dataont des propriétés de rigueur légèrement différentes, comme expliqué dans l'article du wiki Haskell .
Déballage
Cela n'a pas de sens de déballer les composants de a newtype, car il n'y a pas de constructeur. S'il est parfaitement raisonnable d'écrire:
data T = T {-# UNPACK #-}!Int
produisant un objet d'exécution avec un Tconstructeur et un Int#composant. Vous obtenez juste un nu Intavec newtype.
Références :