开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜