web-dev-qa-db-fra.com

Différence entre `data` et` newtype` dans Haskell

Quelle est la différence quand j'écris ceci?

data Book = Book Int Int

versus

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

Grande question!

Il existe plusieurs différences clés.

Représentation

  • Un newtype garantit que vos données auront exactement la même représentation à l'exécution, que le type que vous encapsulez.
  • Tandis que data déclare une toute nouvelle structure de données lors de l'exécution.

Donc, le point clé ici est que la construction de newtype est garantie d'être effacée au moment de la compilation.

Exemples:

  • data Book = Book Int Int

data

  • newtype Book = Book (Int, Int)

newtype

Notez comment il a exactement la même représentation qu'un (Int,Int), Puisque le constructeur Book est effacé.

  • data Book = Book (Int, Int)

data Tuple

A un constructeur Book supplémentaire non présent dans le newtype.

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

enter image description here

Pas de pointeurs! Les deux champs Int sont des champs de taille Word non encadrés dans le constructeur Book.

Types de données algébriques

En raison de ce besoin d'effacer le constructeur, un newtype ne fonctionne que lors de l'encapsulation d'un type de données avec un seul constructeur . Il n'y a aucune notion de nouveaux types "algébriques". Autrement dit, vous ne pouvez pas écrire un équivalent de nouveau type, disons,

data Maybe a = Nothing
             | Just a

car il a plus d'un constructeur. Vous ne pouvez pas non plus écrire

newtype Book = Book Int Int

Rigueur

Le fait que le constructeur soit effacé conduit à des différences de subtilité très subtiles entre data et newtype. En particulier, data introduit un type qui est "levé", ce qui signifie, essentiellement, qu'il a un moyen supplémentaire d'évaluer une valeur inférieure. Puisqu'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 constructeur Book vers (,) Nous permet de mettre une valeur inférieure dans.

Par conséquent, newtype et data ont des propriétés de rigueur légèrement différentes, comme expliqué dans l'article wiki de Haskell .

Déballage

Cela n'a pas de sens de déballer les composants d'un 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 constructeur T et un composant Int#. Vous obtenez simplement un Int avec newtype.


Références:

224
Don Stewart