严格的单构造函数单字段数据声明与newtype

时间:2014-01-24 08:23:12

标签: haskell

Difference between `data` and `newtype` in Haskell以及其他几个问题解决了数据和newtype之间的一般差异。我的问题非常具体。如果G是某种类型,那么

之间是否有任何区别

data T = T !G

newtype T = T G

它们似乎具有相同的严格属性,我不明白为什么编译器有任何理由以不同的方式编译它们,但也许我错过了一些东西。

2 个答案:

答案 0 :(得分:3)

主要区别在于它将如何编译。所有data声明introduce memory overhead,而newtype不声明。

这是内存占用测量库的输出。

import GHC.DataSize

data A = A !Int
newtype B = B Int

main = do
  print =<< (recursiveSize $! A 1)
  print =<< (recursiveSize $! B 1)
  print =<< (recursiveSize $! 1)

输出:

32
16
16

Shachaf在第一条评论中提到了另一个不同之处。

答案 1 :(得分:2)

我将回答一个稍微不同的问题:“newtype是否将任何语义功能添加到Haskell?”。我相信答案是“不”。

假设我们有data Td = Td !Gnewtype Tn = Tn G。然后

  • TdTn拥有完全相同的居民,即G
  • 的居民
  • 当被迫使用WHNF时,两者的行为方式相同:g他们“包含”被迫
  • 他们与case的互动方式不同,但这只是句法。两个版本之间存在直接对应关系。

下表说明newtype Tn如何在data声明中替换为Td case。另一种方式也有翻译。

Tn                                    Td

case tn of _ -> ...                   case td of _ -> ...
case tn of Tn _ -> ...

case tn of Tn x -> ... x ...          let x1 = case tn of Td x -> x in ... x1 ...

case tn of x -> ... x ...             case td of x -> ... x ...

case tn of Tn x -> x `seq` ...        case td of Td _ -> ...         

case tn of Tn x -> x `seq` ... x ...  case td of Td x -> ... x ...     

从语义上讲,我相信Haskell可以避免添加newtype。从句法上讲,newtype可能会使case语句变得不那么尴尬,就是这样。