lundi 23 mars 2015

Minimal restrictions to generate Arbitrary in range

I would like to generate Arbitrary value for ordered tree-like structure whose type is, say



data Tree a = Leaf | Node (Tree a) a (Tree a)


A function that inserts value into this tree while keeping it ordered would require that value should be Ord. But to generate ordered Trees for Arbitrary instance I would need to generate value in range "[low,hi]" and Ord is insufficient for that. So I also required that value is Enum since Enum allows getting values from given boundary. The choose below also requires System.Random.Random:



import Test.QuickCheck.Arbitrary
import System.Random

generateTree :: (Arbitrary a, Ord a, Enum a, Random a) => a -> a -> Gen (Tree a)
generateTree l u = do
genLeaf <- arbitrary
if genLeaf
then return Leaf
else do
x <- choose (l, u)
left <- generateTree l (pred x)
right <- generateTree (succ x) u
return $ Node left x right


So to use this for arbitrary implementation I should require the same classes in Arbitrary class:



instance (Arbitrary a, Ord a, Enum a, Rand.Random a) => Arbitrary (Tree a) where
arbitrary = do
l <- arbitrary
u <- arbitrary
generateTree l u


Here, while requirement Ord a => Tree a is enough for data structure itself, I require (Arbitrary a, Ord a, Enum a, Rand.Random a) => Tree a for it's generator. It looks like leaking implementation details into declaration - probably I look at this wrong way, I am learning Haskell. But still there are questions:



  1. Is there a way to declare more generic generator that does not have as much requirements?

  2. Is there a way to declare other instance for Arbitrary (Tree a) along with one above that would have different set of requirements, something like Arbitrary (Tree Int) that would be used for Ints only?


Aucun commentaire:

Enregistrer un commentaire