2017-05-23 13 views
2

私は機能関数をラップする型に任意のインスタンスを書き込む方法は?

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

をラップし、このタイプを持っている...と私はそののFunctor & Applicativeのインスタンスにquickcheckテストをやってみたいけど、コンパイラが、それは任意のインスタンスを持っていないと文句を言い。

私はそうしようとしましたが、私はランダム関数を生成することに固執しています。

ありがとうございます!

== UPDATE ==

quickcheckプロパティがこの

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 

のように定義されている...とテストは次のようになります。

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タイプの型クラス法をテストする必要がある場合は、TransactionArbitraryまたはCoArbitraryのインスタンスを持つことに意味がないようです(実際に必要な場合は、my answer to this questionが見つかります)。

あなたはこのような方法でプロパティを書くことができる法律をテストするには:あなたが望むよう

{-# 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 1に最後の行in f' d == f dを置き換えることができます。

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

私はこれを見ていますが、一般的な方法でFunctorのプロパティを定義したいと思います。上記の私のコードを参照してください。このようにして、私が書く各タイプのプロパティを書き直す必要はありません – vidi

+0

StateT質問へのリンクは良いです。ありがとう! – vidi

関連する問題