[Haskell-cafe] Ix, Random, and overlapping instances
Lambda The Insignificant
lambda.the.insignificant at gmail.com
Sun Aug 20 17:20:26 EDT 2006
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
> (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,
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