我写这个有什么区别?
data Book = Book Int Int
相对
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
好问题!
有几个关键的区别。
表示
newtype
data
所以这里的关键点是newtype保证 的构造在编译时被擦除。
例子:
newtype Book = Book (Int, Int)
请注意它与 a 具有完全相同的表示形式(Int,Int),因为Book构造函数已被删除。
(Int,Int)
Book
data Book = Book (Int, Int)
有一个额外的Book构造函数不存在于newtype.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
没有指针!这两个Int字段是Book构造函数中未装箱的字大小字段。
Int
代数数据类型
由于需要擦除构造函数,因此 a仅在使用 单个构造函数*newtype包装数据类型时才有效。没有“代数”新类型的概念。也就是说,你不能写一个新类型,比如, *
data Maybe a = Nothing | Just a
因为它有多个构造函数。你也不会写
newtype Book = Book Int Int
严格
构造函数被删除的事实导致data和之间的严格性存在一些非常细微的差异newtype。特别是,data引入了一种“提升”的类型,本质上意味着它有一种额外的方法来评估底部值。由于在运行时没有额外的构造函数newtype,所以这个属性不成立。
Bookto构造函数中的那个额外指针(,)允许我们放入一个底部值。
(,)
因此,newtype严格data属性略有不同,如Haskell wiki 文章中所述。
拆箱
拆箱 a 的组件是没有意义的newtype,因为没有构造函数。虽然这样写是完全合理的:
data T = T {-# UNPACK #-}!Int
生成带有T构造函数和Int#组件的运行时对象。你只是得到一个裸露Int的newtype。
T
Int#