I'm trying to make function primes
which is a list of prime numbers, but somehow I have failed. The compiler throws an error I don't know how to resolve:
Error:
Ambiguous type variable 'a0'
Code:
candidates :: [Integer]
candidates = [2]++[3,5..]
primes :: [Integer]
primes = filter is_prime candidates
is_prime :: Integer -> Bool
is_prime candidate
| candidate == 1 = False
| candidate == 2 = True
| candidate == 3 = True
| otherwise = r_is_prime candidate 0
-- r as recursive
r_is_prime :: Integer -> Integer -> Bool
r_is_prime candidate order
| n_th_prime >= max_compared_prime = True
| candidate `mod` n_th_prime == 0 = False
| otherwise = if (r_is_prime candidate (order+1) ) then True else False
where
n_th_prime = candidates !! fromIntegral(order)
-- this is the line that throws an error...
max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))
In
max_compared_prime = fromIntegral ( ceiling ( fromIntegral ( sqrt ( fromIntegral candidate))))
you have a fromIntegral
too much. sqrt
has type
sqrt :: Floating a => a -> a
so the result of sqrt
is not a member of an Integral
type. And the result of ceiling
is an Integral
type, so the last fromIntegral
is superfluous (but does not harm).
max_compared_prime = ceiling ( sqrt ( fromIntegral candidate))
is all you need in that line.
Note, however, that
n_th_prime = candidates !! fromIntegral(order)
means that to test against the n
-th candidate prime, the list of candidates has to be traversed until the n
-th prime has been reached. Thus testing against the n
-th candidate is O(n) here instead of O(1) [Well, assuming that numbers are bounded] which a single division is.
A more efficient trial division only tries primes for the division and remembers where in the list of primes it was when it goes on to the next prime. For example
is_prime :: Integer -> Bool
is_prime n
| n < 2 = False
| n < 4 = True
| otherwise = trialDivision primes
where
r = floor (sqrt $ fromIntegral n)
trialDivision (p:ps)
| r < p = True
| otherwise = n `rem` p /= 0 && trialDivision ps
Just traverses the list of primes in order to do the trial division, hence going from one prime to the next is a simple step in the list.