[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