How to mix polymorphic functions with functors in ocaml? - ocaml

I have a functor to make a Heap module from a Comparable module, and a polymorphic function to apply Prim's algorithm to graphs with arbitrary labels. Ideally I'd like to be able to write something like:
let prim (graph: 'a graph)=
let module EdgeHeap=Heap.Make(
struct
type t='a edge
...
end
) in
...
let heap=EdgeHeap.create () in
...
but ocamlc says that 'a is unbound. How do I work around this?

Normally, you'd have prim (along with related functions) in a functor of its own that is parameterized over a graph module signature. I.e. something like:
module type GraphSpec = sig
type t
...
end
module GraphAlgorithms(G: GraphSpec) = struct
type graph = ...
module EdgeHeap = Heap.Make(struct
type t = G.t edge
...
end)
let prim (g: graph) = ...
let kruskal (g: graph) = ...
end
This avoids the use of type variables; instead, you pass the type through the GraphSpec functor argument.
But if you just need it for a single function, this may be overkill. You can work around it then by using locally abstract types. A simple example to illustrate how that works:
let min_list (type u) (l: u list) =
let module S = Set.Make(struct
type t = u
let compare = compare
end) in
S.of_list l |> S.min_elt

Related

How does infinite-looping the OCaml type checker using modules work?

The OCaml type-checker infinite-loops on this example:
module type I =
sig
module type A
module F :
functor(X :
sig
module type A = A
module F : functor(X : A) -> sig end
end) -> sig end
end
module type J =
sig
module type A = I
module F : functor(X : I) -> sig end
end
(* Try to check J <= I *)
module Loop(X : J) = (X : I)
source: Andreas Rossberg adapting Mark Lillibridge's example
I don't have a good handle of how/why this works. In particular:
Is the example minimal?
What work are all the sharing constraints A = I, A = A, etc. doing? Are sharing constraints necessary in order to cause this infinite loop?
What work is the inline signature in the first functor doing? That seems to be essential to the example.
Is this trick useful only for infinite-looping, or can arbitrary computation happen in the module system?
Can examples like this be translated to other languages? Traits and classes with type members and parameterized type aliases look a lot like the code above.
The example is pretty minimal, it relies on two essential ingredients:
an abstract module type
a functor to make the abstract module type appear in both covariant and contravariant position.
Answering your high-level questions before going back to the example:
With this trick only the subtyping checker for the module type system is doing an unbounded amount of work. You cannot observe the result of this computation. However, using abstract module type is the key to trick the module type system into doing expansive computation (a module with a chain of 4↑↑4 submodule for instance)
Reproducing this exact problem probably requires both subtyping and impredicativity, I am not sure how often this combination appears outside of module systems.
Going back to the example at hand, I propose to leap a bit into the future with OCaml 4.13 and its with module type constraint. I hope that this makes the ingredients behind this trick a little bit more visible:
module type e = sig end
module type Ieq = sig
module type X
module type A = X
module F : X -> e
end
module type I = sig
module type A
module F : Ieq with module type X = A -> e
end
module type J = Ieq with module type X = I
Opinions may vary, but I find that this form makes it more obvious that in the I case, we have more equations on the functor F component, whereas in the Ieq with module type X = ... case, we have one more equation on the module type A component.
While trying to prove that J<I, we end up moving around those equations without achieving any progress. Let's try to see how that happens step by step.
First, we look at the module type A:
J
I
J.A = module type A = I
I.A = module type A (abstract)
Since I.A is abstract, this is true. Then, we need to compare J.F and I.F, but only after adding the equation A=I from J.
J
I with module type A = I
J.F = I -> e
I.F = (Ieq with module type X = (*A =*) I) -> e
Now, we have a functor. Functors are contravariant in their argument. In other words, to prove that X -> e < Y -> e, we need to prove that Y < X.
Thus, we need to prove that Ieq with module type X = I < I... but this inequation looks a bit familiar. And indeed, we had defined:
module type J = Ieq with module type X = I
Reusing this definitions, this means that we are back to trying to prove J<I, without making any progress.
If we look at our previous steps, the problem started when we extended I with another copy of itself I with module type A = I. Then contravariance allowed us to spread this increase of size to both side of the comparison. Therefore, our inclusion check is always producing more work for its future self and this specific inclusion check never ends.

Interface of arbitrary types for OCaml Plugin

I am using ocaml_plugin to write calculator which is able to evaluate OCaml expressions at run time.
This is my plugin interface.
open Ocaml_plugin.Std
module type S = sig
val f : unit -> float
end
let univ_constr : (module S) Ocaml_dynloader.Univ_constr.t =
Ocaml_dynloader.Univ_constr.create ()
I am able to load functions with the signature unit -> float, for example,
let f () = 3.14159
let f () = 1.5 *. 1.5 *. 3.
and call f () in the main program to evaluate the expression in the function body. However, it supports float type only.
What should I do if I want it to support int? Time.t? Or any arbitrary OCaml type in Pervasive?
let f () = List.length [1;2;3] (* int *)
let f () = Time.now () (* Time.t *)
let f () = "hello world!!!" (* string *)
In order to evaluate at run time, ocaml_plugin seems to be the only way to go. However, in order to let the loader/compiler know what is loaded dynamically, I have to write an interface. How should I change the interface file so that it supports other types?
GADT (Generalized Algebraic Data Type) to rescue.
Although GADT exists for a long time, it is a relatively new topic in OCaml. It helps a lot in writing generic libraries in OCaml safely.
module Value = struct
type 'a t
module Packed = struct
type 'a unpacked = 'a t
type t = T : 'a unpacked -> t
end
end
Value.Packed.t is a packed data type that we want. Theotically any data type 'a can be packed.

OCaml: Type error while combining recursive modules and private type abbreviations

I am currently working with OCaml, and I want to create some types which are somehow secured, in the sense that I want to select only those instances which satisly some properties.
The way that I found to acheive that is to encapsulate my type in a module, making it private, and defining the constructors in such a way that they check if the object that they are trying to make satisfy these properties. As my code is a bit long, I want to split into different modules, but my types are mutually recursive, so I am using recursive modules. I end up in the following situation (I simplified a lot so that it becomes readable)
module rec A
: sig
type t = private int list
val secured_cons : int -> t -> t
end
= struct
type t = int list
let cons (i:int) (x:t) : t = i::x
let secured_cons i x : t = B.checker i x; cons i x
end
and B
: sig
val checker : int -> A.t -> unit
end
= struct
let checker i x = ()
end
But this code is rejected, with the following error message :
Characters 226-227:
let secured_cons i x = B.checker i x; cons i x
^
Error: This expression has type A.t but an expression was expected of type
t = int list
This looks to me very weird, because as we are in the context A, the two types t and A.t are supposed to be equal. From my understanding, what happens is that inside A, the type t is considered to be a synonym for int list whereas outside A, the signature tells us that it is private, so it is just a copy of this type, with a coercion A.t :> int list. The entire point is that there is no coercion the other way around, which is exactly why I want to use private type abbreviations
But in my case I am inside the module A, so I would like to use this extra information to say that my type t should coerce to A.t
Does anyone have a better explanation of why this error is happening, and how I could avoid it? (I have thought of switching to abstract types, but I get exactly the same error)
I have found a way to solve this issue I am posting it here in case anyone else ever encounters the same.
We just have to explicitly specify what types and coercion we expect from the system - here is my example slightly modified in a correct way :
module rec A
: sig
type t = private int list
val secured_cons : int -> t -> t
end
= struct
type t = int list
let cons (i:int) (x:t) : t = i::x
let secured_cons i (x:A.t) = B.checker i x; cons i (x :> t)
end
and B
: sig
val checker : int -> A.t -> unit
end
= struct
let checker i x = ()
end
It might look silly to write let secured_cons i (x:A.t) inside the module A itself, but as far as I understand it, it is the only way to specify to the system that it should go out of the module to check the signature, and use the same type as the signature (so here a private type) instead of the internal type t which is still a synonymous for int list
I had more trickier cases, but this idea could be adapted to each of them, and helped me solve them all.
Still I am not entirely sure of what is happening, and if anyone has clearer explanations, I would be very thankful
You're errors occur because when B.checker is invoked, x is infered as an A.t because of the signature of B.
You can see that easily if you explicitly type the secured_cons function :
let secured_cons i (x:t) : t = B.checker i x; cons i x
which now produces the symmetrical error:
let secured_cons i (x:t) = B.checker i x; cons i x
^
Error: This expression has type t = int list
but an expression was expected of type A.t
In fact you here have a real designing problem in my opinion. If you want the module B to check the values produced by the module A, so without surprise B must inspect in some way the type A.t. Having that type private makes it impossible.
From what i understand you have three options :
remove private
Add a browse, getter function that allows the B module to access the content of the values of type A.t
the way i would do this : put the checking function into the module A
I'd be glad to hear what more experienced users have to say about this, but here is my take on it.
I, as a developer, usually give a lot of importance to the semantics of a code. In your case, the B module is specifically used by the A module, and it has no other goal than that.
Thus, sticking to a nested module (even if it makes your code a bit longer) would be the way to go as far as I am concerned. There is no point is exposing the B module. Below is the refactored example to illustrate.
module A : sig
type t
val secured_cons : int -> t -> t
end = struct
type t = int list
module B : sig
val checker : int -> t -> unit
end = struct
let checker i x = ()
end
let cons i x = i::x
let secured_cons i x = B.checker i x; cons i x
end
And here is the signature of the module as given by utop:
module A : sig type t val secured_cons : int -> t -> t end
which is perfect in my sense because it only shows the interface to your module, and nothing of its implementation.
As a side-note, if you wanted to expose the signature of the B module (to give it to a functor, for example), just move it to the signature of the A module, as follows:
module A : sig
type t
val secured_cons : int -> t -> t
module B : sig
val checker : int -> t -> unit
end
end = struct
type t = int list
module B = struct
let checker i x = ()
end
let cons i x = i::x
let secured_cons i x = B.checker i x; cons i x
end;;
Here is the signature of the module as given by utop:
module A :
sig
type t
val secured_cons : int -> t -> t
module B : sig val checker : int -> t -> unit end
end
Still I am not entirely sure of what is happening, and if anyone has clearer explanations, I would be very thankful
A private type abbreviation of the form type u = private t declares a type u that is distinct from the implementation type t. It is the same as declaring an abstract type with the following two exceptions:
compiler treats the type t, as an implementation type, that opens an avenue for optimizations - this, however, doesn't mean that a type checker considers them the same, for the type checker they are distinct.
typechecker allows a coercion of type u to type t.
So, from a typechecker perspective, these two types are distinct. As always in OCaml type discipline all coercions should be made explicit, and a subtype is not equal to a super type unless it is coerced. In your case, the typechecker is trying to unify type A.t = private int list with type int list since A.t and int list are distinct types, it is rejected. It is, however, allowed to coerce A.t to int list (but not the vice verse).
It might look silly to write let secured_cons i (x:A.t) inside the module A itself
You don't need to write it (at least in your simple example). Just using x :> t is enough.

OCaml: how to use batteries and ppx_deriving.* together?

Currently I'm trying to use Batteries with ppx_deriving.show or something similar.
I am wondering how to use them together usefully.
To create dumping functions, I feel ppx_deriving.show is useful.
But I have a little bit troubles using them together like the followings.
open Batteries
type t = { a: (int,int) Map.t }
[##deriving show]
Now Map.pp is not defined, so it can't be compiled.
My adhoc fix is that I create module Map which include Batteries.Map and define function pp.
open Batteries
module Map = struct
include Map
let pp f g fmt t = ... (* create dump function by man hand *)
end
type t = { a: (int,int) Map.t }
[##deriving show]
It works, but it is painful for me to adapt all of data structures...
Core with ppx_deriving.sexp is an alternative choice, but I prefer Batteries with ppx_deriving.show.
Does anybody know how to solve the problem?
Your fix is the right way. If you want to use deriving for data types M.t declared without [##deriving], you have to give its methods such as M.pp for show by yourself:
module M = struct
include M
let pp = ... (* code for pretty-printing M.t *)
end
There is a way to partially automate this:
module M = struct
include M
type t = M.t = ... (* the same type definition of M.t *)
[##deriving show]
end
It generates M.pp for type t using deriving.
With ppx_import, you can avoid copy-and-pasting of the definition:
module M = struct
include M
type t = [%import: M.t]
[##deriving show]
end
This should be expanded to the former code.
As you have found out, deriving show of Map.t is not really useful though: normally you do not want to see the binary tree representation of Map.t unless you are debugging Map module itself.

OCaml Signature with multiple types

I would like to represent some scalar value (e.g. integers or strings)
by either it's real value or by some NA value and later store them
in a collection (e.g. a list). The purpose is to handle missing values.
To do this, I have implemented a signature
module type Scalar = sig
type t
type v = Value of t | NA
end
Now I have some polymorphic Vector type in mind that contains Scalars. Basically, some of the following
module Make_vector(S: Scalar) = struct
type t = S.v list
... rest of the functor ...
end
However, I cannot get this to work. I would like to do something like
module Int_vector = Make_vector(
struct
type t = int
end
)
module Str_vector = Make_vector(
struct
type t = string
end
)
... and so on for some types.
I have not yet worked a lot with OCaml so maybe this is not the right way. Any advises on how to realize such a polymorphic Scalar with a sum type?
The compiler always responds with the following message:
The parameter cannot be eliminated in the result type.
Please bind the argument to a module identifier.
Before, I have tried to implement Scalar as a sum type but ran into
complexity issues when realizing some features due to huge match clauses. Another (imo not so nice) option would be to use option. Is this a better strategy?
As far as I can see, you are structuring v as an input type to your functor, but you really want it to be an output type. Then when you apply the functor, you supply only the type t but not v. My suggestion is to move the definition of v into your implementation of Make_vector.
What are you trying to do exactly with modules / functors? Why simple 'a option list is not good enough? You can have functions operating on it, e.g.
let rec count_missing ?acc:(acc=0) = function
| None::tail -> count_missing ~acc:(acc+1) tail
| _::tail -> count_missing ~acc tail
| [] -> acc ;;
val count_missing : ?acc:int -> 'a option list -> int = <fun>
count_missing [None; Some 1; None; Some 2] ;;
- : int = 2
count_missing [Some "foo"; None; Some "bar"] ;;
- : int = 1