ewg*_*egw 179 haskell types type-systems newtype
我写这个有什么区别?
data Book = Book Int Int
Run Code Online (Sandbox Code Playgroud)
与
newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid
Run Code Online (Sandbox Code Playgroud)
Don*_*art 227
好问题!
有几个关键的区别.
表示
newtype保证您的数据将会有确切的在运行时相同的表示,为你包的类型.data在运行时声明了一个全新的数据结构.所以这里的关键点newtype是保证在编译时擦除构造.
例子:
data Book = Book Int Int
newtype Book = Book (Int, Int)
请注意它与a的表示形式完全相同(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
Run Code Online (Sandbox Code Playgroud)
因为它有多个构造函数.你也写不出来
newtype Book = Book Int Int
Run Code Online (Sandbox Code Playgroud)
严格
该构造被删除,这一事实导致之间严格一些非常细微的差别data和newtype.特别是,data引入了一种"提升"的类型,基本上意味着它有一种额外的方式来评估底值.由于运行时没有其他构造函数newtype,因此该属性不成立.
Bookto (,)构造函数中的额外指针允许我们将底部值放入.
因此,newtype并且data具有稍微不同的严格性属性,如Haskell wiki文章中所述.
拆箱
取消打包a的组件是没有意义的newtype,因为没有构造函数.虽然写下来是完全合理的:
data T = T {-# UNPACK #-}!Int
Run Code Online (Sandbox Code Playgroud)
使用T构造函数和Int#组件生成运行时对象.你只是得到一个裸Int与newtype.
参考文献: