From what I have read, eq_rect and equality seem deeply interlinked. Weirdly, I'm not able to find a definition on the manual for it.
Where does it come from, and what does it state?
If you use Locate eq_rect you will find that eq_rect is located in Coq.Init.Logic, but if you look in that file there is no eq_rect in it. So, what's going on?
When you define an inductive type, Coq in many cases automatically generates 3 induction principles for you, appending _rect, _rec, _ind to the name of the type.
To understand what eq_rect means you need its type,
Check eq_rect.
here we go:
eq_rect
: forall (A : Type) (x : A) (P : A -> Type),
P x -> forall y : A, x = y -> P y
and you need to understand the notion of Leibniz's equality:
Leibniz characterized the notion of equality as follows:
Given any x and y, x = y if and only if, given any predicate P, P(x) if and only if P(y).
In this law, "P(x) if and only if P(y)" can be weakened to "P(x) if P(y)"; the modified law is equivalent to the original, since a statement that applies to "any x and y" applies just as well to "any y and x".
Speaking less formally, the above quotation says that if x and y are equal, their "behavior" for every predicate is the same.
To see more clearly that Leibniz's equality directly corresponds to eq_rect we can rearrange the order of parameters of eq_rect into the following equivalent formulation:
eq_rect_reorder
: forall (A : Type) (P : A -> Type) (x y : A),
x = y -> P x -> P y
Related
I'm trying to write a macro, called different, to test whether two user-provided arguments are provisionally eq, where the arguments may be bound or unbound. But I'm getting lost in the possibilities (and perhaps logic). The following seems to work, but needs enhancement (including avoiding variable capture and multiple evaluation):
(defmacro different (item1 item2)
`(not (eq (if (boundp ',item1) ,item1 ',item1)
(if (boundp ',item2) ,item2 ',item2))))
The basic idea is to look for any unbound variable, quote it, and then see if that is eq to the value of the other variable. (The goal is to save the end-user from having to decide when to quote arguments, since bound variables are otherwise marked.)
So now:
if x is unbound and y is bound to 'x, or
y is unbound and x is bound to 'y
(different x y) => NIL
if x is unbound and y is bound to 'z, or
y is unbound and x is bound to 'z
(different x y) => T
The main problem is that item1 or item2 can be designators for arbitrary lisp objects (in which case equalp would be substituted for eq). For example:
(defparameter x 3)
(different x 3) => NIL (since they are equalp)
(defparameter x '(a b c))
(different x (c b a)) => T (where (c b a) gets quoted)
Can this be factored into the macro, and can the if statements be brought outside the backquote?
There are only six cases to deal with
Here is a mapping of what is to be done:
For b ≡ bound symbol
For u ≡ unbound symbol
For e ≡ any other value
b b -> eq
b u -> equalp
u u -> equalp
e e -> equalp
e u -> ERROR (makes no sense)
e b -> equalp
Hopefully this helps you organize your branching logic. I like to pull some paper and work through branching when I get an explosion like this. Normally it is possible to reduce it using predicate calculus, or come up with another representation that has less branches.
I'm trying to check the equality between two integers in Coq, but I get this error: "The term "first = second" has type "Prop" which is not a (co-)inductive type.". Is there any library in Coq that provides equality checking? Here is my code:
Definition verify_eq (first : Z) (second : Z) : Z :=
if first = second then 0 else 1.
You're in luck! In the same module where Z is defined (I'm assuming ZArith in the standard library), there's a term Z.eqb : Z -> Z -> bool that gives a a boolean test for integer equality (technically it's in the submodule Z — that's why there's a Z in the name).
Require Import ZArith. (* I assume you already imported this, since you're using Z *)
Definition verify_eq (first : Z) (second : Z) : Z :=
if Z.eqb first second then 0 else 1.
I need to rely on the fact that two Z3 variables
can not have the same name.
To be sure of that,
I've used tuple_example1() from test_capi.c in z3/examples/c and changed the original code from:
// some code before that ...
x = mk_real_var(ctx, "x");
y = mk_real_var(ctx, "y"); // originally y is called "y"
// some code after that ...
to:
// some code before that ...
x = mk_real_var(ctx, "x");
y = mk_real_var(ctx, "x"); // but now both x and y are called "x"
// some code after that ...
And (as expected) the output changed from:
tuple_example1
tuple_sort: (real, real)
prove: get_x(mk_pair(x, y)) = 1 implies x = 1
valid
disprove: get_x(mk_pair(x, y)) = 1 implies y = 1
invalid
counterexample:
y -> 0.0
x -> 1.0
to:
tuple_example1
tuple_sort: (real, real)
prove: get_x(mk_pair(x, y)) = 1 implies x = 1
valid
disprove: get_x(mk_pair(x, y)) = 1 implies y = 1
valid
BUG: unexpected result.
However, when I looked closer, I found out that Z3 did not really fail or anything, it is just a naive (driver) print out to console.
So I went ahead and wrote the exact same test with y being an int sort called "x".
To my surprise, Z3 could handle two variables with the same name when they have different sorts:
tuple_example1
tuple_sort: (real, real)
prove: get_x(mk_pair(x, y)) = 1 implies x = 1
valid
disprove: get_x(mk_pair(x, y)) = 1 implies y = 1
invalid
counterexample:
x -> 1.0
x -> 0
Is that really what's going on? or is it just a coincidence??
Any help is very much appreciated, thanks!
In general, SMT-Lib does allow repeated variable names, so long as they have different sorts. See page 27 of the standard. In particular, it says:
Concretely, a variable can be any symbol, while a function symbol
can be any identifier (i.e., a symbol or an indexed symbol). As a
consequence, contextual information is needed during parsing to know
whether an identifier is to be treated as a variable or a function
symbol. For variables, this information is provided by the three
binders which are the only mechanism to introduce variables. Function
symbols, in contrast, are predefined, as explained later. Recall that
every function symbol f is separately associated with one or more
ranks, each specifying the sorts of f’s arguments and result. To
simplify sort checking, a function symbol in a term can be annotated
with one of its result sorts σ. Such an annotated function symbol is a
qualified identifier of the form (as f σ).
Also on page 31 of the same document, it further clarifies "ambiguity" thusly:
Except for patterns in match expressions, every occurrence of an
ambiguous function symbol f in a term must occur as a qualified
identifier of the form (as f σ) where σ is the intended output sort of
that occurrence
So, in SMT-Lib lingo, you'd write like this:
(declare-fun x () Int)
(declare-fun x () Real)
(assert (= (as x Real) 2.5))
(assert (= (as x Int) 2))
(check-sat)
(get-model)
This produces:
sat
(model
(define-fun x () Int
2)
(define-fun x () Real
(/ 5.0 2.0))
)
What you are observing in the C-interface is essentially a rendering of the same. Of course, how much "checking" is enforced by the interface is totally solver specific as SMT-Lib says nothing about C API's or API's for other languages. That actually explains the BUG line you see in the output there. At this point, the behavior is entirely solver specific.
But long story short, SMT-Lib does indeed allow two variables have the same name used so long as they have different sorts.
In the Idris Tutorial a function for filtering vectors is based on dependent pairs.
filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
filter f [] = (_ ** [])
filter f (x :: xs) with (filter f xs )
| (_ ** xs') = if (f x) then (_ ** x :: xs') else (_ ** xs')
But why is it necessary to put this in terms of a dependent pair instead of something more direct such as?
filter' : (a -> Bool) -> Vect n a -> Vect p a
In both cases the type of p must be determined, but in my supposed alternative the redundancy of listing p twice is eliminated.
My naive attempts at implementing filter' failed, so I was wondering is there a fundamental reason that it can't be implemented? Or can filter' be implemented, and perhaps filter was just a poor example to showcase dependent pairs in Idris? But if that is the case then in what situations would dependent pairs be useful?
Thanks!
The difference between filter and filter' is between existential and universal quantification. If (a -> Bool) -> Vect n a -> Vect p a was the correct type for filter, that would mean filter returns a Vector of length p and the caller can specify what p should be.
Kim Stebel's answer is right on the money. Let me just note that this was already discussed on the Idris mailing list back in 2012 (!!):
filter for vector, a question - Idris Programming Language
What raichoo posted there can help clarifying it I think; the real signature of your filter' is
filter' : {p : Nat} -> {n: Nat} -> {a: Type} -> (a -> Bool) -> Vect a n -> Vect a p
from which it should be obvious that this is not what filter should (or even could) do; p actually depends on the predicate and the vector you are filtering, and you can (actually need to) express this using a dependent pair. Note that in the pair (p ** Vect p a), p (and thus Vect p a) implicitly depends on the (unnamed) predicate and vector appearing before it in its signature.
Expanding on this, why a dependent pair? You want to return a vector, but there's no "Vector with unknown length" type; you need a length value for obtaining a Vector type. But then you can just think "OK, I will return a Nat together with a vector with that length". The type of this pair is, unsurprisingly, an example of a dependent pair. In more detail, a dependent pair DPair a P is a type built out of
A type a
A function P: a -> Type
A value of that type DPair a P is a pair of values
x: a
y: P a
At this point I think that is just syntax what might be misleading you. The type p ** Vect p a is DPair Nat (\p => Vect p a); p there is not a parameter for filter or anything like it. All this can be a bit confusing at first; if so, maybe it helps thinking of p ** Vect p a as a substitute for the "Vector with unknown length" type.
Not an answer, but additional context
Idris 1 documentation - https://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#dependent-pairs
Idris 2 documentation - https://idris2.readthedocs.io/en/latest/tutorial/typesfuns.html?highlight=dependent#dependent-pairs
In Idris 2 the dependent pair defined here
and is similar to Exists and Subset but BOTH of it's values are NOT erased at runtime
Type-Driven Development with Idris presents:
twoPlusTwoNotFive : 2 + 2 = 5 -> Void
twoPlusTwoNotFive Refl impossible
Is the above a function or value? If it's the former, then why is there no variable arguments, e.g.
add1 : Int -> Int
add1 x = x + 1
In particular, I'm confused at the lack of = in twoPlusTwoNotFive.
impossible calls out combinations of arguments which are, well, impossible. Idris absolves you of the responsibility to provide a right-hand side when a case is impossible.
In this instance, we're writing a function of type (2 + 2 = 5) -> Void. Void is a type with no values, so if we succeed in implementing such a function we should expect that all of its cases will turn out to be impossible. Now, = has only one constructor (Refl : x = x), and it can't be used here because it requires ='s arguments to be definitionally equal - they have to be the same x. So, naturally, it's impossible. There's no way anyone could successfully call this function at runtime, and we're saved from having to prove something that isn't true, which would have been quite a big ask.
Here's another example: you can't index into an empty vector. Scrutinising the Vect and finding it to be [] tells us that n ~ Z; since Fin n is the type of natural numbers less than n there's no value a caller could use to fill in the second argument.
at : Vect n a -> Fin n -> a
at [] FZ impossible
at [] (FS i) impossible
at (x::xs) FZ = x
at (x::xs) (FS i) = at xs i
Much of the time you're allowed to omit impossible cases altogether.
I slightly prefer Agda's notation for the same concept, which uses the symbol () to explicitly pinpoint which bit of the input expression is impossible.
twoPlusTwoNotFive : (2 + 2 ≡ 5) -> ⊥
twoPlusTwoNotFive () -- again, no RHS
at : forall {n}{A : Set} -> Vec A n -> Fin n -> A
at [] ()
at (x ∷ xs) zero = x
at (x ∷ xs) (suc i) = at xs i
I like it because sometimes you only learn that a case is impossible after doing some further pattern matching on the arguments; when the impossible thing is buried several layers down it's nice to have a visual aid to help you spot where it was.