小编典典

Haskell中`data`和`newtype`之间的区别

all

我写这个有什么区别?

data Book = Book Int Int

相对

newtype Book = Book (Int, Int) -- "Book Int Int" is syntactically invalid

阅读 120

收藏
2022-06-21

共1个答案

小编典典

好问题!

有几个关键的区别。

表示

  • Anewtype保证您的数据在运行时将具有与您包装的类型完全相同的表示。
  • Whiledata在运行时声明一个全新的数据结构。

所以这里的关键点是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构造函数中未装箱的字大小字段。

代数数据类型

由于需要擦除构造函数,因此 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#组件的运行时对象。你只是得到一个裸露Intnewtype


2022-06-21