I'm trying to create a Hint Rewrite database for a matrix library I've written. However when I write
Hint Rewrite kron_1_r : M_db
I get the following error:
Cannot infer the implicit parameter m of kron_1_r whose type is "nat".
kron_1_r has the type forall {m n : nat} (A : Matrix m n), A ⊗ Id 1 = A, so m and n should be inferred based on the context when autorewrite is called. I'm not sure why it wants a parameter here, or how to tell it to hold off.
You're running into the difference between maximally inserted implicit arguments and normal implicit arguments. The difference is exactly when you use a definition without giving any arguments, the way you are in Hint Rewrite kron_1_r. One solution is of course to use #kron_1_r, which gives the identifier without any implicit arguments.
Unfortunately there's no syntax when creating a definition to give it non-maximally inserted implicit arguments; you can only use {m : nat}. Instead, you'll need to use Arguments kron_1_r [m n] _. after creating kron_1_r to change the implicit behavior of the first two arguments (as suggested by Anton Trunov above).
It's often helpful to use About, which reports the status of implicit arguments (you get these with Print as well, but you usually get too much output when you print theorems since proof terms are large).
Related
I've been trying to understand what Set is after encountering it in Adam Chlipala's book in addition to this great discussion in SO. His first example definition binary ops using Set:
Inductive binop : Set := Plus | Times.
in that book he says:
Second, there is the : Set fragment, which declares that we are defining a datatype that should be thought of as a constituent of programs.
Which confuses me. What does Adam mean here?
In addition, I thought that some additional concrete examples would help my understanding. I am not an expert of Coq so I am not sure what type of examples would help but something simple and very concrete/grounded might be useful.
Note, I have seen that Set is the first "type set" in a the type hierarchy e.g. Set = Type(0) <= Type = Type(1) <= Type(2) <= ... . I guess this sort of makes sense intuitively like I'd assume nat \in Type and all usual programming types to be in it but not sure what would be in Type that wouldn't be in Set. Perhaps recursive types? Not sure if that is the right example but I am trying to wrap my head around what this concept means and it's conceptual (& practical) usefulness.
Though Set and Type are different in Coq, this is mostly due to historical reasons. Nowadays, most developments do not rely on Set being different from Type. In particular, Adam's comment would also make sense if you replace Set by Type everywhere. The main point is that, when you want to define a datatype that you can compute with during execution (e.g. a number), you want to put it in Set or Type rather than Prop. This is because things that live in Prop are erased when you extract programs from Coq, so something defined in Prop would end up not computing anything.
As for your second question: Set is something that lives in Type, but not in Set, as the following snippet shows.
Check Set : Type. (* This works *)
Fail Check Set : Set.
(* The command has indeed failed with message: *)
(* The term "Set" has type "Type" while it is expected to have type *)
(* "Set" (universe inconsistency: Cannot enforce Set+1 <= Set). *)
This restriction is in place to prevent paradoxes in the theory. This is pretty much the only difference you see between Set and Type by default. You can also make them more different by invoking Coq with the -impredicative-set option:
(* Needs -impredicative-set; otherwise, the first line will also fail.*)
Check (forall A : Set, A -> A) : Set.
Universe u.
Fail Check (forall A : Type#{u}, A -> A) : Type#{u}.
(* The command has indeed failed with message: *)
(* The term "forall A : Type, A -> A" has type "Type#{u+1}" *)
(* while it is expected to have type "Type#{u}" (universe inconsistency: Cannot enforce *)
(* u < u because u = u). *)
Note that I had to add the Universe u. declaration to force the two occurrences of Type to be at the same level. Without this declaration, Coq would silently put the two Types at different universe levels, and the command would be accepted. (This would not mean that Type would have the same behavior as Set in this example, since Type#{u} and Type#{v} are different things when u and v are different!)
If you're wondering why this feature is useful, it is not by chance. The overwhelming majority of Coq developments does not rely on it. It is turned off by default because it is incompatible with a few axioms that are generally considered more useful in Coq developments, such as the strong law of the excluded middle:
forall A : Prop, {A} + {~ A}
With -impredicative-set turned on, this axiom yields a paradox, while it is safe to use by default.
I'm a bit confused trying to define some structures using the math-comp library. I want to define a structure that has a function ranging from a set of values and returning lists of other values. I'm trying to define this structure as finType but it is failing (I assume it is because I am returning a list of unknown size).
For example:
Section MySection.
Variables F V : finType.
Structure m := M {
f : {ffun F -> seq V};
...
}.
(* Using the PcanXXXMixin family of lemmas *)
Lemma can_m_of_prod : cancel prod_of_m m_of_prod.
Proof. by case. Qed.
...
Definition m_finMixin := CanFinMixin can_m_of_prod.
This throws the error Unable to unify.
I think the issue is that I am using seq and this is not finite. I am not sure how to describe that it will only return finite lists. I thought I might use n-tuples but this would require specifying a size beforehand (I could include the size along with the F value perhaps? I'm not sure how that would look in this notation).
Is there something I am missing or is there another approach that seems more adequate?
Thanks in advance!
I suggest you specify the bound function directly on the type. This is for example used in Stefania Dumbrava's PhD to bound the maximum arity of a signature and works well if you know the trick:
f : {ffun n -> (bound ...).-tuple A}
Usually bound := \max_S ..., so it works well with the rest of the theory.
I'm getting a type error in the last line of the following program:
Require Import List.
Import ListNotations.
(* This computes to 10 *)
Compute (fold_right plus 0 [1;2;3;4]).
(* I want this to compute to [5;6;7;8] but it gives a type error instead *)
Compute (fold_right app [] [[5;6]; [7;8]]).
This is the error I get:
Error:
The term "app" has type "forall A : Type, list A -> list A -> list A" while it is expected to have type
"Type -> ?A -> ?A" (cannot instantiate "?A" because "A" is not in its scope).
I don't really understand why I am getting this error. What is different between app and plus here?. Does it have to do with app being polymorphic while plus is a monomorphic nat -> nat -> nat function?
In case that matters, my version of Coq is 8.5.
You guessed it right: it does have something to do with app being polymorphic. The problem is that Coq allows implicit arguments to be inferred differently depending on whether the corresponding term is applied to arguments or not. More precisely, non-maximal implicits are only inserted when the term is applied to something, but not inserted if the term is used on its own, like your app. There are two ways to remedy the situation:
1- Force Coq to infer something for that instance, as in fold_right (#app _) [] [[5; 6]; [7; 8]].
2- Use a global declaration that will make the type argument maximally inserted: Arguments app {_} _ _.. For more details on what this is doing, check the reference manual
What does the keyword/command "Some" mean in coq?
Furthermore, how can I look up its definition? Using coq some doesn't really help much given popularity of the word some.
Some is a type constructor of the option type. You can get some infos about such constructor by Checking or Printing them, to get their type or their full implementation.
Edit: what is the option type.
It is a type defined in Coq's prelude (again, use Check or Print to get info on this type). The type is used to state facts about the optional presence of a type: for any type A, None : option A means that there is no value, and Some A: option A means that there is a value (of type A).
Here is an example with the predecessor of a natural number:
Definition myPred (n:nat) : option nat := match n with
| S p => Some p
| O => None
end.
In this example, if you try to compute the predecessor of O, you'll get None (there is no such natural number). Otherwise, you get Some p such that S p = n.
I'm having a hard time understanding Higher Kind vs Higher Rank types. Kind is pretty simple (thanks Haskell literature for that) and I used to think rank is like kind when talking about types but apparently not! I read the Wikipedia article to no avail. So can someone please explain what is a Rank? and what is meant by Higher Rank? Higher Rank Polymorphism? how that comes to Kinds (if any) ? Comparing Scala and Haskell would be awesome too.
The concept of rank is not really related to the concept of kinds.
The rank of a polymorphic type system describes where foralls may appear in types. In a rank-1 type system foralls may only appear at the outermost level, in a rank-2 type system they may appear at one level of nesting and so on.
So for example forall a. Show a => (a -> String) -> a -> String would be a rank-1 type and forall a. Show a => (forall b. Show b => b -> String) -> a -> String would be a rank-2 type. The difference between those two types is that in the first case, the first argument to the function can be any function that takes one showable argument and returns a String. So a function of type Int -> String would be a valid first argument (like a hypothetical function intToString), so would a function of type forall a. Show a => a -> String (like show). In the second case only a function of type forall a. Show a => a -> String would be a valid argument, i.e. show would be okay, but intToString wouldn't be. As a consequence the following function would be a legal function of the second type, but not the first (where ++ is supposed to represent string concatenation):
higherRankedFunction(f, x) = f("hello") ++ f(x) ++ f(42)
Note that here the function f is applied to (potentially) three different types of arguments. So if f were the function intToString this would not work.
Both Haskell and Scala are Rank-1 (so the above function can not be written in those languages) by default. But GHC contains a language extension to enable Rank-2 polymorphism and another one to enable Rank-n polymorphism for arbitrary n.