Haskell列表推导式多条件无限列表生成报错求助
嘿,作为Haskell新手碰到这类问题太正常了,咱们一步步拆解你的代码问题,然后搞定它!
首先看你代码里的几个明显问题:
1. 语法错误:不完整的mod表达式
你写了x mod 20,但没给出判断条件(比如==5)——mod是二元运算符,返回的是整数,而列表推导式的过滤条件必须是布尔值,这直接导致了编译报错。
2. 逻辑矛盾:奇数判断搞反了
你写的odd x == False是在筛选偶数,但你明确要求元素是奇数,这完全和需求相反!其实这里甚至可以不用写odd x,因为x mod 20 ==5已经能保证x是奇数(20的倍数是偶数,加5后必然是奇数),当然如果你想明确加上,直接写odd x就行,不用加== True(Haskell里布尔值可以直接当条件用)。
3. 冗余的x>0条件
你从[0..]开始遍历,但满足x mod20 ==5的最小x是5,已经大于0了,所以这个条件完全可以去掉,保留也不影响,但没必要。
先验证你的条件是否有解
咱们用中国剩余定理确认一下,你要找的数需要满足:
x ≡3 mod13x ≡5 mod20
设x=20k+5,代入第一个式子:20k+5 ≡3 mod13 → 20≡7 mod13,5≡5 mod13,所以7k +5 ≡3 mod13 → 7k ≡11 mod13。
7在mod13下的逆元是2(因为7*2=14≡1 mod13),所以k≡11*2=22≡9 mod13,即k=13m+9。
代入回x的表达式:x=20*(13m+9)+5=260m+185。
所以最小的解是185,之后每次加260(13和20的最小公倍数)就能得到下一个解,所有解都是奇数,完全符合你的要求。
修正后的代码
首先是最贴近你原始写法的修正版本:
take 5 [x | x <- [0..], x `mod` 13 == 3, x `mod` 20 == 5]
如果你想明确加上奇数判断(虽然冗余,但更清晰):
take 5 [x | x <- [0..], odd x, x `mod` 13 == 3, x `mod` 20 == 5]
运行这段代码会得到前5个元素:[185,445,705,965,1225],你可以逐个验证:
- 185 mod13 = 3,mod20=5,是奇数 ✔️
- 445=185+260,加的是13和20的最小公倍数,所以mod13和mod20的结果不变,依然满足所有条件 ✔️
更高效的写法
如果你不想从0开始逐个过滤(毕竟要遍历185个数才找到第一个解),可以直接用我们推导出来的公式生成序列,性能更好:
take 5 [260*m + 185 | m <- [0..]]
这样直接生成符合要求的无限列表,不用过滤,取前5个元素的速度会快很多,尤其是当你需要取大量元素的时候。
内容的提问来源于stack exchange,提问作者Kubaguette The Testobun

