I need to print out a matrix in haskell so it looks like this:
main> putStr (showMat [[1,-500,-4], [100,15043,6], [5,3,10]])
1 -500 -4
100 15043 6
5 3 10
So far I have come up with this:
type Matrix a = [[a]]
type IntMat = Matrix Integer
showMat :: IntMat -> String
showMat [] = ""
showMat ((y:ys):xs) = (printRow (rowmaxs) (elements) (y:ys)) ++ "\n" ++ showMat xs
where rowmaxs = rowMaxs ((y:ys):xs) ; elements = elementLengths (y:ys)
rowMaxs :: IntMat -> [Int]
rowMaxs [] = []
rowMaxs (x:xs) = [length (show (maximum (x)))] ++ (rowMaxs xs)
elementLengths :: [Integer] -> [Int]
elementLengths [] = []
elementLengths (y:ys) = [length (show y)] ++ (elementLengths ys)
printRow :: [Int] -> [Int] -> [Integer] -> String
printRow [] (a:as) (y:ys) = ""
printRow (z:zs) (a:as) [] = ""
printRow [] [] (y:ys) = ""
printRow [] [] [] = ""
printRow (z:zs) (a:as) (y:ys) = addSpaces (z-a) ++ show y ++ [' '] ++ printRow zs as ys
addSpaces :: Int -> String
addSpaces 0 = ""
addSpaces n = " " ++ addSpaces (n-1)
Which returns this:
Main> putStr (showMat [[1,23,1],[23,56,789],[1234,0,1]])
1 23 1
23 56
1234
I can see the loss of the elements at the end of rows is due to the cases in the printRow function, but I don’t know how to fix it. Also the characters don’t take into account the ones printed before them. Any help on how I can fix this would be appreciated.
In
showMatyou calculaterowmaxsandelementsanew for each row. In particular,rowmaxshas an element for each row left in the matrix, butprintRowuses it as meaning something for each column of the matrix.Edit: Here’s a slightly better version of
showMat:It’s still buggy —
rowMaxs(tries to) calculate the maximum length of the numbers in each row, but you really want the maximum length of the numbers in each column. One consequence of that is that you occasionally pass negative numbers toaddSpaces, which doesn’t cope terribly well, so here’s a version ofaddSpacesthat behaves more gracefully:So now we get this:
Better, but not yet working properly.
I have not fixed all the bugs in your code because I sense you are still learning and need the experience of finding them for yourself.
I advise using
map/zipWith/zipWith3instead of explicitly writing the recursion, as it makes code easier to understand.