Reputation: 6340
Is it possible to open or use a functor without an intermediate module? For example, say we have the following set of modules and functors:
module type FOO = sig
val foo : int -> int
end
module Foo1 : FOO = struct
let foo x = x+1
end
module Foo2 : FOO = struct
let foo x = x+2
end
module Bar(Foo : FOO) = struct
open Foo
let apply x = foo x
end
If we try
let _ = Bar(Foo1).apply 1
we get the error
Error: Parse error: currified constructor
Certainly, we can accomplish this with
let _ =
let module Bar' = Bar(Foo1) in
Bar'.apply 1
but it's a little verbose. Alternatively, if we define a module that uses a functor
module Buz(Foo : FOO) = struct
open Bar(Foo)
let buz x = apply x
end
we get the error
Error: This module is not a structure; it has type
functor (Foo : FOO) -> sig val apply : int -> int end
Again, we can fix this with
module Buz(Foo : FOO) = struct
module M = Bar(Foo)
open M
let buz x = apply x
end
but it's more verbose. In addition, we have a new module M
defined in Buz
, which sort of pollutes the namespace
module Buz :
functor (Foo : FOO) ->
sig module M : sig val apply : int -> int end val buz : int -> int end
Really, I just want Buz
to include buz
.
Basically, I'm asking if there's some sort of syntax or trick that I'm missing that let's us write things like Bar(Foo1).apply
or open Bar(Foo1)
.
Upvotes: 4
Views: 1008
Reputation: 35210
You can skip instantiation of a functor if you're accessing a type, module type, or class type. In other words it is possible only inside type expressions. Example:
module type T = sig type t end
module Pair (T : T) = struct type t = T.t * T.t end
module Int = struct type t = int end
type int_pair = Pair(Int).t
What concerning the second part of your question, then if you really want "want Buz to include buz.", then you should use include
:
module Buz(Foo : FOO) = struct
include Bar(Foo)
let buz x = apply x
end
There is difference between open
and include
statement. open X
will not add any definitions from X
, but just add it into a search path. include X
will merely copy paste all definitions from X
into the point where it is included.
If you want only buz
in your module and nothing more, then you can hide it using module signatures:
module type Buz = sig val buz : int -> int end
module Buz(Foo : FOO) : Buz = struct
include Bar(Foo)
let buz = apply
end
Upvotes: 4