There are times when subtyping judgments are too difficult for f-star to figure out automatically, and f-star would like me to spell out my proofs in more detail. I am also running into cases where I would like to write a lemma that just proves f-star can make some type judgment.
A piece of syntax that looks like it does this does parse, but it seems to not do what I want. I suspect I misunderstand what this syntax does. Here I am trying to just prove that x has type nat with a Lemma. Why doesn't this do what I think it does?
let x: nat = 3
val tj_lem: unit -> Lemma (x: nat)
let tj_lem () = ()
I am also surprised that I can write "x: nat" in that position. How can I "prove that x is a nat" if I needed to?
You've hit an ugly corner of F*'s syntax.
https://github.com/FStarLang/FStar/issues/1905
We've been discussing ways to improve it.
In particular, F* allows you to associate names with types that are in some cases meaningless. In your example the name x is meaningless in the x:nat that appears in the type of Lemma. It is interpreted by F* as unit -> Lemma nat: this is the type of a proof that shows that the nat type is inhabited … which isn't particularly interesting. For the record, one way to prove that uninteresting type is
let nat_is_inhabited () : Lemma nat = FStar.Squash.return_squash #nat 0
Now, to your actual question of how to spell out a proof of subtyping. There are many ways. One common way is as follows:
Let's say you have the type
let tp = x:t { p }
And at some point you have
let f (x:t) = … assert (q x); let y : tp = x in …
i.e., because of some contextual information that gives you the property q x, you want to treat x:t at the type tp.
If you can prove a lemma of the form
val q_implies_p (x:t) : Lemma (requires q x) (ensures p x)
then by calling the lemma at the right point in your code, you can give F* and the SMT solver enough information to accept the subtyping of x:t to tp. For example, something like this:
let f (x:t) = … assert (q x); q_implies_p x; let y : tp = x in …
Hope that helps. Sorry about the confusing syntax!
Related
Trying to cobble together a lambda calculus interpreter as a noob project and I have come upon a syntax problem I cannot quite figure out.
Problem being that two constructors of a type behaves the same in some respects and I would like to avoid code duplication. See code below.
type term =
| Lam of string * term * term
| Pi of string * term * term
let rec subst x t s = match s with
| Lam (y,r,q) | Pi (y,r,q) ->
if x = y then LAMORPI (y, subst x t r, q)
else [...]
What I think are called or-patterns seemed like a good fit but I cannot get it to work. Figured perhaps that is what as is for, but I cannot seem to partially as something, which is what I had in mind for LAMORPI to be doing. This case seems like it would have a neat or commonly used idiomatic solution but my google-fu is not strong enough.
What is a usual or otherwise possible solution for this?
It is not possible to use or-pattern in expressions. (And this potential feature raises some issues: see http://gallium.inria.fr/blog/pattern-synonyms-as-expressions for a discussion)
One possibility is to refactor your type to expose the fact that the two constructors only differ by a tag:
type kind = Lam | Pi
type term =
| LamPi of tag * string * term * term
| ...
let rec subst x t s = match s with
| LamPi (tag,y,r,q) ->
if x = y then LamPi (tag, y, subst x t r, q)
else ...
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...
I am currently working with OCaml, and I want to create some types which are somehow secured, in the sense that I want to select only those instances which satisly some properties.
The way that I found to acheive that is to encapsulate my type in a module, making it private, and defining the constructors in such a way that they check if the object that they are trying to make satisfy these properties. As my code is a bit long, I want to split into different modules, but my types are mutually recursive, so I am using recursive modules. I end up in the following situation (I simplified a lot so that it becomes readable)
module rec A
: sig
type t = private int list
val secured_cons : int -> t -> t
end
= struct
type t = int list
let cons (i:int) (x:t) : t = i::x
let secured_cons i x : t = B.checker i x; cons i x
end
and B
: sig
val checker : int -> A.t -> unit
end
= struct
let checker i x = ()
end
But this code is rejected, with the following error message :
Characters 226-227:
let secured_cons i x = B.checker i x; cons i x
^
Error: This expression has type A.t but an expression was expected of type
t = int list
This looks to me very weird, because as we are in the context A, the two types t and A.t are supposed to be equal. From my understanding, what happens is that inside A, the type t is considered to be a synonym for int list whereas outside A, the signature tells us that it is private, so it is just a copy of this type, with a coercion A.t :> int list. The entire point is that there is no coercion the other way around, which is exactly why I want to use private type abbreviations
But in my case I am inside the module A, so I would like to use this extra information to say that my type t should coerce to A.t
Does anyone have a better explanation of why this error is happening, and how I could avoid it? (I have thought of switching to abstract types, but I get exactly the same error)
I have found a way to solve this issue I am posting it here in case anyone else ever encounters the same.
We just have to explicitly specify what types and coercion we expect from the system - here is my example slightly modified in a correct way :
module rec A
: sig
type t = private int list
val secured_cons : int -> t -> t
end
= struct
type t = int list
let cons (i:int) (x:t) : t = i::x
let secured_cons i (x:A.t) = B.checker i x; cons i (x :> t)
end
and B
: sig
val checker : int -> A.t -> unit
end
= struct
let checker i x = ()
end
It might look silly to write let secured_cons i (x:A.t) inside the module A itself, but as far as I understand it, it is the only way to specify to the system that it should go out of the module to check the signature, and use the same type as the signature (so here a private type) instead of the internal type t which is still a synonymous for int list
I had more trickier cases, but this idea could be adapted to each of them, and helped me solve them all.
Still I am not entirely sure of what is happening, and if anyone has clearer explanations, I would be very thankful
You're errors occur because when B.checker is invoked, x is infered as an A.t because of the signature of B.
You can see that easily if you explicitly type the secured_cons function :
let secured_cons i (x:t) : t = B.checker i x; cons i x
which now produces the symmetrical error:
let secured_cons i (x:t) = B.checker i x; cons i x
^
Error: This expression has type t = int list
but an expression was expected of type A.t
In fact you here have a real designing problem in my opinion. If you want the module B to check the values produced by the module A, so without surprise B must inspect in some way the type A.t. Having that type private makes it impossible.
From what i understand you have three options :
remove private
Add a browse, getter function that allows the B module to access the content of the values of type A.t
the way i would do this : put the checking function into the module A
I'd be glad to hear what more experienced users have to say about this, but here is my take on it.
I, as a developer, usually give a lot of importance to the semantics of a code. In your case, the B module is specifically used by the A module, and it has no other goal than that.
Thus, sticking to a nested module (even if it makes your code a bit longer) would be the way to go as far as I am concerned. There is no point is exposing the B module. Below is the refactored example to illustrate.
module A : sig
type t
val secured_cons : int -> t -> t
end = struct
type t = int list
module B : sig
val checker : int -> t -> unit
end = struct
let checker i x = ()
end
let cons i x = i::x
let secured_cons i x = B.checker i x; cons i x
end
And here is the signature of the module as given by utop:
module A : sig type t val secured_cons : int -> t -> t end
which is perfect in my sense because it only shows the interface to your module, and nothing of its implementation.
As a side-note, if you wanted to expose the signature of the B module (to give it to a functor, for example), just move it to the signature of the A module, as follows:
module A : sig
type t
val secured_cons : int -> t -> t
module B : sig
val checker : int -> t -> unit
end
end = struct
type t = int list
module B = struct
let checker i x = ()
end
let cons i x = i::x
let secured_cons i x = B.checker i x; cons i x
end;;
Here is the signature of the module as given by utop:
module A :
sig
type t
val secured_cons : int -> t -> t
module B : sig val checker : int -> t -> unit end
end
Still I am not entirely sure of what is happening, and if anyone has clearer explanations, I would be very thankful
A private type abbreviation of the form type u = private t declares a type u that is distinct from the implementation type t. It is the same as declaring an abstract type with the following two exceptions:
compiler treats the type t, as an implementation type, that opens an avenue for optimizations - this, however, doesn't mean that a type checker considers them the same, for the type checker they are distinct.
typechecker allows a coercion of type u to type t.
So, from a typechecker perspective, these two types are distinct. As always in OCaml type discipline all coercions should be made explicit, and a subtype is not equal to a super type unless it is coerced. In your case, the typechecker is trying to unify type A.t = private int list with type int list since A.t and int list are distinct types, it is rejected. It is, however, allowed to coerce A.t to int list (but not the vice verse).
It might look silly to write let secured_cons i (x:A.t) inside the module A itself
You don't need to write it (at least in your simple example). Just using x :> t is enough.
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.
I have an ocaml type :
type t = A | B | ...
and a function to print things about that type :
let pp_t fmt x = match x with
| A -> Format.fprintf fmt "some nice explanations about A"
| B -> Format.fprintf fmt "some nice explanations about B"
| ...
How could I write a function to print all the explanations ? Something equivalent to :
let pp_all_t fmt =
Format.fprintf fmt A;
Format.fprintf fmt B;
...
but that would warn me if I forget to add a new constructor.
It would be even better to have something that automatically build that function,
because my problem is that t is quiet big and changes a lot.
I can't imagine how I can "iterate" on the type constructors, but maybe there is a trick...
EDIT: What I finally did is :
type t = A | B | ... | Z
let first_t = A
let next_t = function A -> B | B -> C | ... | Z -> raise Not_found
let pp_all_t fmt =
let rec pp x = pp_t fmt x ; try let x = next_t x in pp x with Not_found -> ()
in pp first_t
so when I update t, the compiler warns me that I have to update pp_t and next_t, and pp_all_t doesn't have to change.
Thanks to you all for the advices.
To solve your problem for a complicated and evolving type, in practice I would probably write an OCaml program that generates the code from a file containing a list of the values and the associated information.
However, if you had a function incr_t : t -> t that incremented a value of type t, and if you let the first and last values of t stay fixed, you could write the following:
let pp_all_t fmt =
let rec loop v =
pp_t fmt v;
if v < Last_t then loop (incr_t v)
in
loop First_t
You can't have a general polymorphic incr_t in OCaml, because it only makes sense for types whose constructors are nullary (take no values). But you can write your own incr_t for any given type.
This kind of thing is handled quite nicely in Haskell. Basically, the compiler will write some number of functions for you when the definitions are pretty obvious. There is a similar project for OCaml called deriving. I've never used it, but it does seem to handle the problem of enumerating values.
Since you say you want a "trick", if you don't mind using the unsafe part of OCaml (which I personally do mind), you can write incr_t as follows:
let incr_t (v: t) : t =
(* Please don't use this trick in real code :-) ! See discussion below.
*)
if t < Last_t then
Obj.magic (Obj.magic v + 1)
else
failwith "incr_t: argument out of range"
I try to avoid this kind of code if at all possible, it's too dangerous. For example, it will produce nonsense values if the type t gets constructors that take values. Really it's "an accident waiting to happen".
One needs some form of metaprogramming for such tasks. E.g. you could explore deriving to generate incr_t from the Jeffrey's answer.
Here is a sample code for the similar task : https://stackoverflow.com/a/1781918/118799
The simplest thing you can do is to define a list of all the constructors:
let constructors_t = [A; B; ...]
let pp_all_t = List.iter pp_t constructors_t
This is a one-liner, simple to do. Granted, it's slightly redundant (which gray or dark magic would avoid), but it's still probably the best way to go in term of "does what I want" / "has painful side effects" ratio.