0

我有以下,創建「類型」

type Pos = (Int, Int) 

我要生成這種類型的隨機值有一些限制(這兩個必須是0-8)

我會的任意intance喜歡做類似

instance Arbitrary Pos where 
    arbitrary = do x <- choose(0,8) 
       y <- choose(0,8) 
       return (x,y) 

然後在我的測試中使用它有有效位置。

BC我走樣這是不行的(?)元組

我試圖

其他方法使用的影響在我的測試說

prop_my_prop (x,y) = abs x < 9 && abs y < 9 ==> ... 

,但我認爲這是相當醜陋理論上它可能耗盡快速檢測(超過1000次)。

這是一項任務,所以我只想要一些指示,看看或如何處理這個問題,我不允許更改Pos。

回答

2

唐斯圖爾特的回答描述了可以說最好的方式來做到這一點。但是,如果由於某種原因你不想使用NEWTYPE可以按如下方式使用自定義生成器:

positionsToTest :: Gen Pos 
positionsToTest = do x <- choose (0,8) 
        y <- choose (0,8) 
        return (x,y) 

prop_myTest = forAll positionsToTest (\ pos -> myProperty pos) 

Runnung快速檢查上prop_myTest應該做你想要什麼。

6

BC我走樣這是不行的(?)元組

是的,這是正確的。定義一個新的數據類型,你可以有一個新的實例。

data Pos = Pos Int Int 

newtype Pos = Pos (Int, Int) 

然後,你可以寫出來與大家喜歡的任何發電機自己的任意實例。

+0

我不允許將類型Pos更改爲數據Pos – skyw00lker 2014-10-09 14:10:18

+1

然後您必須將您的生成器編寫爲函數而不是類型的方法。 – 2014-10-09 14:20:43

3

好吧,如果你不能改變Posdatanewtype不管什麼原因,你總是可以做到以下幾點:與Arbitrary實例一起定義的包裝

newtype PosA = PosA { unPosA :: Pos } deriving (Eq,Show) -- and whatever else you need! 

它:

instance Arbitrary PosA where 
    arbitrary = do x <- choose(0,8) 
       y <- choose(0,8) 
       return $ PosA (x,y) 

最後,重寫你想要檢查的所有命題,以便它們的類型不再提及Pos,而只是代替PosA。例如說你有一個功能mirror和鏡像兩次對身份屬性:

mirror :: Pos -> Pos 
mirror (x,y) = (y,x) 

prop_mirror :: Pos -> Bool 
prop_mirror pos = mirror (mirror pos) == pos 

然後,你需要做prop_mirror_A,像這樣

prop_mirror_A :: PosA -> Bool 
prop_mirror_A pos = prop_mirror (unPosA pos) 

(未經測試的代碼!)而你正在參加比賽。你也許可以做一些從prop_mirror由聰明類型類巫術工作「提升」到prop_mirror_A的,但我不打算現在想想:-)

(順便說一句,這是一個很好的理由鍵入同義詞通常不是正確的選擇!)