在 SML 中将两个矩阵相乘

Multiply two matrices in SML

我想在 SML/NJ 中编写一个函数,它将 2 个矩阵作为参数并将它们相乘。

我只能用:

我要写的函数应该是这样的:

fun multiply (a: int list list, b: int list list): int list list

到目前为止我已经这样做了:

fun multiply (a: int list list, b: int list list): int list list =
case a of
[] => []
  | g::rep => [(List.map (fn y => dot(g, y)) transpose(b))] @ (multiply(rep, b))

但是我得到了这个错误:

test.sml:66.21-66.62 Error: operator and operand do not agree [tycon mismatch]
  operator domain: int list list
  operand:         'Z list list -> 'Z list list
  in expression:
(List.map (fn y => dot <exp>)) transpose

如果在函数乘法的最后一行我写 b 而不是 tranpose(b),我没有得到任何错误,但是当然,如​​果我这样做,我不会得到我想要的结果:

fun multiply (a: int list list, b: int list list): int list list =
case a of
[] => []
  | g::rep => [(List.map (fn y => dot(g, y)) b)] @ (multiply(rep, b))

我不知道我还应该做什么。有人可以帮我吗?

存在 a solution for OCaml on RosettaCode 可以翻译。

鉴于插图,

         | [ a,   [ c,
         |   b ]    d ]
---------+-------------
[ 1, 2 ] |   w      x
[ 3, 4 ] |   y      z

然后对第一个矩阵的每一行,计算与第二个矩阵相同的dot乘积。 IE。 w = dot ([1, 2], [a, b])。提取第一个矩阵的行很容易,因为您可以使用列表递归。

提取第二个矩阵的列不太容易,因为它们与列表表示正交(即 a 是第一行的第一个元素,b 是第二行,c是第一行的第二个元素,d是第二行的第二个元素。

您可以通过执行 transpose 来简化从第二个矩阵中提取列,在这种情况下,提取列等同于提取行。此时,您可以采用 "rows" 的成对 dot 乘积(即第一个矩阵中的行和第二个矩阵中的转置列 ("rows"))。

我鼓励对此类操作使用 Array2,因为当您的 "matrices"(列表)参差不齐(具有不同的行长度)时,您也可以避免错误处理。

至少我用你的方案成功了

exception dim_Error;

fun listPair (l1:int list) (l2:int list): (int * int) List.list =  
`if not (List.length l1 = List.length l2) then raise dim_Error
    else List.tabulate (List.length l1, fn i => (List.nth(l1, i),List.nth(l2, i)));`    

fun dotprod (l1:int list) (l2:int list): int = 
    List.foldl (fn (x,y) => x+y) 0 (map (fn (x,y) => x*y) (listPair l1 l2));

fun transpose (matrix: int list list):int list list =
    List.tabulate (List.length (List.nth (matrix, 0)), fn i => List.map (fn j => List.nth (j, i)) matrix);

fun multiply (matrix1: int list list) (matrix2: int list list): int list list =
case matrix1 of 
    [] => []
    |    x::xr => [List.map (fn y => dotprod x y) (transpose matrix2)] @ (multiply xr matrix2);

val A = [[ 21,  ~2,  3, ~1], [  2, 115,  6,  7], [ ~6,  9, 210, 11], [ 13, 14, ~19, 15], [ ~2, 21, ~99,  3], [  5, ~4,  ~1,  9]];
val B = [[2, ~6, 0, 3, 9], [~4, ~1, 2, 1, ~2], [~6, 5, 3, ~5, 1], [10, 9, ~4, 9, ~7]];
val C = [[~4, ~3, 7], [1, ~1, ~2], [~5, 3, 7], [8, ~7, 2], [~8, 3, 6]];

multiply (multiply  A B) C;