问题描述
我写这个有什么不同?
data Book = Book Int Int
对比
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
推荐答案
好问题!
有几个主要区别.
代表
newtype
保证您的数据在运行时具有与您包装的类型完全相同的表示.- 虽然
data
在运行时声明了一个全新的数据结构.
- A
newtype
guarantees that your data will have exactly the same representation at runtime, as the type that you wrap. - While
data
declares a brand new data structure at runtime.
所以这里的关键点是 newtype
的构造保证在编译时被擦除.
So the key point here is that the construct for the newtype
is guaranteed to be erased at compile time.
示例:
data Book = Book Int Int
newtype Book = Book (Int, Int)
注意它如何与 (Int,Int)
具有完全相同的表示,因为 Book
构造函数已被删除.
Note how it has exactly the same representation as a (Int,Int)
, since the Book
constructor is erased.
data Book = Book (Int, Int)
具有 newtype
中不存在的附加 Book
构造函数.
Has an additional Book
constructor not present in the newtype
.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
没有指针!两个 Int
字段是 Book
构造函数中未装箱的字大小的字段.
No pointers! The two Int
fields are unboxed word-sized fields in the Book
constructor.
代数数据类型
由于需要擦除构造函数,newtype
仅在用单个构造函数包装数据类型时才有效.没有代数"新类型的概念.也就是说,你不能写一个 newtype 等价于,比如,
Because of this need to erase the constructor, a newtype
only works when wrapping a data type with a single constructor. There's no notion of "algebraic" newtypes. That is, you can't write a newtype equivalent of, say,
data Maybe a = Nothing
| Just a
因为它有多个构造函数.你也不会写
since it has more than one constructor. Nor can you write
newtype Book = Book Int Int
严格
构造函数被擦除的事实导致了data
和newtype
之间在严格性上的一些非常细微的差异.特别是,data
引入了一种提升"的类型,本质上,这意味着它有一种额外的方法来评估底部值.由于 newtype
在运行时没有额外的构造函数,所以这个属性不成立.
The fact that the constructor is erased leads to some very subtle differences in strictness between data
and newtype
. In particular, data
introduces a type that is "lifted", meaning, essentially, that it has an additional way to evaluate to a bottom value. Since there's no additional constructor at runtime with newtype
, this property doesn't hold.
Book
中指向 (,)
构造函数的额外指针允许我们放入一个底部值.
That extra pointer in the Book
to (,)
constructor allows us to put a bottom value in.
因此,newtype
和 data
的严格性属性略有不同,如 在 Haskell wiki 文章中解释.
As a result, newtype
and data
have slightly different strictness properties, as explained in the Haskell wiki article.
拆箱
拆箱 newtype
的组件没有意义,因为没有构造函数.虽然这样写是完全合理的:
It doesn't make sense to unbox the components of a newtype
, since there's no constructor. While it is perfectly reasonable to write:
data T = T {-# UNPACK #-}!Int
使用 T
构造函数和 Int#
组件生成运行时对象.你只需要一个带有 newtype
的 Int
.
yielding a runtime object with a T
constructor, and an Int#
component. You just get a bare Int
with newtype
.
参考文献:
- "Newtype" on the Haskell wiki
- Norman Ramsey's answer about the strictness properties
这篇关于Haskell中`data`和`newtype`的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!