列表推导的奇怪行为

时间:2017-01-08 15:00:07

标签: haskell functional-programming list-comprehension higher-order-functions

我正在学习Haskell的基础知识并尝试解决项目Euler的简单任务:找到3位数字(100.999)的最大回文。我写了这段代码:

palindrome = maximum $ filter (\a -> reverse a == a) $
                                    map show [ x*y :: Int | x <- [100 .. 999],
                                                            y <- [x, x+1 .. 999]]

它给出了错误的答案= 99999,当我将其更改为x <- [307 .. 999]时,答案仍然是错误的:94249(所有回文,但不是最大的),最后当我将其更改为x <- [308 .. 999],时,它给出了我的答案是:906609。

我真的不明白这种行为:似乎在生成的列表中发生了某种溢出和截断。有人可以解释我这种错误行为吗?我不希望你回答任务:我知道我的解决方案不是很有效率。我只是想让你解释这个代码行为(列表截断或内存问题)。感谢。

1 个答案:

答案 0 :(得分:9)

filter的结果是String值列表,因此maximum按字典顺序对它们进行比较。您需要先将值转换回Int。类型签名可确保read返回正确类型的值。

palindrome :: Int
palindrome = maximum . map read . filter ...

另一种方法是仅在过滤器本身中将值转换为String

palindrome :: Int
palindrome = maximum $ filter (\a -> let sa = show a in reverse sa == sa) [ x*y | x <- [100..999], y <- [x..999]]