I had an interesting Haskell problem the other week: work on columns and rows of a Data.Array i e.
You only have the Ix i, Ord e class constraints, which make sense because the index must be a Data.Ix. The elements also must be Ord to be able to process them.
The thing about Data.Ix is that it's very opaque. It only extends Ord. There is nothing matrix-related in it. One could use Data.Array for a lot of data structures!
But if you do know it's a matrix, although you have no explicit class constraint, there is a nice trick to use: two neighbouring cells will have a Data.Ix.rangeSize of 2!
So, the rows may be extracted by this little function:
byRows :: Ix i => [i] -> [[i]]
byRows indices = incGroupBy isNeighbour $ indices
where isNeighbour x y = 2 == rangeSize (x, y)
which is called like
process :: (Ix i, Ord e) => Array i e -> Something
process matrix =
let rows = byRows $ indices matrix
...
Note the unknown incGroupBy which is a groupBy that takes pairs incrementally.
That's it! I had a lot of ideas about using rangeSize to figure out the matrix dimensions, but pairing cells this way was really clean.
You only have the Ix i, Ord e class constraints, which make sense because the index must be a Data.Ix. The elements also must be Ord to be able to process them.
The thing about Data.Ix is that it's very opaque. It only extends Ord. There is nothing matrix-related in it. One could use Data.Array for a lot of data structures!
But if you do know it's a matrix, although you have no explicit class constraint, there is a nice trick to use: two neighbouring cells will have a Data.Ix.rangeSize of 2!
So, the rows may be extracted by this little function:
byRows :: Ix i => [i] -> [[i]]
byRows indices = incGroupBy isNeighbour $ indices
where isNeighbour x y = 2 == rangeSize (x, y)
which is called like
process :: (Ix i, Ord e) => Array i e -> Something
process matrix =
let rows = byRows $ indices matrix
...
Note the unknown incGroupBy which is a groupBy that takes pairs incrementally.
That's it! I had a lot of ideas about using rangeSize to figure out the matrix dimensions, but pairing cells this way was really clean.