Ix class

Matt Harden matth@mindspring.com
Tue, 15 May 2001 18:43:28 -0500


Hello,

I am working on an Ix instance for one of my types and finding it rather
restrictive.  For me it would be useful to have rangeSize be defined in
the Ix class (with a default definition of course), so that it can be
overridden.

Also, does anybody know why Ix derives from Ord?  It seems to me this is
an unnecessary limitation on the types that can be instances of Ix.  I
cannot think of a reason why the implementation of anything in the Ix or
Array modules would require that every Ix be an Ord (with a minor
exception -- see below).  If an implementation is using a comparison on
an Ix type, chances are it should be using inRange or comparing (index
bnds x) with (index bnds y) instead.

One change would have to be made in the Array module if Ord is removed
from Ix:
	instance  (Ix a, Eq b)  => Eq (Array a b)  where
	    a == a'             =  assocs a == assocs a'
	instance  (Ix a, Ord b) => Ord (Array a b)  where
	    a <=  a'            =  assocs a <=  assocs a'

would become:
	instance  (Ix a, Eq a, Eq b)   => Eq (Array a b)  where
	    a == a'             =  assocs a == assocs a'
	instance  (Ix a, Ord a, Ord b) => Ord (Array a b)  where
	    a <=  a'            =  assocs a <=  assocs a'

As I said, I think this is a very minor issue.

I believe that making these changes in the standard would not impact
existing programs in any way.  Could these changes be considered as a
possible "typo" to be fixed in the Library Report?


P.S. In case anybody's interested, here's why I want to override
rangeSize:

> newtype Honeycomb = Hx (Int,Int) deriving (Eq,Show,Ord)
> 
> indexError = error "Index out of range"
> 
> instance Ix Honeycomb where
>    range   (Hx b1, Hx b2) =
>       [Hx x | x <- range (b1,b2), isHexIx x]
>    inRange (Hx b1, Hx b2) (Hx x) =
>       inRange (b1,b2) x && isHexIx x
>    index   (Hx b1, Hx b2) (Hx x) =
>       let i = index (b1,b2) x in
>          if isHexIx x then i `div` 2 else indexError
> 
> isHexIx :: (Int,Int) -> Bool
> isHexIx (x,y) = x `mod` 2 == y `mod` 2

This implements a honeycomb or hexagonal tiling for a maze generating
program.  The honeycomb is superimposed on a grid such that only every
other square is "active", corresponding to a particular hexagon in the
honeycomb.  It's similar to a checkers game, where only the dark squares
are used.

I would like _any_ pair of Ints to be an acceptable boundary for the
honeycomb, not just the ones that represent valid indexes.  For example,
(Hx (0,0), Hx (15,12)) should be a valid set of bounds.  The current
definition of rangeSize makes this impossible, which is why I would like
to override it.  By the way, the Library Report does not explicitly say
that the bounds have to both be valid indexes, though it does imply this
with the sample definition of rangeSize.

Thanks,
Matt Harden