Zmod m is isomorphic to
{ z | z mod m = z}. For efficiency, it is
constructed from scratch as
- a dedicated record type instead of sig, to avoid repeating the
subset-membership predicate in constructor arguments
- with primitive projections, to avoid the modulus in projection arguments
- using Is_true instead of _ = true to avoid repeating modulus in values
- using small instead of Z.modulo to speed up type-checking of values.
This construction is
not a part of the supported interface of
Zmod, so
the projections are named as
Private_ to exclude them from Search, instead
presenting wrappers with types that do not reveal these optimoizations are.
Bitvector operations that vary the modulus
Effective use of the operations defined here with moduli that are not
convertible to values requires substantial understanding of dependent types,
in particular the equality type, the sigma type, and their eliminators. Even
so, many applications are better served by
Z or by adopting one
common-denominator modulus. See the four variants of
skipn_app and
app_assoc, for a taste of the challenges.