什么是newtype的WHNF以及rseq如何处理newtype?

时间:2012-12-02 12:40:27

标签: haskell concurrency lazy-evaluation newtype

由于newtype在编译期间被有效删除,因此它们没有thunk,只有值。那么如果我使用rseq要求其WHNF会怎样?例如在

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内包含的值!我们可以将newtype的WHNF定义为仅未修改的值,并且它将是一致的。所以我认为问题是,WHNF如何为newtype定义?或者没有严格的定义,“它是什么内部的WHNF”的行为被简单地假设为显而易见的东西?

1 个答案:

答案 0 :(得分:8)

根据报告中Datatype renamings的部分

  

与代数数据类型不同,newtype构造函数N是未提升的,因此N⊥与⊥相同。

下面

Sum ⊥ = ⊥

所以newtype的弱头正常形式是包装类型的WHNF,并且

Sum (lengthyComputation :: Int) `using` rseq

评估lengthyComputation(当评估整个表达时,仅仅是绑定

let x = Sum (lengthyComputation :: Int) `using` rseq

当然没有,但没有newtype构造函数也是如此。)

seq的{​​{3}}是

seq ⊥ b  =  ⊥
seq a b  =  b, if a ≠ ⊥

因此

seq (Sum ⊥) b = ⊥

并在

seq (lengthyComputaton :: Int) b

seq需要找出(对不起拟人化)lengthyComputation :: Int是否为{。为此,它必须评估lengthyComputation :: Int


重新更新:

newtype unlifted ,这意味着构造函数在语义上不是值构造函数(仅在语法上)。与newtype构造函数上的模式匹配相比,data构造函数上的模式匹配不严格。给定

newtype Foo a = Foo { unFoo :: a }  -- record syntax for convenience below

“模式匹配”

function :: Foo a -> Bar
function (Foo x) = whatever x

完全等同于

function y = let x = unFoo y in whatever x

匹配总是成功,并且什么都不评估。 defining equations和“模式匹配”取消强制值的类型。

seq是神奇的,它无法在Haskell中实现。对于seq类型,您可以编写与data相同的函数,例如上面的seqMaybe,在Haskell中,但不能用于(多态)newtype,因为newtype构造函数的“模式匹配”并不严格。您必须匹配包装类型的构造函数,但对于多态newtype,您没有它们。