pseq 可以根据 seq 来定义吗?

Can pseq be defined in terms of seq?

据我所知,seq a b 在返回 b 之前评估(强制)ab。它不保证首先评估 a

pseq a b 首先评估 a,然后 evaluates/returns b.

现在考虑以下问题:

xseq a b = (seq a id) b

函数应用程序需要先计算左操作数(以获得 lambda 形式),并且它不能在进入函数之前盲目地计算右操作数,因为那样会违反 Haskell 的非严格语义。

因此 (seq a id) b 必须首先评估 seq a id,这会强制 aid(以某种未指定的顺序(但评估 id 不执行任何操作)) , 然后 returns id b (即 b);因此 xseq a bb.

之前评估 a

xseqpseq 的有效实现吗?如果不是,上述论点有什么问题(是否可以根据 seq 定义 pseq)?

答案似乎是"no, at least not without additional magic"。

的问题
xseq a b = (seq a id) b

是编译器可以看出seq a id的结果是id,处处严格。如果函数是严格的,则允许函数应用程序首先评估参数,因为这样做不会改变表达式的语义。因此,优化编译器可以首先开始评估 b,因为它知道它最终会需要它。

Can pseq be defined in terms of seq?

在 GHC 中 - 是的。

如 Alec 所述,您还需要 mirror-smoke lazy:

 -- for GHC 8.6.5
import Prelude(seq)
import GHC.Base(lazy)

infixr 0 `pseq`
pseq :: a -> b -> b
pseq x y = x `seq` lazy y

与 GHC 来源中对应的定义相匹配;进口是 非常不同。

对于其他 Haskell 实施,此 可能 有效:

import Prelude(seq)

infixr 0 `pseq`
pseq :: a -> b -> b
pseq x y = x `seq` (case x of _ -> y)

可能 结合 - 至少 - 相当于:

 -- for GHC 8.6.5
{-# NOINLINE pseq #-}

我会让 melpomene 决定这是否也符合 mirror-smoke...