Haskell $! 运算符和无限列表

16

我读过$!运算符会强制执行严格的计算。那为什么这个还是有效的?

Prelude> take 10 $! repeat 1
[1,1,1,1,1,1,1,1,1,1]

我原本以为ghc会永远试图计算由1组成的无限列表。

1个回答

26

$!强制其第二个参数进入弱头归约范式,这基本上意味着它评估其参数的最外层构造函数。因此在您的情况下,它不会强制评估整个列表,而只会评估最外层(即第一个):构造函数。

有一个很好的关于正常形式与WHNF的解释,请参阅Haskell:什么是弱头归约范式?

请注意,如果您强制评估整个列表(例如使用来自Control.DeepSeq模块的$!!运算符),则程序将无法终止:

λ: import Control.DeepSeq (($!!))
λ: take 10 $!! repeat 1
^C

关于弱头规范形式的SO链接线程是一篇很棒的阅读,谢谢! - knick
1
请注意,对于 n > 0take n 必须强制列表进入 WHNF,因此 take 10 $! repeat 1 在操作上与 take 10 $ repeat 1 相同。 - Luis Casillas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接