简体   繁体   中英

Instance declaration in Haskell

I have these two functions:

primes = sieve [2..] 
    where
        sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]
isPrime number = number /= 1 && null [x | x <- takeWhile (\x -> x < (ceiling . sqrt) number) primes, mod number x == 0]

The thing is that when I'm trying to load module which contains those functions, I see following error message:

[2 of 2] Compiling Main             ( euler37.hs, interpreted )

euler37.hs:6:70:
No instance for (RealFrac Int)
  arising from a use of `ceiling'
Possible fix: add an instance declaration for (RealFrac Int)
In the first argument of `(.)', namely `ceiling'
In the expression: ceiling . sqrt
In the second argument of `(<)', namely `(ceiling . sqrt) number'

euler37.hs:6:80:
No instance for (Floating Int)
  arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the second argument of `(.)', namely `sqrt'
In the expression: ceiling . sqrt
In the second argument of `(<)', namely `(ceiling . sqrt) number'

I really can't understand what's the problem, because when I'm trying to make a small function from piece of code, which, as far as I understand, cause these errors, right in ghci, like let f number x = x < (ceiling . sqrt) number I don't see any error messages.

The problem is that primes is a list of Integers (due to your use of mod ), but sqrt operates on floating-point numbers. If you do x < (ceiling . sqrt . fromIntegral) number , then it'll work fine. fromIntegral just converts an integral number into any other numeric type:

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

In this case, since you don't specify any specific floating-point type to convert to, it'll default to using Double values to compute the square root. You could specify another type by changing fromIntegral to something like (fromIntegral :: Integer -> Float) .

The reason you don't see this error in GHCi is because your conditional is fine; it just works on different types to the ones you're using here. Just verifying that a piece of code is correct in isolation isn't enough; for it to pass the type checker, it has to make sense in context too.

You might want to consider using an integer square root algorithm for accuracy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM