Подтвердить что ты не робот

Как генерировать произвольные экземпляры простого типа для быстрой проверки

У меня есть простое определение типа:

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

Я не могу использовать Cell как вход для свойства quickcheck, предположительно потому, что quickcheck не знает, как генерировать значения Cell.

Я понимаю, что мне нужно сделать Cell экземпляром класса Arbitrary.

Как это сделать, например, если я хочу, чтобы ячейка генерировалась со случайными положительными значениями для x и y?

4b9b3361

Ответ 1

Запись экземпляра Arbitrary для вашего типа данных проста. Вам просто нужно реализовать функцию Arbitrary, которая должна вернуть Gen Cell. Самый простой способ сделать это - использовать существующие экземпляры Arbitrary, а также отметить, что Gen является монадой, поэтому мы можем использовать do -notation:

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

Здесь я также использовал модификатор Positive из Test.QuickCheck.Modifiers, чтобы гарантировать, что мы генерируем только целые положительные числа.

Для написания более сложных генераторов посмотрите на различные генераторы из Test.QuickCheck.Gen.

Ответ 2

Вы можете сгенерировать экземпляр Arbitrary, который делает то же самое, используя пакет TemplateHaskell и derive:

import Data.DeriveTH

derive makeArbitrary ''Cell