The Haskell 98 Report
top | back | next | contents | function index
module Ix ( Ix(range, index, inRange, rangeSize) ) where class Ord a => Ix a where range :: (a,a) -> [a] index :: (a,a) -> a -> Int inRange :: (a,a) -> a -> Bool rangeSize :: (a,a) -> Int instance Ix Char where ... instance Ix Int where ... instance Ix Integer where ... instance (Ix a, Ix b) => Ix (a,b) where ... -- et cetera instance Ix Bool where ... instance Ix Ordering where ... |
Ix クラスはある型の値の連続した部分範囲を整数の上に写像する のに用いられる。このクラスは主に配列のインデックスとして用いられる (16 節を見よ)。Ix クラスは メソッド range、index および inRange を含む。index 演算は、範囲の下界と上界を定義する境界の組と 添字を整数に写像する。range 演算はすべての添字を列挙する。 inRange 演算はある特定の添字が境界の組で定義された範囲の中に 入っているかどうかを判定する。
実装はこれらの演算について以下のような法則を仮定して良いことになって
いる。
range (l,u) !! index (l,u) i == i -- when i is in range
inRange (l,u) i
== i `elem` range (l,u)
map index (range (l,u)) == [0..rangeSize (l,u)]
data 宣言上の deriving 節を利用すると、自動的に Ix インスタンスを導出することができる (4.3.3 節)。このように導出 された Ix クラスに対するインスタンス宣言は列挙型(すなわち、 無引数の構成子でのみ構成されているデータ型)、および、単一構成子の データ型(これにはその構成要素が Ix のインスタンスである ような任意の大きなタプルも含まれる)に対してのみ可能である。 Haskell の実装は少なくともサイズ 15 までのタプルについて、Ix インスタンスを提供しなければならない。
ある列挙型に対してその無引数構成子は左から右へ順に 0 から
n - 1 まで順に番号が振られているものと仮定する。これは、
Enum クラスで定義されている番号付けと同じである。
たとえば、以下のデータ型
data Colour = Red | Orange | Yellow | Green | Blue | Indigo | Violet
があるとすると、次のようになる。
range (Yellow,Blue) == [Yellow,Green,Blue]
index (Yellow,Blue) Green == 1
inRange (Yellow,Blue) Red == False
単一構成子データ型に対して、導出インスタンス宣言は図 15.1 のタプルで示したようになる。
module Ix ( Ix(range, index, inRange, rangeSize) ) where
class Ord a => Ix a where
range :: (a,a) -> [a]
index :: (a,a) -> a -> Int
inRange :: (a,a) -> a -> Bool
rangeSize :: (a,a) -> Int
rangeSize b@(l,h) | null (range b) = 0
| otherwise = index b h + 1
-- NB: replacing "null (range b)" by "not (l <= h)"
-- fails if the bounds are tuples. For example,
-- (1,2) <= (2,1)
-- but the range is nevertheless empty
-- range ((1,2),(2,1)) = []
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
The Haskell 98 Report
top | back | next | contents | function index
December 2002