How to use in a submodule a exception created in module (in ocaml) - module

I have a module type A with an exception. A will be implemented by B and C
module type A = sig
type t
val f: t->t->t
exception DivisionParZero
end
module B : A = struct
type t = int
let f a b=
if (a==0) then raise DivisionParZero else b/a
end
end
Ocamlc says when it compiles B:
Error: This variant expression is expected to have type exn
The constructor DivisionParZero does not belong to type exn
I don't understand why it doesn't work.

A is a signature that B needs to fulfill. In your context it means that you have to write the declaration line again:
module B : A = struct
type t = int
exception DivisionParZero
let f a b=
if (a==0) then raise DivisionParZero else b/a
end
You can experiment a little by returning a random value instead of raising the exception and you will see that the compiler tells you that your implementation does not fit the signature:
Error: Signature mismatch:
Modules do not match:
sig type t = int val f : int -> int -> int end
is not included in
A
The extension constructor `DivisionParZero' is required but not provided
File "test.ml", line 4, characters 2-27: Expected declaration

Related

OCAML first class modules signature inference

1) Suppose there is a module
module Int_Sig_1 =
struct
let x = 1
end
;;
2) and an explicit signature of this module
module type INT_SIG =
sig
val x:int
end
;;
3) and i create a first-class module based on the above module and module type
let int_sig_1 = (module Int_Sig_1:INT_SIG)
4) Now i create another module with no explicit signature but same inferred signature as above
module Int_Sig_2 =
struct
let x =2
end
;;
5) As written in Chapter 10 of the book Real World OCAML "The module type doesn't need to be part of the construction of a first-class module if it can be inferred", i try to create a second first class module using the above module but with no explicit module type
let a2 = (module Int_Sig_2);;
I get the following error
Error: The signature for this packaged module couldn't be inferred.
6) then i try to do the same as above in 5, but this time I put the first class module with no module type being create as an element of a list, where the head of the list is a first class module that was created out of an explicit signature in 3 above.
let int_sig= [int_sig_1;(module Int_Sig_2)];;
val int_sig : (module INT_SIG) list = [<module>; <module>] ;;
My question is why 5 above gives me an error and 6 does not fail ?
The problem with (5) is that in general, there are multiple module types that could be infered. In your example, there is at least two valid module types which could be used to pack Int_Sig_2:
module type empty = sig end
module type with_x = sig val x:int end
In other words, both
let a2 = (module Int_Sig_2: empty)
let a2_bis = (module Int_Sig_2:with_x)
are valid. Consequently, the type checker will not try to infer a module type in this situation.
Contrarily, in your example (6), the type of the list is determined by its first element, whose type is (module INT_SIG_2), therefore the type-checker can use this information to infer that the expected type for the second element of the list is (module INT_SIG_2). Nevertheless, reversing the two elements yields a type error. In other words, this is fine:
[(module struct let x = 2 end: with_x); (module struct let x = 1 end)]
however, the reverse yields
[(module struct let x=2 end); (module struct let x = 3 end:with_x)];;
Error: The signature for this packaged module couldn't be inferred.
This is due to the fact that the type-checker has a left-to-right bias and types first the first element of the list first.

OCaml sub-module constrained by a sub-signature

I have a module Mod that is constrained by signature Sig. The module has a Nested sub-module. The signature has a matching Nested sub-signature:
module type Sig = sig
val a : int
module type Nested = sig
val b : int
end
end
module Mod : Sig = struct
let a = 1
module Nested = struct
let b = 2
end
end
However, this gives the following error:
Error: Signature mismatch:
Modules do not match:
sig val a : int module Nested : sig val b : int end end
is not included in
Sig
The field `Nested' is required but not provided
What am I missing?
The way of declaring the nested module was wrong in your code :
module type Sig = sig
val a : int
module Nested : sig val b : int end
end
module Mod : Sig = struct
let a = 1
module Nested = struct
let b = 2
end
end
Look how the submodules are declaring in the following link : http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora131.html
It helps me to fix your error.

Signature mismatch with types in modules/functors

Excuse my potential misuse of terminology, I'm still not very comfortable with OCaml.
We have a functor with the following (abridged) signature:
module type FUNCTORA = sig
type input
type output
type key
type inter
val my_function : input list -> (key * output) list Deferred.t
end
Next, we implement it as such. MYAPP has the same types as above.
module MyFunctor (App : MyAPP) : FUNCTORA = struct
type input = App.input
type output = App.output
type key = App.key
type inter App.value
let my_function lst = ...
end
When trying to compile the implementation, we get this error:
Error: Signature mismatch:
...
Values do not match:
val my_function :
App.input list ->
(App.key * App.output) list Async_kernel.Deferred.t
is not included in
val my_function :
input list -> (key * output) list Async.Std.Deferred.t
It doesn't consider input to include App.input etc, even though we set them to be the same type. How can we get this to type check?
If I make the following changes:
MyAPP => FUNCTORA (* Since you say they are the same *)
type inter App.value => type inter = App.inter (* Syntax/name error *)
Deferred.t => option (* To limit dependence on other modules *)
Then your code compiles for me.
Possibly the problem is with Deferred.t. There are two distinct looking types in the error message.

Dealing with type name conflicts when include'ing two modules in OCaml

can anyone help me for the exercise 12.5 of Jason Hickey's book?
Basically, the question is how to avoid the following conflicting issue due to "include" in practice? Thanks.
# module type XSig = sig
type t
val x : t
end;;
# module A : XSig = struct
type t = int
let x = 0
end;;
# module B : XSig = struct
type t = int
let x = 1
end;;
# module C = struct
include A
include B
end;;
I don't know what the question precisely says, but regarding your code snippet, there are various very different way to interpret what you're trying to do.
What you are currently doing is sealing A and B under two abstract, incompatible signatures, then trying to mix them in a module, only to have a name conflict.
Maybe you just want to avoid the name conflict. The simplest solution, of course, is not to use the same names for both types A.t and B.t. Then you can "not include B":
module C = struct
include A
let x_b = B.x
end
The better solution is to use OCaml 3.12 destructive substitution for signatures, with type t := foo, to mask the type t from the module B:
module C = struct
include A
type u = B.t (* rename B.t into 'u' to avoid name conflict *)
include (B : XSig with type t := u) (* replaces 't' by 'u' *)
end
You may also want the types for modules A and B to be compatible. In this case you must not seal them with abstract types.
module type XSig = sig
type t
val x : t
end
module A = struct
type t = int
let x = 0
end
(* if you want to check that A can be sealed by XSig, do it here,
outside the main declaration *)
let _ = (module A : XSig)
module B = struct
type t = int
let x = 1
end
module C = struct
include (A : XSig with type t := int)
include (B : XSig with type t := int)
end
(* module C : sig
val x = int
end *)
In this example both types A.t and B.t are removed by the destructive subtitution :=. If you want your module C to have a type t, you can write either of:
module C = struct
type t = int
include (A : XSig with type t := t)
include (B : XSig with type t := t)
end
or, using non-destructive substitution (changes the type definition instead of removing it):
module C = struct
include (A : XSig with type t = int)
include (B : XSig with type t := t)
end
See the manual page for destructive substitution type type t := ... for more details, and the one on the classic with type t = ... construction for comparison.

Relaxing type checking when using 'with type' construction in modules

I have defined two module types and two modules
module type FOO = sig type e end
module type BAR = sig type t end
module Foo : FOO = struct type e = int end
module Bar : BAR = struct type t = int end
Then I define a functor as
module Fun (F:FOO) (B:BAR with type t = F.e) = struct type x = string end
(this is a toy example, please ignore the fact that F and B are not used by the functor)
Now, if I define the module
module Bla = Fun (Foo) (Bar)
I get
Error: Signature mismatch:
Modules do not match:
sig type t = Bar.t end
is not included in
sig type t = Foo.e end
Type declarations do not match:
type t = Bar.t
is not included in
type t = Foo.e
Although both Bar.t and Foo.e are defined as int OCaml considers Bar.t and Foo.e to be different. That's just the way the typing system works and it makes sense to consider these two types different in general (c.f. last paragraph of Functors and Type Abstraction).
Question: Sometimes I may want this to pass type checking because for my purposes they can be considered equal. Is there a way to relax this?
Using gasche's suggestion of removing coercion, the above code can be written as
module type FOO = sig type e end
module type BAR = sig type t end
module Foo = struct type e = int end
module Bar = struct type t = int end
module Fun (F : FOO with type e=int) (B : BAR with type t = int) = struct type x = F.e * B.t end
module Bla = Fun (Foo) (Bar)
which compiles fine. Strangely, I get
# let f x : Bla.x = (x,x);;
val f : Foo.e -> Bla.x = <fun>
Question: why does it infer that x is Foo.e? It could as well be Bar.t?
The problem is how you define Foo and Bar : module Foo : FOO = .... By imposing this signature here, you "seal" the module and make the type abstract. It cannot be reverted. You should remove the : FOO coercion here, and use it later when you need the abstraction. You could also use module Foo : (FOO with type e = int) = ....
I'm not sure how the printer chooses amongst equal types, but in this case you can cause it to print a different name by explicitly annotating your function argument:
# let f (x:Bar.t) : Bla.x = (x,x);;
val f : Bar.t -> Bla.x = <fun>