简体   繁体   English

列表推导的奇怪行为

[英]Strange behaviour of list comprehensions

I'm learning basics of Haskell and trying to solve project Euler's simple tasks: find largest palindrome of 3 digit numbers (100.999). 我正在学习Haskell的基础知识并试图解决项目Euler的简单任务:找到3位数字(100.999)的最大回文。 I wrote this code: 我写了这段代码:

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

It gives a wrong answer = 99999, when I change it to x <- [307 .. 999] answer still is wrong: 94249 (all palindromes, but not the largest) and finally when I change it to x <- [308 .. 999], it gives me right answer: 906609. 它给出了错误的答案= 99999,当我将其更改为x <- [307 .. 999]答案仍然是错误的:94249(所有回文,但不是最大的),最后当我将其更改为x <- [308 .. 999],它给了我正确答案:906609。

I really don't understand this behaviour: it seems there is some kind of overflow and truncation happens inside the generated list. 我真的不明白这种行为:似乎在生成的列表中发生了某种溢出和截断。 Can someone explain me this wrong behaviour? 有人可以解释我这种错误行为吗? I don't want you to answer the task: i know my solution is not very efficient. 不希望你回答任务:我知道我的解决方案效率不高。 I just want you to explain this code behaviour (list truncation or memory issues). 我只是想让你解释这个代码行为(列表截断或内存问题)。 Thanks. 谢谢。

The result of filter is a list of String values, so maximum is comparing them lexicographically. filter的结果是String值列表,因此maximum是按字典顺序比较它们。 You need to convert the values back to Int s first. 您需要先将值转换回Int The type signature ensures that read returns values of the correct type. 类型签名确保read返回正确类型的值。

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

Another approach is to only convert a value to a String in the filter itself: 另一种方法是仅在过滤器本身中将值转换为String

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM