packages feed

quickspec-0.9.6: examples/Arrays.hs

-- Arrays.

{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, DeriveDataTypeable #-}
import Test.QuickCheck
import Test.QuickSpec
import Data.Typeable
import Data.Array

put :: Ix i => i -> a -> Array i a -> Array i a
put ix v arr = arr // [(ix, v)]

arrays :: forall a. (Typeable a, Ord a, Arbitrary a) => a -> [Sig]
arrays a = [
  -- Don't include head, or functions on natural numbers---they
  -- generate too many irrelevant terms.
  prelude (undefined :: a) `without` ["head", "*", "0", "1"],
  lists (undefined :: Int) `without` ["head"],

  ["x", "y", "z"] `vars` (undefined :: a),
  ["a"]           `vars` (undefined :: Array Int a),
  -- Generate ranges using a custom generator to improve test data
  -- distribution.
  ["r"]           `gvars` genRange,

  "!"             `fun2` ((!)       :: Array Int a -> Int -> a),
  "put"           `fun3` (put       :: Int -> a -> Array Int a -> Array Int a),
  "listArray"     `fun2` (listArray :: (Int, Int) -> [a] -> Array Int a),
  "elems"         `fun1` (elems     :: Array Int a -> [a]),
  "indices"       `fun1` (indices   :: Array Int a -> [Int])]

instance Arbitrary a => Arbitrary (Array Int a) where
  arbitrary = do
    (low, high) <- genRange
    elems <- arbitrary :: Gen (Int -> Maybe a)
    return (array (low, high) [(i, x) | i <- [low..high], Just x <- [elems i]])

genRange :: Gen (Int, Int)
genRange = do
  low <- choose (-2, 2)
  high <- fmap (low +) (choose (-1, 2))
  return (low, high)

-- Use Two instead of A to improve the chance of getting the right test data.
main = quickSpec (arrays (undefined :: Two))