parametros - functores y monadas haskell
Diferencia entre `data` y` newtype` en Haskell (1)
¿Cuál es la diferencia cuando escribo esto?
data Book = Book Int Int
newtype Book = Book(Int, Int) -- "Book Int Int" is syntactically invalid
Gran pregunta!
Hay varias diferencias clave.
Representación
- Un
newtype
garantiza que sus datos tendrán exactamente la misma representación en tiempo de ejecución, como el tipo que envuelve. - Mientras que los
data
declaran una nueva estructura de datos en tiempo de ejecución.
Entonces, el punto clave aquí es que la construcción para el newtype
está garantizada para ser borrada en tiempo de compilación.
Ejemplos:
-
data Book = Book Int Int
-
newtype Book = Book (Int, Int)
Tenga en cuenta que tiene exactamente la misma representación que a (Int,Int)
, ya que el constructor del Book
se borra.
-
data Book = Book (Int, Int)
Tiene un constructor de Book
adicional no presente en el newtype
.
-
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
¡Sin punteros! Los dos campos Int
son campos de tamaño de palabra no empaquetados en el constructor del Book
.
Tipos de datos algebraicos
Debido a esta necesidad de borrar el constructor, un newtype
solo funciona cuando se envuelve un tipo de datos con un solo constructor . No hay noción de nuevos tipos "algebraicos". Es decir, no puede escribir un nuevo tipo equivalente, por ejemplo,
data Maybe a = Nothing
| Just a
ya que tiene más de un constructor Tampoco puedes escribir
newtype Book = Book Int Int
Rigor
El hecho de que el constructor se borre conduce a algunas diferencias muy sutiles en el rigor entre los data
y newtype
. En particular, los data
presentan un tipo que se "levanta", lo que significa, esencialmente, que tiene una forma adicional de evaluar a un valor inferior. Como no hay ningún constructor adicional en tiempo de ejecución con newtype
, esta propiedad no se cumple.
Ese puntero adicional en el constructor Book
to (,)
nos permite poner un valor inferior en.
Como resultado, newtype
y data
tienen propiedades de rigor ligeramente diferentes, como se explica en el artículo de la wiki de Haskell .
Unboxing
No tiene sentido unbox los componentes de un newtype
, ya que no hay un constructor. Si bien es perfectamente razonable escribir:
data T = T {-# UNPACK #-}!Int
produciendo un objeto de tiempo de ejecución con un constructor T
y un componente Int#
. Usted acaba de obtener un Int
newtype
con newtype
.
Referencias
- "Newtype" en la wiki de Haskell
- La respuesta de Norman Ramsey sobre las propiedades de rigor