簡體   English   中英

Haskell錯誤:無法將預期的類型“布爾”與推斷的類型“ IO b”匹配

[英]Haskell error: Couldn't match expected type `Bool' against inferred type `IO b'

我不明白問題是什么。 “ a”不是布爾值,也不應該是布爾值。 那么為什么期望布爾值呢?

碼:

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 = ...;
                           .... }
probablyPrime n 0 = False

這告訴哈斯克爾說的返回類型probablyPrimeBool 但是,在第二種情況下,您要處理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)指出的那樣。

可能是Prime的類型應該是IO Bool,因此您的第一個模式匹配應該使用return函數將False的純值提升到IO monad中,基本上進行更改:

probablyPrime n 0 = False

probablyPrime n 0 = return False

在不使用不安全功能的情況下,您無法逃避IO monad,但是除非您確切知道自己在做什么,否則不應該這樣做。

盡可能避免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 ):

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

這使您可以避免在絕對必要之前進入IO

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM