[英]Why haskell seq function makes first argument to WHNF?
我认为seq很难理解,因为它是WHNF的第一个论点。
如果seq将第一个参数设为范式,则很容易理解。
使用WHNF相比NF有什么好处?
为什么Haskell委员会选择在seq函数中使用WHNF?
首先,Haskell的API在WHNF和NF之间没有优先选择:它同时提供seq
和deepseq
。
因此,也许您的问题是为什么WHNF根本存在? 简而言之,这是最少的评估。 完整的计算将如下所示:
但是,Haskell很懒,它会尝试进行尽可能少的计算以获得最终结果。 例如,要计算列表l
的长度,Haskell必须知道l
是[]
还是_ : t
。 然后递归有关t
的相同问题。 因此,它只需要数量的构造函数:
在最终构造函数[]
。 根据定义,这是连续的WHNF,它们仅提取值的最外部构造函数。
最外层的构造函数是您必须真正了解对某个值进行操作所必须知道的最少信息,例如在的case of
选择一个分支,例如length
恰好在上面。 这是WHNF胜过NF的兴趣。
请注意,对于简单的类型,如Int
,每个价值是自身的构造函数( 2
, -7
, 15
,......),所以WHNF = NF他们。
最后,您几乎不需要关心所有这一切:尽可能快地执行程序是编译器的工作。 在对foldl (+) 0 [1..100]
的求值中,如果您试图弄清楚列表[1..100]
在NF中完成的时间,那将是完全错误的。 编译器将此折叠转换为该尾递归循环
let sum ret i =
if i == 100 then 100 + ret
else sum (ret+i) (i+1) in
sum 0 1
这意味着它根本不会评估列表。 不幸的是,在某些情况下,当生成程序的最终结果时,编译器无法知道某个值将始终位于NF中。 然后,浪费时间和RAM使其保持deepseq
(形成deepseq
东西deepseq
):从一开始就更好地进行deepseq
。 否则您的编译器可能会出现性能错误,因此您必须使用seq
或deepseq
帮助它。 探查器将告诉您代码的哪些部分运行缓慢。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.