
On 12/19/2016 01:31 PM, mike h wrote:
There are (several hundred) sequential operations on a grid 50 x 6 - initially all zeroes ...
At this point my knowledge of Haskell is being pushed (which is good) but I have a feeling that my approach is not ‘correct’ once it gets beyond the parsing. Should each of the evalRect, evalRotRow and evalRotCol be called with a Screen (i.e. the grid at the root of this question)? Is the state monad a fit for this problem? Should I change my approach or is using vector the way forward?
This is just plain difficult to do functionally, don't be discouraged. Using mutable vectors is going to speed things up, but it isn't going to simplify anything conceptually. If I were you, I would start by making everything work slowly-but-safely on a tiny grid, accessing (and checking) everything by indices. First, write yourself a function that can modify one entry on the screen. Then, using that, a function that can modify one row. Then implement the matrix "transpose", and you get column operations for free: transpose, do the thing for rows, and then transpose back. Rather than evaluate the expressions at the same time you parse them, I would convert them to functions instead. So the instruction "rect 3x2" would get converted into a function that takes a Screen and outputs a Screen. If you do that for all of the instructions, then you can just compose everything. If "rect 3x2" gives you the function `f1` and "rect 5x7" gives you the function `f2`, then `f1 . f2` does one followed by the other. Your program will wind up being one long composition of functions that you can construct from the list of expressions. You can compose an entire list of functions with a fold: ghci> let times n x = n*x ghci> let fs = [ times n | n <- [1..10] ] ghci> foldr (.) id fs 1 -- 10 times 9 times 8 times... times 1 3628800 If you need it to be fast, then you can switch the list of lists to a mutable vector of mutable vectors. All you should have to change is the function that modifies one entry, since the rest will be implemented in terms of that. On the other hand, if it's already fast enough, it would be very sexy to use something like fixed-vector to ensure that the row/column lengths are statically checked =)