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

Haskell 严格的单构造函数单字段数据声明与newtype,haskell,Haskell,还有几个其他问题涉及数据和newtype之间的一般差异。我的问题很具体。如果G是某种类型,那么 数据T=T!G 及 newtype T=T G 它们似乎具有相同的严格性属性,我不明白为什么编译器有任何理由以不同的方式编译它们,但可能我遗漏了一些东西。主要的区别在于如何编译。所有数据声明,而newtype不声明 这是内存占用测量库的输出 import GHC.DataSize data A = A !Int newtype B = B Int main = do print =<&l

还有几个其他问题涉及数据和newtype之间的一般差异。我的问题很具体。如果
G
是某种类型,那么

数据T=T!G

newtype T=T G


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

主要的区别在于如何编译。所有
数据
声明,而
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)

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

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

假设我们有
数据Td=Td!G
新类型Tn=Tn G
。然后

  • Td
    Tn
    的居民完全相同,即
    G
  • 当强制执行WHNF时,两者的行为方式相同:强制执行它们“包含”的
    g
  • 它们与
    case
    的交互方式不同,但这只是语法上的。这两个版本之间有直接的对应关系
下表说明了如何在
案例
语句中用
数据
替换
新类型
Tn
。另外还有一个反方向的翻译

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
。从语法上讲,新类型可能会使
case
语句不那么尴尬,仅此而已。

您的问题得到了回答。
有什么作用代表中的
!G
?语义上存在差异:
未定义的->()
未定义的
<代码>未定义的B的案例->()
()
@schachaf哇,这是一个我不知道的案例。谢谢。@shachaf,我想你说得一针见血。我猜在新类型上进行模式匹配是不可行的,而在严格数据类型上进行模式匹配是一种强制代表中的
!Int
?@AlexanderSupertramp它声明应该严格地计算字段,而不是惰性地(默认值)。如果是
newtype
包装,则包装的类型只能是严格的,因此不需要砰的一声。Td既有
bottom
又有
T bottom
,而
Tn
只有
T bottom
。在
Td
中,
bottom
Td bottom
是无法区分的。
Td的案例Td
“whee”
@SebastianRedl:你想说什么?请注意,
G
是一个严格的数据字段,因此td的情况td 强制它。
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 ...