写这篇文章有什么区别?
data Book = Book Int Int
与
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
答案 0 :(得分:219)
很棒的问题!
有几个关键的区别。
<强>表示强>
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
到(,)
构造函数中的额外指针允许我们将底值放入。
因此,newtype
和data
的严格性属性略有不同,如explained in the Haskell wiki article。
<强>开箱强>
取消装箱newtype
的组件是没有意义的,因为没有构造函数。虽然写下来是完全合理的:
data T = T {-# UNPACK #-}!Int
使用T
构造函数和Int#
组件生成运行时对象。您只需Int
newtype
。{/ p>
参考: