1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
<title>The Haskell 1.3 Library Report: Indexing Operations</title>
<body bgcolor="#ffffff"> <i>The Haskell 1.4 Library Report</i><br> <a href="index.html">top</a> | <a href="numeric.html">back</a> | <a href="array.html">next</a> | <a href="libindex.html">contents</a> <br><hr>
<a name="sect5"></a>
<h2>5<tt> </tt>Indexing Operations</h2><p>
<table border=2 cellpadding=3>
<tr><td>
<tt><br>
module Ix ( Ix(range, index, inRange), rangeSize ) where<br>
<br>
class (Show a, Ord a) => Ix a where<br>
range :: (a,a) -> [a]<br>
index :: (a,a) -> a -> Int<br>
inRange :: (a,a) -> a -> Bool<br>
<br>
rangeSize :: (Ix a) => (a,a) -> Int<br>
<br>
instance Ix Char where ...<br>
instance Ix Int where ...<br>
instance Ix Integer where ...<br>
instance (Ix a, Ix b) => Ix (a,b) where ...<br>
-- et cetera<br>
instance Ix Bool where ...<br>
instance Ix Ordering where ...<br>
</tt></td></tr></table>
The <tt>Ix</tt> class is used to map a continuous subrange of values in a
type onto integers. It is used primarily for array indexing (see
Section <a href="array.html#arrays">6</a>).
The <tt>Ix</tt> class contains the methods <tt>range</tt>,
<tt>index</tt>, and <tt>inRange</tt>.
The <tt>index</tt> operation maps a bounding pair, which defines the lower
and upper bounds of the range, and a
subscript, to an integer. The <tt>range</tt> operation enumerates all
subscripts; the <tt>inRange</tt> operation tells whether a particular subscript
lies in the range defined by a bounding pair.<p>
An implementation is entitled to assume the following laws about these
operations:
<tt><br>
<br>
range (l,u) !! index (l,u) i == i -- when i is in range<br>
<br>
inRange (l,u) i == i `elem` range (l,u)<br>
<br>
<p>
</tt><a name="sect5.1"></a>
<h3>5.1<tt> </tt>Deriving Instances of <tt>Ix</tt></h3><p>
Derived instance declarations for the class <tt>Ix</tt> are only possible
for enumerations (i.e. datatypes having
only nullary constructors) and single-constructor datatypes,
including arbitrarily large tuples, whose constituent types are
instances of <tt>Ix</tt>.
<UL><LI>
For an <I>enumeration</I>, 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 <tt>Enum</tt> class. For example,
given the datatype:
<tt><br>
<br>
data Colour = Red | Orange | Yellow | Green | Blue | Indigo | Violet<br>
<br>
</tt>we would have:
<tt><br>
<br>
range (Yellow,Blue) == [Yellow,Green,Blue]<br>
index (Yellow,Blue) Green == 1<br>
inRange (Yellow,Blue) Red == False<br>
<br>
</tt><LI>
For <I>single-constructor datatypes</I>, the derived instance declarations
are as shown for tuples in
Figure <a href="ix.html#prelude-index">1</a>.
</UL><p>
<table border=2 cellpadding=3>
<tr><td>
<tt><br>
instance (Ix a, Ix b) => Ix (a,b) where<br>
range ((l,l'),(u,u'))<br>
= [(i,i') | i <- range (l,u), i' <- range (l',u')]<br>
index ((l,l'),(u,u')) (i,i')<br>
= index (l,u) i * rangeSize (l',u') + index (l',u') i'<br>
inRange ((l,l'),(u,u')) (i,i')<br>
= inRange (l,u) i && inRange (l',u') i'<br>
<br>
-- Instances for other tuples are obtained from this scheme:<br>
--<br>
-- instance (Ix a1, Ix a2, ... , Ix ak) => Ix (a1,a2,...,ak) where<br>
-- range ((l1,l2,...,lk),(u1,u2,...,uk)) =<br>
-- [(i1,i2,...,ik) | i1 <- range (l1,u1),<br>
-- i2 <- range (l2,u2),<br>
-- ...<br>
-- ik <- range (lk,uk)]<br>
--<br>
-- index ((l1,l2,...,lk),(u1,u2,...,uk)) (i1,i2,...,ik) =<br>
-- index (lk,uk) ik + rangeSize (lk,uk) * (<br>
-- index (lk-1,uk-1) ik-1 + rangeSize (lk-1,uk-1) * (<br>
-- ...<br>
-- index (l1,u1)))<br>
--<br>
-- inRange ((l1,l2,...lk),(u1,u2,...,uk)) (i1,i2,...,ik) =<br>
-- inRange (l1,u1) i1 && inRange (l2,u2) i2 &&<br>
-- ... && inRange (lk,uk) ik<br>
</tt><div align=center><h3>Derivation of Ix instances</h3></div><a name="prelude-index"></a>
</td></tr></table>
<p>
<a name="sect5.2"></a>
<h3>5.2<tt> </tt>Library <tt>Ix</tt></h3>
<tt><br>
module Ix ( Ix(range, index, inRange), rangeSize ) where<br>
<br>
class (Show a, Ord a) => Ix a where<br>
range :: (a,a) -> [a]<br>
index :: (a,a) -> a -> Int<br>
inRange :: (a,a) -> a -> Bool<br>
<br>
rangeSize :: Ix a => (a,a) -> Int<br>
rangeSize b@(l,h) | l > h = 0<br>
| otherwise = index b h + 1 <br>
<br>
<br>
instance Ix Char where<br>
range (c,c') = [c..c']<br>
index b@(c,c') ci<br>
| inRange b ci = fromEnum ci - fromEnum c<br>
| otherwise = error "Ix.index: Index out of range."<br>
inRange (c,c') ci = fromEnum c <= i && i <= fromEnum c'<br>
where i = fromEnum ci<br>
<br>
instance Ix Int where<br>
range (m,n) = [m..n]<br>
index b@(m,n) i<br>
| inRange b i = i - m<br>
| otherwise = error "Ix.index: Index out of range."<br>
inRange (m,n) i = m <= i && i <= n<br>
<br>
instance Ix Integer where<br>
range (m,n) = [m..n]<br>
index b@(m,n) i<br>
| inRange b i = fromInteger (i - m)<br>
| otherwise = error "Ix.index: Index out of range."<br>
inRange (m,n) i = m <= i && i <= n<br>
<br>
instance (Ix a,Ix b) => Ix (a, b) -- as derived, for all tuples<br>
instance Ix Bool -- as derived<br>
instance Ix Ordering -- as derived<br>
instance Ix () -- as derived<br>
<p>
<hr><i>The Haskell 1.4 Library Report</i><br><a href="index.html">top</a> | <a href="numeric.html">back</a> | <a href="array.html">next</a> | <a href="libindex.html">contents</a> <br><font size=2>April 4, 1997</font>
</tt>
|