【发布时间】:2020-12-15 04:36:42
【问题描述】:
在 Haskell 中有很多关于生成素数的主题,但在我看来,它们都依赖于 'isPrime' 函数,如果我们还不知道素数序列,应该如下所示:
isPrime k = if k > 1 then null [ x | x <- [2,3..(div k 2) + 1], k `mod` x == 0]
else False
(div 可能会替换为 sqrt,但仍然...)
我尝试根据“归纳定义”构造素数(假设我们有一组前 n 个素数,然后是 (n+1)th 个素数是最小整数,使得前 n 个素数都不是它的除数)。我试过用斐波那契数列的方式来做,即:
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fibs !! n
where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
我最终得到了这个:
-- checking if second number is a divisor of first one
ifDoesn'tDivide :: Int -> Int -> Bool
ifDoesn'tDivide n k
| mod n k == 0 = False
| otherwise = True
-- generating list which consists of first n prime numbers
firstPrimes :: Int -> [Int]
-- firstPrimes 1 = [2]
firstPrimes n = take n primes
where primes = 2:(tail primes) ++
[head [x | x <- [3,4..], k <- primes, ifDoesn'tDivide x k == True]]
但它不起作用,堆栈溢出当n >= 2。关于如何修复它的任何建议?
“Haskell 可以根据自身定义数据结构,从而创建无限的数据结构”。前面提到的那些素数和斐波那契数列是根据自身定义数据结构的具体情况,斐波那契数列可以正常工作,但这些primes 不行。
我是否遗漏了什么,这两种算法在本质上是不同的吗?
附:所以,我想,我只是在寻找最“Haskellish”的方式来做到这一点。
【问题讨论】:
-
ifDoesn'tDivide n k = n`mod`k/=0。一般来说,很少有任何理由明确提及True或False。 — 无论如何,所以... 你的问题是什么? -
它不起作用。如果 n>=2 则堆栈溢出。寻求有关如何解决它的建议。
-
如果
primes应该是一个无限列表,那么tail primes也是一个无限列表。将某些内容附加到无限列表是行不通的。 -
@n.'pronouns'm。但我们不知道它是否应该是无限的,Haskell 也不知道。 Haskell 实际上一无所知,除了我们告诉它的
primes = 2 : tail primes ++ expr,即head primes =: 2和tail primes =: tail primes。 -
@WillNess 我没有说 Haskell 知道什么。我说的是程序员的想法。程序员认为它应该是无限的吗?如果是这样,那么 ++ing 任何东西可能是个坏主意。
标签: haskell sequence primes idioms induction