· haskell

Haskell: Print friendly representation of an Array

Quite frequently I play around with 2D arrays in Haskell but I’ve never quite worked out how to print them in a way that makes it easy to see the contents.

I’m using the array from the ‘Data.Array’ module because it seems to be easier to transform them into a new representation if I want to change a value in one of the cells.

The function to create one therefore looks like this:

import Data.Array

grid :: Int -> a -> Array(Int, Int) a
grid size value = array ((0,0),(size-1,size-1)) [((x,y),value) | x<-[0..size-1], y<-[0..size-1]]

Which we can use like this:

> grid 2 0
array ((0,0),(1,1)) [((0,0),0),((0,1),0),((1,0),0),((1,1),0)]

I wanted to get the output to read like this:

0 0
0 0

I initially tried to override the ‘Show’ implementation but wasn’t very successful in trying to do that - I’m not sure whether that’s actually possible but someone on the IRC channel suggested I should probably try and write my own function to print it out.

I ended up with the following:

printGrid :: Show a => Array (Int, Int) a -> IO [()]
printGrid grid = sequence $ map (putStrLn . textRepresentation) $ toSimpleArray grid

toSimpleArray :: Array (Int, Int) a -> [[a]]	
toSimpleArray grid = [[grid ! (x, y) | x<-[lowx..highx]] |  y<-[lowy..highy]] 
	where ((lowx, lowy), (highx, highy)) =  bounds grid

textRepresentation :: Show a => [a] -> String
textRepresentation row = foldl (\acc y -> acc ++ (show y) ++ " ") "" row

The toSimpleArray function converts the array back into a format which is easier to deal with. So for a simple array:

> toSimpleArray (grid 2 0)

We then map over the new array and apply textRepresentation over each row to get a text representation.

The textRepresentation function works like this:

> textRepresentation [1, 2, 3]
"1 2 3 "

After that we map putStrLn over the result which gives us a collection of IO monads.

Unfortunately that still doesn’t print the array out so we need sequence which I came across in the Learn You A Haskell tutorial:

sequence takes a list of I/O actions and returns an I/O actions that will perform those actions one after the other. The result contained in that I/O action will be a list of the results of all the I/O actions that were performed.

And eventually this is how we use printGrid:

> printGrid $ grid 2 0
0 0 
0 0 

There must be ways to simplify some of that code so if you can see any let me know in the comments!

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket