2

我正在努力将 F# 中的这段矩阵乘法转换为 Haskell(请忘记并行组件):

Parallel.For(0, rowsA, (fun i->
        for j = 0 to colsB - 1 do
           for k = 0 to colsA - 1 do
              result.[i,j] <- result.[i,j] + a.[i,k] * b.[k,j]))  
    |> ignore

我设法放在一起的是

sum (map (\(i, j, k) -> (my.read (a,i,k)) * (my.read (b, k, j))) [ (i, j, k) | i <- [0..rowsA], j <- [0..colsB], k <- [0..colsA] ]) 

--my.read reads the values of the respective cells from 'my' database

目的是从我的数据库中读取矩阵 a 和矩阵 b 的单元格,并进行矩阵乘法,最终可以由不同的代理分部分执行。这是通过设置 i 、 j 和 k 的边界来控制的,但在这里不相关。

我试图将上面的 F# 示例翻译成 haskell。我正在努力解决的问题是结果不是所有内容的总和,而是在位置 i, j(F# result.[i,j] - 单元格是结果矩阵) 处应该有一个结果列表。我看不到如何发出正确的结果(i,j)。也许我必须进一步分解?

4

2 回答 2

3

原始代码到底在做什么?另外,什么是类型签名my.read?我假设它的签名类似于Num b => (a, Int, Int) -> IO b,在这种情况下,此代码甚至无法编译。如果my . read在 IO monad 中,那么您可以将其写为:

myfunc = do
    let indices = [(i, j, k) | i <- [0..rowsA],
                               j <- [0..colsB],
                               k <- [0..colsA]]

    -- Since `my . read` returns a value in the IO monad,
    -- we can't just multiply the values returned.
    r1 <- mapM (\(i, j, k) -> (my . read) (a, i, k)) indices
    r2 <- mapM (\(i, j, k) -> (my . read) (b, k, j)) indices

    -- We can multiply r1 and r2 together though,
    -- since they are values extracted from the IO monad
    return $ sum $ zipWith (*) r1 r2

我现在能给你的最好建议是使用 ghci 来找出你的类型。

于 2013-08-09T20:51:27.297 回答
3

试着分开

a :: [(a,a,a)]
a = [ (i, j, k) | i <- [0..rowsA], j <- [0..colsB], k <- [0..colsA] ]

进入

b :: [[(a,a,a)]]
b = [ [ (i, j, k) | k <- [0..colsA]] | i <- [0..rowsA], j <- [0..colsB] ]

你有一个“行”列表 - 矩阵

总和列表是

m = [ [ (i, j, k) | k <- [0..colsA]] | i <- [0..rowsA], j <- [0..colsB] ]
listSum = map sum $ map (map (\(i,j,k) -> my_read (a,i,k) * my_read(b,k,j))) m
于 2013-08-09T21:09:19.230 回答