Haskell记忆化斐波那契代码中!!运算符的作用疑问
理解Haskell记忆化斐波那契代码里的
!!运算符 这段代码靠Haskell的惰性求值实现斐波那契函数的记忆化,而!!运算符是把“惰性列表”转换成“索引查询函数”的关键,下面拆解细节:
第二行代码的拆解
memoized_fib = (map fib [0 ..] !!) 可以拆成两部分看:
map fib [0..]:生成一个无限惰性列表,列表第n位的元素对应fib n的结果。因为Haskell是惰性求值,这个列表不会一次性计算所有元素,只有当某个位置的元素被需要时才会触发计算,且计算后的结果会被缓存下来。(xs !!):这是对!!运算符的部分应用。!!本身的类型是[a] -> Int -> a,当只传入第一个参数(也就是上面的无限列表xs),它会变成一个类型为Int -> a的函数——这个函数接受一个索引n,返回列表xs的第n个元素。
所以memoized_fib本质上就是这个部分应用后的函数:输入整数n,返回无限列表里第n位的元素。
记忆化的实现逻辑
当调用memoized_fib 5时:
- 会触发取无限列表的第5个元素,也就是计算
fib 5 fib 5依赖memoized_fib 3和memoized_fib 4,这又会触发计算列表的第3、4位元素- 以此类推,直到触发
fib 0和fib 1的基础情况 - 所有计算过的列表元素都会被缓存,后续再调用
memoized_fib时,直接取缓存好的值,不需要重新递归计算
!!的核心作用
你之前知道!!是按索引检索列表元素的运算符,这点完全正确——这里它的作用就是把“存储斐波那契值的惰性列表”转换成了“接受索引返回对应值的函数”,刚好匹配memoized_fib的类型Int -> Integer。没有!!的话,我们手里只有一个列表,没法直接用索引去调用它,而部分应用!!后,就得到了我们需要的函数形式。
内容的提问来源于stack exchange,提问作者Alfy B
相关产品推荐
相关产品推荐

