array

Array は主に多次元配列の表現に利用します。

ArrayVector の使い分け

1 次元配列の場合は Vector を使うことが多いです (API がリッチため) 。 Array には添字アクセス以外の API がほぼありませんが、 accumArray がハマる場合は Array を使うこともあります。

2 次元配列の場合は Array を使うことが多いです:

  • 2 次元の可変配列は Array でしか表現できない気がします (?)
  • 2 次元の不変配列も Array の方が添字アクセスが綺麗になります:
    • arr ! (y, x)
    • vec VU.! (x + y * w)

class Ix

array の添字は Ix クラスで抽象されています。 Ix を知ることで Array の API が理解できるようになります。

IxIntChar などに対して実装されており、また n 次元に拡張されています。

Ix の使い方 (1 次元)

Ix を試してみます。まずは REPL を起動します:

$ ghci
Prelude> import Data.Ix
Prelude Data.Ix>

Ix クラスの index 関数は、添字範囲 \([x1, x2]\) に対する相対位置を返します:

Prelude Data.Ix> index (0, 4) 2
2
Prelude Data.Ix> index (2, 6) 2
0

Ix の使い方 (2 次元)

Ix は n 次元に拡張されており、 2 次元の添字も表現できます:

Prelude Data.Ix> index ((0, 0), (5, 5)) (0, 1)
1
Prelude Data.Ix> index ((0, 0), (5, 5)) (1, 0)
6
Prelude Data.Ix> index ((0, 0), (5, 5)) (5, 5)
36

注意すべきなのは、タプルの右端の値が 1 次元目を表すということです。 Row-major な行列の場合は、 Array 生成時のサイズは (h, w) であり、 Array への添字アクセスには (y, x) (すなわち (row, column) ) を使います。

Immutable array

accumArray で生成

accumArray は配列への畳み込みです。使い方はリンク先の通り:

Prelude> import Data.Array
Prelude Data.Array> accumArray (+) 0 (1, 3) [(1, -1), (2, 1), (2, 2), (3, 5)]
--                             ~~~ ~  ~~~~    ~~~~
--                             |   |  |       |
--                             |   |  |       +--- (添字 1, 添字 1 に対する入力 -1)
--                             |   |  +--- 添字範囲 = [1, 3]
--                             |   +--- 初期の蓄積値 = 0
--                             +--- (\蓄積値 入力 -> 新しい蓄積値)
array (1,3) [(1,-1),(2,3),(3,5)]

Mutable array

ST モナドを使った配列操作

TODO

IO モナドを使った配列操作

TODO

accumArray からの thaw (解凍)

TODO

注意点

タプルの array には boxed array を使わざるを得ない

TODO