[Haskell-cafe] Ix, Random, and overlapping instances

Lambda The Insignificant lambda.the.insignificant at gmail.com
Sun Aug 20 17:20:26 EDT 2006

Greetings Haskellers,

I have recently found myself in a situation where I was needing to  
general tuples of randomized things; in my case, two coordinates and  
a custom data type, Direction.  As it is always better to generalize,  
I decided to try to write some code which would generalize randomR to  
any type which is Ix-able:

 > instance Ix i => Random i where
 >    random = error "No supported instance for random"
 >    randomR r g
 >        = let
 >          r' = range r
 >          (i, g') = randomR (0,length r'-1) g
 >          in
 >          (r' !! i, g')

This works splendidly; with my given example above, I could do:

 > data Dir = N | NE | E | SE | S | SW | W | NW deriving (Eq, Ord,  
Show, Ix)

     ghci> newStdGen >>= print . take 10 . randomRs ((1,1,N),(10,10,NW))

     [(5,4,S), (3,10,SE), (6,5,N), (6,6,NW), (10,8,SE), (3,10,W),  
(10,3,E), (1,6,NE), (10,10,SE), (3,3,S)]

As you can see, this results in random tuple(s) of these indexable  
types.  My implementation required -fallow-overlapping-instances and - 
fallow-undecidable-instances for the code to compile.

A few questions:

1) How does the compiler determine how to choose a particular  
instance for those cases where they overlap?  I noticed that if I  
tried to generate a random :: Int, I was getting the error message  
defined in the above instance, indicating that the compiler was  
choosing my implementation over the default for Int (obviously  
because Int is an instance of Ix).  Is there some way to exclude  
classes in the class qualifier, or to provide an instance as a  
default case without resorting to -fallow-overlapping-instances?

2) Is there a logical overlap between class Ix and class Bounded?  It  
seems that we could use the ranges of data types of Bounded to  
generate a reasonably sane `random` implementation for all Ix, if we  
can guarantee that all Ix instances are Bounded.  Would adding an  
additional class constraint be sufficient to catch the major cases?   
i.e., instance (HasBounds i, Ix i) => Random i where ...

3) Is there some reason that Ix is restricted to the Int datatype?   
Is there anything preventing us from moving to a genericIx,or  
something along those lines which support any integral type (say  
Integer), or is it merely for performance reasons that we use Int?   
Is the expectation that if you are using spaces larger than what an  
Int can accommodate, you should be using a different mechanism?

Thanks much for any comments you all can give.


Lambda the Insignificant

More information about the Haskell-Cafe mailing list