我尝试重新定义已定义索引的值时出现<<loop>>
错误。
简化示例:
ghci > let axs = array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]
ghci > axs
array (1,5) [(1,^CInterrupted.
这将循环。我假设Data.Array
的懒惰性质是造成这种行为的原因。
另一方面,这不会循环,并将按预期工作(重新定义索引1)。
ghci > array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1,6)]
array (1,5) [(1,6),(2,2),(3,3),(4,4),(5,5)]
有没有办法通过递归自我来重新定义索引值? 我假设我需要强制对所需索引进行评估,以便能够更新&#34;再次使用前一个值。 这是可能的还是我不应该/不能这样使用阵列?
答案 0 :(得分:5)
在递归定义中,右边定义的东西的含义是它的最终值。所以
x = x + 1
将是一个无限循环。在数组定义中(在GHC中),索引的值是它的最后一次出现,所以
axs = array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]
与
相同axs = array (1,5) [(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]
这一点的重要部分是
axs' = array (1,1) [(1, 1 + axs!1)]
与
的想法相同x = 1 + x
请注意&#34;重新定义&#34;在Haskell标准中根本不允许在数组定义中,并且总是循环或抛出异常。 GHC允许它,但这并不严格是与标准的一致。
即使在GHC中,重新定义&#34;并非当务之急。您不是逐个设置数组中的值。相反,数组定义是整个数组的声明性规范。
如果您想要一种构造数组的命令式方法,请使用st monad
未经测试:
arr = runSTArray $ do
retArr <- newArray (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5)]
curVal <- readArray retArr 1
writeArray retArr 1 (curVal + 1)
retArr