相关疑难解决方法(0)

Haskell:什么是弱头正常形式?

什么是弱头范式(WHNF)是什么意思?什么是头标准型(HNF)和范式(NF)是什么意思?

真实世界Haskell说:

熟悉的seq函数将表达式计算为我们称之为head normal form(缩写为HNF)的表达式.它一旦到达最外面的构造函数("头部")就会停止.这与正常形式(NF)不同,其中表达式被完全评估.

您还将听到Haskell程序员引用弱头正常形式(WHNF).对于正常数据,弱头正常形式与头部正常形式相同.差异只出现在功能上,而且我们在这里无关紧要.

我已经阅读了一些资源和定义(Haskell WikiHaskell邮件列表自由词典),但我没有得到它.有人可能举一个例子或提供外行定义吗?

我猜它会类似于:

WHNF = thunk : thunk

HNF = 0 : thunk 

NF = 0 : 1 : 2 : 3 : []
Run Code Online (Sandbox Code Playgroud)

如何做seq($!)与WHNF和HNF有关?

更新

我还是很困惑.我知道有些答案会忽略HNF.通过阅读各种定义,似乎WHNF和HNF中的常规数据之间没有区别.但是,它似乎与功能有所区别.如果没有差异,为什么还seq需要foldl'

另一个混淆点来自Haskell Wiki,它指出seq减少到WHNF,并且对以下示例不做任何处理.然后他们说他们必须seq用来强迫评估.那不是强迫它到HNF吗?

常见的新手堆栈溢出代码:

myAverage = uncurry (/) . foldl' (\(acc, len) x -> (acc+x, len+1)) (0,0)
Run Code Online (Sandbox Code Playgroud)

了解seq和弱头正常形式(whnf)的人可以立即明白这里出了什么问题.(acc + x,len + 1)已经在whnf中,所以seq将值减少到whnf,对此无效.这段代码将像原始的foldl示例一样构建thunks,它们只是在元组内部.解决方案只是强制元组的组件,例如

myAverage …
Run Code Online (Sandbox Code Playgroud)

haskell definition strictness weak-head-normal-form

279
推荐指数
6
解决办法
3万
查看次数

Haskell有尾递归优化吗?

我今天在unix中发现了"time"命令,并认为我会用它来检查Haskell中尾递归和正常递归函数之间运行时的差异.

我写了以下函数:

--tail recursive
fac :: (Integral a) => a -> a
fac x = fac' x 1 where
    fac' 1 y = y
    fac' x y = fac' (x-1) (x*y) 

--normal recursive
facSlow :: (Integral a) => a -> a
facSlow 1 = 1
facSlow x = x * facSlow (x-1)
Run Code Online (Sandbox Code Playgroud)

这些都是有效的,记住它们只是用于这个项目,所以我没有费心去检查零或负数.

但是,在为每个编写一个main方法,编译它们,并使用"time"命令运行它们时,两者都具有相似的运行时,正常的递归函数使尾递归函数边缘化.这与我在lisp中关于尾递归优化的内容相反.这是什么原因?

optimization haskell tail-recursion lazy-evaluation tail-call-optimization

82
推荐指数
3
解决办法
2万
查看次数