更新Matrix Haskell

时间:2012-11-23 11:46:33

标签: haskell matrix functional-programming

我将通过列表[[a]]

列出项目中的矩阵
  • 这是一个好主意还是我应该更好地使用数组?

  • 如何使用索引(i,j)

  • 更改场所元素

3 个答案:

答案 0 :(得分:9)

当然,基于列表的解决方案永远不会像优化的紧密阵列那样快,因为必要的间接性以及所有缓存局部性问题。然而,这只是一个恒定的开销因素(可能很大,但大约为100)。

然而,有趣的是,对矩阵的嵌套列表方法并不像看起来那么糟糕:列表仍然是以传统的纯功能方式最自然地处理的数据结构。正如millimoose所说,你不能只是以纯粹的方式就地改变一个元素,你必须用一个元素改变整个事物的副本*。对于 n n 紧密阵列矩阵,这是 O n 2 ) - 对于较大的 n 几乎不可接受。

虽然长度 m 的列表中的随机访问已经 O m ),因此比数组更糟糕,对于更复杂的操作,它不会变得更糟。您可以“修改” O m )中的列表,您可以访问 n n 嵌套列表在 O n )中,您可以在 O n )中修改它!因此,如果您想对大型矩阵进行无损更新,[[a]]实际上比Array a i更快。

哦,这是如何工作的 - 好吧,像

type Matrix a = [[a]]
updateMatrixAt :: (Int,Int) -> (a->a) -> Matrix a -> Matrix a
updateMatrixAt(i,j) f mat
 | (upperRows, thisRow : lowerRows ) <- splitAt i mat
 , (leftCells, thisCell: rightCells) <- splitAt j thisRow
         =                  upperRows
          ++ (leftCells ++ (f thisCell): rightCells)
                          : lowerRows
 | otherwise = error "Tried to index matrix outside range"

会做到这一点。


*有have been attempts to avoid this,但我担心这已被证明是死路一条。如果你想要真正的高性能,你应该在ST monad中使用破坏性更新,它没有任何问题,虽然它可能不太好。

答案 1 :(得分:5)

如何使用自己的数据类型包裹Map (Int,Int) a?更改元素是微不足道的,特别是对于稀疏矩阵,您可以节省大量内存。

答案 2 :(得分:0)

  

如何使用索引(i,j)更改场所元素?

一般来说,你不能。您必须创建一个更改了一个元素的新矩阵。 (使用Array代替列表会使the // operator稍微容易一些。)看起来您可以使用MArray进行就地更改,但几乎所有代码都会必须使用IO