
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@parsci.com

On Thursday 08 December 2011, 21:55:46, Paul Monday wrote:
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?
No, the data declaration doesn't provide any such context, hence you have to specify it at the use site (I don't think for types which aren't instances of Unbox there are any values other than _|_, though). You can make the Unbox constraint available from the data declaration if you use GADTs, {-# LANGUAGE GADTs #-} data UMatrix e where UMatrix :: U.Unbox a => V.Vector (U.Vector a) -> UMatrix a Then pattern-matching on a UMatrix makes the Unbox dictionary of a available.

Perfect … Thanks Daniel! Paul Monday Parallel Scientific, LLC. paul.monday@parsci.com On Dec 8, 2011, at 2:13 PM, Daniel Fischer wrote:
On Thursday 08 December 2011, 21:55:46, Paul Monday wrote:
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?
No, the data declaration doesn't provide any such context, hence you have to specify it at the use site (I don't think for types which aren't instances of Unbox there are any values other than _|_, though).
You can make the Unbox constraint available from the data declaration if you use GADTs,
{-# LANGUAGE GADTs #-}
data UMatrix e where UMatrix :: U.Unbox a => V.Vector (U.Vector a) -> UMatrix a
Then pattern-matching on a UMatrix makes the Unbox dictionary of a available.
participants (3)
-
Daniel Fischer
-
Felipe Almeida Lessa
-
Paul Monday