Functors in separate files in OCaml? - ocaml

I want to have a big functor Hello(Blah: Blah_type) and save it in the file hello.ml, but how do I do this?
If I was just in my top level file, I'd have
module Hello(Blah: Blah_type) =
struct
val x = 2
end
but how do I put the argument in hello.ml? I can't just have the whole file being "val x = 2" ... ?

OCamlPro has a compiler patch and external tool which may support this:
http://www.ocamlpro.com/blog/2011/08/10/ocaml-pack-functors.html
As far as I know the official compiler release does not support .ml files as functors.

It is not possible. Source files are always represented as ordinary modules, not functors. This is trivially solved with one extra open.

To complement ygrek's answer with a real code sample, instead of a file foo.ml with content
module type S = sig
(* ... *)
end
module Hello (M : S) = struct
(* ... *)
end
module M : S = struct
(* ... *)
end
module H = Hello(M)
(* ... *)
You could have hello.ml with content
module type S = sig
(* ... *)
end
module Make (M : S) = struct
(* ... *)
end
and foo.ml rewritten as
module M : Hello.S = struct
(* ... *)
end
module H = Hello.Make(M)
(* ... *)
PS: In case you find it confusing, the module sealing M : S or M : Hello.S is optional (M will be coerced to this signature when passed to the functor anyway), it was just to show how this can be done.

Related

How to fix the OCaml compile error when using type annotations with functors?

I am new to OCaml and I am trying use functors. When I use the module type annotations with the functors, this results in a compile time error in my code.
When I remove the : Printable (from the module FromToString line) and the : ToString (from the module IntToString line) annotations, the following program compiles without error:
module type ToString =
sig
type t
val to_string: t -> string
end
module type Printable =
sig
type t
val print: t -> unit
end
module FromToString (S:ToString) : Printable =
struct
type t = S.t
let print a = print_string ( S.to_string a)
end
module IntToString : ToString =
struct
type t = int
let to_string = string_of_int
end
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
However, when I add these annotations (as shown in the code) the compiler gives the following error:
File "Functor.ml", line 26, characters 28-29:
Error: This expression has type int but an expression was expected of type
PrintableInt.t = FromToString(IntToString).t
How can I use these annotations without causing a compile error?
The root issue is that your signature constraints make the resulting module far too opaque. When you constrain your functor result:
module FromToString (S:ToString) : Printable = ...
you are making the type t an abstract type, which can only be consumed by the to_string function and never been produced. In other words, a module of type Printable is unusable by itself.
When starting with functor, it is very often useful to look at the module type inferred by the compiler for the resulting module.
In the FromToString case, this is:
module FromToString (S:ToString) : sig
type t = S.t
val print: t -> unit
end = ...
You can see that the inferred module type of the result
sig
type t = S.t
val print: t -> unit
end
that it is quite similar to Printable except that now the type t is equal to the type t of the argument module S.
Thus, it is possible to reuse Printable to write the full module type of the result by adding a type equality with a with constraint:
module FromToString (S:ToString): Printable with type t = S.t = struct
type t = S.t
let print a = print_string ( S.to_string a)
end
The same issue appears for IntToString and can be fixed in a similar way:
module IntToString : ToString with type t = int =
struct
type t = int
let to_string = string_of_int
end
Then the compiler error is gone:
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
One has to make the type t public, using the with notation:
module type ToString =
sig
type t
val to_string: t -> string
end
module type Printable =
sig
type t
val print: t -> unit
end
module FromToString (S:ToString) : Printable with type t = S.t =
struct
type t = S.t
let print a = print_string ( S.to_string a)
end
module IntToString : ToString with type t =int =
struct
type t = int
let to_string = string_of_int
end
module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3

OCaml Unbound value enf

I have a question about using a local function in a global function.
I tried to write the function which appears in the picture, but an error said
unbound value of f
It's strange that this error occurs. It should not appear because I defined the definition of the function enf in affichage.
Here is a picture of a relevant part of my code:
What can be the reason of this error?
enf is not defined when affichage is defined, so since the body of affichage refers to enf, this results in an unbound value error. In order to have mutually recursive functions, you'll need something of the form
let rec affichage (* ... *) =
(* ... *)
and enf (* ... *) =
(* ... *)
in
(* ... *)
;;

Losing type precision from module signature

Let's say I had a simple module MyFoo that looks something like this
module MyFoo = struct
type t =
| A of string
| B of int
let to_string thing =
match thing with
| A str -> str
| B n -> string_of_int n
end
With this definition, it works great and as expected — I can do something like
let _ = MyFoo.A "";;
- : MyFoo.t = MyFoo.A ""
without any problems.
Now maybe I want to create a functor that consumes modules with this structure, so I define a module signature that describes generally what this looks like and call it BaseFoo
module type BaseFoo = sig
type t
val to_string : t -> string
end
If I redefine MyFoo the same way but giving it this signature like
module MyFoo : BaseFoo = struct
type t =
| A of string
| B of int
let to_string thing =
match thing with
| A str -> str
| B n -> string_of_int n
end
I lose the precision of its type t (is there a better way to describe what happens here?) — for example:
let _ = MyFoo.A "";;
Error: Unbound constructor MyFoo.A
What exactly is going on here and why does it happen? Is there a canonical way for dealing with this kind of problem (besides just leaving off the signature)?
I've tried manually including the signature and the specific type type definition too but get a different kind of error (this probably isn't the right approach).
module MyFoo : sig
include BaseFoo
type t = | A of string | B of int
end = struct
type t =
| A of string
| B of int
let to_string thing =
match thing with
| A str -> str
| B n -> string_of_int n
end
let _ = MyFoo.A "test";;
Error: Multiple definition of the type name t.
Names must be unique in a given structure or signature.
You don't need the signature
What is going on is pretty much what you describe: giving MyFoo the BaseFoo signature in its definition restricts it to the signature.
Why? Because this is what specifying a signature at this place is for. The canonical solution is to leave of the signature (usually, letting the signature definition next to the module definition will be clear enough for the reader).
Note that when you call MyFoo on your functor, the signature will be checked. My usual choice is to rely on that.
A few workarounds
Given what you've tried, I guess this could be interesting to you:
module type BaseFoo = sig ... end
module MyFoo = struct ... end
module MyFooHidden : BaseFoo = MyFoo (* Same as defining MyFoo : BaseFoo *)
module MyFooWithType :
BaseFoo with type t = MyFoo.t
= MyFoo (* What you want *)
The with type t = t' clause allows you to annotate a module signature to add type information to it. It is quite useful, especially when dealing with functors. See here for more information.
MyFooHidden may seem useless, but you can see it as a check that MyFoo has the right signature. You can still use MyFoo however you want after all. MyFooWithType is actually (a bit) less useful because if you change your signature to add a type you'd want exported, you'd need to add the export here too.
Using include
As for your include try. Well, nice try! You were almost there:
module MyFoo : sig
type t = A of string | B of int
include BaseFoo with type t := t
end
The with type t := t' is a bit different in that it doesn't perform an equality but a replacement. The type t definition is removed from the BaseFoo signature altogether and all instances are replaced with your own t, that way you don't get any double definition problem. See here for more details.
As you point out, this is probably not the approach you want, as you no longer easily know that MyFoo is indeed a BaseFoo.

Standard ML export operator from structure as infix

I would like to declare an infix operator within a structure a for use outside the structure. But I cannot seem to get the "infixness" to be recognized outside the structure even when the structure has been opened. Here is an example using Poly/ML:
> structure A = struct infix 6 ++ fun a ++ b = a + b end;
structure A: sig val ++: int * int -> int end
> 1 A.++ 2;
poly: : error: Type error in function application.
Function: 1 : int
Argument: A.++ : int * int -> int
Reason: Value being applied does not have a function type
Found near 1 A.++ 2
Static Errors
> let open A in 1 ++ 2 end;
poly: : error: Type error in function application.
Function: 1 : int
Argument: ++ : int * int -> int
Reason: Value being applied does not have a function type
Found near let open A in 1 ++ 2 end
Static Errors
Is this a limitation of Standard ML?
Yes, this is not supported by Standard ML. You'll have to re-declare the fixity and, optionally, the precedence every time you open that structure. One way to get around it is to declare the fixity globally, i.e., outside any structure, but this isn't well supported with separate compilation and it isn't very modular either. You can read more about it and a possible workaround on the MLton's InfixingOperators page.
For my own projects, I've defined a shortcut in my text editor that will expand into both an open declaration as well as a fixity one.
Also, as a personal style guide, I'm not declaring the precedence. If I need to mix multiple infix operators into the same expression, I'll rather use parentheses explicitly. Eye-parsing an identifier as infix is easy, parsing the precedence is not.

Confusing type declaration?

I haven't worked with SML in awhile and I came across this line of code:
type memory = string -> int;
Does this define 'memory' to be a function which takes a string a returns an int, or something else entirely? I've searched for a similar declaration but I can't seem to find one or figure out what it does.
When I put it into SML/NJ, I just get this:
- type memory = string -> int;
type memory = string -> int
memory is not a function , it's just an abbreviation for a type that is a function that takes as input a string and returns an int.
So whenever you would like to write that something is of type string->int you can just write it's of type memory.
For example instead of writing:
- fun foo(f : string->int, s) = f s;
val foo = fn : (string -> int) * string -> int
you could write:
- fun foo( f: memory, s) = f s;
val foo = fn : memory * string -> int
Such type declarations can make your code more readable (e.g. instead of writing that a pair x is of type int*int like (x: int*int), you can just create an abbreviation type pair = int*int and then you can write that x is of type pair like this (x: pair)).