2010-12-01 37 views
0

Je ne comprends pas quel est le problème. 'a' n'est pas un booléen et ne devrait pas être un booléen. Alors, pourquoi Bool est-il attendu?Erreur Haskell: Impossible de faire correspondre le type attendu `Bool 'au type inféré` IO b'

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) 

Erreur:

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

Vous devez faire attention à la syntaxe de votre appel de fonction. Vous utilisez 'f (x, y)' plusieurs fois, mais cela n'a presque jamais raison dans Haskell - il applique la fonction à un seul tuple; vous voulez 'f x y'. –

+3

(en fait, pour être plus précis, vous * le * voulez pour 'randomRIO' mais pas 'defComp') –

+1

Y a-t-il un problème de base avec la logique ici? Si vous êtes '&&' -ing 'probablementPrime n t' tout le long de' t = 0' et 'probablementPrime n 0' est' False', alors vous aurez toujours 'False'. –

Répondre

3

Le type de probablyPrime devrait être IO Bool, de sorte que votre premier match de motif doit soulever la valeur pure de faux dans la monade IO en utilisant la fonction de retour , changer fondamentalement:

probablyPrime n 0 = False 

à

probablyPrime n 0 = return False 

Vous ne pouvez pas esacpe la monade IO sans utiliser de fonctions non sécurisées, mais vous ne devriez pas le faire à moins de savoir exactement ce que vous faites.

+0

Merci. Mon code échappe-t-il à la monade IO, ou voulez-vous dire que je ne devrais pas l'essayer? –

+0

Andreas Sjöström @ Non, mais on dirait que vous essayez avec le premier motif. le runtime et le système d'exploitation de Haskell exécuteront des actions d'E/S en utilisant la fonction principale. Il y a des façons de forcer une fuite de la monade IO mais vous devriez très rarement le faire si jamais. Ce n'est généralement pas le cas d'autres monades comme la monade d'état. –

5
probablyPrime n 0 = False 

Cela indique haskell que le type de retour est probablyPrimeBool. Cependant, dans le second cas, vous avez affaire à des monades et vous retournez IO Bool, donc les types ne correspondent pas.

Remplacez False par return False et cela fonctionnera.

Vous devrez aussi changer

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

à

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

ou quelque chose comme

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

comme Andrew Jaffe a souligné.

+1

Mais la ligne 'let ret = (pas comp) && (probablementPrime n t-1)' implique un retour 'Bool' pour' probablementPrime', donc cette expression doit aussi être levée dans la monade (non?). –

+0

Je parle de son apparence sur le RHS - '(&&)' est Bool-> Bool-> Bool'. –

+0

@Andrew: Ah, bah, bien sûr. Je n'ai pas pensé/lu correctement. Oui, cela doit être levé. – sepp2k

0

Il est une bonne idée d'éviter IO chaque fois que vous le pouvez, et en utilisant le State monade est un moyen pratique de le faire ici:

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 

Pour tester si un nombre est (probablement) prime que vous effectuez les opérations suivantes (note que j'ai changé l'ordre des arguments à probablyPrime, puisque t est moins susceptible de varier de n):

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

Cela vous permet d'éviter d'entrer dans IO jusqu'à ce que ce soit absolument nécessaire.