Hi I am writing an extraction from Coq to Ocaml, I would like to convert type:
positive --> int32
N -> int32
but I want to keep type Z is int
Here is the code I am doing to extract these conditions:
Require Import ZArith NArith.
Require Import ExtrOcamlBasic.
(* Mapping of [positive], [N], [Z] into [int32]. *)
Extract Inductive positive => int32
[ "(fun p-> let two = Int32.add Int32.one Int32.one in
Int32.add Int32.one (Int32.mul two p))"
"(fun p->
let two = Int32.add Int32.one Int32.one in Int32.mul two p)" "Int32.one" ]
"(fun f2p1 f2p f1 p -> let two = Int32.add Int32.one Int32.one in
if p <= Int32.one then f1 () else if Int32.rem p two = Int32.zero then
f2p (Int32.div p two) else f2p1 (Int32.div p two))".
Extract Inductive N => int32 [ "Int32.zero" "" ]
"(fun f0 fp n -> if n=Int32.zero then f0 () else fp n)".
Extract Inductive Z => int [ "0" "" "(~-)" ]
"(fun f0 fp fn z -> if z=0 then f0 () else if z>0 then fp z else fn (-z))".
I cannot do it to keep Z -> int because the definition of Z in Coq's library (BinInt.v)
Inductive Z : Set :=
| Z0 : Z
| Zpos : positive -> Z
| Zneg : positive -> Z.
I got an error: (function coq_Zdouble_plus_one)
File "BinInt.ml", line 38, characters 4-5:
Error: This expression has type int but an expression was expected of type
int32
BinInt.ml
open BinPos
open Datatypes
(** val coq_Z_rect :
'a1 -> (int32 -> 'a1) -> (int32 -> 'a1) -> int -> 'a1 **)
let coq_Z_rect f f0 f1 z =
(fun f0 fp fn z -> if z=0 then f0 () else if z>0 then fp z else fn (-z))
(fun _ ->
f)
(fun x ->
f0 x)
(fun x ->
f1 x)
z
(** val coq_Z_rec : 'a1 -> (int32 -> 'a1) -> (int32 -> 'a1) -> int -> 'a1 **)
let coq_Z_rec f f0 f1 z =
(fun f0 fp fn z -> if z=0 then f0 () else if z>0 then fp z else fn (-z))
(fun _ ->
f)
(fun x ->
f0 x)
(fun x ->
f1 x)
z
(** val coq_Zdouble_plus_one : int -> int **)
let coq_Zdouble_plus_one x =
(fun f0 fp fn z -> if z=0 then f0 () else if z>0 then fp z else fn (-z))
(fun _ ->
Int32.one)
(fun p ->
((fun p-> let two = Int32.add Int32.one Int32.one in
Int32.add Int32.one (Int32.mul two p))
p))
(fun p -> (~-)
(coq_Pdouble_minus_one p))
x
If I extract Z -> int32, it is Ok, but it is not what I want.
Your problem is that Z is internally built upon positive.
Inductive Z : Set := Z0 : Z
| Zpos : positive -> Z
| Zneg : positive -> Z
.
This means that whenever you get a Z, you're really getting a positive and some extra info.
If you really want to use different types for Z and positive, you'll have to insert conversion functions between int and int32. You might be able to do that with the extraction feature, but I'm not sure how – or even if – that's possible.
Another problem I see is that code inside a match on Zs will get positives to work with, meaning that you'll be constantly converting between the types and losing any extra precision one of the types might have over the other. If at all possible, I'd use the same type for both.
Related
I have to define the signature tEXP of a functor which, starting from a module A with signature tARITH, constructs an abstract type representing expressions. This type of expressions will be named t.
the signature have to declare different operations to build an expression:
from a constant of type A.t (cst operation)
as the opposite of an expression (opp)
as an operation on two expressions (add and mul)
Finally, a compute operation will describe the evaluation of an expression to obtain its value (of type A.t).
I have written this so far :
module type tARITH = sig
type t
val zero : t
val one : t
val add : t -> t -> t
val mul : t -> t -> t
val opp : t -> t
val of_int : int -> t
val to_string : t -> string
end
module INT : tARITH = struct
type t = int
let zero = 0;;
let one =1;;
let add x y = x+y;;
let mul x y = x*y;;
let opp x = -x;;
let of_int x= x;;
let to_string x= string_of_int x;;
end ;;
type m3 = Zero | Un | Deux
module M3:tARITH = struct
type t = m3
let zero = Zero;;
let one = Un;;
let add m n = if m=Zero && n=Zero || n=Un && m=Deux || m=Un && n=Deux then Zero
else if m=Deux && n=Zero || m=Un && n=Un || m=Zero && n=Deux then Deux
else Un;;
let mul m n = if m=Deux && n=Deux || m=Un && n=Un then Un
else if m=Deux && n=Un || n=Deux && m=Un then Deux
else Zero;;
let opp m = match m with
|Zero->Zero
|Un->Deux
|Deux->Un;;
let of_int m = match (m mod 3) with
|0->Zero
|1->Un
|2->Deux
|(-1)->opp Un
|(-2)->opp Deux
|_->Zero;;
let to_string x = match x with
|Zero->"0"
|Un->"1"
|Deux->"2" ;;
end;;
and here the signature of tEXP :
module type tEXP =
sig
type t = Constante of m3 | Somme of t*t | Produit of t*t
val cst t -> t;;
val opp x -> t ;;
val add x -> y -> t
val mul x -> y -> t
val compute x -> A.x;;
end ;;
module EXP = functor (A: tARITH)-> struct
type t = Constante of m3 | Somme of t*t | Produit of t*t
let cst x = x;;
let opp x = match x with
|Constante(x) -> x
|Constante(x)-> x
|Somme(x,y)-> A.plus (calculer x) (calculer y)
|Produit(x,y)-> A.mult (calculer x) (calculer y) ;;
let add x y = A.plus (calculer x) (calculer y);;
let mul x y = A.mul (calculer x) (calculer y) ;;
let compute x = A.x;;
end;;
I get an error at "sig" and the first "x", I don't really know why.
Thank you for your help. Here is the final answer:
module type tEXP = functor (A : tARITH) -> sig
type t
val cst : A.t -> t
val opp : t -> t
val add : t -> t -> t
val mul : t -> t -> t
val compute : t -> A.t
end;;
module EXP = functor (A : tARITH) -> struct
type t = Const of A.t | Opp of t | Add of t*t | Mul of t*t
let cst c = Const (c)
let add ex1 ex2 = Add (ex1, ex2)
let opp exp = Opp (exp)
let mul ex1 ex2 = Mul (ex1, ex2)
let rec compute expr = match expr with
Const (c) -> c
| Opp (e) -> A.opp (compute e)
| Add(e1, e2) -> A.add (compute e1) (compute e2)
| Mul(e1, e2) -> A.mul (compute e1) (compute e2)
end;;
Is it best to always eta-expand as a fool-proof rule of thumb in OCaml ?
type 'x recordx = { x : int }
type 'y recordy = { y : int }
let rec ok : type n a. n recordx -> a recordy -> int =
fun algebrah x -> ok algebrah x
let rec ok : type a. a recordy -> int =
fun x ->
let go : type b. b recordy -> int = ok in
go x
let rec ok : type n a. n recordx -> a recordy -> int =
fun x y ->
let go : type b. b recordy -> int = fun y -> ok x y in
go y
let rec ok : type n a. n recordx -> a recordy -> int =
fun x y ->
let go = ok x in
go y
(* This definition has type
'b recordy -> int which is less general than
'b0. 'b0 recordy -> int
*)
let rec ko : type n a. n recordx -> a recordy -> int =
fun x y ->
let go : type b. b recordy -> int = ko x in
go y
The relaxed value restriction classifies the eta-expanded form fun y -> f x y as a value that can thus be generalized by let bindings, contrarily to the non-value f y. See https://ocaml.org/manual/polymorphism.html#s%3Aweak-polymorphism .
Moreover, in a eager language like OCaml, eta-expansion does change the semantics of functions. Consider
let print x =
Format.printf "x=%s#." x;
fun y -> Format.printf "y=%s#."
and
let print1 = print "x"
let print2 y = print "x" y
Thus, eta-expansion is a semantic-changing transformation rather than a "foolproof" transformation.
I have a module in one file that contains the type type move = Move of int. In another file, I open this module and can refer to the type by ModuleName1.move. But is it possible to construct an instance of this type in the second file, given that I'd have to use the Move i syntax, and since that Move parameter/keyword isn't really accessible from the second file?
Here's the module where I want to instantiate the type from the first module (which is called Game and contains the type type move = Move of int. It's right at the end, in the next_move function, that I want to construct a (Move 0) and pass it to make_tree, however it doesn't recognize Move since it's a parameterized type constructor from the other module:
#use "sig_player.ml" ;;
#use "game.ml" ;;
module TestAIPlayer =
struct
module PlayerGame = Game
open PlayerGame
let max_depth = 4 ;;
(* Data Definition *)
type tree = Node of PlayerGame.state * PlayerGame.move * tree list ;;
let rec make_tree (root: PlayerGame.state * PlayerGame.move) (d: int): tree =
let (s, m) = root in
let lms = PlayerGame.legal_moves s in
match lms, d with
| [], _ | _, 0 -> Node (s, m, [])
| _, _ -> Node (s, m, (List.map
(fun mv -> make_tree ((PlayerGame.next_state s mv), mv) (d - 1))
lms)) ;;
let compare_node (n1: PlayerGame.move * float) (n2: PlayerGame.move * float)
(comp: 'a -> 'a -> 'a): PlayerGame.move * float =
match n1, n2 with
| (m1, f1), (m2, f2) -> if (comp f1 f2) = f1 then n1 else n2 ;;
let rec minimax (t: tree) (mm: bool): PlayerGame.move * float =
match t with
| Node (s, m, []) -> (m, PlayerGame.estimate_value s)
| Node (s, m, children) -> let propagated = List.map
(fun c -> minimax c (not mm)) children in
(match mm with
| true -> List.fold_right
(fun x y -> compare_node x y max)
propagated (m, neg_infinity)
| false -> List.fold_right
(fun x y -> compare_node x y min)
propagated (m, infinity)) ;;
let next_move s = minimax (make_tree (s, (Move 0)) max_depth) true ;;
end ;;
module AIPlayer = (TestAIPlayer : PLAYER with module PlayerGame := Game) ;;
I'am trying to decrypt the return of calc function below but i'am very confused.
I have the f function that takes 3 ints and returns an int.
The calc fuction i think should return val calc : int -> int = <fun> because f has to take 3 ints, i'am giving it x and y so now it needs one more to return another int, the final result. Why it this logic not correct?
I can't make any sense of the actual output, specially with the polymorfic values when i forced parameters in f to be integers.
# let f (x : int) (y : int) (z : int) = x + y + z;;
val f : int -> int -> int -> int = <fun>
# let calc x y f = f x y;;
val calc : 'a -> 'b -> ('a -> 'b -> 'c) -> 'c = <fun>
In the expression let calc x y f = f x y;;, f is a locally-bound variable (calc binds x, y and then f) rather than the function you have defined before.
If you had written let calc x y = f x y;; then you'd have the expected result.
The function calc contains no reference to the functionf. There is an argument named f be it could be named g without changing anything: let calc x y g = g x y. If you want to use the function f you have defined above and not any function of the right type, you must not pass f as an argument, you should rewrite calc like this:
let f x y z = x + y + z
let calc x y = f x y
and then calc will have the type int -> int -> (int -> int) which is more commonly written as int -> int -> int -> int.
Are the two types: int -> int -> int and int -> (int -> int) the same?
If I write let f x = fun y -> x + y + 1, utop returns int -> int -> int. But I want is a function that takes an int as a parameter and then return a function which also takes an int and returns int, i.e., int -> (int -> int)
Is there a way to do that?
Also for (’a * ’b -> ’c) -> (’a -> ’b -> ’c), I wrote let f g = fun a b -> g (a,b), but it returns (’a * ’b -> ’c) -> ’a -> ’b -> ’c, the parentheses are eliminated. But why?
If a new function is returned as result, will it be anyway curried?
Usually, in lambda-calculus all functions have 1 arguments. Functions that take two arguments (not a tuple) are functions which take 1 argument and return another functions. If you look at the problem from this point of view you will understand that -> is right-associative.
Yes, they are the same. The arrow is a right-associative infix constructor, which is why the parentheses are redundant on the right.
It is perhaps helpful to realise that
let f x y z = e
is simply syntactic sugar for
let f = fun x -> fun y -> fun z -> e
Everything else follows form there.
Well yes, they are the same.
You can try it out, just type in
let f x y = x + y + 1;;
val f : int -> int -> int = <fun>
# let g = f 1;;
val g : int -> int = <fun>
# let _ = List.map g [1;2;3];; (* would do the same with (f 1) instead of g *)
- : int list = [3; 4; 5]
The whole idea is that function are by default curryfied. And as a -> ( b -> c ) and a -> b -> c are equivalent, they are displayed as the lightest type possible.