Ошибка Haskell: не удалось сопоставить ожидаемый тип `Bool 'с логическим типом` IO b' - PullRequest
0 голосов
/ 01 декабря 2010

Я не понимаю, в чем проблема.«а» не является bool и не должно быть bool.Так почему же ожидается bool?

Код:

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)

Ошибка:

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 definition of `probablyPrime':
    probablyPrime n t
                    = do { a <- randomRIO (3, n - 1 :: Integer);
                           let comp = ...;
                           let ret = ...;
                           .... }

Ответы [ 3 ]

5 голосов
/ 01 декабря 2010
probablyPrime n 0 = False

Это говорит haskell, что тип возвращаемого значения probablyPrime равен Bool. Однако во втором случае вы имеете дело с монадами и возвращаете IO Bool, поэтому типы не совпадают.

Измените False на return False, и оно будет работать.

Вам также придется изменить

let ret  = (not comp) && (probablyPrime n t-1)

до

prob <- probablyPrime n (t-1)
let ret = (not comp) && prob

или что-то вроде

ret <- liftM ((not comp) &&) (probablyPrime n (t-1))

как указал Эндрю Джаффе.

3 голосов
/ 01 декабря 2010

Типом вероятноPrime должен быть IO Bool, поэтому ваше первое сопоставление с образцом должно поднять чистое значение False в монаду IO с помощью функции возврата, в основном измените:

probablyPrime n 0 = False

до

probablyPrime n 0 = return False

Вы не можете покинуть монаду ввода-вывода без использования небезопасных функций, но вам не следует делать это, если вы точно не знаете, что делаете.

0 голосов
/ 03 декабря 2010

Рекомендуется избегать IO всякий раз, когда вы можете, и использование монады State предоставляет удобный способ сделать это здесь:

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

Чтобы проверить, является ли число (вероятно) простым, вы делаете следующее (обратите внимание, что я изменил порядок аргументов на probablyPrime, поскольку t с меньшей вероятностью будет отличаться от n):

evalState (probablyPrime 10 7057) <$> newStdGen :: IO Bool

Это позволяет вам не заходить в IO, пока это не станет абсолютно необходимым.

...