module Data.Ix (
-- * The 'Ix' class
Ix
( range -- :: (Ix a) => (a,a) -> [a]
, index -- :: (Ix a) => (a,a) -> a -> Int
, inRange -- :: (Ix a) => (a,a) -> a -> Bool
, rangeSize -- :: (Ix a) => (a,a) -> Int
)
-- * Deriving Instances of @Ix@
-- $derived
) where
import "base" Data.Ix
{- $derived
It is possible to derive an instance of @Ix@ automatically, using
a @deriving@ clause on a @data@ declaration.
Such derived instance declarations for the class @Ix@ are only possible
for enumerations (i.e. datatypes having
only nullary constructors) and single-constructor datatypes,
whose constituent types are instances of @Ix@. A Haskell implementation
must provide @Ix@ instances for tuples up to at least size 15.
For an /enumeration/, the nullary constructors are assumed to be
numbered left-to-right with the indices being 0 to n-1 inclusive.
This is the same numbering defined by the @Enum@ class. For example,
given the datatype:
> data Colour = Red | Orange | Yellow | Green | Blue | Indigo | Violet
we would have:
> range (Yellow,Blue) == [Yellow,Green,Blue]
> index (Yellow,Blue) Green == 1
> inRange (Yellow,Blue) Red == False
For /single-constructor datatypes/, the derived instance declarations
are as shown for tuples:
> 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'
>
> -- Instances for other tuples are obtained from this scheme:
> --
> -- instance (Ix a1, Ix a2, ... , Ix ak) => Ix (a1,a2,...,ak) where
> -- range ((l1,l2,...,lk),(u1,u2,...,uk)) =
> -- [(i1,i2,...,ik) | i1 <- range (l1,u1),
> -- i2 <- range (l2,u2),
> -- ...
> -- ik <- range (lk,uk)]
> --
> -- index ((l1,l2,...,lk),(u1,u2,...,uk)) (i1,i2,...,ik) =
> -- index (lk,uk) ik + rangeSize (lk,uk) * (
> -- index (lk-1,uk-1) ik-1 + rangeSize (lk-1,uk-1) * (
> -- ...
> -- index (l1,u1)))
> --
> -- inRange ((l1,l2,...lk),(u1,u2,...,uk)) (i1,i2,...,ik) =
> -- inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
> -- ... && inRange (lk,uk) ik
-}