Pet*_*lák 8 concurrency haskell lazy-evaluation newtype
由于newtype在编译期间有效地删除了s,因此它们没有thunk,只有值.那么如果我要求使用WHNF会怎么样rseq?例如在
Sum (lengthyComputation :: Int) `using` rseq
Run Code Online (Sandbox Code Playgroud)
在哪里Sum定义为
newtype Sum a = Sum { getSum :: a }
Run Code Online (Sandbox Code Playgroud)
会lengthyComputation得到评估吗?它是否在某处指定/记录,以便我可以指望它?
更新:让我更详细地解释一下我的疑虑.直观地说:" newtype严格要求它的WHNF是包含在内的WHNF".但我觉得这是一个非常不精确的捷径,而且推理并不那么明确.让我举个例子:
对于标准data类型,WHNF可以定义为一种形式,我们知道哪个构造函数用于构造值.例如,如果我们没有seq,我们可以创建自己的
seqMaybe :: Maybe a -> b -> b
seqMaybe Nothing = id
seqMaybe _ = id
Run Code Online (Sandbox Code Playgroud)
对于任何data类型,只需通过其中一个构造函数上的模式匹配.
现在我们来看看吧
newtype Identity a = Identity { runIdentity :: a }
Run Code Online (Sandbox Code Playgroud)
并创建一个类似的seqIdentity功能:
seqIdentity :: Identity a -> b -> b
seqIdentity (Identity _) = id
Run Code Online (Sandbox Code Playgroud)
显然,这里没有任何东西被强迫给WHNF.(毕竟,我们总是知道使用了什么构造函数.)编译后,seqIdentity将完全相同const id.事实上,不可能创建多态seqIdentity,这样就会强制评估包含在内的值Identity!我们可以将a的WHNF定义newtype为简单的未经修改的值,并且它将是一致的.所以我相信问题是,WHNF是如何为newtypes 定义的?或者没有严格的定义,并且"它是什么内部的WHNF"的行为被简单地假设为显而易见的东西?
根据报告中有关数据类型重命名的部分,
与代数数据类型不同,newtype构造函数N是未提升的,因此N⊥与⊥相同.
这里
Sum ? = ?
Run Code Online (Sandbox Code Playgroud)
所以新类型的弱头正常形式是包裹类型的WHNF,并且
Sum (lengthyComputation :: Int) `using` rseq
Run Code Online (Sandbox Code Playgroud)
评估lengthyComputation(评估整个表达式时,仅仅是绑定
let x = Sum (lengthyComputation :: Int) `using` rseq
Run Code Online (Sandbox Code Playgroud)
当然没有,但没有newtype构造函数也是如此).
的定义方程为seq顷
seq ? b = ?
seq a b = b, if a ? ?
Run Code Online (Sandbox Code Playgroud)
因此
seq (Sum ?) b = ?
Run Code Online (Sandbox Code Playgroud)
并在
seq (lengthyComputaton :: Int) b
Run Code Online (Sandbox Code Playgroud)
将seq需要找出(遗憾的拟人化)是否lengthyComputation :: Int是⊥与否.要做到这一点,它必须评估lengthyComputation :: Int.
重新更新:
newtypes是未提升的,这意味着构造函数在语义上不是值构造函数(仅在语法上).与newtype构造函数上的模式匹配相比,data构造函数上的模式匹配相反.特定
newtype Foo a = Foo { unFoo :: a } -- record syntax for convenience below
Run Code Online (Sandbox Code Playgroud)
一个"模式匹配"
function :: Foo a -> Bar
function (Foo x) = whatever x
Run Code Online (Sandbox Code Playgroud)
完全等同于
function y = let x = unFoo y in whatever x
Run Code Online (Sandbox Code Playgroud)
匹配总是成功,并且什么都不评估.构造函数只强制类型,并在其上"模式匹配"取消强制值的类型.
seq是神奇的,它无法在Haskell中实现.您可以在Haskell中编写一个与上面seq的data类型相同的函数seqMaybe,但不能用于(多态)newtype,因为newtype构造函数上的"模式匹配"并不严格.你必须匹配包装类型的构造函数,但对于多态newtype,你没有它们.