The search for instances of canonical structures in this case is an intuitive counter. Suppose you have the following things:
- structure type
S and type T ; - field
proj : S -> T of S ; - element
x : T ; and - an
st : S element that was declared canonical, so proj st is defined as x .
In your example, we will have:
S = finTypeT = Typeproj = Finite.sortx = boolst = bool_finType .
The search for the canonical structure is launched only in the following case: when the type checking algorithm tries to find the value in order to correctly fill the hole in the equation proj _ = x . He will then use st : S to fill this hole. In your example, you expected the algorithm to understand that bool can be used as finType , converting it to bool_finType , which is not quite what is described above.
To get Coq to do what you want, you need to use the join problem of this form. For instance,
Variable P : finType -> Prop. Check ((fun (T : finType) (x : T) => PT) _ true).
What's going on here? Remember that Finite.sort declared as coercion from finType to Type , so x : T really means x : Finite.sort T When you apply the fun expression to true : bool , Coq should find a solution for Finite.sort _ = bool . Then it finds bool_finType because it was declared as canonical. So the bool element is what launches the search, but not quite the bool itself.
As ejgallego noted, this pattern is so common that ssreflect provides a special syntax [finType of ...] . But it may be useful to understand what is happening under the hood.
source share