My understanding of row polymorphism in ML is that we can access the row variable within the function.
fun f {x : real, y : real, R} = {x = 2 * x, y = 2 * y, R};
=> (* f : {x : real, y : real, _ : ..a} -> {x : real, y : real, _ : ..a} *)
f {x = 2.0, y = 3.0, z = 4.0};
=> (* it = {x = 4.0, y = 6.0, z = 4.0}; *)
Just curious if this is possible in PureScript.
I assume you want to update some properties of a record without discarding the other properties:
f :: forall r. { x :: Int, y :: Int | r } -> { x :: Int, y :: Int | r }
f r = r { x = r.x * 2, y = r.y * 2 }
Related
I'm attempting to use Fix to express a well-founded function.
It has Fix_eq to unwrap it for 1 level, however, the confusing
part is that Fix_eq is expressed in terms of Fix_sub instead of Fix.
The difference appears to be that
Check Fix.
(* ... *)
(forall x : A, (forall y : A, R y x -> P y) -> P x) ->
Check Fix_sub.
(* ... *)
(forall x : A, (forall y : {y : A | R y x}, P (proj1_sig y)) -> P x) ->
Fix uses 2 arguments and Fix_sub packages them both together into a sig.
So, they are essentially equivalent. However, I don't see any included
convenience functions to switch between Fix and Fix_sub. Is there
a reason that Fix_eq doesn't work with Fix ? How is it supposed
to be used?
I'm aware of Program and Function, but here I am trying to use Fix directly.
Which version and libraries are you using?
in 8.16 I get
Fix_eq:
forall [A : Type] [R : A -> A -> Prop] (Rwf : well_founded R)
(P : A -> Type) (F : forall x : A, (forall y : A, R y x -> P y) -> P x),
(forall (x : A) (f g : forall y : A, R y x -> P y),
(forall (y : A) (p : R y x), f y p = g y p) -> F x f = F x g) ->
forall x : A, Fix Rwf P F x = F x (fun (y : A) (_ : R y x) => Fix Rwf P F y)
and Fib_subis unknown.
You may have imported some module which masks the definitions from Coq.Init.Wf ?
I'm writing Agda code as I read the HoTT book. I'm stuck on Lemma 2.3.9:
data _≡_ {X : Set} : X -> X -> Set where
refl : {x : X} -> x ≡ x
infix 4 _≡_
-- Lemma 2.1.2
_·_ : {A : Set} {x y z : A} -> x ≡ y -> y ≡ z -> x ≡ z
refl · refl = refl
-- Lemma 2.3.1
transp : {A : Set} {P : A -> Set} {x y : A} -> x ≡ y -> P x -> P y
transp refl f = f
lemma2'3'9 : {A : Set}{P : A -> Set}{x y z : A}{p : x ≡ y}{q : y ≡ z}{u : P x} ->
(transp q (transp p u)) ≡ (transp (p · q) u)
lemma2'3'9 {p = refl} {q = refl} = ?
Type-checking with Adga Emacs Mode gives me the following error:
?0 : transp refl (transp refl u) ≡ transp (refl · refl) u
_X_53 : Set [ at /home/user/prog/agda/sample.agda:12,38-39 ]
———— Errors ————————————————————————————————————————————————
Failed to solve the following constraints:
P x =< _X_53 (blocked on _X_53)
Questions
What is '_X_53', and why is it greater than or equal to (P x)?
How can I get rid of this error?
Note
I wrote a working example of Lemma 2.3.9 in Coq, so I'm assuming it's possible in Agda.
Inductive eq {X:Type} (x: X) : X -> Type :=
| refl : eq x x.
Notation "x = y" := (eq x y)
(at level 70, no associativity)
: type_scope.
Definition eqInd{A} (C: forall x y: A, x = y -> Type) (c: forall x: A, C x x (refl x)) (x y: A): forall p: x = y, C x y p :=
fun xy: x = y => match xy with
| refl _ => c x
end.
Definition dot'{A}{x y: A}: x = y -> forall z: A, y = z -> x = z :=
let D := fun x y: A => fun p: x = y => forall z: A, forall q: y = z, x = z in
let d: forall x, D x x (refl x) := let E: forall x z: A, forall q: x = z, Type := fun x z: A => fun q: x = z => x = z in
let e := fun x => refl x
in fun x z => fun q => eqInd E e x z q
in fun p: x = y => eqInd D d x y p.
(* Lemma 2.1.2 *)
Definition dot{A}{x y z: A}: x = y -> y = z -> x = z :=
fun p: x = y => dot' p z.
Definition id {A} := fun a: A => a.
(* Lemma 2.3.1 *)
Definition transp{A} {P: A -> Type} {x y: A}: x = y -> P x -> P y :=
fun p =>
let D := fun x y: A => fun p: x = y => P x -> P y in
let d: forall x, D x x (refl x) := fun x => id
in eqInd D d x y p.
Lemma L_2_3_9{A}{P: A -> Type}{x y z: A}{p: x = y}{q: y = z}{u: P x}:
transp q (transp p u) = transp (dot p q) u.
Proof.
unfold transp, dot, dot'.
rewrite <- q.
rewrite <- p.
reflexivity.
Qed.
_X_53 is a meta variable, i.e., an unknown part of a term. In order to figure out this unknown part of the term, Agda tries to resolve the meta variable. She does so by looking at the context the meta variable appears in, deriving constraints from this context, and determining possible candidate solutions for the meta variable that meet the constraints.
Among other things, Agda uses meta variables to implement implicit arguments. Each implicit argument is replaced with a meta variable, which Agda then tries to resolve within a context that includes the remaining arguments. This is how values for implicit arguments can be derived from the remaining arguments, for example.
Sometimes Agda is unable to figure out an implicit argument, even though one would think that she should be able to. I.e., Agda is unable to resolve the implicit argument's meta variable. This is when she needs a little assistance, i.e., we have to explicitly specify one or more of the implicit arguments. Which is what #gallais suggests in the comment.
=< compares two types. A =< B means that something of type A can be put where something of type B is required. So, if you have a function that takes a B, you can give it an A and it'll type check. I think that this is mostly used for Agda's sized types. In your case, I think, this can be read as type equality instead.
But back to the error message. Agda fails to find a solution for _X_53. The constraint that needs to be met is P x =< _X_53. If, in your case, =< is type equality, then why doesn't Agda simply set _X_53 to P x?
According to my very limited understanding, the reason is higher-order unification, which is a bit of a - to use a very technical term - capricious and finicky beast. _X_53 isn't the complete truth here. Meta variables can be functions and thus have arguments. According to the Agda debug log, the actual unification problem at hand is to unify _X_53 A P x x and P x. If I remember things correctly, then the two xs in the former are a problem. Take this with a grain of salt, though. I'm not a type theorist.
Long story short, sometimes Agda fails to figure out an implicit argument because unification fails and it's a bit hard to understand why exactly.
Finally, something related: The following article talks a bit about best practices for using implicit arguments: Inference in Agda
Update
I guess the two xs are a problem, because they keep Agda from finding a unique solution to the unification problem. Note that both, λ a b c d. P c and λ a b c d. P d would work for _X_53 in that both would make _X_53 A P x x reduce to P x.
Could some explain how to complete this proof? (please don't give the actual answer, just some guidance :)
The exercise is from SF volume1, as stated in the title and it goes like this:
(** **** Exercise: 3 stars, standard (injection_ex3) *)
Example injection_ex3 : forall (X : Type) (x y z : X) (l j : list X),
x :: y :: l = z :: j ->
j = z :: l ->
x = y.
Now, I'm trying to tackle this by injection on H0 after introducing all terms. After injection and rewriting by H2, I end up with the following goal and I have no idea how to move forward.
1 subgoal (ID 174)
X : Type
x, y, z : X
l, j : list X
H2 : x = z
H3 : y :: l = j
H1 : j = z :: l
============================
z = y
It's clear that if I manage to add :: l to both sides of the equation, then I can complete with reflexivity, but what tactic would allow me to add :: l to both sides?
Best regards
From H3 and H1, you should be able to get a hypothesis on which you can use injection again to conclude.
I'm defining an indexed inductive type in Coq:
Module Typ.
(* My index -- a t is a `t H` or a `t Z`. *)
Inductive hz : Set := H | Z .
(* I'd like to use this relation to constrain Cursor and Arrow. *)
(* E.g. one specialized Cursor has type `t H -> t Z -> t Z` *)
Inductive maxHZ : hz -> hz -> hz -> Type :=
| HZ : maxHZ H Z Z
| ZH : maxHZ Z H Z
| HH : maxHZ H H H
.
Inductive t : hz -> Type :=
| Num : t H
| Hole : t H
| Cursor : t H -> t Z
| Arrow : forall a b c, t a -> t b -> t c
| Sum : forall a b c, t a -> t b -> t c
.
End Typ.
How can I constrain my Arrow / Sum indices to be the same shape as the maxHZ relation (short of creating more constructors, like ArrowHZ : t H -> t Z -> t Z).
One approach:
(* Bring the coercion is_true into scope *)
From Coq Require Import ssreflect ssrfun ssrbool.
Module Typ.
(* My index -- a t is a `t H` or a `t Z`. *)
Inductive hz : Set := H | Z .
(* I'd like to use this relation to constrain Cursor and Arrow. *)
(* E.g. one specialized Cursor has type `t H -> t Z -> t Z` *)
Definition maxHZ (x y z : hz) : bool :=
match x, y, z with
| H, Z, Z
| Z, H, Z
| H, H, H => true
| _, _, _ => false
end.
Inductive t : hz -> Type :=
| Num : t H
| Hole : t H
| Cursor : t H -> t Z
| Arrow : forall a b c, maxHZ a b c -> t a -> t b -> t c
| Sum : forall a b c, maxHZ a b c -> t a -> t b -> t c
.
End Typ.
the other:
Inductive t : hz -> Type :=
| Num : t H
| Hole : t H
| Cursor : t H -> t Z
| Arrow : forall a b c, t a -> t b -> t c
| Sum : forall a b c, t a -> t b -> t c
.
Definition t_wf x (m : t x) : bool :=
match m with
| Arrow a b c _ _ => maxHZ a b c
| Sum a b c _ _ => maxHZ a b c
| _ => true
end.
Definition t' x := { m : t x | t_wf x m }.
(* This is automatically a subtype. *)
I am learning Homotopic Type Theory (HoTT) and its relation to COQ.
Especially the path induction concept of the identity type is still mysterious to me.
Therefore I made some experiments with COQ.
Let's start with a simple Lemma for the standard equality type using path induction:
Lemma eq_sym: forall (x y:nat), x = y -> y = x.
intros.
apply (match H in (_ = y0) return y0 = x with eq_refl => eq_refl end).
Defined.
Now let's see if that is a special handling of the COQ "eq" type. Therefore let's define a new equality type (only for nat) with an analogous symmetry lemma:
Inductive est (x : nat) : nat -> Prop :=
est_refl: est x x.
Lemma est_sym: forall (x y:nat), est x y -> est y x.
intros.
apply (match H in (est _ y0) return est y0 x with est_refl => est_refl x end).
Defined.
Ok, this works in the same way like the standard "=" type.
Now let's generalise it:
Inductive tri (x : nat) : nat->nat->Prop :=
tri_refl: tri x x x.
Lemma tri_sym: forall (x y z:nat), tri x y z -> tri z x y.
intros.
apply (match H in (tri _ y0 z0) return tri z0 x y0 with tri_refl => tri_refl x end).
Defined.
My question is:
How does this relate to the theory of HoTT?
Is this a generalised path induction which is not part of HoTT?
Your "three-ended equality" is equivalent to a pair of equality proofs, in the sense that we can write Coq functions that convert back and forth between the two forms. (These are the eq_of_teq and teq_of_eq terms in the excerpt below.)
Section Teq.
Variable T : Type.
Inductive teq (x : T) : T -> T -> Prop :=
| teq_refl : teq x x x.
Definition teq_of_eq {x y z} (e1 : x = y) (e2 : x = z) : teq x y z :=
match e1 in _ = y' return x = z -> teq x y' z with
| eq_refl => fun e2 =>
match e2 in _ = z' return teq x x z' with
| eq_refl => teq_refl x
end
end e2.
Definition eq_of_teq1 {x y z} (te : teq x y z) : x = y :=
match te in teq _ y' z' return x = y' with
| teq_refl => eq_refl
end.
Definition eq_of_teq2 {x y z} (te : teq x y z) : x = z :=
match te in teq _ y' z' return x = z' with
| teq_refl => eq_refl
end.
Definition teq_eq_teq x y z (te : teq x y z) :
teq_of_eq (eq_of_teq1 te) (eq_of_teq2 te) = te :=
match te as te' in teq _ y' z' return teq_of_eq (eq_of_teq1 te') (eq_of_teq2 te') = te' with
| teq_refl => eq_refl
end.
Definition eq_teq_eq1 x y z (e1 : x = y) (e2 : x = z) :
eq_of_teq1 (teq_of_eq e1 e2) = e1 :=
match e1 as e1' in _ = y' return eq_of_teq1 (teq_of_eq e1' e2) = e1' with
| eq_refl =>
match e2 as e2' in _ = z' return eq_of_teq1 (teq_of_eq eq_refl e2') = eq_refl with
| eq_refl => eq_refl
end
end.
Definition eq_teq_eq2 x y z (e1 : x = y) (e2 : x = z) :
eq_of_teq2 (teq_of_eq e1 e2) = e2 :=
match e1 as e1' in _ = y' return eq_of_teq2 (teq_of_eq e1' e2) = e2 with
| eq_refl =>
match e2 as e2' in _ = z' return eq_of_teq2 (teq_of_eq eq_refl e2') = e2' with
| eq_refl => eq_refl
end
end.
End Teq.
The teq_eq_teq, eq_teq_eq1 and eq_teq_eq2 lemmas show that the converting back and forth does not change the terms we start with; hence, both representations are equivalent. In this sense, Coq does not have more expressive power than HoTT just because we can define a teq.
In basic Martin-Löf type theory (the formal system upon which HoTT is based), you don't gain much by carrying a pair of equalities between the same terms, since the only thing you can do with such equalities is to perform casts on the types of the terms you manipulate. Thus, it doesn't really matter usually whether you have only one or two equality proofs between terms.
The situation changes a little bit in HoTT because of the addition of the univalence axiom, which allows us to use equality proofs between types in a computationally interesting way. This is because a proof of A = B in HoTT can be any bijection between the types A = B. In that setting, a proof of teq A B C would be equivalent to two bijections: one between A and B, and the other one between A and C.