据我所知,seq a b
在返回a
之前评估(强制)b
和b
。它不能保证首先评估a
。
pseq a b
首先评估a
,然后评估/返回b
。
现在考虑以下事项:
xseq a b = (seq a id) b
函数应用程序需要首先计算左操作数(以获得lambda形式),并且在进入函数之前不能盲目地评估右操作数,因为这会违反Haskell的非严格语义。
因此,(seq a id) b
必须首先评估seq a id
,强制a
和id
(以某种未指定的顺序(但评估id
什么也不做)),然后返回id b
(b
);因此xseq a b
会在a
之前评估b
。
xseq
是pseq
的有效实施吗?如果没有,上述论点有什么问题(并且可以根据pseq
来定义seq
吗?
答案 0 :(得分:0)
答案似乎是“不,至少没有额外的魔法”。
问题
xseq a b = (seq a id) b
是编译器可以看到seq a id
的结果是id
,这在任何地方都是严格的。如果函数是严格的,则允许函数应用程序首先对自变量求值,因为这样做不会改变表达式的语义。因此,优化编译器可以首先开始评估b
,因为它知道最终将需要它。
答案 1 :(得分:0)
可以用
pseq
来定义seq
吗?
在GHC中-是的。
如Alec所述,您还需要镜像烟雾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 #-}
我让美洛美来决定这是否也符合镜象烟雾...