[Haskell-beginners] Matrix / Matrix Addition

Paul Monday paul.monday at parsci.com
Thu Dec 8 21:55:46 CET 2011


I'm working on simple matrix / matrix addition for a short project.  Doing this with lists (not worrying about matrix sizes and such) is relatively easy and makes quite a bit of sense to me:

basically:

madd :: Num a => [[a]] -> [[a]] -> [[a]]

I could read this as:
- with a as a Numeric type, take two lists of lists of Numerics  and return a list of lists of Numerics

And then to do the job simple
madd m n = zipWith (zipWith (+)) m n

And I can read that easily enough:
-- madd has two inputs, m and n and it will do the function "zipWith (+)" across its inputs of the inner lists from m and n (the rows, basically)

Ok, so
madd [[1,2,3], [4,5,6], [7,8,9]] [[10,11,12], [13,14,5], [16,17,18]]

yields [[11,13,15],[17,19,11],[23,25,27]]

Cool

I can get a little nicer (possibly) if I use a Matrix type:

data Matrix a = Matrix [[a]]
    deriving (Show, Eq)

madd :: Num a => [[a]] -> [[a]] -> [[a]]
madd m n = zipWith (zipWith (+)) m n

madd2 :: (Num a) => Matrix a -> Matrix a -> Matrix a
madd2 (Matrix m) (Matrix n) = Matrix $ zipWith (zipWith (+)) m n

The only real change in terms of the code is in the madd2 definition where I have to construct a Matrix to return from the results of the zipWiths … and some better type safety of course.

*Main> madd2 (Matrix [[1,2,3], [4,5,6], [7,8,9]]) (Matrix [[10,11,12], [13,14,5], [16,17,18]])
Matrix [[11,13,15],[17,19,11],[23,25,27]]

Cool'

Now, I really want to use Unboxed Vectors.  As I look around the web and poke around through various resources, I believe that I need the rows to be unboxed but the columns can be boxed … the actual operations on the rows will give me the speed up I desire.

So, here it is:

import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as U

data UMatrix a = UMatrix (V.Vector (U.Vector a))
    deriving (Show, Eq)
 
madd3 :: (U.Unbox a, Num a) => UMatrix a -> UMatrix a -> UMatrix a
madd3 (UMatrix m) (UMatrix n) = UMatrix $ V.zipWith (U.zipWith (+)) m n

And it works … (really, when I started writing this note, I was completely lost … welcome to the power of sitting and walking through Haskell)

madd3 (UMatrix (Data.Vector.fromList [Data.Vector.Unboxed.fromList [1,2,3], Data.Vector.Unboxed.fromList [4,5,6], Data.Vector.Unboxed.fromList [7,8,9]])) (UMatrix (Data.Vector.fromList [Data.Vector.Unboxed.fromList [10,11,12], Data.Vector.Unboxed.fromList [13,14,5], Data.Vector.Unboxed.fromList [16,17,18]]))

I have ONE thing that I can't really explain …

Why does the declaration of madd3 REQUIRE the use of U.Unbox a as a data type?
madd3 :: (U.Unbox a, Num a) => UMatrix a -> UMatrix a -> UMatrix a

I would have thought that my declaration of UMatrix would have done this?

Cheers.

Paul Monday
Parallel Scientific, LLC.
paul.monday at parsci.com







More information about the Beginners mailing list