Haskell Data.Vector.modify with嵌套向量

Haskell Data.Vector.modify with嵌套向量,haskell,haskell-vector,Haskell,Haskell Vector,我有一个向量嵌套在另一个向量中。以更新此矩阵。因此,我将其用于内部向量,但是否也需要将其用于外部向量?我从评论中得到的建议仍然有效,如果不需要对不规则数组进行操作,则通常的矩形数组实现更好。以下是向量向量的缺点的简短列表: 性能损失:外部向量必须装箱(这意味着额外的间接指针) 安全性:不能保证所有行的长度相同 在参差不齐的阵列上操作很麻烦 尽管如此,问题仍然存在:如何在适当的位置修改向量的向量。下面我将提供一个示例函数,它使用变异来反转不规则数组的行,另一个函数同时反转行和列。不同之处在于,

我有一个向量嵌套在另一个向量中。以更新此矩阵。因此,我将其用于内部向量,但是否也需要将其用于外部向量?

我从评论中得到的建议仍然有效,如果不需要对不规则数组进行操作,则通常的矩形数组实现更好。以下是向量向量的缺点的简短列表:

  • 性能损失:外部向量必须装箱(这意味着额外的间接指针)
  • 安全性:不能保证所有行的长度相同
  • 在参差不齐的阵列上操作很麻烦
尽管如此,问题仍然存在:如何在适当的位置修改向量的向量。下面我将提供一个示例函数,它使用变异来反转不规则数组的行,另一个函数同时反转行和列。不同之处在于,在前者中,我们只对每一行的元素进行变异,而在后者中,我们还对对应于行本身的外框向量进行变异:

{-#语言等级}
进口管制。单子为M
进口管制站
导入前奏曲作为P
导入数据。向量为V
将Data.Vector.Generic.Mutable作为VGM导入
将Data.Vector.Mutable导入为VM
将Data.Vector.Primitive作为VP导入
将Data.Vector.Primitive.Mutable导入为VPM
raggedModifyRows::
首席副总裁
=>(对于所有s.V.向量(VPM.MVector SA)->ST s())
->V.向量(VP.向量a)
->V.向量(VP.向量a)
raggedModifyRows操作arr=runST$do
--解冻将创建每行的副本,以便安全地修改它们
mvs(对于所有s.VM.MVector s(VPM.MVector SA)->ST s())
->V.向量(VP.向量a)
->V.向量(VP.向量a)
raggedModify操作arr=runST$do
arr'>=reverseST
设m=VM.length mrows
M.forM[0..(M`div`2)-1]$\i->do
反向“i”
VM.swap mrows i(m-i-1)
反向“i”
M.when(奇数M)$反向(M`div`2)
可按如下方式使用:

λ>m=生成矩阵(3,4)$\(i,j)->i+j
λ> m
[[0,1,2,3],[1,2,3,4],[2,3,4,5]]
λ> 反转器
[[3,2,1,0],[4,3,2,1],[5,4,3,2]]
λ> 反转m
[[5,4,3,2],[4,3,2,1],[3,2,1,0]]
λ> m=发电机标记(V.fromList[1,2,3])$\(i,j)->i+j
λ> m
[[0],[1,2],[2,3,4]]
λ> 反转器
[[0],[2,1],[4,3,2]]
λ> 反转m
[[4,3,2],[2,1],[0]]
或者,我们可以使用
Data.Vector.modify
对外部向量进行操作,或者映射在所有行中使用
modify
的破坏性操作。有各种各样的方法来实现它,这取决于您试图实现的目标,例如:

λ>m=generateRagged(V.fromList[1,2,3])$\(i,j)->i+j
λ> V.map(VP.modify reverseST)m
[[0],[2,1],[4,3,2]]
λ> V.modify reverseST(V.map(VP.modify reverseST)m)
[[4,3,2],[2,1],[0]]
我确实建议对常规多维数组使用。因此,这里还有一个示例,说明如何通过以下方式实现相同的目标:

{-#语言灵活上下文}
进口管制。单子为M
将Data.Massiv.Array作为
可逆矩阵::可变rIX2e=>Array rIX2e->Array rIX2e
反向矩阵=
使用MarraySt arr$\marr->do
设Sz2 m n=msize marr
ix2@(m2:.n2)=m`div`2:。n`div`2
A.forM_u0..:ix2)$\ix@(i:.j)->do
A.swapM marr ix(m-i-1:.n-j-1)
A.swapM_umarr(i:.n-j-1)(m-i-1:.j)
当(奇数m)$A.forM(0..:n2)$\j->
A.swapM_umarr(m2:j)(m2:n-j-1)
当(奇数n)$A.forM(0..:m2)$\i->
A.swapM umarr(i:.n2)(m-i-1:.n2)
可按如下方式使用:

λ>a=makeArrayR P Seq(Sz2 3 4)$\(i:.j)->i+j
λ> a
数组P序列(Sz(3:4))
[ [ 0, 1, 2, 3 ]
, [ 1, 2, 3, 4 ]
, [ 2, 3, 4, 5 ]
]
λ> 反向矩阵a
数组P序列(Sz(3:4))
[ [ 5, 4, 3, 2 ]
, [ 4, 3, 2, 1 ]
, [ 3, 2, 1, 0 ]
]

如果要修改矩阵,为什么不使用矩阵而不是向量?这里有一种处理任意维数组的类似方法,就像您在vector:Yep上使用
modify
。首先说要修改哪一行,然后说如何修改那一行(即修改元素)。除非你期望一个不规则的数组,否则应该避免向量向量的方法,因为它有严重的缺点。首先是性能损失:外部向量必须装箱(这意味着额外的间接指针),其次是安全性:无法保证行的长度,最后但并非最不重要的是,对它的操作变得非常麻烦;)我希望Vector的黑客页面会给出这样的建议!这会让我省去好几天的头疼。你可以向vector包提交一个pull请求,将其放入摘要中,这样它就会出现在hackage上。在
reverseMatrix
中,约束
可变rIX2e
实现了什么?它是否引用了
Data.Massiv.Array.Mutable
?如何通过修改元素来修改矩阵,比如从
Int
(Int,String)
?首先,我认为类型签名中的
r
需要约束为
U
>它是否引用Data.Massiv.Array.Mutable?它引用类,但上述模块中的所有函数都将在具有该类实例的数组上工作。使用
U
for
r
是好的,除了
String
[Char]
)没有
Unbox
实例之外,因此将元素转换为
(Int,String)
不是一个好主意。其次,一旦有了可变数组,就不能更改其元素的类型。如果你仔细想想,很明显,不同类型的元素可能会占用更多的内存,所以你必须分配新的可变数组并填充它。尽管如此,通常可以避免可变接口,以纯方式重写算法,尝试一下