2012-04-27 28 views
0

我有一個從Network.HTTP獲取ResponseCode的函數。爲了使用QuickCheck測試它,我想寫一個用於ResponseCode的Arbitrary實例。 (如果您不知道,那麼ResponseCode只是該庫中三個整數:類型ResponseCode =(Int,Int,Int))。使用任意實例生成三元組(Network.HTTP.ResponseCode)

所以我寫了這樣的事情:

instance Arbitrary ResponseCode where 
    arbitrary = triple (elements [1..6]) 
     where triple f = (f, f, f) 

首先,GHC抱怨說我使用類型的方法是不是標準的Haskell,所以我將不得不使用一些編譯器標誌(這是不是真的我想要什麼,因爲我覺得必須有一個簡單的解決方案,這個簡單的問題沒有標誌)。

其次,我的任意函數有錯誤的類型,這很明顯。但後來我真的不知道如何編寫一個函數來返回一個從1到6的隨機Ints的三元組。

如果有人能幫助我,我將不勝感激。

謝謝。

回答

5

首先,有已經是這兩個實例:

instance Arbitrary Int 
instance (Arbitrary a, Arbitrary b, Arbitrary c) => 
     Arbitrary (a, b, c) 

這意味着(智力,INT,INT)已經是任意的一個實例。這意味着類型同義詞ResponseCode已經是一個實例。你不能定義和使用第二個實例。

你可以嘗試使用Test.QuickCheck.Gen.suchThat,但我推測它在這種情況下不能很好地工作。如果可以的話,我建議使用NEWTYPE包裝:

import Test.QuickCheck 
import Network.HTTP.Base 
import Control.Applicative 
import System.Random 

newtype Arb'ResponseCode = Arb'ResponseCode { arb'ResponseCode :: ResponseCode } 
    deriving (Show) 

instance Arbitrary Arb'ResponseCode where 
    arbitrary = do 
     responseCode <- (,,) <$> f <*> f <*> f 
     return (Arb'ResponseCode responseCode) 
    where f = elements [1..6] 

-- To use this you can call 
-- (fmap arb'ResponseCode arbitrary) 
-- instead of just (arbitrary) 

又或者使用內置的(智力,INT,INT)實例和後處理與(SUCC(mod 6)。)的三個要素。

+0

很好的答案。唯一我要補充的是,如果你要創建一個新類型,並且由於'ResponseCode'顯然只有六個可能的值,所以你可以定義類似'data ResponseCode = Success |部分|失敗| FileNotFound | NotAuthorized |我是一個小茶壺「或者其他一些東西。 – 2012-04-27 15:08:42