Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell pseq可以用seq定义吗?_Haskell_Lazy Evaluation_Strictness - Fatal编程技术网

Haskell pseq可以用seq定义吗?

Haskell pseq可以用seq定义吗?,haskell,lazy-evaluation,strictness,Haskell,Lazy Evaluation,Strictness,据我所知,seq a b在返回b之前计算(强制)a和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在b

据我所知,
seq a b
在返回
b
之前计算(强制)
a
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
b
之前对
a
进行求值

xseq
pseq
的有效实现吗?如果没有,上面的论点有什么问题(是否可以用
seq
来定义
pseq

答案似乎是“没有,至少没有额外的魔力”

问题在于

xseq a b = (seq a id) b
编译器可以看到
seq a id
的结果是
id
,这在任何地方都是严格的。如果函数是严格的,则允许函数应用程序首先计算参数,因为这样做不会更改表达式的语义。因此,优化编译器可以首先开始计算
b
,因为它知道它最终将需要它

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实现,这可能会起作用:

可能与(至少)相当于:

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

我将让melpomene决定这是否也符合镜像烟雾…

如果编译器决定内联
id
以形成
seqa(\x->x)
,那么它还可以看到
\x->x
在WHNF中,因此
seqa(\x->x)
可以“优化”为
a
。实际上是按照
seq
和来实现的,这是一个“非常神奇”的标识函数,编译器知道在严格性分析过程中永远不会内联。你要寻找的魔法真的存在。@melpomene抱歉,我的意思是
seq a(\x->x)b
可以变成
seq a((\x->x)b)
-一般来说,如果
y
在WHNF中,则
seq a y o
可能变成
seq a(y o)
。我不知道编译器是否会执行这样的优化,但它肯定会。我相信,就“原始操作语义”(即假装编译器根本不会更改代码)而言,您的函数是正确的——它只是在出现优化时发生故障。(事实上,
lazy
从字面上等同于
id
——因此你的
xseq
从字面上等同于
pseq
,并且两者都等同于
seq
,只是在操作上不一样)你似乎认为
fx
必须首先计算
f
,但情况可能不是这样。如果strictness analyzer证明
f
strict,我认为运行时可以首先将
x
计算为WHNF,而不改变语义。我不确定这是否真的发生在GHC优化器中。到目前为止,我看到有五个人对这个问题投了反对票。我很想知道为什么。这是一个漂亮的问题和答案。任何
-O0
没有执行严格性分析的实现都应该允许您在其自己的模块中定义一个低效版本的
lazy
<代码>懒惰::a->a;lazy x=x{-#NOINLINE lazy}。只要模块没有显示
lazy
在其参数中实际上是严格的,并且没有为其生成展开,您就应该是好的。GHC special将其内联到Core Prep中,就在Core-to-Core编译管道的末尾。
 -- for GHC 8.6.5
{-# NOINLINE pseq #-}