我自己的Haskell函数中存在类型错误

我自己的Haskell函数中存在类型错误,haskell,Haskell,我刚开始学习Haskell,在基本掌握了它的一些知识之后,我试着写一个简单的函数来测试一个数n的素性,这就是我想到的: isPrime n i= 如果n

我刚开始学习Haskell,在基本掌握了它的一些知识之后,我试着写一个简单的函数来测试一个数n的素性,这就是我想到的:

isPrime n i=
如果n<2
然后0
如果n==2 | | n==3,则为else
那么1
如果(n`mod`i)==0,则为else
然后0
否则,如果i==楼层(sqrt(n))
那么1
其他isPrime n(i+1)
该算法本身似乎是有效的(我用另一种语言测试了它),但是,当尝试调用任何数字时(即iPrime 5 2),我得到以下错误:

<interactive>:9:1:
Could not deduce (Floating a10) arising from a use of `isPrime'
from the context (Num a)
  bound by the inferred type of it :: Num a => a
  at <interactive>:9:1-11
The type variable `a10' is ambiguous
Note: there are several potential instances:
  instance Floating Double -- Defined in `GHC.Float'
  instance Floating Float -- Defined in `GHC.Float'
In the expression: isPrime 5 2
In an equation for `it': it = isPrime 5 2

<interactive>:9:9:
Could not deduce (Num a10) arising from the literal `5'
from the context (Num a)
  bound by the inferred type of it :: Num a => a
  at <interactive>:9:1-11
The type variable `a10' is ambiguous
Note: there are several potential instances:
  instance Integral a => Num (GHC.Real.Ratio a)
    -- Defined in `GHC.Real'
  instance Num Integer -- Defined in `GHC.Num'
  instance Num Double -- Defined in `GHC.Float'
  ...plus three others
In the first argument of `isPrime', namely `5'
In the expression: isPrime 5 2
In an equation for `it': it = isPrime 5 2
但这只会返回一个不同的错误,甚至无法编译

编辑:以下是此版本的错误:

Prime.hs:10:48:
No instance for (RealFrac Integer) arising from a use of `floor'
In the second argument of `(==)', namely `floor (sqrt (n))'
In the expression: i == floor (sqrt (n))
In the expression:
  if i == floor (sqrt (n)) then 1 else isPrime n (i + 1)

Prime.hs:10:54:
No instance for (Floating Integer) arising from a use of `sqrt'
In the first argument of `floor', namely `(sqrt (n))'
In the second argument of `(==)', namely `floor (sqrt (n))'
In the expression: i == floor (sqrt (n))
请帮助我,我应该如何更改代码以使其正常工作?提前感谢。

不平等

i < sqrt n
这导致了一种解决方案,我们只检查通过
sqrt n
的素数是否不除以
n

primes :: [Integer]
primes = filter isPrime [1..]

isPrime :: Integer -> Bool
isPrime n = if n < 2
                then False
                else if n == 2 || n == 3
                     then True
                     else all (\i -> n `mod` i /= 0) . takeWhile (\i -> i*i <= n) $ primes

main = print $ take 10 primes

您应该尝试在ONCE中查找
sqrt
。添加类型注释的错误通常更深刻,应该指向实际问题。您应该将它添加到您的帖子中。@chi我明白了,所以sqrt实际上需要一个浮点型变量。但是如果我写
isPrime::Double->Double->Double
,例如,
mod
函数停止工作,因为它需要整数类型的数字。@MrTsjolder哇,我不知道这个存在,它非常有用!谢谢,这实际上解决了问题,尽管我仍然不明白如何使用sqrtI修复代码。我刚刚看到您的编辑,使用
go
替换函数非常有用!另外,最初我是用
Bool
编写的,只是为了调试而对其进行了更改。虽然效率低下,但计算非整数表达式的方法是
from integral
I==(floor$sqrt$from integral n)
@PeterDam我想说的是,平方根运算通常比平方一个
整数要慢得多。。。但后来我在GHCi中进行了短暂的测试,实际上速度快了一点。。。甚至稍微使用
Int
。只需在这里留下一点不可忽略的无关注意事项,如
如果x那么True,否则..
,等等,都有点多余:)
i^2 < n
i*i < n
isPrime n i = 
    if n < 2
        then 0
        else if n == 2 || n == 3
             then 1
             else if    (n `mod` i) == 0
                  then 0
                  else if i*i < n
                       then isPrime n (i + 1)
                       else 1

main = print $ isPrime 13 2
isPrime :: Integral a => a -> Bool
isPrime n = go n 2
    where
        go n i =
            if n < 2
                then False
                else if n == 2 || n == 3
                     then True
                     else if    (n `mod` i) == 0
                          then False
                          else if i*i < n
                               then go n (i + 1)
                               else True

main = print $ filter isPrime [1..30]
primes :: [Integer]
primes = filter isPrime [1..]

isPrime :: Integer -> Bool
isPrime n = if n < 2
                then False
                else if n == 2 || n == 3
                     then True
                     else all (\i -> n `mod` i /= 0) . takeWhile (\i -> i*i <= n) $ primes

main = print $ take 10 primes
primes :: [Integer]
primes = filter isPrime [1..]

isPrime :: Integer -> Bool
isPrime n = if n < 2
                then False
                else if n == 2 || n == 3
                     then True
                     else all (\i -> n `mod` i /= 0) . takeWhile (<= root_n) $ primes
            where
                root_n = floor . sqrt . fromIntegral $ n

main = print $ take 10 primes