Ix.hs

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'

Plain-text version of Ix.hs | Valid HTML?