web-dev-qa-db-ja.com

クイックチェックのために単純なタイプの任意のインスタンスを生成する方法

私は単純な型の定義を持っています:

data Cell = Cell {
    x       :: Int,
    y       :: Int
  } deriving (Show)

クイックチェックプロパティへの入力としてCellを使用することはできません。おそらく、クイックチェックがセル値を生成する方法を知らないためです。

私の理解では、CellをArbitrary型クラスのインスタンスにする必要があります。

たとえば、セルをxとyのランダムな正の値で生成したい場合、どうすればよいですか?

37
liammclennan

データ型にArbitraryのインスタンスを作成するのは簡単です。 arbitrary関数を実装する必要があります。これはGen Cellを返すはずです。これを行う最も簡単な方法は、既存のArbitraryインスタンスを利用することです。また、Genはモナドであるため、do-表記を使用できます。

instance Arbitrary Cell where
   arbitrary = do
     Positive x <- arbitrary
     Positive y <- arbitrary
     return $ Cell x y

あるいは、ジェネレーターは、Control.Applicativeの演算子を使用してエレガントに記述できることがよくあります。

instance Arbitrary Cell where
   arbitrary = Cell <$> pos <*> pos
     where pos = getPositive <$> arbitrary  -- getPositive requires QC >= 2.5

ここでは、 Test.QuickCheck.ModifiersPositive修飾子も使用して、正の整数のみを生成するようにしました。

より複雑なジェネレーターを作成するには、 Test.QuickCheck.Gen のさまざまなジェネレーターを参照してください。

49
hammar

TemplateHaskellと derive packageを使用して、同じことを行うArbitraryインスタンスを生成できます。

import Data.DeriveTH

derive makeArbitrary ''Cell
18
Koterpillar