2012-11-12 165 views
4

我試圖編寫一個素數生成器,並利用MillerRabin公式檢查數字是否爲素數,然後將數字返回給我。 這裏是我下面的代碼:無法與實際類型'Bool'匹配的預期類型'Bool'

primegen :: Int -> IO Integer 
primegen bits = 
    fix $ \again -> do 
     x <- fmap (.|. 1) $ randomRIO (2^(bits - 1), 2^bits - 1) 
     if primecheck x then return x else again 

primesTo100 = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] 

powerMod :: (Integral a, Integral b) => a -> a -> b -> a 
powerMod m _ 0 = 1 
powerMod m x n | n > 0 = join (flip f (n - 1)) x `rem` m where 
    f _ 0 y = y 
    f a d y = g a d where 
    g b i | even i = g (b*b `rem` m) (i `quot` 2) 
      | otherwise = f b (i-1) (b*y `rem` m) 

witns :: (Num a, Ord a, Random a) => Int -> a -> IO [a] 
witns x y = do 
    g <- newStdGen 
    let r = [9080191, 4759123141, 2152302898747, 3474749600383, 341550071728321] 
     fs = [[31,73],[2,7,61],[2,3,5,7,11],[2,3,5,7,11,13],[2,3,5,7,11,13,17]] 
    if y >= 341550071728321 
     then return $ take x $ randomRs (2,y-1) g 
     else return $ snd.head.dropWhile ((<= y).fst) $ zip r fs 

primecheck :: Integer -> IO Bool 
primecheck n | n `elem` primesTo100 = return True 
        | otherwise = do 
    let pn = pred n 
     e = uncurry (++) . second(take 1) . span even . iterate (`div` 2) $ pn 
     try = return . all (\a -> let c = map (powerMod n a) e in 
            pn `elem` c || last c == 1) 
    witns 100 n >>= try 

我不明白什麼用IO布爾回事。而且我發現了以下錯誤......

Couldn't match expected type `Bool' with actual type `IO Bool' 
In the return type of a call of `primecheck' 
In the expression: primecheck x 
In a stmt of a 'do' block: if primecheck x then return x else again 

如果我改變IO布爾只是一個正常的布爾,他們會給我:

Couldn't match expected type `Bool' with actual type `m0 a0' 

感謝您的幫助傢伙!我很感激。

+0

你可能會考慮在['MonadRandom']寫這篇(http://hackage.haskell.org/packages/archive/MonadRandom/0.1.8 /doc/html/Control-Monad-Random.html)而不是'IO'。 – leftaroundabout

回答

3

由於primecheck返回IO Bool,當您在primegen中調用它時,您需要對它進行排序,而不是像純函數那樣調用它。

primegen :: Int -> IO Integer 
primegen bits = 
    fix $ \again -> do 
     x <- fmap (.|. 1) $ randomRIO (2^(bits - 1), 2^bits - 1) 
     success <- primecheck x 
     if success then return x else again 
+0

謝謝!現在精美的作品。 – user805981

4
if primecheck x then return x else again 

是無效的,因爲primecheck x返回IO Bool類型的值。你想用序列做記號或東西的單子,如:

primecheck x >>= (\val -> if val then return x else again) 
+0

謝謝!現在工作! – user805981

相關問題