When you say “pair type former” do you mean that Array<U32> & U32 is what Rust would call (Array<U32>, U32)? If so, why does that example function actually return a value of this type? It sure looks like it returns plain U32.
> You can use an erased argument as many times as you want, in erased positions.
What’s the rationale for this? Why is an “erased” position special? What is an erased position, anyway?
ISTM if I want to use an affine term that has zero size at runtime as a token that may be used at most once, I think I wouldn’t want an exception for using it in an “erased” position. Can I have a function like a -> a & a where the input is “erased”?
Yes, `Array<U32> & U32` is just `(Array<U32>, U32)` and now that you point it I believe I made a bad choice, no excuses. Also, `arr[3]` doesn't return a number. It returns a copy of the same array, plus a number. So, if the element at index 3 is 123, tthen, `arr[3]` will return `(arr, 123)`. Now, you might be thinking: that's terrible. And yes, it is. I realize it now. I should have made the `arr[3]` syntax return 123. It is there for a very good reason though. It preserves linearity. It is part of the termination argument that makes Bend consistent. But yes, exposing it to the end user was most likely a mistake. I will redesign that syntax. Sorry about it.
In the everything-copyable case, you can just read an element.
In the nothing-copyable case, the syntax is irrelevant: the operation (arr, elem) = arr.read(index) is invalid.
You may want to take a look at how Rust deals with this. In Rust, even if T: !Copy, you can take a reference to an array element. If a language can't manage this sort of reference, you may need a more restrictive mechanism, perhaps as a pair of swaps (but then you need a default value) or some mechanism using closures that get called on the element and are required to return it.