Reputation: 1366
I just started learning Hasekll a few days ago and was playing around with ranges when I ran into a cryptic error while trying a quick and dirty prime number checker.
isprime n = all ((<) 0) [n `rem` k | k <- [2..n-1]] -- okay
isprime' n = all ((<) 0) [n `rem` k | k <- [2..(ceiling . sqrt) n]] -- compiles but busted
Example:
Prelude> isprime 19
True
Prelude> isprime' 19
<interactive>:46:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘isprime'’
prevents the constraint ‘(Floating a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Floating Double -- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
• In the expression: isprime' 19
In an equation for ‘it’: it = isprime' 19
<interactive>:46:10: error:
• Ambiguous type variable ‘a0’ arising from the literal ‘19’
prevents the constraint ‘(Num a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Double -- Defined in ‘GHC.Float’
instance Num Float -- Defined in ‘GHC.Float’
...plus two others
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the first argument of ‘isprime'’, namely ‘19’
In the expression: isprime' 19
In an equation for ‘it’: it = isprime' 19
So I checked the following, and both turn out as expected.
Prelude> [rem 19 k | k <- [2.. 19-1]]
[1,1,3,4,1,5,3,1,9,8,7,6,5,4,3,2,1]
Prelude> [rem 19 k | k <- [2..(ceiling . sqrt) 19]]
[1,1,3,4]
Can anyone help me understand the issue? If there is a good section in the online Haskell tutorials, would appreciate a pointer. Thanks!
Upvotes: 0
Views: 206
Reputation: 116139
Use an explicit conversion, instead:
[2..(ceiling . sqrt . fromIntegral) n]
Otherwise, you are calling sqrt
on the type of n
, forcing that type to be a Floating
. The rest of the code already requires n
to have some Integral
type.
These two requirements can not be satisfied: standard numeric types are either floating point, or fixed point (Integral
, roughly).
It would also greatly help if you started to write your functions from their type annotations. This prevents GHC to infer a type which was not intended -- when that happens errors are detected much later on, causing confusion.
Upvotes: 1