Haskell素数函数不起作用

Haskell素数函数不起作用,haskell,syntax,primes,Haskell,Syntax,Primes,在过去的几天里,我开始学习Haskell,这段代码我遇到了麻烦。我正在尝试创建一个函数,该函数将生成一个素数列表,给定初始列表(至少包含2个)、最大列表长度、当前除数的索引(应该从1开始,通过将当前数除以到目前为止的所有素数进行测试)和要测试的当前数(奇数) 我知道它不是很优雅或高效,但这段代码不会编译或运行,所以我想在优化之前先修复它。尽管这方面的建议也很酷 primes = [2,3,5,7,11,13] genPrimes primes max curDiv curTest | l

在过去的几天里,我开始学习Haskell,这段代码我遇到了麻烦。我正在尝试创建一个函数,该函数将生成一个素数列表,给定初始列表(至少包含2个)、最大列表长度、当前除数的索引(应该从1开始,通过将当前数除以到目前为止的所有素数进行测试)和要测试的当前数(奇数)

我知道它不是很优雅或高效,但这段代码不会编译或运行,所以我想在优化之前先修复它。尽管这方面的建议也很酷

primes = [2,3,5,7,11,13]

genPrimes primes max curDiv curTest 
  | length primes >= max = primes
  | primes !! curDiv > floor . sqrt curTest = genPrimes (primes ++ [curTest]) max 1 (curTest + 2)
  | curTest `mod` primes !! curDiv == 0 = genPrimes primes max 1 (curTest + 2) 
  | curTest `mod` primes !! curDiv /= 0 = genPrimes primes max (curDiv + 1) curTest
当我试图编译上述代码时,出现以下错误:

无法将预期类型'a0->c0'与实际类型'Integer'匹配
预期类型:[a0->c0]
实际类型:[整数]
在'genPrimes'的第一个参数中,即'primes'
表达式中:genPrimes primes 50 1 15

您已经反转了“:”的参数:标量向左,或者您可以创建一个单例列表并连接:

| primes !! curDiv > floor . sqrt curTest = genPrimes (primes++[curTest]) max 1 curTest + 2

您已将“:”的参数反转:标量向左,或者您可以创建一个单例列表并连接:

| primes !! curDiv > floor . sqrt curTest = genPrimes (primes++[curTest]) max 1 curTest + 2

嗯。已经给出了正确的答案,但您的解决方案不太习惯。下面是生成无限素数列表的简单方法:

primes = 2 : filter isPrime [3,5..]

isPrime n = all ((/=0).(n `mod`)) $ takeWhile (\p -> p*p <= n) primes
primes=2:过滤器isPrime[3,5..]

iPrime n=all((/=0)。(n`mod`)$takeWhile(\p->p*pja)。已经给出了正确的答案,但您的解决方案不是很地道。以下是生成无限素数列表的简单方法:

primes = 2 : filter isPrime [3,5..]

isPrime n = all ((/=0).(n `mod`)) $ takeWhile (\p -> p*p <= n) primes
primes=2:过滤器isPrime[3,5..]

iPrime n=all((/=0)。(n`mod`)$takeWhile(\p->p*p至少您的代码应该是

primes = [2,3,5,7,11,13]

genPrimes primes max = go primes (length primes) 1 (last primes + 2)
 where
  go prs len d t 
   | len >= max               = prs
   | (prs !! d) > (floor . sqrt . fromIntegral) t
                              = go (prs++[t]) (len+1) 1 (t + 2)
   | t `rem` (prs !! d) == 0  = go  prs        len    1 (t + 2) 
   | t `rem` (prs !! d) /= 0  = go  prs        len  (d + 1)  t

test n = print $ genPrimes primes n
main = test 20
然后重新组织它(将为每个候选编号执行的测试抽象为
noDivs
函数):

然后将
noDivs
重写为

noDivs lim t = foldr (\p r -> p > lim || rem t p /= 0 && r) False
然后您注意到,
go
只是过滤通过
noDivs
测试的数字:

genPrimes primes max = take max (primes ++ filter theTest [t, t+2..])
 where
  t = last primes + 2
  theTest t = noDivs (floor . sqrt . fromIntegral $ t) t
但这还不起作用,因为测试需要将
素数
传递给
节点
,但我们正在构建这个
素数
列表(正如
获取最大值(素数++…)
),那么是否存在恶性循环?不,因为我们只测试数字的平方根:

genPrimes primes max = take max wholePrimes 
 where
  wholePrimes = primes ++ filter theTest [t, t+2..]
  t           = last primes + 2
  theTest t   = noDivs (floor . sqrt . fromIntegral $ t) t wholePrimes
但最后,
genPrimes
中没有什么特别之处,它只是对
take
的一个美化调用,而initial
primes
列表实际上可以缩小,因此我们得到(稍微更改
noDivs
的参数排列,使其界面更通用):

primes=2:3:filter(noDivs$tail primes)[5,7..]
noDivs factors t=--如果提供的因子列表太短,则返回True
设lim=(floor.sqrt.from整数$t)
在foldr(\p r->p>lim | | rem t p/=0&&r)真因子中

--all((/=0.rem t)$takeWhile(至少您的代码应该是

primes = [2,3,5,7,11,13]

genPrimes primes max = go primes (length primes) 1 (last primes + 2)
 where
  go prs len d t 
   | len >= max               = prs
   | (prs !! d) > (floor . sqrt . fromIntegral) t
                              = go (prs++[t]) (len+1) 1 (t + 2)
   | t `rem` (prs !! d) == 0  = go  prs        len    1 (t + 2) 
   | t `rem` (prs !! d) /= 0  = go  prs        len  (d + 1)  t

test n = print $ genPrimes primes n
main = test 20
然后重新组织它(将为每个候选编号执行的测试抽象为
noDivs
函数):

然后将
noDivs
重写为

noDivs lim t = foldr (\p r -> p > lim || rem t p /= 0 && r) False
然后您注意到,
go
只是过滤通过
noDivs
测试的数字:

genPrimes primes max = take max (primes ++ filter theTest [t, t+2..])
 where
  t = last primes + 2
  theTest t = noDivs (floor . sqrt . fromIntegral $ t) t
但这还不起作用,因为测试需要将
素数
传递给
节点
,但我们正在构建这个
素数
列表(正如
获取最大值(素数++…)
),那么是否存在恶性循环?不,因为我们只测试数字的平方根:

genPrimes primes max = take max wholePrimes 
 where
  wholePrimes = primes ++ filter theTest [t, t+2..]
  t           = last primes + 2
  theTest t   = noDivs (floor . sqrt . fromIntegral $ t) t wholePrimes
但最后,
genPrimes
中没有什么特别之处,它只是对
take
的一个美化调用,而initial
primes
列表实际上可以缩小,因此我们得到(稍微更改
noDivs
的参数排列,使其界面更通用):

primes=2:3:filter(noDivs$tail primes)[5,7..]
noDivs factors t=--如果提供的因子列表太短,则返回True
设lim=(floor.sqrt.from整数$t)
在foldr(\p r->p>lim | | rem t p/=0&&r)真因子中

--全部((/=0.rem t)$takeWhile(一般来说,除了给出错误的代码之外,发布准确的错误消息是一个好主意。这使我们更容易帮助您。除了给出错误的代码之外,发布准确的错误消息通常是一个好主意。这使我们更容易帮助您。好的,谢谢,我不知道。将其更改为concatenate列表,但现在我得到了一个运行时错误..编辑了我的原始帖子。好的,谢谢,我不知道。将其更改为连接列表,但现在我得到了一个运行时错误..编辑了我的原始帖子。是的,它更好,谢谢!!我正在寻找隐藏那些“帮助者”的方法带递归的变量——我已经有过好几次这样的问题了。是的,非常好,谢谢!!我正在寻找一种方法来隐藏那些“助手”带递归的变量——我曾多次遇到过这个问题。这是有道理的,尽管lambda表达式对我来说仍然有点可怕。但我不明白的是,为什么它比我的代码运行得快一些,因为它基本上做着相同的事情。我的理解正确吗(n
mod
)只是一个有一个输入的函数吗?如果不显式定义输入,如何才能做到这一点?最好从[.这是有道理的,尽管lambda表达式对我来说仍然有点吓人。但我不明白的是,为什么它比我的代码运行得快一些,因为它基本上在做同样的事情。我的理解正确吗(n
mod
)只是一个有一个输入的函数吗?如果不显式定义输入,你怎么能这样做呢?@最好从[]开始。