Is there a way to enforce that when a typeclass is used, a particular instance is immediately found?
Right, now I'm getting an existential variable when there is no instance available, but I want to get an error.
A simple example will explain much better what I'm trying to achieve. I'm trying to get a function evaluation with implicit casting for certain types. In this case I want to have only one possible implicit cast X' -> X.
Class Evaluation (A B C : Type) : Type :=
{
cast_eval : (A -> B) -> C -> B
}.
Instance DirectEvaluation (A B : Type) : Evaluation A B A :=
{
cast_eval := fun f x => f x
}.
Parameter (X X' X'' Y : Type) (f : X -> Y) (x : X) (x' : X') (x'' : X'') (x_cast : X' -> X).
Instance XDashEvaluation : Evaluation X Y X' :=
{
cast_eval := fun ff xx => f (x_cast xx)
}.
Compute (cast_eval f x). (* f x *)
Compute (cast_eval f x'). (* f (x_cast x') *)
Compute (cast_eval f x''). (* (let (cast_eval) := ?Evaluation in cast_eval) f x'' *)
Is there a way to get an error when calling (cast_eval f x'')?
One way to get an error would be make a Definition first:
Definition e := cast_eval f x''.
Compute e.
Related
All
I am trying to understand the Church numerals, mentioned in the SF-LF book, chp4.
Definition cnat := forall X : Type, (X -> X) -> X -> X.
Definition one : cnat :=
fun (X : Type) (f : X -> X) (x : X) => f x.
Check cnat.
Check one.
And I get
cnat
: Type
one
: cnat
It seems cnat is some kind of type, and function at the same time. How can it be both type and function? Anyone can help explain a little more about this?
The "forall (X : Type)," syntax is a way to form a type, from a type parameterized by X. forall (X : Type), (X -> X) -> X -> X is a type of functions, which given a type X produce a value of type (X -> X) -> X -> X (which is itself a function).
The "fun (X : Type) =>" syntax is a way to form a function, from a term parameterized by X. fun (X : Type) (f : X -> X) (x : X) => f x is a function, which given a type X produce the function fun (f : X -> X) (x : X) => f x (which is itself a function).
What fun and forall have in common is that they involve binders, like (X : Type) (also like (f : X -> X), (x : X)). fun is a construct that involves binders to form functions, but not all constructs that involve binders form functions: forall is a construct that involves binders to form types.
So i was doing an exercise for learning coq. and I was trying to defind a type according to this encoding:
forall X.(X -> X) -> X -> X;`and this is from Alonzo Church(he proposed an encoding for natural number) as below:
0 , f:x:x
1 , f:x:fx
2 , f:x:f(fx)
3 , f:x:f(f(fx))
.....
n , f:x:fnx:
My code is like below:
Definition nat := forall X : Type, (X -> X) -> X -> X.
And the exercise require me to define expressions zero,one,two and three that encode the corresponding numbers as elements of nat:
Below is what I thought it will be
Definition zero : nat :=
fun (X : Type) (f : X -> X) (x : X) => x.
Definition one : nat :=
fun (X : Type) (f : X -> X) (x : X) => f x.
Definition two : nat :=
fun (X : Type) (f : X -> X) (x : X) => f (f x).
Definition three : nat :=
fun (X:Type)(f: X -> X)(x: X) => f ( f ( f x )).
My question is I need to prove that the plus n one = succ n. and the n is my defined type Nat
I have a succ function defined as below:
Definition succ (n : nat) : nat :=
fun (X : Type) (f : X -> X) (x : X) => f (n X f x).
my plus function defined as below:
Definition plus (n m : nat) : nat :=
fun (X : Type) (f : X -> X) (x : X) => (n X f (m X f x)).
The thing is when I tried to prove plus n one = succ n, I stuck in the middle and have no idea how to prove.
code as below:
Theorem plus_succ: forall (n : nat),
plus n one = succ n.
Proof.
intros.
1 subgoal
n : nat
______________________________________(1/1)
plus n one = succ n
and there's no way I can do inversion or any other tactic...(I am new to Coq, I've learnt list,poly,induction and tactics so far)
So that brings me to the thought that probably one, two or maybe all of my definition I defined above are not accurate.
Tons of appreciation if anyone can help me or give me some hints! Thankssss!
Using Church encodings in Coq is not a bad idea per-se, but you won't be able to say much about the inhabitants of this type (beside constructing some of them as you did).
The first issue is that inhabitants of this Church encoding are functions, and you will be able to show that two functions are equal in pure Coq only if they compute to the same value (up to unfolding, beta-reductions, reductions of match and fixes).
This is not the case for plus n one and succ n: you have on the lhs fun X f x => f (n X f x) and on the rhs fun X f x => n X f (f x). What you could hope to prove is forall (X : type) (f : X -> X) (x : X), f (n X f x) = n X f (f x), and you would then need to use functional extensionality, an axiom stating that the equality between functions is determined by the value of the functions at each point of their domain (see Coq.Logic.FunctionalExtensionality in the stdlib for more details on that point). This axiom is frequently assumed, but it is not innocent either (e.g. it does block computations).
The second issue you will run into is that you expect the inhabitants of nat = forall X, (X -> X) -> X -> X to be functions parametric in their first argument X : Type, but there is nothing actually enforcing that. Indeed, you can construct non-parametric inhabitants if you assume additional axioms, for instance excluded-middle. In pure Coq (without any axiom), there are results due to Bernardy and Lasson that show that indeed all inhabitants of your type nat are parametric, however you cannot internalize this result. And without parametricity, you have no bullets to prove equations such as f (n X f x) = n X f (f x).
So your troubles come from these two issues:
in absence of functional extensionality, the equalities that you can prove between functions are quite limited, and
you are not able in pure Coq to express internally that a quantification over types is parametric.
If you want to learn more about these issues on parametricity and what can still be achieved using Church encodings (or variants of these), I would recommend having a look at Chlipala's Parametric Higher-Order Abstract Syntax.
I'm trying to prove that injective functions are left invertible in Coq. I've reached a point in my proof where my goal is an "exists" proposition. I want to define a function that uses terms from proof scope (types and functions I've intro'ed before) and then show the function to the "exists" goal. Here's what I wrote so far:
(* function composition *)
Definition fun_comp {A B C: Type} (f:A -> B) (g:B -> C) : A -> C :=
fun a: A => g (f a).
Notation "g .o f" := (fun_comp f g) (at level 70).
Definition nonempty (A: Type) := exists a: A, a = a.
(* identity function for any given type *)
Definition fun_id (A: Type) := fun a: A => a.
(* left invertible *)
Definition l_invertible {A B: Type} (f: A -> B) :=
exists fl:B->A, fl .o f = fun_id A.
Definition injective {A B: Type} (f: A -> B) :=
forall a a': A, f a = f a' -> a = a'.
(* is a given element in a function's image? *)
Definition elem_in_fun_image {A B: Type} (b: B) (f: A -> B) :=
exists a: A, f a = b.
Theorem injective_is_l_invertible:
forall (A B: Type) (f: A -> B), nonempty A /\ injective f -> l_invertible f.
Proof.
intros A B f H.
destruct H as [Hnempty Hinj].
unfold l_invertible.
unfold nonempty in Hnempty.
destruct Hnempty as [a0].
(* here would go my function definition and invoking "exists myfun" *)
Here's the function I'm trying to define:
Definition fL (b: B) := if elem_in_fun_image b f
then f a
else a0.
Here's what the proof window looks like:
1 subgoal
A : Type
B : Type
f : A -> B
a0 : A
H : a0 = a0
Hinj : injective f
========================= (1 / 1)
exists fl : B -> A, (fl .o f) = fun_id A
How do I do this? I'm very new to Coq so other comments and pointers are welcome.
This definition cannot be performed in the basic logic. You need to add in a few extra axioms:
(* from Coq.Logic.FunctionalExtensionality *)
functional_extensionality : forall A B (f g : A -> B),
(forall x, f x = g x) -> f = g
(* from Coq.Logic.Classical *)
classic : forall P : Prop, P \/ ~ P
(* from Coq.Logic.ClassicalChoice *)
choice : forall (A B : Type) (R : A->B->Prop),
(forall x : A, exists y : B, R x y) ->
exists f : A->B, (forall x : A, R x (f x)).
The goal is to define a relation R that characterizes the left inverse that you want to construct. The existentially quantified f will then be the inverse! You will need the classic axiom to show the precondition of choice, and you will need functional extensionality to show the equation that you want. I'll leave it as an exercise to find out what R needs to be and how to complete the proof.
Your script should start with the following line.
Require Import ClassicalChoice FunctionalEquality.
Because, as suggested by #arthur-azevedo-de-amorim, you will need these axioms.
Then, you should use choice with the relation "R y x" being
"f x = A or there is no element in A such whose image by f is y".
You will need the axiom classic to prove the existential statement that is required by choice:
assert (pointwise : forall y: B, exists x : A,
f x = y \/ (forall x : A f x <> y)).
choice will give you an existential statement for a function that returns the value you want. You only need to say that this function is the right one. You can give a name to that function by typing destruct (choice ... pointwise) (you have to fill in the ...).
You will have to prove an equality between two functions, but using the axiom functional_extensionality, you can reduce this problem to just proving that the two functions are equal on any x.
For that x, just instantiate the characteristic property of the function (as produced by destruct (choice ... pointwise) with the
value f x. There is a disjuction, but the right-hand side case is self-contradictory, because obviously f x is f x for some x.
For the left-hand side case, you will get an hypothesis of the form (I name the function produced by (choice ... pointwise) with the name it:
f (it (f x)) = f x
Here you can apply your injectivity assumption. to deduce that it (f x) = x.
This pretty much spells out the proof. In my own, experiment, I used classic, NNP, not_all_ex_not, functional_extensionality, which are lemmas coming from ClassicalChoice of FunctionalEquality.
Most probably I'm trying to achieve something flawed, but I'm running into a need to have a constructor in the definition of another constructor.
Silly example:
Inductive silly_type : Type :=
| constr1 : nat -> silly_type
| constr2 : forall (x : silly_type), (exists n : nat, (x = constr1 n)) -> silly_type.
There are two ways how to create elements of silly_type, either with natural number and constr1 or using constr2 and element of silly_type that was created with constr1.
The above definition of silly_type is not valid in coq, but I do not know how to overcome this in my less silly example.
Less silly example:
I'm trying to have an inductive type expr representing typed expressions.
Let's first start with an inductive type representing types:
Inductive type : Type :=
| base_type : nat -> type
| arrow_type : type -> type -> type
| iso_arrow_type : type -> type -> type.
There are some base types indexed with integers, arrow_type representing function between types and iso_arrow_type representing invertible functions between types.
Notation:
Notation "A --> B" := (arrow_type A B) (at level 30, right associativity).
Notation "A <-> B" := (iso_arrow_type A B).
Type for expressions:
Inductive expr : type -> Type :=
| var : forall (X : type) (n : nat), expr X
| eval : forall {X Y : type} (f : expr (X --> Y)) (x : expr X), expr Y
| inv : forall {X Y : type}, expr ((X <-> Y) --> (Y <-> X))
| to_fun : forall {X Y : type}, expr ((X <-> Y) --> (X --> Y))
| to_iso : forall {X Y : type} (f : expr (X --> Y)), (is_invertible f) -> expr (Y --> X).
You can create an indexed variables of any type with var, evaluate a function with eval, invert an invertible function with inv, cast an invertible function to the actual function with to_fun such that you can evaluate it with eval.
The problem is with the last constructor to_iso. Sometimes, I will know that a function(element of X --> Y) is actually invertible and I want some mechanism to cast it to the type X <-> Y.
However, to define is_invertible I think that I need to use eval. This leads me to the problem that the constructor eval needs to be in the definition of the constructor to_iso.
To define is_invertible, we first need to define a notion of equality of expr:
Inductive ExprEq : forall (X : type), X -> X -> Prop :=
| expr_eq_refl : forall {X : type}, forall (x : X), ExprEq X x x
| eq_on_values : forall {X Y : type}, forall (f g : (X --> Y)), (forall (x : X), f[x] == g[x]) -> f == g
where
"x == y" := (ExprEq _ x y) and "f [ x ]" := (eval f x) and "x =/= y" := (not (ExprEq _ x y)).
Thus, we have standard reflexivity x == x and equality of functions f==g can be decided by equality on all elements f[x]==g[x].
Now, we are ready to define is_invertible:
Definition is_invertible {X Y : type} (f : X --> Y) : Prop := exists g : Y --> X, (forall x, g[f[x]] == x) /\ (forall y, f[g[y]] == y).
This definition of is_invertible is problematic, it is using eval(f[x] := (eval f x)). Furthermore, the problem is a bit more complicated. We need to define the type ExprEq that already uses eval to define its constructors.
Constrain: keep expr decidable
What I really want to preserve is that the equality(=) of expr is decidable, i.e. being able to prove
Lemma eq_expr_dec {X : type} (x y : type) : {x=y} + {x<>y}.
I really do not care about decidability of the defined equality ==, but decidability of = is important for me.
You can use dependent types to index your constructors. For example
Inductive silly_type : nat -> Type :=
| constr1 : nat -> silly_type 0
| constr2 : silly_type 0 -> silly_type 1.
So you can only use values produced by constr1 in constr2. This approach should work in general to distinguish values created with different constructors.
I am writing a small program so that I can work some proofs of deMorgans laws using the type introduction/elimination rules from the HoTT book (et. al.). My model/example code is all here, https://mdnahas.github.io/doc/Reading_HoTT_in_Coq.pdf. So far I have,
Definition idmap {A:Type} (x:A) : A := x.
Inductive prod (A B:Type) : Type := pair : A -> B -> #prod A B.
Notation "x * y" := (prod x y) : type_scope.
Notation "x , y" := (pair _ _ x y) (at level 10).
Section projections.
Context {A : Type} {B : Type}.
Definition fst (p: A * B ) :=
match p with
| (x , y) => x
end.
Definition snd (p:A * B ) :=
match p with
| (x , y) => y
end.
End projections.
Inductive sum (A B : Type ) : Type :=
| inl : A -> sum A B
| inr : B -> sum A B.
Arguments inl {A B} _ , [A] B _.
Arguments inr {A B} _ , A [B].
Notation "x + y" := (sum x y) : type_scope.
Inductive Empty_set:Set :=.
Inductive unit:Set := tt:unit.
Definition Empty := Empty_set.
Definition Unit := unit.
Definition not (A:Type) : Type := A -> Empty.
Notation "~ x" := (not x) : type_scope.
Variables X:Type.
Variables Y:Type.
Goal (X * Y) -> (not X + not Y).
intro h. fst h.
Now I don't really know what the problem is. I've examples of people using definitions, but they always involve "Compute" commands, and I want to apply the rule fst to h to get x:X, so they are not helpful.
I tried "apply fst." which got me
Error: Cannot infer the implicit parameter B of fst whose type is
"Type" in environment:
h : A * B
In a proof context, Coq expects to get tactics to execute, not expressions to evaluate. Since fst is not defined as a tactic, it will give Error: The reference fst was not found in the current environment.
One possible tactic to execute along the lines of what you seem to be trying to do is set:
set (x := fst h).
I want to apply the rule fst to h to get x:X
I believe you can do
apply fst in h.
If you just write apply fst, Coq will apply the fst rule to the goal, rather than to h. If you write fst h, as Daniel says in his answer, Coq will attempt to run the fst tactic, which does not exist. In addition to Daniel's set solution, which will change the goal if fst h appears in it (and this may or may not be what you want), the following also work:
pose (fst h) as x. (* adds x := fst h to the context *)
pose proof (fst h) as x. (* adds opaque x : X to the context, justified by the term fst h *)
destruct h as [x y]. (* adds x : X and y : Y to the context, and replaces h with pair x y everywhere *)