2010-12-01 45 views
0

我不明白問題是什麼。 'a'不是一個bool,不應該是一個bool。那麼爲什麼布爾有望?Haskell錯誤:無法匹配預期的類型`Bool'與推斷的類型`IO b'

代碼:

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

你需要小心你的函數調用語法。你可以使用`f(x,y)`幾次,但是這在Haskell中幾乎是不對的 - 它將函數應用於單個元組;你想`f x y`。 – 2010-12-01 14:25:32

+3

(實際上,更確切地說,你*希望它爲'randomRIO`而不是'defComp`) – 2010-12-01 14:59:40

+1

這裏的邏輯沒有一個基本的問題嗎?如果'&'-ing`可能是't`一直到`t = 0`和`probablyPrime n 0`爲`False`,那麼你總是會得到`False`。 – 2010-12-01 15:34:16

回答

3

類型probablyPrime應該是IO布爾,所以你的第一個模式匹配應該使用恢復功能提升的假純值進入IO單子,基本不變:

probablyPrime n 0 = False 

probablyPrime n 0 = return False 

你不能在不使用不安全函數的情況下避免IO monad,但除非你確切地知道你在做什麼,否則你不應該這樣做。

5
probablyPrime n 0 = False 

這告訴哈斯克爾說的probablyPrime返回類型是Bool。然而,在第二種情況下,您正在處理monads並返回IO Bool,因此類型不匹配。

更改Falsereturn 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)) 

安德魯·賈菲指出。

0

這是爲了避免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,直到它絕對必要。

相關問題