# QuickCheck generator of (List, Index) where index within list range

19 Nov 2014

As of March 2020, School of Haskell has been switched to read-only mode.

### (List,Index) pair generator keeping the index within range

``````class Arbitrary a where

arbitrary :: Gen a

shrink :: a -> [a]
``````

QuickCheck Gen is a monad.

Here is the Arbitrary instance for lists, taken from the QuickCheck source

``````instance Arbitrary a => Arbitrary [a] where
arbitrary = sized \$ \n ->
do k <- choose (0,n)       -- list length
sequence [ arbitrary | _ <- [1..k] ] -- :: m [a]

shrink xs = shrinkList shrink xs
``````

Let's add an index generator within [0, length list) except for empty lists giving 0 as index.

``````
data ListWithIdx a = ListWithIdx [a] Int deriving (Eq, Show)

instance Arbitrary a => Arbitrary (ListWithIdx a) where

arbitrary = sized \$ \n -> do
k <- choose (0, n) -- list length
i <- if k == 0 then return 0 else choose (0, k-1)

list <- sequence [ arbitrary | _ <- [1..k] ]
-- wrap them in the new type
return \$ ListWithIdx list i``````

Adding a shrink function to the instance: shrink the list and lessen the index according to lengths difference

``````
shrink (ListWithIdx xs i) =

map wrap \$ shrinkList shrink xs
where
lenXs = length xs

wrap ys = assert (lenYs <= lenXs) \$

ListWithIdx ys \$ max 0 \$ i - (lenXs - lenYs)
where
lenYs = length ys``````

Test it:

``````import Data.List as L
import Test.QuickCheck.Gen
import Test.QuickCheck as Q
import Control.Exception (assert)

data ListWithIdx a = ListWithIdx [a] Int deriving (Eq, Show)

-- include Arbitrary instance for ListWithIdx here
-- with arbitrary and shrink methods

propIndexIsInRange :: [ListWithIdx Int] -> Bool
propIndexIsInRange xs = all test xs
where
test (ListWithIdx list idx) = if null list
then idx == 0
else idx >= 0 && idx < length list
main :: IO ()
main = quickCheckWith Q.stdArgs {Q.maxSuccess = 30, Q.maxSize = 22}
propIndexIsInRange
``````