Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It'll be perfectly safe with a smart constructor and stored dimensions. Of course there are no natural implementations for the operations <code>signum</code> and <code>fromIntegral</code> (or maybe a diagonal matrix would be fine for the latter).</p> <pre class="lang-hs prettyprint-override"><code>module Matrix (Matrix(),matrix,matrixTranspose) where import Data.List (transpose) data Matrix a = Matrix {matrixN :: Int, matrixM :: Int, matrixElems :: [[a]]} deriving (Show, Eq) matrix :: Int -&gt; Int -&gt; [[a]] -&gt; Matrix a matrix n m vals | length vals /= m = error "Wrong number of rows" | any (/=n) $ map length vals = error "Column length mismatch" | otherwise = Matrix n m vals matrixTranspose (Matrix m n vals) = matrix n m (transpose vals) instance Num a =&gt; Num (Matrix a) where (+) (Matrix m n vals) (Matrix m' n' vals') | m/=m' = error "Row number mismatch" | n/=n' = error "Column number mismatch" | otherwise = Matrix m n (zipWith (zipWith (+)) vals vals') abs (Matrix m n vals) = Matrix m n (map (map abs) vals) negate (Matrix m n vals) = Matrix m n (map (map negate) vals) (*) (Matrix m n vals) (Matrix n' p vals') | n/=n' = error "Matrix dimension mismatch in multiplication" | otherwise = let tvals' = transpose vals' dot x y = sum $ zipWith (*) x y result = map (\col -&gt; map (dot col) tvals') vals in Matrix m p result </code></pre> <p>Test it in ghci:</p> <pre class="lang-hs prettyprint-override"><code>*Matrix&gt; let a = matrix 3 2 [[1,0,2],[-1,3,1]] *Matrix&gt; let b = matrix 2 3 [[3,1],[2,1],[1,0]] *Matrix&gt; a*b Matrix {matrixN = 3, matrixM = 3, matrixElems = [[5,1],[4,2]]} </code></pre> <p>Since my <code>Num</code> instance is generic, it even works for complex matrices out of the box:</p> <pre class="lang-hs prettyprint-override"><code>Prelude Data.Complex Matrix&gt; let c = matrix 2 2 [[0:+1,1:+0],[5:+2,4:+3]] Prelude Data.Complex Matrix&gt; let a = matrix 2 2 [[0:+1,1:+0],[5:+2,4:+3]] Prelude Data.Complex Matrix&gt; let b = matrix 2 3 [[3:+0,1],[2,1],[1,0]] Prelude Data.Complex Matrix&gt; a Matrix {matrixN = 2, matrixM = 2, matrixElems = [[0.0 :+ 1.0,1.0 :+ 0.0],[5.0 :+ 2.0,4.0 :+ 3.0]]} Prelude Data.Complex Matrix&gt; b Matrix {matrixN = 2, matrixM = 3, matrixElems = [[3.0 :+ 0.0,1.0 :+ 0.0],[2.0 :+ 0.0,1.0 :+ 0.0],[1.0 :+ 0.0,0.0 :+ 0.0]]} Prelude Data.Complex Matrix&gt; a*b Matrix {matrixN = 2, matrixM = 3, matrixElems = [[2.0 :+ 3.0,1.0 :+ 1.0],[23.0 :+ 12.0,9.0 :+ 5.0]]} </code></pre> <hr> <p><strong>EDIT: new material</strong></p> <p>Oh, you want to just override the <code>(*)</code> function without any <code>Num</code> stuff. That's possible to o but you'll have to remember that the Haskell standard library has reserved <code>(*)</code> for use in the <code>Num</code> class.</p> <pre class="lang-hs prettyprint-override"><code>module Matrix where import qualified Prelude as P import Prelude hiding ((*)) import Data.List (transpose) class Multiply a where (*) :: a -&gt; a -&gt; a data Matrix a = Matrix {matrixN :: Int, matrixM :: Int, matrixElems :: [[a]]} deriving (Show, Eq) matrix :: Int -&gt; Int -&gt; [[a]] -&gt; Matrix a matrix n m vals | length vals /= m = error "Wrong number of rows" | any (/=n) $ map length vals = error "Column length mismatch" | otherwise = Matrix n m vals matrixTranspose (Matrix m n vals) = matrix n m (transpose vals) instance P.Num a =&gt; Multiply (Matrix a) where (*) (Matrix m n vals) (Matrix n' p vals') | n/=n' = error "Matrix dimension mismatch in multiplication" | otherwise = let tvals' = transpose vals' dot x y = sum $ zipWith (P.*) x y result = map (\col -&gt; map (dot col) tvals') vals in Matrix m p result a = matrix 3 2 [[1,2,3],[4,5,6]] b = a * matrixTranspose </code></pre> <p>Testing in ghci:</p> <pre class="lang-hs prettyprint-override"><code>*Matrix&gt; b Matrix {matrixN = 3, matrixM = 3, matrixElems = [[14,32],[32,77]]} </code></pre> <p>There. Now if a third module wants to use both the <code>Matrix</code> version of <code>(*)</code> and the <code>Prelude</code> version of <code>(*)</code> it'll have to of course import one or the other qualified. But that's just business as usual.</p> <p>I could've done all of this without the <code>Multiply</code> type class but this implementation leaves our new shiny <code>(*)</code> open for extension in other modules.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload