2010-12-01 8 views
0

문제점을 이해할 수 없습니다. 'a'는 bool이 아니며 bool이되어서는 안됩니다. 그렇다면 부랑교는 왜 기대 되는가?하스켈 오류 : 예상 유형 '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)'를 여러 번 사용 합니다만, 하스켈에서는 거의 불가능합니다. 이것은 하나의 튜플에 함수를 적용합니다. 당신은'f x y'를 원한다. –

+3

(실제로, 더 정확하게 말하자면'randomRIO'를 원하지만'defComp'가 아닙니다.) –

+1

논리에 대한 기본적인 문제가 있습니까? 만약 당신이''아마도''프라임 n t'를't = 0'으로,'아마도 프라임 n 0'을'거짓'이라면,'False'가됩니다. –

답변

3

probablyPrime의 유형 첫 번째 패턴 일치가 리턴 기능을 사용하여 IO 모나드에 거짓의 순수한 가치를 해제해야하므로, IO BOOL해야한다 기본적으로 변경 :

probablyPrime n 0 = False 

probablyPrime n 0 = return False 

안전하지 않은 기능을 사용하지 않고 IO 모나드를 숨길 수는 없지만 수행중인 작업을 정확히 모르는 경우에는하지 말아야합니다.

+0

감사합니다. 내 코드가 IO 모나드를 벗어나지 않습니까, 아니면 그냥 시도하지 말아야한다는 의미입니까? –

+0

Andreas Sjöström @ 아니요.하지만 처음 패턴 일치로 시도한 것처럼 보입니다. haskell 런타임 및 OS는 main 함수를 사용하여 IO 작업을 실행합니다. IO 모나드를 강제로 탈출시킬 수있는 방법이 있지만, 그렇게 할 필요는 거의 없습니다. 이것은 보통 모나드 같은 다른 모나드의 경우는 아닙니다. –

5
probablyPrime n 0 = False 

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)) 

있다.

+1

'let ret = (not comp) && (maybePrime n t-1)'줄은'probablyPrime'에 대한'Bool' 리턴을 의미하므로, 표현식을 모나드로 들여 올 필요가 있습니다. –

+0

나는 RHS에서 그 모습을 말하고있다.'(&&)'는'Bool-> Bool-> Bool'이다. –

+0

@Andrew : 물론 아, 바. 나는 생각하지 않았거나 제대로 읽지 않았다. 예, 그게 해제해야합니다. – sepp2k

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 

는 테스트하려면 (tn보다 차이가 덜하기 때문에, 내가 probablyPrime에 인수의 순서를 변경했습니다 참고) : 이것은 당신이에 스테핑 피할 수

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

반드시 필요한 때까지.

관련 문제