Haskell中`data`和`newtype`之间的区别 [英] Difference between `data` and `newtype` in Haskell
问题描述
data Book = Book Int Int
newtype Book = Book(Int,Int) - Book Int Int在语法上无效
伟大的问题!
有几个关键区别。
代表
-
newtype
可确保您的数据完全符合在运行时使用相同的表示形式,作为您打包的类型。 -
data 在运行时声明一个全新的数据结构。 >
所以关键在于 newtype
的结构保证被擦除在编译时。
示例:
数据Book = Book Int Int
-
newtype Book = Book(Int,Int)
(Int,Int)具有完全相同的表示形式,因为<$
$ b
数据Book = Book(Int ,Int)
Book
构造函数不存在于 newtype
。
-
data Book = Book { - #UNPACK# - }!Int { - #UNPACK# - }!Int
- 诺曼拉姆齐的答案有关严格性质
$ b
没有p ointers!这两个 Int
字段是 Book
构造函数中的非字框大小字段。
代数数据类型 由于需要擦除构造函数,所以 ,因为它有多个构造函数。你也不能写 严格性 构造函数被擦除的事实导致了一些非常细微的差异 因此, 拆箱 这对unbox没有任何意义一个 产生一个带有 引用: /www.haskell.org/haskellwiki/Newtyperel =noreferrer> Haskell wiki上的Newtype
newtype
仅在使用单个构造函数封装数据类型时才起作用。没有代数新类型的概念。也就是说,你不能写出新的类型,例如,
data也许a = Nothing
|只是一个
newtype Book = Book Int Int
data
和 newtype
之间的严格性。特别是, data
引入了一个提升类型,实质上,它意味着它有一个额外的方法来评估最低值。由于在运行时没有使用 newtype
的附加构造函数,所以此属性不成立。
Book 到
(,)
构造函数允许我们设置最低值。
newtype
和 data
具有稍微不同的严格属性,正如在Haskell wiki文章
newtype
的组件,因为没有构造函数。尽管写完全是合理的:
data T = T { - #UNPACK# - }!Int
T
构造函数的运行时对象,并且一个 Int#
组件。你只需在> Int
中加入 newtype
。
$ b
What is the difference when I write this?
data Book = Book Int Int
newtype Book = Book(Int, Int) -- "Book Int Int" is syntactically invalid
Great question!
There are several key differences.
Representation
- A
newtype
guarantees that your data will have exactly the same representation at runtime, as the type that you wrap. - While
data
declares a brand new data structure at runtime.
So the key point here is that the construct for the newtype
is guaranteed to be erased at compile time.
Examples:
data Book = Book Int Int
newtype Book = Book (Int, Int)
Note how it has exactly the same representation as a (Int,Int)
, since the Book
constructor is erased.
data Book = Book (Int, Int)
Has an additional Book
constructor not present in the newtype
.
data Book = Book {-# UNPACK #-}!Int {-# UNPACK #-}!Int
No pointers! The two Int
fields are unboxed word-sized fields in the Book
constructor.
Algebraic data types
Because of this need to erase the constructor, a newtype
only works when wrapping a data type with a single constructor. There's no notion of "algebraic" newtypes. That is, you can't write a newtype equivalent of, say,
data Maybe a = Nothing
| Just a
since it has more than one constructor. Nor can you write
newtype Book = Book Int Int
Strictness
The fact that the constructor is erased leads to some very subtle differences in strictness between data
and newtype
. In particular, data
introduces a type that is "lifted", meaning, essentially, that it has an additional way to evaluate to a bottom value. Since there's no additional constructor at runtime with newtype
, this property doesn't hold.
That extra pointer in the Book
to (,)
constructor allows us to put a bottom value in.
As a result, newtype
and data
have slightly different strictness properties, as explained in the Haskell wiki article.
Unboxing
It doesn't make sense to unbox the components of a newtype
, since there's no constructor. While it is perfectly reasonable to write:
data T = T {-# UNPACK #-}!Int
yielding a runtime object with a T
constructor, and an Int#
component. You just get a bare Int
with newtype
.
References:
- "Newtype" on the Haskell wiki
- Norman Ramsey's answer about the strictness properties
这篇关于Haskell中`data`和`newtype`之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!