将嵌套for循环转换为Haskell

时间:2013-08-09 20:11:29

标签: haskell

我正在努力将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)。也许我必须进一步区分它?

2 个答案:

答案 0 :(得分:3)

原始代码究竟在做什么?另外,my.read的类型签名是什么?我假设它会有一个类似于Num b => (a, Int, Int) -> IO b的签名,在这种情况下,这段代码甚至不会编译。如果{mon}中有my . read,那么您可以将其写为:

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来计算你的类型。

答案 1 :(得分: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