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