module D = struct type t = float list end
module DF(D) = struct type t = D.t end
gets a syntax error in utop
However,
module D = struct type t = float list end;;
module DF(D) = struct type t = D.t end
Does not
Utop ignores everything on the right of ;; since ;; signals the end of a toplevel phrase.
Related
I wonder why one example fails and not the other.
(* this fails *)
(* (l fails to type check)
This expression has type 'a but an expression was expected of type
(module M.TFixU)
The module type M.TFixU would escape its scope
*)
let foldList1 (type ar) algr l =
let module M = FixT (ListIntF) in
let (module LU : M.TFixU) = l in
assert false
(* but this works *)
let foldList2 (type ar) algr l =
let (module LU : FixT(ListIntF).TFixU) = l in
assert false
complete code
module Higher = struct
type ('a, 't) app
module type NewType1 = sig
type 'a s
type t
val inj : 'a s -> ('a, t) app
val prj : ('a, t) app -> 'a s
end
module NewType1 (X : sig
type 'a t
end) =
struct
type 'a s = 'a X.t
type t
external inj : 'a s -> ('a, t) app = "%identity"
external prj : ('a, t) app -> 'a s = "%identity"
end
end
module Fix = struct
open Higher
module FixT (T : NewType1) = struct
module type T_Alg = sig
type a
val alg : (a, T.t) app -> a
end
module type TFixU = sig
module App : functor (A : T_Alg) -> sig
val res : A.a
end
end
type tFixU = (module TFixU)
end
end
module Pb = struct
open Higher
open Fix
(* intro *)
type 'r listIntF = Empty | Succ of (int * 'r)
module ListIntF = NewType1 (struct
type 'r t = 'r listIntF
end)
(* this fails *)
let foldList1 (type ar) algr l =
let module M = FixT (ListIntF) in
let (module LU : M.TFixU) = l in
(* (l fails to type check)
This expression has type 'a but an expression was expected of type
(module M.TFixU)
The module type M.TFixU would escape its scope
*)
let module T = LU.App (struct
type a = ar
let alg = algr
end) in
T.res
(* but this doesn't *)
let foldList2 (type ar) algr l =
let (module LU : FixT(ListIntF).TFixU) = l in
let module T = LU.App (struct
type a = ar
let alg = algr
end) in
T.res
end
In the first case, the type of l is unified with the type defined in the module M, which defines the module type. Since the type is introduced after the value l, which is a parameter in an eager language so it already exists, the value l receives a type that doesn't yet exist at the time of its creation. It is the soundness requirement of the OCaml type system that the value lifetime has to be enclosed with its type lifetime, or more simply each value must have a type. The simplest example is,
let x = ref None (* here `x` doesn't have a type since it is defined later *)
type foo = Foo;; (* the `foo` scope starts here *)
x := Some Foo (* foo escapes the scope as it is assigned to `x` via `foo option` *)
Another simplified example, that involves a function parameter is the following,
let foo x =
let open struct
type foo = Foo
end in
match x with
| Some Foo -> true (* again, type foo escapes the scope as it binds to `x` *)
| None -> false
A very good article that will help you understand in-depth scopes and generalization is Oleg Kiselyov's How OCaml type checker works -- or what polymorphism and garbage collection have in common.
Concerning the second case, you clearly specified the type of l using the applicative nature of OCaml functors. And since the typechecker knows that the lifetime of FixT(ListIntF).TFixU is greater than the lifetime of l it is happy.
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
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.
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>
module type ELEMENT =
sig
type element_i
end
module Element:ELEMENT =
struct
type element_i = N of int | CNN of cnn
end
module type SEMIRING =
functor (E:ELEMENT)->
sig
type elements
end
module Semiring:SEMIRING =
functor(Element:ELEMENT) ->
struct
let zero = (Element.element_i 0) (*ERROR: Unbounded Value; Same with N 0*)
end
How can I create objects of the type element_i inside Semiring module here?
You can allow the programmer to create values of type element_i inside Semiring by not hiding the constructors of this type, as you are currently doing.
Instead, define the signature ELEMENT as:
module type ELEMENT =
sig
type element_i = N of int | CNN of cnn
end
This makes your functor Semiring expect more of its Element argument: instead of any type Element.element_i, it now only accepts a type with exactly these constructors. But on the plus side it can now apply the constructors to build values of this type, for instance Element.N 12
There's actually two problems with your example. The first is pointed out by Pascal (i.e., the constructors of element_i are hidden by the signature). The second is that the module Element in the functor is not the same as module Element you declared above. The Element argument to the functor is a "hiding" the definition of Element the same way a function parameter would "hide" a variable:
let x = 0
let f = fun x -> (* x here is a different x... *)
module type T = sig (* ... *) end
module M : T = struct (* ... *) end
module F = functor (M : T) -> (* M here is a different M... *)