You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell数组增量更新:使用//运算符反转数组遇问题

Haskell数组反转问题解析

第一个代码结果全为1的原因

你写的列表推导式[(i, x!j) | i<-[1..4], j<-[4,3..1]]生成的是笛卡尔积:

  • 当i=1时,j遍历4,3,2,1,生成(1, x!4), (1, x!3), (1, x!2), (1, x!1)
  • 当i=2时,j再次遍历4,3,2,1,生成(2, x!4), (2, x!3), (2, x!2), (2, x!1)
  • 以此类推,最终生成16个元组

而//运算符的规则是后出现的更新会覆盖之前同下标的更新,所以每个下标i最后被设置的是j=1时的x!1(也就是1),最终数组所有元素都是1。

两段代码结果不同的原因

[4,3..1]并不是enumFromTo 4 1的语法糖:

  • [4,3..1]对应的是enumFromThenTo 4 3 1,指定了起始值4、第二个元素3(步长为-1),所以会生成[4,3,2,1]
  • enumFromTo 4 1对于整数类型来说,是从4递增到1,这个序列是空的(因为4>1,无法递增到达)

所以第二个代码里的列表推导式因为j的序列为空,没有生成任何更新元组,数组保持原样。

正确的数组反转实现

要实现反转,需要让下标i和对应的反转下标j一一配对,而不是笛卡尔积。可以用zip来关联两个序列:

test = listArray (1,4) [1..4]

-- 方法1:用zip直接配对下标和反转下标
reverser x = x // [(i, x!j) | (i,j) <- zip [1..4] [4,3..1]]

-- 方法2:更简洁的写法
reverser x = x // zip [1..4] (map (x!) [4,3..1])

运行reverser test会得到预期结果:array (1,4) [(1,4),(2,3),(3,2),(4,1)]

如果后续需要反转指定区间(比如从a到b),只需要调整zip里的序列即可,例如反转下标2到3:

reverseRange x a b = x // [(i, x!j) | (i,j) <- zip [a..b] [b,b-1..a]]

内容的提问来源于stack exchange,提问作者Alfy B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 19:34:49