Is it possible to declare type-dependent Notation in Coq? - overloading

As Coq has a powerful type inference algorithm, I am wondering whether we can "overload" notations for different rewriting based on the Notation's variables.
As an example, I will borrow a piece of my work on formalizing a typed language's semantics in Coq. In this formalization, I have both pairs of types and pairs of expressions, and I would like to use the same symbol for their respective constructor: { _ , _ }.
Inductive type: Type := ... | tpair: type -> type -> type | ...
Inductive expr: Type := ... | epair: expr -> expr -> expr | ...
Notation "{ t1 , t2 }" := tpair t1 t2
Notation "{ e1 , e2 }" := epair e1 e2
I know the last statement will raise an error because of the notation being already defined; I would appreciate if somebody has thought about trickery around it, or if there is another "official" way of doing this.

One easy way to overload notations is by using scopes. In fact you should use scopes most of the time so that your notations don't mix with notations from other work that you might include or that might include yours.
Using scope delimiters, you could have { t1 , t2 }%ty and { e1 , e2 }%exp for instance (with the delimiters ty and exp to disambiguate).
That said, in order to leverage typing information, there is one trick involving typeclasses which is to have a generic notion of pairs which comes with its own notation, and then declaring instances of that. See example below:
Class PairNotation (A : Type) := __pair : A -> A -> A.
Notation "{ x , y }" := (__pair x y).
Instance PairNotationNat : PairNotation nat := {
__pair n m := n + m
}.
Axiom term : Type.
Axiom tpair : term -> term -> term.
Instance PairNotationTerm : PairNotation term := {
__pair := tpair
}.
Definition foo (n m : nat) : nat := { n , m }.
Definition bar (u v : term) := { u , v }.

Related

Single colon in OCaml

I'm confused with the syntax "single colon" in OCaml.
Snippet:
let update_variable (old_state : state) (var_name : var) (new_value : value) : var -> value option =
fun x -> if x = var_name then Some new_value else old_state x
The type inference of this function is state->var->value->value option. I'm confused with the colon before the var->value option. What does it mean? Is an additional parameter omitted?
A colon in OCaml is used to indicate typing. Usually, when you see something like ident : type, it means you're indicating ident has type type. For instance, you could do something
let a : int = 3
This also extends to function definition; however, in this case, since there are many identifiers before the =, it may confuse you about which identifier is being typed. Well, it's actually the whole thing before that is typed, the idea being that it will match what you have in your code. For instance, if you have something like
let f (x : 'a) : 'b =
...
it means f : 'a -> 'b. You could understand it as
let (f (x : 'a)) : 'b =
...
even though this is not valid syntax. This is because when, in your code, you will see something like f x, you'll know it will have type 'b.
Please note that explicit typing is rarely used in OCaml. In this case it is being used to give update_variable a more specific type than would otherwise be inferred.
Consider a simple, contrived example:
utop #
type foo = Foo
let f a b = a = b
let g (a : foo) (b : foo) = a = b;;
type foo = Foo
val f : 'a -> 'a -> bool = <fun>
val g : foo -> foo -> bool = <fun>
Without explicit type hints, in function f there is nothing know about parameters a and b except that they must be the same type.
We'd get the same behavior in g except that we've explicitly told it a and b must be of type foo. We can achieve the same by only specifying the type of one of the two parameters.
utop #
let h (a : foo) b = a = b;;
val h : foo -> foo -> bool = <fun>

How to build a list of heterogeneous dependant pairs in Coq

I'd like to be able to have an heterogeneous sequence of dependent pairs (T, f) where T is in Set and f if a function T -> bool such as
Definition classif :
seq (forall T : Set, T -> bool) :=
[:: (fun b : bool => b); (fun n : nat => false)].
Note: I'm using SSReflect syntax for lists.
Clearly the type written above is not the right one.
Is it possible ?
#ThéoWinterhalter's answer is the way to go here. Just add a precision w.r.t. his answer [I initially posted it as a comment but that hindered the readability of the code…]:
the type you are looking for here is {T : Set & T -> bool}, it is a Σ-type and relies on the following inductive:
Print sigT.
Inductive sigT (A : Type) (P : A -> Type) : Type :=
existT : forall x : A, P x -> {x : A & P x}
And to ease your definition of classif, you could also define a shortcut:
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Definition sigma (T' : Set) f := (existT (fun A : Set => A -> bool) T' f).
Definition classif :
seq {T : Set & T -> bool} :=
[:: sigma (fun b : bool => b); sigma (fun n : nat => false)].
You're looking for dependent pairs and are writing dependent functions instead.
The type of pointed types is
{ A : Set & A }
Then you can build for instance the pair of nat and 1:
Check (existT (fun A : Set => A) nat 1) : { A : Set & A }.
It is nicer with some notations but there you have it.

Coq: Use equality of types for type checking a term in a definition

I have a question regarding type checking definitions in Coq. I ran into a situation where I have two terms of type t1 and t2, where I know that t1 and t2 are equal (t1 = t2) from the definition. However, I cannot use those two terms together since the types are not considered equal by the type checker. I tried to isolate a minimum example modeling the situation (yeah I know that's a stupid property, but I just want it to get type checked ;) ):
Require Import Coq.Lists.List.
Lemma myLemma :
forall t1 t2 : Type,
forall (l1 : list t1) (l2 : list t2),
t1 = t2 ->
l1 = l2.
Just assume that I cannot write (l2 : list t1) directly instead, since I get it from another definition.
I tried using Program because I hoped that I could somehow defer the task to prove that the types match, but that did not help (got the same type checking errors).
If the example above is not sufficient for making the problem clear, here's an excerpt from my actual problem:
Definition taclet_sound_new (t : taclet) :=
forall K st seSt, let S := (sig K) in
[(K, st)] |= (pathC seSt) ->
(forall K', let S' := (sig K') in
S' = (newSig t S) ->
exists (seSt' : (#sestatesc (newSig t S))),
List.In seSt' (apply t S seSt) ->
[(K', st)] |= (conv S' (pathC seSt'))).
The system complains that The term "pathC seSt'" has type "#pathCond (newSig t S)" while it is expected to have type "#pathCond S'".; however, from the premise S' = (newSig t S) I would expect that it somehow should be possible to get that definition type checked.
(Remark: conv is a trivial definition which I only added for improving Coq's output -- Definition conv (S : signature) (pc : (#pathCond S)) : list (#formulas S) := pc. -- without that, it says The term "pathC seSt'" has type "pathCond" while it is expected to have type "list formulas". which hid the actual problem.)
For completeness: The record taclet is defined as
Record taclet : Type := {
defined (prog : P) : Prop;
newSig (S1 : signature) : signature ;
apply : forall (S1 : signature),
(#sestatesc S1) -> list (#sestatesc (newSig S1)) ;
}.
So there is that newSig term in there. Therefore, the alternative definition
Definition taclet_sound_new (t : taclet) :=
forall K st seSt, let S := (sig K) in
[(K, st)] |= (pathC seSt) ->
(forall K', let S' := (sig K') in
exists (seSt' : (#sestatesc S')),
S' = (newSig t S) ->
List.In seSt' (apply t S seSt) ->
[(K', st)] |= (pathC seSt')).
Also does not type check, with the similar error The term "apply t S seSt" has type "list (sestatesc P (newSig t S))" while it is expected to have type "list (sestatesc P S')". which, again, should be clear from the premise.
I would be very happy if anybody could help me out. That type checking mechanism of Coq is sometimes a little inconvenient... ;)
Thanks in advance!
/edit (2018-09-27): Although I gave myself an answer below that appeases the type checker, I still run into a lot of problems when trying to solve my problems around some theorems and definitions in the area of predicate logic. For instance, I totally fail to define a satisfying version of a conservativity theorem (if a formula is valid in a structure, it's also valid in all extensions) due to type checking, and even if a add a crazy constraint (the extension shares the same signature, so it's not really an extension) and add a (working) cast, I cannot prove it!
This time, I thought I give a complete example. I isolated the problem and put it into a single file "firstorder.v" as a GitHub Gist (https://gist.github.com/rindPHI/9c55346965418bd5db26bfa8404aa7fe). There are comments in the document explaining the challenges I discovered for myself. If anybody finds an answer to one or two of the "main challenges" in there, I'd be really happy to know about them (and would accept this as an answer to the question here). Thanks again! I hope that a solution to those problems not only helps me, but also others out there that are getting desperate due to dependent problems ;)
Thanks to the comment of Anton, I managed to resolve the issue in a way. This answer to the first question cited by Anton made me think about writing a cast function (I also tried to use the other alternative, JMeq, but it lead me nowhere -- probably I don't really understand it). I thought I'd share the solution, in case it helps somebody.
First, I wrote the following cast function and used it via two wrappers (which I won't post since they're not generally interesting:
Definition simple_cast {T1 T2 : Type} (H : T1 = T2) (x : T1) : T2 :=
eq_rect T1 (fun T3 : Type => T3) x T2 H.
(Remark: I did not directly come up with the eq_rect term, for that I'm not enough of a pro user; however, it's possible to do the following in Coq, which I find quite interesting: Definition simple_cast {T1 T2 : Type} (H : T1 = T2) (x : T1) : T2. rewrite -> H in x. assumption. Defined. If you then Print simple_cast, you get a term that you can simplify a bit and directly post into the definition to make it more explicit. Constructing the term that way is significantly easier since you can work with simple tactics).
Next, I came up with the following definition which spared me the wrappers:
Definition cast {T : Type} {T1 T2 : T} (H : T1 = T2) (f : T -> Type) (x : f T1) :=
eq_rect T1 (fun T3 : T => f T3) x T2 H.
Regarding the simple list example, the following code type checks:
Lemma myLemma :
forall t1 t2 : Type,
forall (l1 : list t1) (l2 : list t2),
forall (H : t2 = t1),
l1 = cast H (list) l2.
My actual code snippet also type checks:
Definition taclet_sound_new (t : taclet) :=
forall K st seSt, let S := (sig K) in
[(K, st)] |= (pathC seSt) ->
(forall K', let S' := (sig K') in
forall (H : (newSig t S) = S'),
exists (seSt' : (#sestatesc (newSig t S))),
List.In seSt' (apply t S seSt) ->
[(K', st)] |= (cast H (#pathCond) (pathC seSt'))).
Finally, I can cast expressions in Coq (given that there's named evidence that the cast is OK -- I can live with that)!
/edit: I now found a library for such casts: The Heq library. With that, myLemma looks like
Lemma myLemma :
forall t1 t2 : Type,
forall (l1 : list t1) (l2 : list t2),
forall (H : t2 = t1),
l1 = << list # H >> l2.
so you don't have to write your own cast function.
Unfortunately, I couldn't really eliminate the casts in proofs (regardless of whether I use my own cast or the one of Heq); it seems that you need to be a really experienced dependent types hacker to do so. Or my lemmas are wrong, which I don't think however. For those of you who really want to get into the topic, there's a chapter on equalities in Adam Chlipala's great CPDT book; in my case, I'll personally just "admit" some proofs simplifying those expressions and build upon that. At least it type checks...

OCaml - GADT mapping

I'm struggling with understanding some aspects of using GADTs in OCaml. Let me try and talk you through my example and my understanding ...
I'm trying to implement Simon Peyton-Jones' classic paper on Combinatorial Contracts (https://www.microsoft.com/en-us/research/wp-content/uploads/2000/09/pj-eber.pdf)
I want to be able to manipulate an Observable, defined as a function from a date to a value of some type (realistically a float or a bool). So, using GADTs I define a function type and an Observation type
type _ value =
| Float : float -> float value
| Bool : bool -> bool value
type _ obs = Observation : (date -> 'v value) -> (date -> 'v) obs
What I think I am defining is that
a value is either a float or a bool (built using the Float or Bool constructors, and
an obs is a function from a date to one of the value types, so either a date -> float or a date -> bool
Now I define an expression, which enables me to combine Observables
type _ expr =
| Konst : 'v value -> 'v expr
| Obs : 'v obs -> 'v expr
| Lift : ('v1 -> 'v2) * 'v1 expr -> 'v2 expr
So far so good. An expression is either a constant, an observation (which is either a date->float or date->bool), or a function applied to an expression.
Now I want to be able to evaluate an Observable. In reality, an Observable is built on a random process, so I have a Distribution module (Note that in the original paper the idea is to separate out the concept of an Observable, from it's implementation - so we could implement through lattices, monte carlo, or whatever approach we want).
module type Distribution_intf =
sig
type element = Element of float * float
type t = element list
val lift : t -> f:(float -> float) -> t
val expected : t -> float
end
so, given a compose function
let compose f g = fun x -> f (g x)
I should be able to think about the evaluation of an Observable. Here is a mapping function (I've taken out the Boolean case for clarity)
type rv = date -> Distribution.t
let rec observable_to_rv : type o. o Observable.expr -> rv =
let open Distribution in
function
| Konst (Float f) -> fun (_:date) -> [Element(1.0, f)]
| Lift (f,obs) -> compose (lift ~f) (observable_to_rv o) (*ERROR HERE *)
Now things get problematic. When I try and compile, I get the following error message (on the Lift pattern match):
Error: This expression has type v1#0 -> o
but an expression was expected of type float -> float
Type v1#0 is not compatible with type float
I don't understand why: A Lift expression has type
Lift: ('v1 -> 'v2) * 'v1 expr -> 'v2 expr
So given a Lift(f,o), then shouldn't the compiler constrain that since observable_to_rv has type date -> float, then 'v2 must be a float, and since lift has type float -> float then 'v1 must be a float, so Lift should be defined on any tuple of type (float -> float, float expr).
What am I missing ?
Steve
You are missing the fact that the type variable 'v1 in Lift is existentially quantified:
Lift: ('v1 -> 'v2) * 'v1 expr -> 'v2 expr
means
Lift: ∃'v1. ('v1 -> 'v2) * 'v1 expr -> 'v2 expr
In other words, given a value Lift(f,x): 'b expr the only information that the type checker has is that there is a type 'a such that f:'a -> 'b and x:'a expr, nothing more.
In particular going back to your error message (with a somewhat recent version of compiler(≥ 4.03)):
Type $Lift_'v1 is not compatible with type float
it is not possible to unify this existential type introduced by the Lift constructor to the float type, or any concrete type, because there no information left in the type system on the actual concrete type hidden behind 'v1 at this point.
EDIT:
The essence of your problem is that you are trying to build a float random variable from a chain of expression 'a expr which can contain intermediary expressions of any type and just need to result with 'a expression. Since you can neither express the condition only float sub-expression in the type system nor construct non-float random variable with your current design, this spells trouble.
The solution is either to remove the ability to build non-float expression or to add the ability to handle non-float random variables .Taking the second option would look like
module Distribution:
sig
type 'a element = {probability:float; value: 'a}
type 'a t = 'a element list
val lift : 'a t -> f:('a -> 'b) -> 'b t
val expected : float t -> float
end = struct … end
Then your observable_to_rv random variable typed as 'a expr -> 'a rv will type-check.

__ in Ocaml extracted from Coq

Ocaml code extracted from Coq includes (in some cases) a type __ and a function __ defined as follows:
type __ = Obj.t
let __ = let rec f _ = Obj.repr f in Obj.repr f
The documentation says that in the past, such type was defined as unit (and thus __ could be taken as ()) but there exist (rare) cases where a value of type __ is applied to a value of type __.
__ uses undocumented functions of the Obj module from OCaml, but it seems that what is defined is essentially a totally polymorphic function that eats all its arguments (whatever their number).
Is there some documentation regarding the cases where __ cannot be eliminated and values of this type are applied to values of the same type, both from a theoretical (construct Coq terms where elimination is impossible) and from a practical (show a realistic case where this occurs) point of view?
The references cited in the README give a nice overview of the erasure problem. Specifically, both this report and this article exaplain in detail how the type schemes and logical parts of CIC terms are erased, and why one must have __ x = __. The problem is not exactly that __ may be applied to itself, but that it may be applied to anything at all.
Unfortunately, it is not at all clear if having this behavior is important in any non-pathological case. The motivation given there is to be able to extract any Coq term, and the documents do not mention any cases that are really interesting from a practical standpoint. The example given on 3 is this one:
Definition foo (X : Type) (f : nat -> X) (g : X -> nat) := g (f 0).
Definition bar := foo True (fun _ => I).
Executing Recursive Extraction bar. gives the following result:
type __ = Obj.t
let __ = let rec f _ = Obj.repr f in Obj.repr f
type nat =
| O
| S of nat
(** val foo : (nat -> 'a1) -> ('a1 -> nat) -> nat **)
let foo f g =
g (f O)
(** val bar : (__ -> nat) -> nat **)
let bar =
foo (Obj.magic __)
Since foo is polymorphic on Type, there is no way of simplifying the f O application on its body, because it could have computational content. However, since Prop is a subtype of Type, foo can also be applied to True, which is what happens in bar. When we try to reduce bar, thus, we will have __ being applied to O.
This particular case is not very interesting, because it would be possible to fully inline foo:
let bar g =
g __
Since True can't be applied to anything, if g corresponds to any legal Coq term, its __ argument also wouldn't be applied to anything, and therefore it would be safe to have __ = () (I believe). However, there are cases where it is not possible to know in advance whether an erased term can be further applied or not, which makes the general definition for __ necessary. Check out for instance the Fun example here, near the end of the file.