Haskell素数函数不起作用
在过去的几天里,我开始学习Haskell,这段代码我遇到了麻烦。我正在尝试创建一个函数,该函数将生成一个素数列表,给定初始列表(至少包含2个)、最大列表长度、当前除数的索引(应该从1开始,通过将当前数除以到目前为止的所有素数进行测试)和要测试的当前数(奇数) 我知道它不是很优雅或高效,但这段代码不会编译或运行,所以我想在优化之前先修复它。尽管这方面的建议也很酷Haskell素数函数不起作用,haskell,syntax,primes,Haskell,Syntax,Primes,在过去的几天里,我开始学习Haskell,这段代码我遇到了麻烦。我正在尝试创建一个函数,该函数将生成一个素数列表,给定初始列表(至少包含2个)、最大列表长度、当前除数的索引(应该从1开始,通过将当前数除以到目前为止的所有素数进行测试)和要测试的当前数(奇数) 我知道它不是很优雅或高效,但这段代码不会编译或运行,所以我想在优化之前先修复它。尽管这方面的建议也很酷 primes = [2,3,5,7,11,13] genPrimes primes max curDiv curTest | l
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
的一个美化调用,而initialprimes
列表实际上可以缩小,因此我们得到(稍微更改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
的一个美化调用,而initialprimes
列表实际上可以缩小,因此我们得到(稍微更改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表达式对我来说仍然有点可怕。但我不明白的是,为什么它比我的代码运行得快一些,因为它基本上做着相同的事情。我的理解正确吗(nmod
)只是一个有一个输入的函数吗?如果不显式定义输入,如何才能做到这一点?最好从[.这是有道理的,尽管lambda表达式对我来说仍然有点吓人。但我不明白的是,为什么它比我的代码运行得快一些,因为它基本上在做同样的事情。我的理解正确吗(nmod
)只是一个有一个输入的函数吗?如果不显式定义输入,你怎么能这样做呢?@最好从[]开始。