我写这篇文章的时候有什么不同?
data Book = Book Int Int
对比
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
发布于 2011-05-05 04:58:40
问得好!
这里有几个关键的区别。
Representation
newtype
保证您的数据在运行时将具有与您包装的类型完全相同的表示。data
在运行时声明了一个全新的数据结构。所以这里的关键点是保证newtype
的构造在编译时被擦除。
示例:
data Book = Book Int Int
newtype Book = Book (Int, Int)
请注意,由于Book
构造函数已被擦除,因此它的表示与(Int,Int)
完全相同。
data Book = Book (Int, Int)
具有newtype
中不存在的附加Book
构造函数。
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
没有指针!在Book
构造函数中,这两个Int
字段是未装箱的单词大小的字段。
代数数据类型
由于需要擦除构造函数,因此仅当使用作为单个构造函数包装数据类型时,newtype
才有效。没有“代数”新类型的概念。也就是说,你不能写一个新类型的等价物,比如说,
data Maybe a = Nothing
| Just a
因为它有多个构造函数。你也不会写
newtype Book = Book Int Int
严格性
构造函数被擦除这一事实导致了data
和newtype
之间在严格性方面的一些非常细微的差异。特别是,data
引入了一个“提升”的类型,这意味着,本质上,它有一种额外的方法来计算到最低值。因为newtype
在运行时没有额外的构造函数,所以这个属性不成立。
到(,)
的Book
构造函数中的额外指针允许我们将底部值放入。
因此,与explained in the Haskell wiki article一样,newtype
和data
具有略微不同的严格属性。
拆箱
拆开newtype
的组件是没有意义的,因为没有构造函数。虽然这样写是完全合理的:
data T = T {-# UNPACK #-}!Int
生成具有T
构造函数和Int#
组件的运行时对象。您只需使用newtype
获得一个空Int
即可。
参考文献
的严格性属性
https://stackoverflow.com/questions/5889696
复制相似问题