e1add07d6710c53ef1974aee559d10b705fb55fc
[packages/haskell2010.git] / Data / Ix.hs
1 {-# LANGUAGE CPP, PackageImports #-}
2 #if __GLASGOW_HASKELL__ >= 701
3 {-# LANGUAGE Safe #-}
4 #endif
5
6 module Data.Ix (
7 -- * The 'Ix' class
8 Ix
9 ( range -- :: (Ix a) => (a,a) -> [a]
10 , index -- :: (Ix a) => (a,a) -> a -> Int
11 , inRange -- :: (Ix a) => (a,a) -> a -> Bool
12 , rangeSize -- :: (Ix a) => (a,a) -> Int
13 )
14
15 -- * Deriving Instances of @Ix@
16
17 -- $derived
18 ) where
19 import "base" Data.Ix
20
21 {- $derived
22 It is possible to derive an instance of @Ix@ automatically, using
23 a @deriving@ clause on a @data@ declaration.
24 Such derived instance declarations for the class @Ix@ are only possible
25 for enumerations (i.e. datatypes having
26 only nullary constructors) and single-constructor datatypes,
27 whose constituent types are instances of @Ix@. A Haskell implementation
28 must provide @Ix@ instances for tuples up to at least size 15.
29
30 For an /enumeration/, the nullary constructors are assumed to be
31 numbered left-to-right with the indices being 0 to n-1 inclusive.
32 This is the same numbering defined by the @Enum@ class. For example,
33 given the datatype:
34
35 > data Colour = Red | Orange | Yellow | Green | Blue | Indigo | Violet
36
37 we would have:
38
39 > range (Yellow,Blue) == [Yellow,Green,Blue]
40 > index (Yellow,Blue) Green == 1
41 > inRange (Yellow,Blue) Red == False
42
43 For /single-constructor datatypes/, the derived instance declarations
44 are as shown for tuples:
45
46 > instance (Ix a, Ix b) => Ix (a,b) where
47 > range ((l,l'),(u,u'))
48 > = [(i,i') | i <- range (l,u), i' <- range (l',u')]
49 > index ((l,l'),(u,u')) (i,i')
50 > = index (l,u) i * rangeSize (l',u') + index (l',u') i'
51 > inRange ((l,l'),(u,u')) (i,i')
52 > = inRange (l,u) i && inRange (l',u') i'
53 >
54 > -- Instances for other tuples are obtained from this scheme:
55 > --
56 > -- instance (Ix a1, Ix a2, ... , Ix ak) => Ix (a1,a2,...,ak) where
57 > -- range ((l1,l2,...,lk),(u1,u2,...,uk)) =
58 > -- [(i1,i2,...,ik) | i1 <- range (l1,u1),
59 > -- i2 <- range (l2,u2),
60 > -- ...
61 > -- ik <- range (lk,uk)]
62 > --
63 > -- index ((l1,l2,...,lk),(u1,u2,...,uk)) (i1,i2,...,ik) =
64 > -- index (lk,uk) ik + rangeSize (lk,uk) * (
65 > -- index (lk-1,uk-1) ik-1 + rangeSize (lk-1,uk-1) * (
66 > -- ...
67 > -- index (l1,u1)))
68 > --
69 > -- inRange ((l1,l2,...lk),(u1,u2,...,uk)) (i1,i2,...,ik) =
70 > -- inRange (l1,u1) i1 && inRange (l2,u2) i2 &&
71 > -- ... && inRange (lk,uk) ik
72 -}