Haskell“No instance for”错误 [英] Haskell "No instance for" error

查看:331
本文介绍了Haskell“No instance for”错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试着写一个函数来检查一个数是否为素数。我写到:

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

isPrime :: Int - > Bool
isPrime n = primeCheck n(floor(sqrt n))

错误:


没有使用 floor'$ b引起的(RealFrac Int)
的实例$ b可能的修正:为(RealFrac Int)添加实例声明
primeCheck'的第二个参数中,即(floor(sqrt n))'
在表达式中:primeCheck n(floor(sqrt n))
在等式
isPrime'中:
isPrime n = primeCheck n(floor(sqrt n))

 由于使用`sqrt'而导致(浮点型)没有实例

可能的修正:添加(Floating Int)的实例声明
在`floor'的第一个参数中,即`(sqrt n)'
在`primeCheck'的第二个参数中,即`(floor(sqrt n)) '
在表达式中:primeCheck n(floor(sqrt n))失败,模块加载:无。


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

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

isPrime :: Int - > Bool
isPrime n = primeCheck n(floor(RealFrac(sqrt(Floating n))))



<
$ b


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



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

我该如何解决这个问题?

解决方案

浮动是一个 typeclass ,不是构造函数或函数。你似乎已经发现你需要转换 n 类型。正确的方法是使用 fromIntegral

  isPrime n = primeCheck n $ floor $ sqrt $(fromInteral n :: Double)

我们可以看到它的工作原理通过遵循函数的类型签名。

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

因为 sqrt 需要一些浮动类型(即a类型是类型类型的实例 Floating ),我们可以从 Int 转换为 Double 使用 fromIntegral 。请注意,来自整合的签名是

 (积分a,数字b )=> a  - > b 

Int Integral (所以输入类型可以)并且 Double 是 Num

然后我们用 sqrt 来获得一个新的 Double



floor 需要一个参数, RealFrac Double 碰巧是浮动 RealFrac的一个实例,所以它会完成这项工作(不需要转换)。
floor 会将平方根转换回类型 Int



请注意,由于来自整数的输出类型是多态的,因此输入类型 sqrt floor ,我们必须指定转换的类型为 Double ,否则编译器不会知道 Num / 浮动 / RealFrac 实例转换为。您可能会在... 中看到错误歧义类型'a'。



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



EDIT



事实证明,来自整数的的显式类型签名是 not 需要。因此

  isPrime n = primeCheck n $ floor $ sqrt $ fromInteral n 

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


I am trying to write a function that checks if a number is prime. I wrote this :

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))

And I get these errors :

No instance for (RealFrac Int) arising from a use of floor' Possible fix: add an instance declaration for (RealFrac Int) In the second argument ofprimeCheck', namely (floor (sqrt n))' In the expression: primeCheck n (floor (sqrt n)) In an equation forisPrime': 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.

When I change the code to this to hopefully fix the problem:

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))))

I get this :

Not in scope: data constructor `RealFrac'

Not in scope: data constructor `Floating'

How can I fix this?

解决方案

Floating is a typeclass, not a constructor or function. You do seem to have figured out that you need to convert the type of n. The correct way to do this would be using fromIntegral:

isPrime n = primeCheck n $ floor $ sqrt $ (fromIntegral n :: Double)

We can see why this works by following the type signatures of the functions.

From the type signature of isPrime, we see n has type Int.

Since sqrt expects some Floating type (i.e. a type that is an instance of the typeclass Floating), we can convert from an Int to a Double using fromIntegral. Note that the signature of fromIntegral is

(Integral a, Num b) => a -> b

Int is an instance of Integral (so the input type is okay) and Double is an instance of Num so the output type is okay.

Then we take the sqrt to get a new Double.

floor expects an argument whose type is an instance of RealFrac. Double happens to be an instance of both Floating and RealFrac, so it will do the job (no conversion necessary). floor will convert the square root back to type Int.

Note that since the output type of fromIntegral is polymorphic, as is the input type of sqrt and floor, we have to specify the type of the conversion as Double, otherwise the compiler won't know which Num/Floating/RealFrac instance to convert to. You might see the error ambiguous type 'a' in ....

You can see the type signatures of many functions using Hoogle

EDIT

It turns out the explicit type signature for the fromIntegral is not required. Thus

isPrime n = primeCheck n $ floor $ sqrt $ fromIntegral n

suffices. In my opinion, it would be clearer to just provide the explicit signature, but it is not necessary in this case. You can read more about it here.

这篇关于Haskell“No instance for”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆