递归map函数作用异常及mystery列表元素推导疑问
为什么递归map函数不是只作用于列表的最后两个元素?
你这里的核心误解是对Haskell惰性递归列表的求值逻辑搞错啦!咱们一步步拆解这个mystery = 0 : 10 : (map (+1) mystery)的真实展开过程,对比你的推导就能明白问题出在哪。
首先明确Haskell列表的核心特性:惰性求值 + 递归引用的是整个列表
Haskell的列表是惰性生成的——它不会一次性算出所有元素,而是在你需要某个元素时才去计算。而且这里的map (+1) mystery引用的是完整的mystery列表本身,不是你以为的“当前已经生成的前缀片段”。
正确的元素推导步骤
咱们逐个推导前8个元素:
- 初始定义:
mystery = 0 : 10 : rest,其中rest = map (+1) mystery - 取第3个元素:需要计算
rest的第一个元素,也就是map (+1) mystery的第一个元素——把+1作用在mystery的第一个元素0上,得到1,所以第3个元素是1 - 取第4个元素:计算
rest的第二个元素,也就是map (+1) mystery的第二个元素——把+1作用在mystery的第二个元素10上,得到11,所以第4个元素是11 - 取第5个元素:计算
rest的第三个元素,也就是map (+1) mystery的第三个元素——此时mystery的第三个元素已经算出是1,所以+1 1 = 2,第5个元素是2 - 取第6个元素:计算
rest的第四个元素,也就是map (+1) mystery的第四个元素——mystery的第四个元素是11,所以+1 11 = 12,第6个元素是12 - 取第7个元素:对应
map (+1) mystery的第五个元素,mystery第五个元素是2,所以+1 2 = 3,第7个元素是3 - 取第8个元素:对应
map (+1) mystery的第六个元素,mystery第六个元素是12,所以+1 12 = 13,第8个元素是13
最终前8个元素就是[0,10,1,11,2,12,3,13],和标准答案一致。
你的推导错在哪?
你误以为每次是把当前已生成的列表片段(比如第一次的[0,10])做map (+1)后追加到原列表后面,但实际上map (+1) mystery是对整个无限递归的mystery列表做映射。当你计算后续元素时,mystery已经生成了新的元素(比如第3个元素1),map会继续对这些新元素做+1操作,而不是重复处理之前的前缀。
用代码展开的方式更直观:
mystery = 0 : 10 : (+1) (head mystery) -- 第3个元素:+1 0 =1 : (+1) (head (tail mystery)) -- 第4个元素:+1 10=11 : (+1) (head (tail (tail mystery))) -- 第5个元素:+1 1=2 : (+1) (head (tail (tail (tail mystery)))) -- 第6个元素:+1 11=12 : ...
内容的提问来源于stack exchange,提问作者aquaman9
相关产品推荐
相关产品推荐

