由于newtype
s 在编译期间被有效地删除,它们没有 thunk,只有值。那么如果我使用 WHNF 请求它会发生什么rseq
?例如在
Sum (lengthyComputation :: Int) `using` rseq
其中Sum
定义为
newtype Sum a = Sum { getSum :: a }
会lengthyComputation
被评估吗?它是否在某处指定/记录,以便我可以依靠它?
更新:让我更详细地解释我的疑问。直观地说:“newtype
很严格,它的 WHNF 是包裹在里面的东西的 WHNF”。但我觉得这是一个非常不精确的捷径,推理也不是很清楚。让我举个例子吧:
对于标准data
类型,WHNF 可以定义为我们知道哪个构造函数用于构造值的形式。例如,如果我们没有seq
,我们可以创建自己的
seqMaybe :: Maybe a -> b -> b
seqMaybe Nothing = id
seqMaybe _ = id
同样对于任何data
类型,只需在其构造函数之一上进行模式匹配即可。
现在让我们采取
newtype Identity a = Identity { runIdentity :: a }
并创建一个类似的seqIdentity
功能:
seqIdentity :: Identity a -> b -> b
seqIdentity (Identity _) = id
显然,这里没有什么是强制 WHNF 的。(毕竟,我们总是知道使用了什么构造函数。)编译后,seqIdentity
将与const id
. 事实上,不可能创建多态性seqIdentity
,这样它会强制评估包裹在里面的值Identity
!我们可以将 a 的 WHNF anewtype
简单地定义为未修改的值,并且它是一致的。所以我认为问题是,WHNF 是如何为newtype
s 定义的?还是没有严格的定义,并且“这是内部的WHNF”行为被简单地假设为显而易见的事情?