Haskell中`data`和`newtype`之间的区别
我写这个有什么不同?
data Book = Book Int Int
newtype Book = Book(Int, Int) -- "Book Int Int" is syntactically invalid
伟大的问题!
有几个关键的区别。
表示
newtype
保证您的数据将有完全相同的表示在运行时,为你包的类型。 data
在运行时声明一个全新的数据结构。 因此,这里的关键点是,对于构建newtype
保证在编译时被删除。
例子:
data Book = Book Int Int
newtype Book = Book (Int, Int)
请注意它是如何具有与(Int,Int)
完全相同的表示形式的,因为Book
构造函数已被擦除。
data Book = Book (Int, Int)
有一个额外的Book
构造函数不在newtype
。
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
没有指针! 这两个Int
字段是Book
构造函数中的拆箱字段大小的字段。
代数数据类型
因为这需要抹去的构造,一个newtype
包裹有一个构造函数数据类型时才会起作用。 没有“代数”新类型的概念。 也就是说,你不能写一个新的类型,比如说,
data Maybe a = Nothing
| Just a
因为它有多个构造函数。 你也不能写
newtype Book = Book Int Int
严格
该构造被删除,这一事实导致之间严格一些很细微的差别data
和newtype
。 特别是, data
引入了“提升”的类型,实质上意味着它有一种额外的方式来评估最低价值。 由于在运行时没有使用newtype
附加构造函数,因此此属性不成立。
Book
to (,)
构造函数中的额外指针允许我们将底部值放入。
其结果是, newtype
和data
具有略微不同的严格性,因为Haskell的wiki文章中所说明的。
拆箱
它没有意义拆箱一的组件newtype
,因为没有构造函数。 尽管写作是完全合理的:
data T = T {-# UNPACK #-}!Int
产生一个带T
构造函数的运行时对象和一个Int#
组件。 你只需要用newtype
得到一个newtype
Int
。
参考文献: