配列の練習にData.Array で数独のテーブルを表現してみます。
import Data.Array data Cell = Cell{digit::Int, mark::Char} deriving(Eq,Show) blockSize :: ((Int, Int), (Int, Int)) blockSize = ((1,1),(3,3)) type Block = Array (Int, Int) Cell -- 3 x 3 のセルを持つブロック block :: Block block = array blockSize $ zip (range blockSize) (repeat (Cell 0 '*')) {- Main> block -- > array ((1,1),(3,3)) [((1,1),Cell {digit = 0, mark = '*'}),((1,2),Cell {digit = 0, mark = '*'}),((1,3),Cell {digit = 0, mark = '*'}), ((2,1),Cell {digit = 0, mark = '*'}),((2,2),Cell {digit = 0, mark = '*'}),((2,3),Cell {digit = 0, mark = '*'}), ((3,1),Cell {digit = 0, mark = '*'}),((3,2),Cell {digit = 0, mark = '*'}),((3,3),Cell {digit = 0, mark = '*'})] -} type Sudoku = Array (Int, Int) (Array (Int, Int) Cell) -- 3 x 3 のブロックを持つ数独テーブル sudoku :: Array (Int, Int) (Array (Int, Int) Cell) sudoku = array blockSize $ zip (range blockSize) (repeat block) {- Main> sudoku -- > array ((1,1),(3,3)) [ ((1,1),array ((1,1),(3,3)) [((1,1),Cell {digit = 0, mark = '*'}),((1,2),Cell {digit = 0, mark = '*'}),((1,3),Cell {digit = 0, mark = '*'}), ((2,1),Cell {digit = 0, mark = '*'}),((2,2),Cell {digit = 0, mark = '*'}),((2,3),Cell {digit = 0, mark = '*'}), ((3,1),Cell {digit = 0, mark = '*'}),((3,2),Cell {digit = 0, mark = '*'}),((3,3),Cell {digit = 0, mark = '*'})]), ((1,2),array ((1,1),(3,3)) [((1,1),Cell {digit = 0, mark = '*'}),((1,2),Cell {digit = 0, mark = '*'}),((1,3),Cell {digit = 0, mark = '*'}), ((2,1),Cell {digit = 0, mark = '*'}),((2,2),Cell {digit = 0, mark = '*'}),((2,3),Cell {digit = 0, mark = '*'}), ((3,1),Cell {digit = 0, mark = '*'}),((3,2),Cell {digit = 0, mark = '*'}),((3,3),Cell {digit = 0, mark = '*'})]), ((1,3),array ((1,1),(3,3)) [((1,1),Cell {digit = 0, mark = '*'}),((1,2),Cell {digit = 0, mark = '*'}),((1,3),Cell {digit = 0, mark = '*'}), ((2,1),Cell {digit = 0, mark = '*'}),((2,2),Cell {digit = 0, mark = '*'}),((2,3),Cell {digit = 0, mark = '*'}), ((3,1),Cell {digit = 0, mark = '*'}),((3,2),Cell {digit = 0, mark = '*'}),((3,3),Cell {digit = 0, mark = '*'})]), ((2,1),array ((1,1),(3,3)) [略]), ((2,2),array ((1,1),(3,3)) [略]), ((2,3),array ((1,1),(3,3)) [略]), ((3,1),array ((1,1),(3,3)) [略]), ((3,2),array ((1,1),(3,3)) [略]), ((3,3),array ((1,1),(3,3)) [略])] -} -- ! で配列要素の取得です。 -- // で配列要素の書き換えですが、要素を書き換えるのではなく、 -- 新しい配列が作られます。 changeCell :: Sudoku -> (Int, Int) -> (Int, Int) -> Int -> Char -> Sudoku changeCell table pBlock pCell newNum newMark = table // [(pBlock,((sudoku ! pBlock) // [(pCell,Cell{digit = newNum, mark=newMark})]) )] {- -- 左上の隅を書き換えてみる。 Main> changeCell sudoku (1,1) (1,1) 999 'x' -- > array ((1,1),(3,3)) [((1,1),array ((1,1),(3,3)) [((1,1),Cell {digit = 999, mark = 'x'}) ・・・略・・・ ] -- 右下の隅を書き換えてみる。 Main> changeCell sudoku (3,3) (3,3) 999 'x' -- > array ((1,1),(3,3)) [ ・・・略・・・ ((3,3),array ((1,1),(3,3)) [ ・・・略・・・ ((3,3),Cell {digit = 999, mark = 'x'})])]