Haskell 严格的单构造函数单字段数据声明与newtype
还有几个其他问题涉及数据和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
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 ...