If you check the type of your add and sub , you will see a problem.
ghci> :t add add :: Num a => [[a]] -> [[a]] -> [[a]] ghci> :t sub sub :: Num a => [[a]] -> [[a]] -> [[a]]
Michael's suggestion was to essentially expand the 2D list and reinstall it in the Num instance methods. Another way to do this is to change the add and sub methods for working with matrices. Here I use the βriseβ approach, where I write combinators to βraiseβ a function from one type to another.
With these combinators, defining add and sub is just a matter of sub it right.
add, sub :: Num a => Matrix a -> Matrix a -> Matrix a add = liftMatrixOp add2D sub = liftMatrixOp sub2D add2D, sub2D :: Num a => [[a]] -> [[a]] -> [[a]] add2D = lift2dOp (+) sub2D = lift2dOp (-)
Now that we have functions that work with matrices, the Num instance is simple
instance (Num a) => Num (Matrix a) where (+) = add (-) = sub ..etc..
Of course, we could combine lift2dOp and liftMatrixOp in one convenient function:
Now try: define liftMatrix :: (a -> a) -> Matrix a -> Matrix a , the lift function for unary functions. Now use this to define negate , abs and signum . The docs assume that abs x * signum x should always be equivalent to x . See if this is true for our implementation.
ghci> quickCheck (\xs -> let m = Matrix xs in abs m * signum m == m) +++ OK, passed 100 tests.
In fact, if you write liftMatrix with a softer type signature, you can use it to define an instance of Functor for matrices.
liftMatrix :: (a -> b) -> Matrix a -> Matrix b instance Functor (Matrix a) where fmap = liftMatrix
Now think about how you can implement fromInteger . Implementing this allows you to do such things in ghci:
ghci> Matrix [[1,2],[3,4]] + 1 Matrix [[2,3],[4,5]]
The way it works the way I implemented it, anyway. Remember that any number literal n in Haskell code is actually converted to fromInteger n , so this works.
I think this time is enough fun, but if you need more exercise, try participating in this Arbitrary instance of Matrices:
instance Arbitrary a => Arbitrary (Matrix a) where arbitrary = liftM Matrix arbitrary