Haskell列表推导式嵌套生成器返回非预期结果疑问
问题原因分析
Haskell中包含多个生成器的列表推导等价于嵌套循环逻辑,右侧的生成器对应内层循环,会优先遍历完所有取值。
你的现有代码:
f :: [Integer] f = [x-n | x <- [1,2..], n <- [0,1..]]
执行时会先取第一个x的值1,之后不断遍历n的无限列表[0,1,2,3...]计算1-n。因为n是无限列表,内层循环永远不会结束,你永远拿不到x取2、3等值的计算结果,所以take 10 f拿到的全是x=1时的计算结果,即[1,0,-1,-2,-3,-4,-5,-6,-7,-8]。
正确实现方案
如果你需要让x和n按位置一一对应取值,也就是第k个x对应第k个n,可以选择以下两种实现方式:
方案1:使用zipWith实现
不需要开启任何扩展,直接用自带的zipWith函数同步遍历两个列表:
f :: [Integer] f = zipWith (-) [1,2..] [0,1..]
方案2:使用ParallelListComp扩展
开启ParallelListComp扩展后,列表推导的多个生成器会按位置同步取值,更贴近你原来的书写习惯:
{-# LANGUAGE ParallelListComp #-} f :: [Integer] f = [x-n | x <- [1,2..] | n <- [0,1..]]
两种方案执行take 10 f都会得到你预期的[1,1,1,1,1,1,1,1,1,1]。
内容的提问来源于stack exchange,提问作者user12854069
相关产品推荐
相关产品推荐

