Haskell - Prime Powers 练习 - 无限合并

发布于 2024-12-13 16:20:21 字数 1088 浏览 5 评论 0原文

在大学我的任务是:

定义以下函数:

primepowers :: 整数 -> [整数]

计算给定参数 n 的素数前 n 次幂的无限列表,按 asc 排序。 那是, primepowers n 按升序包含 的元素

{p^i | p 是质数,1≤i≤n}。

在完成这项任务后,我陷入了死胡同。我有以下四个功能:

merge :: Ord t => [t] -> [t] -> [t]
merge [] b = b
merge a [] = a
merge (a:ax) (b:bx)
  | a <= b    = a : merge ax (b:bx)
  | otherwise = b : merge (a:ax) bx

primes :: [Integer] 
primes = sieve [2..]
    where sieve [] = []
          sieve (p:xs) = p : sieve (filter (not . multipleOf p) xs)
            where multipleOf p x = x `mod` p == 0   

powers :: Integer -> Integer -> [Integer] 
powers n num = map (\a -> num ^ a) [1..n]

primepowers :: Integer -> [Integer]
primepowers n = foldr merge [] (map (powers n) primes)

我认为它们独立工作,因为我已经使用一些示例输入进行了测试。 merge 将两个有序列表合并为一个有序列表 primes 返回无限的素数列表 powers 计算 num 的 n 次方(即 num^1 、 num^2 ... num^n )

我尝试合并 primepowers 中的所有内容,但函数未进行评估,没有任何反应,分别存在某种无限循环。

我对素数或幂的优化不感兴趣。只是我不明白为什么这不起作用。或者我的方法不好,不实用,不是haskell?

At university my task is the following :

define the following function:

primepowers :: Integer -> [Integer]

that calculates the infinite list of the first n powers of the prime numbers for a given parameter n, sorted asc.
That is,
primepowers n contains in ascending order the elements of

{p^i | p is prime, 1≤i≤n}.

After working on this task I came to a dead end. I have the following four functions:

merge :: Ord t => [t] -> [t] -> [t]
merge [] b = b
merge a [] = a
merge (a:ax) (b:bx)
  | a <= b    = a : merge ax (b:bx)
  | otherwise = b : merge (a:ax) bx

primes :: [Integer] 
primes = sieve [2..]
    where sieve [] = []
          sieve (p:xs) = p : sieve (filter (not . multipleOf p) xs)
            where multipleOf p x = x `mod` p == 0   

powers :: Integer -> Integer -> [Integer] 
powers n num = map (\a -> num ^ a) [1..n]

primepowers :: Integer -> [Integer]
primepowers n = foldr merge [] (map (powers n) primes)

I think that they work independently, as I have tested with some sample inputs.
merge merges two ordered lists to one ordered list
primes returns infinite list of prime numbers
powers calculates n powers of num (that is num^1 , num^2 ... num^n)

I try to merge everything in primepowers, but functions are not evaluated nothing happens respectively theres some kind of infinite loop.

I am not interested in optimization of primes or powers. Just I don't understand why that does not work. Or is my approach not good, not functional, not haskell?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

小嗲 2024-12-20 16:20:21

我怀疑问题是:primes 是一个无限列表。因此,map (n) primes 是(有限)列表的无限列表。当您尝试foldr merge []它们全部在一起时,merge必须评估每个列表的头部...

由于列表的数量是无限的,所以这是一个无限环形。


我建议转换结构,例如:

primepowers n = foldr merge [] [map (^i) primes | i <- [1..n]]

I suspect the problem is: primes is an infinite list. Therefore, map (powers n) primes is an infinite list of (finite) lists. When you try to foldr merge [] them all together, merge must evaluate the head of each list...

Since there are an infinite number of lists, this is an infinite loop.


I would suggest transposing the structure, something like:

primepowers n = foldr merge [] [map (^i) primes | i <- [1..n]]
等待我真够勒 2024-12-20 16:20:21

虽然您可能无法将其用于您的作业,但可以使用 素数数据-ordlist来自 Hackage 的软件包。

import Data.List.Ordered
import Data.Numbers.Primes

primePowers n = mergeAll [[p^k | k <- [1..n]] | p <- primes]

请注意,mergeAll 能够合并无限数量的列表,因为它假定除了列表本身已排序之外,列表的头部也是有序的。因此,我们也可以轻松地使其适用于无限幂:

allPrimePowers = mergeAll [[p^k | k <- [1..]] | p <- primes]

While you can probably not use this for your assignment, this can be solved quite elegantly using the primes and data-ordlist packages from Hackage.

import Data.List.Ordered
import Data.Numbers.Primes

primePowers n = mergeAll [[p^k | k <- [1..n]] | p <- primes]

Note that mergeAll is able to merge an infinite number of lists because it assumes that the heads of the lists are ordered in addition to the lists themselves being ordered. Thus, we can easily make this work for infinite powers as well:

allPrimePowers = mergeAll [[p^k | k <- [1..]] | p <- primes]
心凉 2024-12-20 16:20:21

您的程序陷入无限循环的原因是您试图仅通过使用每个列表按升序排序的不变量来合并无限多个列表。在程序可以输出“2”之前,它必须知道没有一个列表包含小于 2 的任何值。这是不可能的,因为列表有无限多个。

The reason why your program runs into an infinite loop is that you are trying to merge infinitely many lists only by using the invariant that each list is sorted in the ascending order. Before the program can output “2,” it has to know that none of the lists contains anything smaller than 2. This is impossible because there are infinitely many lists.

微凉徒眸意 2024-12-20 16:20:21

您需要以下功能:

mergePrio (h : l) r = h : merge l r

You need the following function:

mergePrio (h : l) r = h : merge l r
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文