use*_*425 9 haskell lazy-evaluation
我试图更好地理解Haskell的懒惰,例如当它评估函数的参数时.
从这个来源:
但是当一个调用
const被评估时(这就是我们感兴趣的情况,毕竟这里),它的返回值也被评估......这是一个很好的一般原则:一个函数显然在其返回值上是严格的,因为当需要对函数应用程序进行求值,它需要在函数体中评估返回的内容.从那里开始,您可以通过查看返回值总是依赖于什么来了解必须评估的内容.你的函数在这些参数中是严格的,在其他参数中是懒惰的.
那么Haskell中的函数总是评估自己的返回值?如果我有:
foo :: Num a => [a] -> [a]
foo [] = []
foo (_:xs) = map (* 2) xs
head (foo [1..]) -- = 4
Run Code Online (Sandbox Code Playgroud)
根据以上段落map (* 2) xs,必须进行评估.直觉上,我认为这意味着应用于map整个列表 - 导致无限循环.但是,我可以成功地取得结果.我知道:在Haskell 中是懒惰的,所以这是否意味着评估map (* 2) xs只意味着构建尚未完全评估的其他东西?
评估应用于无限列表的函数意味着什么?如果在评估函数时总是评估函数的返回值,函数是否可以实际返回thunk?
编辑:
bar x y = x
var = bar (product [1..]) 1
Run Code Online (Sandbox Code Playgroud)
此代码不会挂起.当我创造时var,它不会评估它的身体吗?或者它设定bar到product [1..],而不是评价是什么?如果后者bar没有在WHNF中恢复它的身体,那么它真的"评估"x吗?如果它不依赖于计算,怎么可能bar是严格的?xproduct [1..]
aug*_*tss 12
首先,Haskell没有说明评估何时发生,所以问题只能给出具体实现的明确答案.
以下是我所知道的所有非并行实现,例如ghc,hbc,nhc,hugs等(所有基于G机器的,顺便说一句).
顺便说一句,要记住的是,当你听到Haskell的"评价"时,它通常意味着"评估为WHNF".
与严格语言不同,您必须区分函数的两个"调用者",第一个是词法调用发生的位置,第二个是需要值的位置.对于严格的语言,这两者总是重合,但不适合懒惰的语言.让我们举个例子,让它复杂一点:
foo [] = []
foo (_:xs) = map (* 2) xs
bar x = (foo [1..], x)
main = print (head (fst (bar 42)))
Run Code Online (Sandbox Code Playgroud)
该foo功能发生在bar.评估bar将返回一对,并且该对的第一个组件是对应的thunk foo [1..].那么bar严格语言中的调用者是什么,但是在懒惰语言的情况下它根本不调用foo,而只是构建闭包.
现在,在main函数中我们实际需要的值是head (fst (bar 42))因为我们必须打印它.所以head实际上会调用该函数.该head函数由模式匹配定义,因此它需要参数的值.所以fst被称为.它也是由模式匹配定义的,需要它的参数,因此bar被调用,bar并将返回一对,fst并将评估并返回其第一个组件.现在终于foo被"召唤"了; 并且通过调用我的意思是thunk被评估(因为它有时在TIM术语中被称为输入),因为需要该值.foo调用实际代码的唯一原因是我们想要一个值.所以foo最好返回一个值(即WHNF).该foo函数将评估其参数并最终进入第二个分支.这里它将尾部调用代码map.该map函数由模式匹配定义,它将评估其参数,这是一个缺点.因此map将返回以下内容{(*2) y} : {map (*2) ys},我用它{}来表示正在构建的闭包.因此,你可以看到map只返回一个cons单元,头部是一个闭包,尾部是一个闭包.
为了更好地理解Haskell的操作语义,我建议你看一些描述如何将Haskell转换为一些抽象机器的文章,比如G-machine.
| 归档时间: |
|
| 查看次数: |
1440 次 |
| 最近记录: |