Haskell - 列表理解

问题描述 投票:0回答:1

我的练习是定义一个函数,该函数返回给定区间内至少三位数的素数列表。它必须与列表理解。

例如,在这种情况下,它必须返回 primeNumbers 100 200 = [101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181 , 191, 193, 197, 199].

这是我的代码

primesNumbers :: Int -> Int -> [Int]
primesNumbers a b = [n | n <- [a..b], n > 99, all (\x -> n `mod` x /= 0) [x | x <- [2.. max a b]]]

但是在这种情况下 primeNumbers 100 200,它只返回 [].

什么问题?

haskell functional-programming integer list-comprehension
1个回答
0
投票

问题

首先,让我指出一个事实,即可能不需要

n > 99
。如果
a
大于 100,
n
不能小于 99。要么你想要所有大于 99 的素数,要么你做错了。 所以我会在没有它的情况下工作。

如果我们分解你的代码,就有可能写成

primesNumbers :: Int -> Int -> [Int]
primesNumbers a b = [n | n <- [a..b], f a b n]

f :: Int -> Int -> Int -> Bool
f a b n = all (\x -> n `mod` x /= 0) [x | x <- [2.. max a b]]

如果我们想为

f
提供一个更好的名字,我们可以查看代码,发现它试图测试 2 和
max a b
之间的所有数字是否都是
n
的约数。所以让调用
f
函数
can_be_divided_by_a_number_between_a_and_b
.

所以你现在的功能是

primesNumbers a b = [n | n <- [a..b], can_be_divided_by_a_number_between_a_and_b a b n]

当你调用

primeNumbers 100 200
时,你想找到100到200之间的所有数字
n
,不能被2到200之间的数字整除。现在,101是一个相关的选择吗?不,因为很明显 101 可以被 100 到 200 之间的数字整除……它可以被自己整除。

解决方案

现在你可以看到这不是你想要的。你的上限太高了。你想找到一种方法来表达它不能被严格地介于 1 和它本身之间的数字相除,即 Haskell 中的 ]1、n[

[2 .. n-1]

让我们想办法写

cant_be_divided_by_a_number_stritly_between_2_and_itself
。为了简洁起见,我将其称为
is_prime
,因为这是它的定义。

is_prime :: Int -> Bool
is_prime n = all (\x -> n `mod` x /= 0) [x | x <- [2 .. n-1]]

现在可以轻松编写函数了。因为你想要

a
b
之间的所有质数,所以是

primeNumbers a b = [n | n <- [a..b], is_prime n]

结论

依我拙见,你应该从后者开始……写作

primeNumbers a b = [n | n <- [a..b], is_prime n]

是自上而下方法的开始,可帮助您将问题分解为更小的问题并逐步提供解决方案。 编写下一步

is_prime n
比尝试一步解决所有问题要容易得多。

你可以看到它可以很容易地推广到所有可能的谓词

p
with

verify_p_between_a_and_b p a b = = [n | n <- [a..b], p n]

所以

primesNumbers = verify_p_between_a_and_b is_prime

:)

© www.soinside.com 2019 - 2024. All rights reserved.