【问题标题】:haskell list of primes construction; ambiguos type variablehaskell 素数构造列表;歧义类型变量
【发布时间】:2023-04-02 10:05:02
【问题描述】:

我正在尝试创建函数primes,它是一个素数列表,但不知何故我失败了。编译器抛出一个我不知道如何解决的错误:

错误:

Ambiguous type variable 'a0'

代码:

candidates :: [Integer]
candidates = [2]++[3,5..]

primes :: [Integer]
primes = filter is_prime candidates

is_prime :: Integer -> Bool
is_prime candidate
    | candidate == 1 = False
    | candidate == 2 = True
    | candidate == 3 = True
    | otherwise = r_is_prime candidate 0

-- r as recursive
r_is_prime :: Integer -> Integer -> Bool
r_is_prime candidate order
    | n_th_prime >= max_compared_prime = True
    | candidate `mod` n_th_prime  == 0 = False
    | otherwise = if (r_is_prime candidate (order+1) ) then True else False
    where 
        n_th_prime = candidates !! fromIntegral(order)
        -- this is the line that throws an error...
        max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))

【问题讨论】:

  • primes = 2 : 3 : [n | n<-[5,7..], foldr (\p r-> p*p>n || (rem n p /= 0 && r)) True (tail primes)]

标签: haskell ambiguous


【解决方案1】:

max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))

你的fromIntegral 太多了。 sqrt 有类型

sqrt :: Floating a => a -> a

所以sqrt 的结果不是Integral 类型的成员。而ceiling 的结果是Integral 类型,所以最后一个fromIntegral 是多余的(但不会造成伤害)。

max_compared_prime = ceiling ( sqrt ( fromIntegral candidate))

这就是你所需要的。

但请注意,

n_th_prime = candidates !! fromIntegral(order)

意味着要针对n-th 候选素数进行测试,必须遍历候选列表,直到达到n-th 素数。因此,针对n-th 候选者的测试在这里是 O(n) 而不是 O(1) [好吧,假设数字是有界的],单个除法是。

更有效的试除法只尝试除法的素数,并记住当它进入下一个素数时它在素数列表中的位置。例如

is_prime :: Integer -> Bool
is_prime n
    | n < 2     = False
    | n < 4     = True
    | otherwise = trialDivision primes
      where
        r = floor (sqrt $ fromIntegral n)
        trialDivision (p:ps)
            | r < p     = True
            | otherwise = n `rem` p /= 0 && trialDivision ps

只需遍历素数列表以进行试除法,因此从一个素数到下一个素数是列表中的一个简单步骤。

【讨论】:

  • 如何测试 O(1) 中的第 n 个素数?
  • 通过记住你在素数列表中的位置。我将编辑一个更有效的is_prime 实现。
  • 我不知道问题出在哪里,但是您的 is_prime 版本没有返回任何答案...(尝试“primes !! 5”但它没有返回任何内容...。 )
  • 啊,因为 ceiling (sqrt 5) 是 3。现在修正了,floor 而不是 ceiling
  • 这很奇怪。它在这里工作。它究竟以哪种方式不适合您? - 除了,我之前不小心在我的答案中编辑了错误的“天花板”,哎呀。
【解决方案2】:

你的fromIntegrals 太多了

max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))

应用于sqrt 结果的fromIntegral 导致错误。如果我们查看类型签名,我们有:

fromIntegral :: (Num b, Integral a) => a -> b
sqrt :: Floating a => a -> a

所以要正确推断fromIntegral (sqrt x) 的类型,Haskell 需要找到同时具有FloatingIntegral 实例的类型(以便sqrt 的结果与fromIntegral 的参数匹配)。 Haskell 找不到这样的类型,因此(基本上)要求您指定一个(但没有一个)。解决方案是忽略这个fromIntegral:

max_compared_prime = fromIntegral ( ceiling ( sqrt ( fromIntegral candidate)))

其他说明

括号并不是特别惯用的 Haskell,因此该行可以/应该写成:

max_compared_prime = fromIntegral . ceiling . sqrt . fromIntegral $ candidate

另外ceiling的结果不需要转换,甚至可以是:

max_compared_prime = ceiling . sqrt . fromIntegral $ candidate

【讨论】:

    【解决方案3】:

    从 'sqrt' 之前删除 'fromIntegral',如:

    max_compared_prime = fromIntegral ( ceiling ( sqrt ( fromIntegral candidate)))
    

    类型有:

    sqrt :: Floating a => a -> a
    fromIntegral :: (Integral a, Num b) => a -> b
    

    sqrt 的输出是“浮动”,而不是积分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      • 1970-01-01
      相关资源
      最近更新 更多