- 论坛徽章:
- 5
|
本帖最后由 starwing83 于 2012-03-30 13:58 编辑
回复 63# OwnWaterloo
擦……回错了……重回
关于foldr转foldl的我搞清楚了。这里说明一下。首先,我们有:
- foldr' f i [] = i
- foldr' f i (x:xs) = f x (foldr' f i xs)
复制代码 当定义foldl‘’的时候,我们有:
- foldl'' f i xs = foldr' (\b g x -> g (f x b)) id xs i
复制代码 首先我们知道,foldl的功能是对f和i,[x1, x2, ... , xn], 产生这样的计算过程:
- ( ... ((i `f` x1) `f` x2) ... ) `f` xn)
复制代码 而foldr是产生这么一个计算过程:
- (x1 `f` (x2 `f` ( ... ( xn `f` i)) ... )
复制代码 从foldr的定义中可以很清楚的看到这种转换。
现在我们看用foldr的那个定义是如何处理的。首先用`f`计算xn和i:
- (\b g x -> g(f x b)) xn id
- --> (\ x -> id (x `f` xn))
- --> (\x -> x `f` xn)
复制代码 由此可知,我们将xn放到了右边,并延缓了计算(直到给出x为止)
然后我们以这个函数、给出的函数和xn-1计算新的值:
- (\b g x -> g (f x b)) xn-1 (\x -> x `f` xn)
- --> (\ x -> (\x -> x `f` xn) (x `f` xn-1))
- --> (\x -> ((x `f` xn-1) `f` xn))
复制代码 一样的过程,将xn-1插入到了xn之前,并延缓执行。
以此类推,最后的结果就是将计算按照foldl的方式安排好了,但是所有的计算都被延缓了。
最后,给出一个初始值i,启动整个计算,这个计算就是foldl的了。
问题是:
1. 展开的时候,有没有栈的问题?会不会有无穷展开导致编译错误的情况?
2. 这种延缓的执行启动的时候,是否是in-place执行的?就和foldl一样?
3. foldr本身是延缓执行的。它能不能通过参数调整的方式做到in-place执行?比如,先执行最后一个,然后逐次向前迭代,做到in-place?
4. 最后,Haskell有没有尾调用?Haskell的优化可以保证到什么程度?在逻辑上有迭代执行的可能性的时候,Haskell是不是一定可以迭代执行? |
|