haskell - una - ¿Cómo decirle a QuickCheck que genere solo índices de lista válidos para un parámetro?
sintaxis de una etiqueta (3)
Digamos que quiero escribir algunas pruebas unitarias para la función (!!)
.
my_prop xs n = ...
Quiero restringir n solo a índices válidos y sé que podría hacer algo como
my_prop xs n = (not.null) (drop n xs) ==> ...
Pero esto hace que la gran mayoría de los casos generados no sean válidos y se desechen. ¿Hay alguna manera de configurar las cosas para que QuickCheck genere primero la lista xs
y use su valor para generar solo casos válidos de n
?
Como lo sugirió Daniel Wagner, una posibilidad es crear mi propio tipo de datos y darle una instancia Arbitrary
.
data ListAndIndex a = ListAndIndex [a] Int deriving (Show)
instance Arbitrary a => Arbitrary (ListAndIndex a) where
arbitrary = do
(NonEmpty xs) <- arbitrary
n <- elements [0..(length xs - 1)]
return $ ListAndIndex xs n
NonEmpty
es de un tipo personalizado en Test.QuickCheck.Modifiers
para generar listas no vacías.
Puede crear un generador que solo cree índices válidos y escriba su propiedad como
import Test.QuickCheck
import Test.QuickCheck.Gen
import System.Random
indices :: [a] -> Gen Int
indices xs = MkGen $ /sg _ -> fst $ randomR (0, length xs - 1) sg
my_prop :: [Char] -> Property
my_prop xs = not (null xs) ==> forAll (indices xs) (/i -> xs !! i /= ''0'')
eliminando el argumento Int
.