2009-09-19 74 views
12

我有一個類型類Atomic,它定義了將某些類型轉換爲包裝器值(或從包裝器值轉換)的函數(Atom)。我想定義一個QuickCheck屬性,其中聲明:「對於所有的Atomic實例,可以安全地存儲和檢索任何值。」該物業是這樣的:針對多種類型測試QuickCheck屬性?

class Atomic a where 
    toAtom :: a -> Atom 
    fromAtom :: Atom -> Maybe a 

prop_AtomIdentity x = fromAtom (toAtom x) == Just x 

但是,如果我只是嘗試運行通過快速檢查該屬性,它只是挑選一個實例(Bool)和測試它。我目前周圍的工作定義爲在測試列表中的每個支持的原子類型類型簽名,但是這是冗長且容易出錯:

containerTests = 
    [ run (prop_AtomIdentity :: Bool -> Bool) 
    , run (prop_AtomIdentity :: Word8 -> Bool) 
    , run (prop_AtomIdentity :: String -> Bool) 
    {- etc -} ] 

我試圖定義一個函數,它會自動執行此操作:

forallAtoms :: (Atomic a, Show a) => (a -> Bool) -> [TestOptions -> IO TestResult] 
forallAtoms x = 
    [ run (x :: Bool -> Bool) 
    , run (x :: Word8 -> Bool) 
    , run (x :: String -> Bool) 
    {- etc -} ] 

containerTests = forallAtoms prop_AtomIdentity 

但它失敗,一個類型檢測錯誤:

Tests/Containers.hs:33:0: 
    Couldn't match expected type `Word8' against inferred type `String' 
    In the first argument of `run', namely `(x :: Word8 -> Bool)' 
    In the expression: run (x :: Word8 -> Bool) 
    In the expression: 
     [run (x :: Bool -> Bool), run (x :: Word8 -> Bool), 
     run (x :: String -> Bool)] 

有沒有更好的方法來測試對多種類型的一個QC財產?如果不是,是否可以使工作原理工作或者不受類型系統支持?

回答

12

我不能編譯你的代碼,所以...盲拍:

嘗試

forallAtoms :: (forall a. (Atomic a, Show a) => a -> Bool) -> [TestOptions -> IO TestResult] 

的類型簽名。這需要-XRankNTypes語言擴展。

你,因爲我看到的問題是,GHC試圖找到一個類型x :: (a -> Bool)來插入a整個功能範圍,但你已經給三個不同的存在。

+0

簡直不敢相信。謝謝! – 2009-09-19 18:58:05

相關問題