我不明白问题是什么。 'a'不是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 = ...;
.... }
答案 0 :(得分:5)
probablyPrime n 0 = False
这告诉haskell probablyPrime
的返回类型是Bool
。但是在第二种情况下,您正在处理monad并返回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))
正如Andrew Jaffe指出的那样。
答案 1 :(得分:3)
mightPrime的类型应该是IO Bool,所以你的第一个模式匹配应该使用return函数将纯值False提升到IO monad,基本上改变:
probablyPrime n 0 = False
到
probablyPrime n 0 = return False
你不能在不使用不安全功能的情况下使用IO monad,但除非你确切知道自己在做什么,否则不应这样做。
答案 2 :(得分:0)
最好尽可能避免使用IO
,并且使用State
monad提供了一种方便的方法:
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
1}}):
evalState (probablyPrime 10 7057) <$> newStdGen :: IO Bool
这使您可以避免踩到IO
,直到绝对必要。