2017-05-23 32 views
2

我有这种类型的包装功能如何为封装函数的类型编写任意实例?

newtype Transaction d e r = Transaction (d -> Either e (d,r)) 

...我想为它的函子&应用型实例做快速检查测试,但编译器抱怨说,它不具有任意实例。

我试图这样做,但我坚持生成随机函数。

谢谢!

的快速检查属性这样

type IdProperty f a = f a -> Bool 
functorIdProp :: (Functor f, Eq (f a)) => IdProperty f a 
functorIdProp x = (fmap id x) == id x 

type CompositionProperty f a b c = f a -> Fun a b -> Fun b c -> Bool 
functorCompProp :: (Functor f, Eq (f c)) => CompositionProperty f a b c 
functorCompProp x (apply -> f) (apply -> g) = (fmap (g . f) x) == (fmap g . fmap f $ x) 

instance (Arbitrary ((->) d (Either e (d, a)))) => Arbitrary (DbTr d e a) where 
    arbitrary = do 
     f <- ...??? 
     return $ Transaction f 

...和测试定义== == UPDATE看起来是这样的:

spec = do 
    describe "Functor properties for (Transaction Int String)" $ do 
    it "IdProperty (Transaction Int String) Int" $ do 
     property (functorIdProp :: IdProperty (Transaction Int String) Int) 

    it "CompositionProperty (Transaction Int String) Int String Float" $ do 
     property (functorCompProp :: CompositionProperty (Transaction Int String) Int String Float) 
+0

[?也许这将是有用的(https://mail.haskell.org/pipermail/haskell- cafe/2010-September/083735.html)但是,我想想你会从这些随机函数中获得什么。我会说,一些边缘案例是这需要的一切。 –

回答

3

您应该使用Test.QuickCheck.Function包装器测试功能。如果你只需要为你的Transaction类型(但如果你真的需要它,你可以找到my answer to this question)测试类型分类法则,那么ArbitraryCoArbitrary例子对于Transaction似乎没有意义。

要测试法,你可以在这样的方式写属性:

{-# LANGUAGE DeriveFunctor #-} 

import Test.QuickCheck 
import Test.QuickCheck.Function 

newtype Transaction d e r = Transaction (d -> Either e (d,r)) 
    deriving (Functor) 

-- fmap id ≡ id 
prop_transactionFunctorId :: Int 
          -> Fun Int (Either Bool (Int,String)) 
          -> Bool 
prop_transactionFunctorId d (Fun _ f) = let t    = Transaction f 
              Transaction f' = fmap id t 
             in f' d == f d 

那么,这可能看起来不漂亮,漂亮,只要你想。但是这是测试任意函数的好方法。例如,我们可以最后一行in f' d == f d更换到in f' d == f 1,看看它是如何失败的,如果它失败:

ghci> quickCheck prop_transactionFunctorId 
*** Failed! Falsifiable (after 2 tests and 4 shrinks):  
0 
{0->Left False, _->Right (0,"")} 
+0

我看到这个,但我想以通用的方式定义Functor属性。看到我上面的代码。这样我就不必重写我写的每种类型的属性 – vidi

+0

StateT问题的链接很好。谢谢! – vidi