Extract functor in Coq to OCaml using Extraction mechanism of Coq - ocaml

I have a function PolyInterpretation (http://color.inria.fr/doc/CoLoR.PolyInt.APolyInt.html)
Definition PolyInterpretation := forall f : Sig, poly (arity f).
and a module signature TPolyInt(http://color.inria.fr/doc/CoLoR.PolyInt.APolyInt_MA.html)
Module Type TPolyInt.
Parameter sig : Signature.
Parameter trsInt : PolyInterpretation sig.
Parameter trsInt_wm : PolyWeakMonotone trsInt.
End TPolyInt.
Module PolyInt (Export PI : TPolyInt).
Then in my file rainbow.v, I define a module TPolyInt_imp purpose to use functor PolyInt
Module TPolyInt_imp.
Variable arity : symbol -> nat.
Variable l : list {g : symbol & poly (arity f).
Definition sig := Sig arity.
Definition trsInt f := fun_of_pairs_list f l.
...
End TPolyInt_imp.
Where fun_of_pairs_list has type: forall f: Cpf0.symbol, list {g : symbol & poly (arity g)} -> poly (arity f)
Then I define a module P:
Module Export P := PolyInt TPolyInt_imp.
The Coqproof assistant accepted the definition P above.
Then I used extraction to extract to OCaml.
I write it in another file: extraction.v
Extraction Language Ocaml.
Set Extraction Optimize.
Set Extraction AccessOpaque.
Separate Extraction rainbow.P.
It works fine.
Here is the code after the extraction
module TPolyInt_imp =
struct
(** val arity : symbol -> int **)
let arity =
failwith "AXIOM TO BE REALIZED"
(** val l : (symbol, poly) sigT list **)
let l =
failwith "AXIOM TO BE REALIZED"
(** val coq_sig : coq_Signature **)
let coq_sig =
coq_Sig arity
(** val trsInt : symbol -> poly **)
let trsInt f =
fun_of_pairs_list arity f l
end
module P = PolyInt(TPolyInt_imp)
Because inside the functor TPolyInt_imp they included Variable and generate the failwith AXIOMthen I decided to define a new signature to contain all those variables.
Module Type Arity.
Variable arity : symbol -> nat.
Variable l : list {g : symbol & poly (arity g)}.
End Arity.
Then define a new functor taking (Arity) as a parameter. And inside this functor I define module TPolyInt_imp (like TPolyInt_imp before).
Module S (Import A: Arity).
Module TPolyInt_imp.
Definition sig := Sig arity.
Definition trsInt f := fun_of_pairs_list f l.
...
End TPolyInt_imp.
Module P := PolyInt TPolyInt_imp.
End S.
Then I use the extraction to extract it to Ocaml.
Extraction Language Ocaml.
Set Extraction Optimize.
Set Extraction AccessOpaque.
Separate Extraction S.
Then I got an error saying that:
Error: Signature mismatch:
...
Values do not match:
val trsInt : Cpf0.symbol -> Polynom.poly
is not included in
val trsInt : APolyInt.coq_PolyInterpretation
File "rainbow.ml", line 534, characters 8-14: Actual declaration
The code after the extraction:
module type Arity =
sig
val arity : symbol -> int
val l : (symbol, poly) sigT list
end
module S =
functor (A:Arity) ->
struct
module TPolyInt_imp =
struct
(** val coq_sig : coq_Signature **)
let coq_sig =
coq_Sig A.arity
(** val trsInt : symbol -> poly **)
let trsInt f =
fun_of_pairs_list A.arity f A.l
end
module P = PolyInt(TPolyInt_imp)
What is wrong with the extraction? and the reason why they have this error? How can I correct my code that I can get the success compile after the extraction?
Also I do not want to define a new module that implement the signature Arity.
I am so sorry for my code lacking of type and not able to compile. I am trying to give the idea of my problem.

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>

In OCaml, write a function that works Base.Map and Base.Hashtbl

So I want to write a function that takes a first class module as an argument that works on Base.Map and Base.Hashtbl, but I'm running into a problem. This code illustrates what's going on:
module type Len_intf = sig
type t
val length : t -> int
end
let show (type a) (module L : Len_intf with type t = a) h =
printf "len: %d\n" ## L.length h
let test (type a) h =
show (module Hashtbl : Len_intf with type t = a) h
Attempting to compile this results in:
Error: Signature mismatch:
...
Type declarations do not match:
type ('a, 'b) t = ('a, 'b) Poly.t
is not included in
type t
They have different arities.
File "test.ml", line 2, characters 2-8:
Expected declaration
File "src/hashtbl_intf.ml", line 552, characters 2-17:
Actual declaration
Is this even possible, due to the different type arity of Hashtbl and Map?
Writing a function that takes a first-class module is certainly possible (you did so), and it can be called like that:
let test (type a) (type b) h =
let module M = struct
type t = (a,b) Hashtbl.t
let length = Hashtbl.length
end in
show (module M) h
But I do not think it is possible to do it the way you want. Indeed, type equalities come afterwards, in addition to what the signature already describes. They cannot prevent a type arity mismatch.

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.

OCaml: higher kinded polymorphism (abstracting over modules?)

Let's say I have a list of options:
let opts = [Some 1; None; Some 4]
I'd like to convert these into an option of list, such that:
If the list contains None, the result is None
Otherwise, the various ints are collected.
It's relatively straightforward to write this for this specific case (using Core and the Monad module):
let sequence foo =
let open Option in
let open Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
However, as the question title suggests, I'd really like to abstract over the type constructor rather than specialising to Option. Core seems to use a functor to give the effect of a higher kinded type, but I'm not clear how I can write the function to be abstracted over the module. In Scala, I'd use an implicit context bound to require the availability of some Monad[M[_]]. I'm expecting that there's no way of implicitly passing in the module, but how would I do it explicitly? In other words, can I write something approximating this:
let sequence (module M : Monad.S) foo =
let open M in
let open M.Monad_infix in
List.fold ~init:(return []) ~f:(fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) foo;;
Is this something that can be done with first class modules?
Edit: Okay, so it didn't actually occur to me to try using that specific code, and it appears it's closer to working than I'd anticipated! Seems the syntax is in fact valid, but I get this result:
Error: This expression has type 'a M.t but an expression was expected of type 'a M.t
The type constructor M.t would escape its scope
The first part of the error seems confusing, since they match, so I'm guessing the problem is with the second - Is the problem here that the return type doesn't seem to be determined? I suppose it's dependent on the module which is passed in - is this a problem? Is there a way to fix this implementation?
First, here is a self-contained version of your code (using the legacy
List.fold_left of the standard library) for people that don't have
Core under hand and still want to try to compile your example.
module type MonadSig = sig
type 'a t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val return : 'a -> 'a t
end
let sequence (module M : MonadSig) foo =
let open M in
let (>>=) = bind in
List.fold_left (fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) (return []) foo;;
The error message that you get means (the confusing first line can
be ignored) that the M.t definition is local to the M module, and
must not escape its scope, which it would do with what you're trying
to write.
This is because you are using first-class modules, that allow to
abstract on modules, but not to have dependent-looking types such as
the return type depends on the argument's module value, or at least
path (here M).
Consider this example:
module type Type = sig
type t
end
let identity (module T : Type) (x : T.t) = x
This is wrong. The error messages points on (x : T.t) and says:
Error: This pattern matches values of type T.t
but a pattern was expected which matches values of type T.t
The type constructor T.t would escape its scope
What you can do is abstract on the desired type before you abstract on the first-class module T, so that there is no escape anymore.
let identity (type a) (module T : Type with type t = a) (x : a) = x
This relies on the ability to explicitly abstract over the type variable a. Unfortunately, this feature has not been extended to abstraction over higher-kinded variables. You currently cannot write:
let sequence (type 'a m) (module M : MonadSig with 'a t = 'a m) (foo : 'a m list) =
...
The solution is to use a functor: instead of working at value level, you work at the module level, which has a richer kind language.
module MonadOps (M : MonadSig) = struct
open M
let (>>=) = bind
let sequence foo =
List.fold_left (fun acc x ->
acc >>= fun acc' ->
x >>= fun x' ->
return (x' :: acc')
) (return []) foo;;
end
Instead of having each monadic operation (sequence, map, etc.) abstract over the monad, you do a module-wide abstraction.

A strange example of typing in Ocaml

it is quite strange that this ocaml snippet is well typed by the toplevel. Look at the structure, if g is of type int->int as shown in the toplevel, the h x = g x part of the structure would not be able to get type-unified. So can any one clarify a bit?
module Mymodule : sig
val h:int ->int
val g: string-> string
end = struct
let g x = x
let h x = g x
end
This is the topelevel's response:
module Mymodule : sig val h : int -> int val g : string -> string end
The important thing to understand here is that OCaml performs type inference in a compositional manner, i.e., it will first infer type of struct ... end and only then it will match the inferred types against sig ... end to verify that the structure really does implement the signature.
For example, if you write
module Monkey : sig val f : int -> int end =
struct
let f x = x
end
then OCaml will be happy, as it will see that f has a polymorphic type 'a -> 'a which can be specialized to the required type int -> int. Because the sig ... end makes Monkey opaque, i.e., the signature hides the implementation, it will tell you that f has type int -> int, even though the actual implementation has a polymorphic type.
In your particular case OCaml first infers that g has type 'a -> 'a, and then that the type of h is 'a -> 'a as well. So it concludes that the structure has the type
sig val g : 'a -> 'a val h : 'a -> 'a end
Next, the signature is matched against the given one. Because a function of type 'a -> 'a can be specialized to int -> int as well as string -> string OCaml concludes that all is well. Of course, the whole point of using sig ... end is to make the structure opaque (the implementation is hidden), which is why the toplevel does not expose the polymorphic type of g and h.
Here is another example which shows how OCaml works:
module Cow =
struct
let f x = x
let g x = f [x]
let a = f "hi"
end
module Bull : sig
val f : int -> int
val g : 'b * 'c -> ('b * 'c) list
val a : string
end = Cow
The response is
module Cow :
sig
val f : 'a -> 'a
val g : 'a -> 'a list
val a : string
end
module Bull :
sig
val f : int -> int
val g : 'a * 'b -> ('a * 'b) list
val a : string end
end
I'd say that the string -> string typing isn't applied to g until it's exported
from the module. Inside the module (since you don't give it a type) it has the type
'a -> 'a. (Disclaimer: I'm not a module expert, trying to learn though.)