Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating a 2D grid in Haskell

Tags:

haskell

Learning haskell and want a function to generate a 2D grid similar to how you might in C:

int data[3][3]

what's an acceptable and elegant approach? Zip? Foldl?

I could declare one like:

x = [[0,0,0],
     [0,0,0],
     [0,0,0]]

But I would like a function with x y parameters. Struggling to understand the easiest way without for/while loops :(

like image 742
Dominic Bou-Samra Avatar asked Jun 05 '11 03:06

Dominic Bou-Samra


3 Answers

You seem to be asking "what should I use instead of Arrays in Haskell", right? You asked about using lists, which certainly aren't arrays and should be avoided for any serious work requiring non-sequential access (for example, lists give O(n) element access instead of O(1)).

The packages you should consider: array (old, standard Haskell arrays), vector (new, uses stream fusion, fast, an API that's actually reasonable, boxed or unboxed, but only one dimension unless you nest them), and repa (only works on newer GHC versions, but allows multi-dimensional arrays and parallel operations even on unboxed representations).

The easiest way to initialize any of these (I assume you mean "initialize" when you say "generate") is their respective "fromList" functions. For example:

import Data.Vector as V
...
    V.fromList $ map V.fromList [[01,02,03],[11,12,13],[22,22,23]]
like image 167
Thomas M. DuBuisson Avatar answered Oct 17 '22 11:10

Thomas M. DuBuisson


I'd use a list of lists (:: [[a]]), possibly with some new type to ensure that that all lists are of equal length.

To create a list containing n values, you can use replicate :: Int -> a -> [a], so to generate a list of lists, you'd just replicate the list again...

grid :: Int -> Int -> a -> [[a]]
grid x y = replicate y . replicate x

Here, the a parameter allows you to generate lists with any "zero" value of any type. This can be used like so:

> grid 3 3 0
[[0,0,0],[0,0,0],[0,0,0]]
> grid 2 3 False
[[False,False],[False,False],[False,False]]

EDIT: This coordinate system uses (y, x) I realize (I was thinking in (row, column)). You can just swap the x and y in grid to get the "usual" system.

like image 43
vicvicvic Avatar answered Oct 17 '22 12:10

vicvicvic


If you want to have something not too complicated with fast reads and reasonable fast "updates", you should consider using a Map (import Data.Map) with (x,y) pairs as keys. Add helper functions for range checks and for returning default values for missing entries, and you have a good replacement (as long as the matrix isn't huge)

like image 3
Landei Avatar answered Oct 17 '22 12:10

Landei