While this may occasionally ends into unfriendly cases.
Given this:
dataprop SEQ(i:int, e:int) =
| SEQ1(1, e) of int(e)
| SEQN(i, e) of ([_:int] SEQ(i-1, _), int(e))
One may want to have this:
prval s7 = SEQ1(7)
prval s78 = SEQN(s7,8)
prval s789 = SEQN(s78,9)
the i of s78 should be derived from the i of s7 and the i of s789 should be derived from the i of s78. But the constraint solver does not handle it well, it complains it can't solve the constraint about i.
It seems better to explicitly tell it how to compute it. Indeed, given this (compare third lines):
dataprop SEQ(i:int, e:int) =
| SEQ1(1, e) of int(e)
| SEQN(i+1, e) of ([_:int] SEQ(i, _), int(e))
Now fine, no complaints from the constraint solver:
prval s7 = SEQ1(7)
prval s78 = SEQN(s7,8)
prval s789 = SEQN(s78,9)
Unfortunately, in the while, it also breaks the cool style of having index and constraint parameters match (while there is no need to give these).
prval s7:SEQ(1,7) = SEQ1{1,7}(7)
prval s78:SEQ(2,8) = SEQN{1,8}(s7,8)
prval s789:SEQ(3,9) = SEQN{2,9}(s78,9)
Second line: i as an index, is 2, while as a constraint parameter, it's 1.
Third line: i as an index, is 3, while as a constraint parameter, it's 2.
With the initial:
dataprop SEQ(i:int, e:int) =
| SEQ1(1, e) of int(e)
| SEQN(i, e) of ([_:int] SEQ(i-1, _), int(e))
There is no more divergence, and both match:
prval s7:SEQ(1,7) = SEQ1{1,7}(7)
prval s78:SEQ(2,8) = SEQN{2,8}(s7,8)
prval s789:SEQ(3,9) = SEQN{3,9}(s78,9)
While this is more verbose, as either one of the index or the constraint parameter, needs to be explicitly given.
So when in a prior message I have said “I personally will ban the style of case #2, to make constraints parameter and indexes match”, it was easy to say, in practice, this may not be easy to always follow this style and be terse together.
Some more stuffs to have in mind …