Haskell"没有实例"错误

jas*_*son 4 haskell

我正在尝试编写一个函数来检查数字是否为素数.我写了这个:

primeCheck :: Int -> Int -> Bool
primeCheck n i 
    | n == 2 = True
    | i == 1 = True
    | n `mod` i == 0 = False
    | otherwise = primeCheck n (i -1)

isPrime :: Int -> Bool
isPrime n = primeCheck n (floor (sqrt n))
Run Code Online (Sandbox Code Playgroud)

我收到这些错误:

使用floor' Possible fix: add an instance declaration for (RealFrac Int) In the second argument ofprimeCheck'时没有(RealFrac Int)的实例,即isPrime (floor (sqrt n))' In the expression: primeCheck n (floor (sqrt n)) In an equation for':isPrime n = primeCheck n(floor(sqrt n))

No instance for (Floating Int)
  arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `floor', namely `(sqrt n)'
In the second argument of `primeCheck', namely `(floor (sqrt n))'
In the expression: primeCheck n (floor (sqrt n)) Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

当我将代码更改为此以希望解决问题时:

primeCheck :: Int -> Int -> Bool
primeCheck n i 
    | n == 2 = True
    | i == 1 = True
    | n `mod` i == 0 = False
    | otherwise = primeCheck n (i -1)

isPrime :: Int -> Bool
isPrime n = primeCheck n (floor (RealFrac (sqrt  (Floating n))))
Run Code Online (Sandbox Code Playgroud)

我明白了:

不在范围内:数据构造函数`RealFrac'

不在范围内:数据构造函数`Floating'

我怎样才能解决这个问题?

cro*_*eea 8

Floating类型类,而不是构造函数或函数.你似乎已经发现你需要转换类型n.正确的方法是使用fromIntegral:

isPrime n = primeCheck n $ floor $ sqrt $ (fromIntegral n :: Double)
Run Code Online (Sandbox Code Playgroud)

我们可以通过遵循函数的类型签名来了解其原因.

从类型签名isPrime,我们看到n有类型Int.

由于sqrt需要某种Floating类型(即作为类型类的实例的类型Floating),我们可以从Inta 转换为Doubleusing fromIntegral.请注意,签名fromIntegral

(Integral a, Num b) => a -> b
Run Code Online (Sandbox Code Playgroud)

Int是一个实例Integral(所以输入类型是可以的),并且Double是一个实例,Num所以输出类型是好的.

然后我们采取sqrt新的方式Double.

floor期望一个参数,其类型是一个实例RealFrac.Double恰好是两者的一个实例Floating RealFrac,所以它会做的工作(无需转换). floor将平方根转换回类型Int.

注意,由于输出型fromIntegral是多态的,因为是输入型sqrtfloor,我们必须指定转换为的类型Double,否则编译器将不知道哪个 Num/Floating/ RealFrac转换为实例.您可能会看到错误ambiguous type 'a' in ....

您可以使用Hoogle查看许多功能的类型签名

编辑

原来,为明确的类型签名fromIntegral不是必需的.从而

isPrime n = primeCheck n $ floor $ sqrt $ fromIntegral n
Run Code Online (Sandbox Code Playgroud)

就足够了.在我看来,提供明确的签名会更清楚,但在这种情况下并不是必需的.你可以在这里阅读更多相关信息.