I have just discovered the existence of maximal and non-maximal arguments (see https://coq.inria.fr/refman/Reference-Manual004.html#sec109).
But is there some motivation to use one over the other? Is one more recent than the other? Maximal implicit arguments simply need {}
to be created, whereas one has to use Arguments
or Implicit Arguments
to specify non-maximal ones. Does it mean that maximal implicit arguments should be preferred?
Yes there is, but (as usual) "it depends". Let's first discuss a little bit the difference between them.
Maximally-inserted implicit (MII) arguments add the next level of "implicitness" to the language. Ordinary (non-MII) arguments get inserted only when a function is applied to at least one argument. Furthermore, Coq inserts those arguments only before some provided explicit argument.
MII arguments are more "eager": Coq considers them inserted after some supplied explicit argument. A corner case: if a function's signature starts with an MII argument, it suffices to mention the function name (even without application) for Coq to turn it into a partially applied function (it doesn't happen with non-MII arguments). Sometimes this eager behavior helps to write succinct code and sometimes its a bit of a nuisance, because it forces us to insert otherwise redundant
@
symbols to suppress insertion of implicit arguments.Let me show some simple examples, drawn mostly from the reference manual or the standard library.
Preamble:
The
length
function has non-MII first argument:That's why the following simple code fails (it fails because
length
is not partially applied, soA
is not inserted):One have to write something like this to make it work:
Another way would be to use MII arguments. Intuitively, in this case Coq replaces
length
with(@length _)
:But sometimes maximally inserted arguments are getting into the way, when one wants to use some function or a constructor in its most general form (not partially applied). A working example with non-MII arguments from the
Coq.Lists.List
module:But
exact Forall2_nil
won't work in the case of MII arguments. Theconstructor
will help us, though:One more instance of premature implicit argument insertion (from
Coq.Init.Logic
). This works with non-MII arguments:But, here we have to add '@':
Sometimes tactics of the form
<tactic-name> ... with (_ := _).
will fail in the presence of MII arguments. Here is another (working) example fromCoq.Init.Logic
:But MII arguments impede our progress:
I don't know I hope someone could shed some light on it.
By default, the directive
Set Implicit Arguments.
declares non-maximally inserted implicit arguments. So Coq is conservative (but not too much) about the level of implicitness. I'd stick to non-MII arguments by default, inserting{}
where appropriate.