Hi Stephan,
Thanks for the link to Leslie's recent note on (not) reusing TLA+ modules.
I must say that reasoning on simple abstractions in TLA+ is great - it enforces you to focus on the solutions instead of the details.
On the other hand, I still find choosing the simplest possible abstractions pretty challenging and when they don't end up being simple I resort to 'reusing'.
It's a strong habit from programming :)
Out of curiosity I tried to implement your "horribly inefficient" version, but I get:
In computing initial states, the right side of \IN is not enumerable.
in:
channels \in [p \in Player |-> Seq(Msg)]
after overriding Nat as:
Nat = 1..2
Here you can find the full source code: [1]
After overriding Nat with 1..2 the following types should look like this:
Msg == Nat
=> Msg == 1..2
Seq(S) == UNION {[1..n -> S] : n \in Nat}
=> Seq(S) == UNION {[1..n -> S] : n \in 1..2}
and TLC should see channels like below:
channels \in [p \in Player |-> UNION {[1..n -> 1..2] : n \in 1..2}]
How is that still not enumerable ?
I also found another way of reusing, by extracting the whole 'channels' variable to separate module.
It might be useful.
Here is the source: [2]
In case you would like to run it in Toolbox, here are all examples with configured models: [3]
Cheers.