1

I'm having a <<loop>> error for trying to redefine a value on an already defined index.

Simplified example:

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.

This will loop. I'm assuming that the lazy nature of Data.Array is what is causing that behaviour.

This, on the other hand, won't loop and will work as expected (redefines index 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)]

Is there any way to redefine an indexed value with recursion to self? I'm assuming I need to force the evaluation of the wanted index to be able to "update" the value again using the previous one. Is that possible or I shouldn't/can't use the array this way?

2
  • Should that be array (1, 6) ... since you have 6 elements, not 5? The documentation says that this is indeed possible because array is only strict in the index. It has to check each index to ensure that it's within the bounds and unique. You also have to have unique indices, so if you change it to (6, 1 + axs ! 1) then it'll work without problems. Commented Apr 18, 2014 at 14:19
  • Yep, I do understand that it will work. If I change (1,1+axs!1) to (1,1 + axs!2) it will work. But I'm looking for a workaround to this self-referential behaviour (so it doesn't loop). As can be seen in the second example, indices in the list don't have to be unique, but it seems that recursion only works for indices which aren't equal to the current element (if recursion is defined). For example, even this will work: let axs = array (1,5) [(1,1),(2,2),(3,3),(4,4 + axs!5),(5,5),(1, 1 + axs!2)] Commented Apr 18, 2014 at 14:25

1 Answer 1

5

In a recursive definition, the meaning of the thing being defined on the right is its final value. So

x = x + 1

will be an infinite loop. In an array definition (in GHC), the value of an index is its last appearance, so

axs = array (1,5) [(1,1),(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]

is the same as

axs = array (1,5) [(2,2),(3,3),(4,4),(5,5),(1, 1 + axs!1)]

the important part of this is

axs' = array (1,1) [(1, 1 + axs!1)]

which is the same idea as

x = 1 + x

Note that "redefinition" in array definitions is not permitted by the Haskell standard at all, and should always loop or throw an exception. GHC allows it, but that is not strictly is agreement with the standard.

Even in GHC the "redefinition" is not imperative. You are not one by one setting the values in the array. Rather, an array definition is a declarative specification for the entire array.

If you want an imperative approach to constructing arrays, use the st monad

This is not tested:

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
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.