【问题标题】:Ambiguous type variable error related to n ** 0.5与 n ** 0.5 相关的模糊类型变量错误
【发布时间】:2023-03-31 19:08:01
【问题描述】:

最终编辑:

我的最终功能是:

isPrime n = n > 1 && n < 4
    || n `mod` 2 /= 0
    && n `mod` 3 /= 0
    && length [x | x <- [5, 11..round (sqrt (fromIntegral n))], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0

问题是我试图将n 视为sqrt n 中的Floatingn mod x 中的Integral。所以我不得不做fromIntegral n 强制 n 被视为Integral 而不是Floating

另外我只是搞砸了我的一些代码。


所以我有两个功能:

primes = filterPrime [2..]
    where filterPrime (p:xs) = p : filterPrime [x | x <- xs, x `mod` p /= 0]

以上直接来自 haskell.org,例如 take 5 primes 的结果为 [2,3,5,7,11]

我的函数isPrime如下:

isPrime n = isPrime n = n > 1 && n < 4
    || (n `mod` 2 == 0 || n `mod` 3 == 0)
    && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0

但是,当我打电话给isPrime 时,我得到了错误:

EulerMath.hs:6:33: error:
    * No instance for (RealFrac Int) arising from a use of `round'
    * In the expression: round (n ** 0.5)
      In the expression: [5, 11 .. round (n ** 0.5)]
      In a stmt of a list comprehension: x <- [5, 11 .. round (n ** 0.5)]
  |
6 |     && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
  |                                 ^^^^^^^^^^^^^^^^

EulerMath.hs:6:40: error:
    * No instance for (Floating Int) arising from a use of `**'
    * In the first argument of `round', namely `(n ** 0.5)'
      In the expression: round (n ** 0.5)
      In the expression: [5, 11 .. round (n ** 0.5)]
  |
6 |     && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
  |                                        ^^^^^^^^

EulerMath.hs:6:45: error:
    * No instance for (Fractional Int) arising from the literal `0.5'
    * In the second argument of `(**)', namely `0.5'
      In the first argument of `round', namely `(n ** 0.5)'
      In the expression: round (n ** 0.5)
  |
6 |     && length [x | x <- [5, 11..round (n ** 0.5)], n `mod` x == 0 || n `mod` (x + 2) == 0] == 0
  |                                             ^^^

我不知道如何正确注释isPrime 函数(阅读:我根本不知道如何正确注释)所以我没有收到此错误

【问题讨论】:

  • 要注释你添加一行:isPrime :: Int -&gt; Bool.
  • 有纯粹的整数算法来求整数平方根的底。例如,请参阅here。所以你可以完全避免处理浮点数。

标签: haskell


【解决方案1】:

问题是,n ** 0.5(或者干脆写成sqrt n)要求nFloating

(**) :: Floating a => a -> a -> a
sqrt :: Floating a => a -> a

但是mod 要求nIntegral

mod :: Integral a => a -> a -> a

Haskell 是一种没有隐式类型转换的语言,因此您不能只将Int 传递给sqrt。你可以在 GHCi 中尝试一下:

x = 4 :: Int
sqrt x -- error

要解决该冲突,您可以使用fromIntegral :: (Integral a, Num b) =&gt; a -&gt; b 这样的函数,它允许您将任何Integral 类型转换为任何Num 类型,并且所有Floating 类型都是Num,因此您将能够在sqrt 中使用n

isPrime n = length [x | x <- take (round (sqrt (fromIntegral n))) primes, n `mod` x == 0] == 0

另外,我们可以用$应用操作符简化一下,省略一些()null函数来检查列表是否为空:

isPrime n = null [x | x <- take (round $ sqrt $ fromIntegral n) primes, n `mod` x == 0]

在那里试试:https://repl.it/@Yuri12358/so-primes

【讨论】:

  • 感谢您和 n,我刚刚编辑为 round (sqrt (fromIntegral n))。 '代词' m.它工作得很好。非常感谢
【解决方案2】:

我们来看看tge涉及的运算符的类型。

(**) :: Floating a => a -> a -> a
mod :: Integral a => a -> a -> a

您将两个运算符应用于同一个变量n。然而,没有一种类型可以同时满足这两个约束,即使在哪里,Haskell 也不知道如何选择一个。

有几种方法可以解决这个问题。一种是说fromIntegral n ** 0.5(或者,也许更好,使用sqrt)。另一个可以找到here

最后但并非最不重要的一点是,您可能需要注意,从素数列表中获取 √n 个元素并不是很有意义。您需要小于 √n 的素数。查看takeWhile 函数。

【讨论】:

  • 是的,我不知道我为什么要做素数。我将我的素数函数与the 6k + 1 test 的函数混合在一起。那只是一个oopsie doopsie。我编辑了代码以使用sqrt n,我编辑了代码以使用round (sqrt n),但两者仍然导致Floating Int的错误。
  • 不能取整数的平方根。你看过fromIntegral吗?
  • 感谢您和 Yuri,我刚刚编辑为 round (sqrt (fromIntegral n)),它运行良好。非常感谢
猜你喜欢
  • 2012-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
  • 2013-12-13
相关资源
最近更新 更多