What is the type signature of this Haskell function?

I wrote a function to check if a number is prime or not:

prime n = prime' n 2 (floor (sqrt n)) where prime' ncu | n `mod` c == 0 = False | c > u = True | otherwise = prime' n (c+1) u 

I can not understand what a signature is like this function. At first I thought it should be like this:

 prime :: Integral a => a -> Bool 

But then I get compilation errors because sqrt expects Floating a and floor expect RealFrac a instead of Integral a . When I delete the type signature, it compiles, but the function does not work:

 *Euler> :t prime prime :: (Integral a, RealFrac a, Floating a) => a -> Bool *Euler> prime 5 <interactive>:1:0: Ambiguous type variable `t' in the constraints: `Floating t' arising from a use of `prime' at <interactive>:1:0-6 `RealFrac t' arising from a use of `prime' at <interactive>:1:0-6 `Integral t' arising from a use of `prime' at <interactive>:1:0-6 Probable fix: add a type signature that fixes these type variable(s) 

How can I make this function work?

+4
source share
4 answers

The problem is that you are using sqrt in n , which causes n be a floating point number; and you also use mod on n , which causes n to be an integer. Intuitively, looking at your code, n must be an integer, so you cannot directly call it sqrt . Instead, you can use something like fromIntegral to convert it from an integer to another number type.

 prime :: (Integral a) => a -> Bool prime n = prime' n 2 (floor (sqrt (fromIntegral n))) where prime' ncu | n `mod` c == 0 = False | c > u = True | otherwise = prime' n (c+1) u 
+12
source

Just move on to the last one, that the other answers are not covered ...

 *Euler> :t prime prime :: (Integral a, RealFrac a, Floating a) => a -> Bool 

The typechecker method states that prime can accept an argument of type a , while a is an instance of the Integral , RealFrac and Floating classes at once.

 *Euler> prime 5 <interactive>:1:0: Ambiguous type variable `t' in the constraints: `Floating t' arising from a use of `prime' at <interactive>:1:0-6 `RealFrac t' arising from a use of `prime' at <interactive>:1:0-6 `Integral t' arising from a use of `prime' at <interactive>:1:0-6 Probable fix: add a type signature that fixes these type variable(s) 

When you request its prime 5 , however, it complains that none of the 5 types by default can satisfy these conditions.

It is possible that you could write your own

 instance (Integral a, RealFrac b, Floating b) => Integral (Either ab) where ... instance (Integral a, RealFrac b, Floating b) => RealFrac (Either ab) where ... instance (Integral a, RealFrac b, Floating b) => Floating (Either ab) where ... 

(and you will also need to add Num , Ord , Real , Fractional , etc. instances), and then prime 5 will be acceptable, since there is 5 :: Either Integer Float that satisfies type conditions.

+3
source

Alternatively, you can change the upper bound test:

 prime n = prime' n 2 where prime' nc | n `mod` c == 0 = False | c * c > n = True | otherwise = prime' n (c+1) 

Btw, you do not need n as an argument to prime' , since it is constant in all calls.

+3
source

You can change (sqrt n) to (sqrt (fromInteger n)) to make the function work properly. This is necessary since the sqrt type is:

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

so this is wrong, for example:

 sqrt (2 :: Int) 
+2
source

All Articles