content: module Ix ( Ix(range, index, inRange), rangeSize ) where
  import Prelude
  
  class  (Ord a) => Ix a  where
      range               :: (a,a) -> [a]
      index               :: (a,a) -> a -> Int
      inRange             :: (a,a) -> a -> Bool
  
  rangeSize :: Ix a => (a,a) -> Int
  rangeSize b@(l,h) | null (range b) = 0
                    | otherwise      = index b h + 1 
  -- NB: replacing "null (range b)" by  "l > h" fails if
  -- the bounds are tuples.  For example,
  --  (2,1) > (1,2), 
  -- but 
  -- range ((2,1),(1,2)) = []
  
  
  instance  Ix Char  where
      range (m,n) = [m..n]
      index b@(c,c') ci
          | inRange b ci  =  fromEnum ci - fromEnum c
          | otherwise     =  error "Ix.index: Index out of range."
      inRange (c,c') i    =  c <= i && i <= c'
  
  instance  Ix Int  where
      range (m,n) = [m..n]
      index b@(m,n) i
          | inRange b i   =  i - m
          | otherwise     =  error "Ix.index: Index out of range."
      inRange (m,n) i     =  m <= i && i <= n
  
  
  instance  Ix Integer  where
      range (m,n) = [m..n]
      index b@(m,n) i
          | inRange b i   =  fromInteger (i - m)
          | otherwise     =  error "Ix.index: Index out of range."
      inRange (m,n) i     =  m <= i && i <= n
  
  
  --instance (Ix a,Ix b) => Ix (a, b) -- as derived, for all tuples
  --instance Ix Bool                  -- as derived
  --instance Ix Ordering              -- as derived
  --instance Ix ()                    -- as derived
  
  
  
  instance  (Ix a, Ix b)  => Ix (a,b) where
      range ((l,l'),(u,u'))
           = [(i,i') | i <- range (l,u), i' <- range (l',u')]
      index ((l,l'),(u,u')) (i,i')
           =  index (l,u) i * rangeSize (l',u') + index (l',u') i'
      inRange ((l,l'),(u,u')) (i,i')
           = inRange (l,u) i && inRange (l',u') i'
  