Haskell error: Couldn't match expected type `Bool' against inferred type `IO b'
I do not understand what the problem is. 'a' is not a bool and should not be a bool. So why is bool expected?
Code:
probablyPrime n 0 = False
probablyPrime n t =
do a <- randomRIO(3, n-1 :: Integer)
let comp = defComp(a,n)
let ret = (not comp) && (probablyPrime n t-1)
return ret
defComp a n = xcon1 && xcon2
where (s,m) = findsm n
x = a^m `mod` n
xcon1 = x /= 1 || x /= n-1
xcon2 = comploop x n s
comploop x n 0 = False
comploop x n s = x1 || (comploop x n (s-1))
where x1 = (x^2 `mod` n) == 1
findsm n = (s,m)
where m = findm n
s = n/m
findm n = m
where f = (logBase 2 n) - (truncate (logBase 2 n))
m' = 2^f
m = m_ify m'
m_ify m | m mod 1 == 0 = m
| otherwise = m_ify (m*2)
Error:
Couldn't match expected type `Bool' against inferred type `IO b'
In a stmt of a 'do' expression:
a <- randomRIO (3, n - 1 :: Integer)
In the expression:
do { a <- randomRIO (3, n - 1 :: Integer);
let comp = defComp ...;
let ret = (not comp) && (probablyPrime n t - 1);
return ret }
In the definit开发者_StackOverflowion of `probablyPrime':
probablyPrime n t
= do { a <- randomRIO (3, n - 1 :: Integer);
let comp = ...;
let ret = ...;
.... }
probablyPrime n 0 = False
This tells haskell that the return type of probablyPrime
is Bool
. However in the second case, you're dealing with monads and returning IO Bool
, so the types don't match.
Change False
to return False
and it will work.
You will also have to change
let ret = (not comp) && (probablyPrime n t-1)
to
prob <- probablyPrime n (t-1)
let ret = (not comp) && prob
or something like
ret <- liftM ((not comp) &&) (probablyPrime n (t-1))
as Andrew Jaffe pointed out.
The type of probablyPrime should be IO Bool, so your first pattern match should lift the pure value of False into the IO monad using return function, basically change:
probablyPrime n 0 = False
to
probablyPrime n 0 = return False
You cannot esacpe the IO monad without using unsafe functions but you should not do this unless you know exactly what you're doing.
It's a good idea to avoid IO
whenever you can, and using the State
monad provides a convenient way to do so here:
import Control.Applicative ((<$>))
import Control.Monad (liftM, replicateM)
import Control.Monad.State (State, evalState, get, put)
import System.Random
probablyPrime :: RandomGen g => Int -> Int -> State g Bool
probablyPrime t = liftM and . replicateM t . checkOnce
where
checkOnce :: RandomGen g => Int -> State g Bool
checkOnce n = do
(a, gen) <- randomR (3, n - 1) <$> get
put gen
return . not $ defComp a n
defComp = undefined
To test whether a number is (probably) prime you do the following (note that I've changed the order of the arguments to probablyPrime
, since t
is less likely to vary than n
):
evalState (probablyPrime 10 7057) <$> newStdGen :: IO Bool
This allows you to avoid stepping into IO
until it's absolutely necessary.
精彩评论