Explicit polymorphic type in record - ocaml

In OCaml, it is possible to define explicit polymorphic type in a record
type foo = { f : 'a. unit -> 'a };;
It seems we can assign only general values to f like
{ f = fun () -> failwith ""; }
or
{ f = fun () -> exit 1; }
How to use this language feature in real world? Is there any good practical example?

This isn't really connected with records. If you declare any function to have type 'a. unit -> 'a (takes nothing and returns whatever the caller wanted) then you can only use it for functions that don't return.
Here's a slightly more useful example: a record containing a function for finding the length of lists (of any type).
# type foo = { f : 'a. 'a list -> int };;
type foo = { f : 'a. 'a list -> int; }
# let foo = { f = List.length };;
val foo : foo = {f = <fun>}
# foo.f [1;2;3];;
- : int = 3
It can be useful if you wanted to pass a function like List.length as an argument to another function, and have it use it on multiple types:
Say we want to pass List.length to test. We can't do it directly:
# let test fn = fn [1;2;3] + fn ["a";"b";"c"];;
Error: This expression has type string but an expression was expected of type
int
But we can use a record:
# let test foo = foo.f [1;2;3] + foo.f ["a";"b";"c"];;
val test : foo -> int = <fun>
# test foo;;
- : int = 6

Related

How to apply [##deriving show] to a type from module parameter of my functor?

I have a functor that takes a Set type like:
module type MySet = functor (S : Set.S) -> sig
val my_method : S.t -> S.elt -> S.elt list option
end
module MySet_Make : MySet = functor (S : Set.S) -> struct
let my_method set el = Some [el] (* whatever *)
end
module IntSet = Set.Make(Int)
module MyIntSet = MySet_Make(IntSet)
S.elt is the type of elements of the set
I want to apply [##deriving show] (from https://github.com/ocaml-ppx/ppx_deriving#plugin-show) to S.elt within my functor somehow, so that in one of my methods I can rely on having a show : S.elt -> string function available.
I feel like it must be possible but I can't work out the right syntax.
Alternatively - if there's a way to specify in the signature that the Set type S was made having elements of a "showable" type.
e.g. I can define:
module type Showable = sig
type t [##deriving show]
end
...but I can't work out how to specify that as a type constraint to elements of (S : Set.S)
You can construct new signatures that specify the exact function show you need:
module MySet_Make(S : sig
include Set.S
val show : elt -> string
end) = struct
let my_method _set el =
print_endline (S.show el);
Some [el]
end
Then you can build the actual module instance by constructing the module with the needed function:
module IntSet = struct
include Set.Make(Int)
(* For other types, this function could be created by just using [##deriving show] *)
let show = string_of_int
end
module MyIntSet = MySet_Make(IntSet)
Ok, after a couple of hours more fumbling around in the dark I found a recipe that does everything I wanted...
First we define a "showable" type, representing a module type that has had [##deriving show] (from https://github.com/ocaml-ppx/ppx_deriving#plugin-show) applied to it:
module type Showable = sig
type t
val pp : Format.formatter -> t -> unit
val show : t -> string
end
(I don't know if there's some way to get this directly from ppx_deriving.show without defining it manually?)
Then we re-define and extend the Set and Set.OrderedType (i.e. element) types to require that the elements are "showable":
module type OrderedShowable = sig
include Set.OrderedType
include Showable with type t := t
end
module ShowableSet = struct
include Set
module type S = sig
include Set.S
end
module Make (Ord : OrderedShowable) = struct
include Set.Make(Ord)
end
end
I think with the original code in my question I had got confused and used some kind of higher-order functor syntax (?) ...I don't know how it seemed to work at all, but at some point I realised my MySet_Make was returning a functor rather than a module. So we'll fix that now and just use a normal functor.
The other thing we can fix is to make MySet a further extension of ShowableSet ... so MySet_Make will take the element type as a parameter instead of another Set type. This makes the eventual code all simpler too:
module type MySet = sig
include ShowableSet.S
val my_method : t -> elt -> elt list option
val show_el : elt -> string
end
module AdjacencySet_Make (El : OrderedShowable) : AdjacencySet
with type elt = El.t
= struct
include ShowableSet.Make(El)
let my_method set el = Some [el] (* whatever *)
let show_el el = El.show el (* we can use the "showable" elements! *)
end
Then we just need an OrderedShowable version of Int as the element type. Int is already ordered so we just have to extend it by deriving "show" and then we can make a concrete MySet:
module Int' = struct
include Int
type t = int [##deriving show]
end
module MyIntSet = MySet_Make(Int')
And we can use it like:
# let myset = MyIntSet.of_list [3; 2; 8];;
# print_endline (MyIntSet.show_el 3);;
"3"

Use abstract module as part of type definition separate from module

I'm trying to use the module type Partial_information which is constructed via the functor Make_partial_information as the type of the field contents in the type Cell.t. However, I'm getting the error Unbound module Partial_information.
open Core
(* module which is used as argument to functor *)
module type Partial_type = sig
type t
val merge : old:t -> new_:t -> t
end
(* type of result from functor *)
module type Partial_information = sig
type a
type t = a option
val merge : old:t -> new_:t -> t
val is_nothing : t -> bool
end
(* The functor *)
module Make_partial_information(Wrapping : Partial_type):
(Partial_information with type a = Wrapping.t)
= struct
type a = Wrapping.t
type t = a option
let merge ~(old : t) ~(new_ : t) =
match (old, new_) with
| (None, None) -> None
| (None, Some a) -> Some a
| (Some a, None) -> Some a
| (Some a, Some b) -> (Wrapping.merge ~old:a ~new_:b) |> Some
let is_nothing (it: t) : bool = (is_none it)
end
(* Checking to make sure understanding of functor is correct *)
module Int_partial_type = struct
type t = int
let merge ~old ~new_ = new_ [##warning "-27"]
end
module Int_partial_information = Make_partial_information(Int_partial_type)
(* Trying to use _any_ type which might have been created by the functor as a field in the record *)
module Cell = struct
type id = { name : string ; modifier : int }
type t = {
(* Error is here stating `Unbound module Partial_information` *)
contents : Partial_information.t ;
id : id
}
end
Module types are specifications for modules. They do not define types by themselves. They are also not constructed by functors in any way.
Consequently, it is hard to tell what you are trying to do.
As far I can see, you can simply define your cell type with a functor:
module Cell(P : Partial_information) = struct
type id = { name : string ; modifier : int }
type partial
type t = {
contents : P.t;
id : id
}
end
Or it might be even simpler to make the cell type polymorphic:
type 'a cell = {
contents : 'a;
id : id
}
since the type in itself is not particularly interesting nor really dependent upon
the type of contents.
P.S:
It is possible to use first class modules and GADTs to existentially quantify over a specific implementation of a module type. But it is unclear if it is worthwhile to explode your complexity budget here:
type 'a partial_information = (module Partial_information with type a = 'a)
module Cell = struct
type id = { name : string ; modifier : int }
type t = E: {
contents : 'a ;
partial_information_implementation: 'a partial_information;
id : id
} -> t
end

Mutually recursive module and functor in OCaml

I have defined an interface A to be used by several functors, and notably by MyFunctor :
module type A = sig
val basic_func: ...
val complex_func: ...
end
module MyFunctor :
functor (SomeA : A) ->
struct
...
let complex_impl params =
...
(* Here I call 'basic_func' from SomeA *)
SomeA.basic_func ...
...
end
Now I want to define a module B with implements the interface A. In particular, the implementation of complex_func should use basic_func through complex_impl in MyFunctor :
module B = struct
let basic_func = ...
let complex_func ... =
let module Impl = MyFunctor(B) in
Impl.complex_impl ...
end
However, this code doesn't compile as B is not fully declared in the context of MyFunctor(B). Obviously B depends on MyFunctor(B), which itself depends on B, so I tried to use the rec keyword on module B, but it didn't work out.
So, is it possible to do something like this ? It would be useful as I have several modules B_1, ..., B_n that use the same implementation of B_k.complex_func in terms of B_k.basic_func.
Or is there a better pattern for my problem ? I know that I can declare complex_impl as a regular function taking basic_func as a parameter, without using a functor at all :
let complex_impl basic_func params =
...
basic_func ...
...
But in my case complex_impl uses many basic functions of A, and I think that the paradigm of functors is clearer and less error-prone.
Edit : I followed this answer, but in fact, A uses some type t that is specialized in B :
module type A = sig
type t
val basic_func: t -> unit
val complex_func: t -> unit
end
module MyFunctor :
functor (SomeA : A) ->
struct
let complex_impl (x : SomeA.t) =
SomeA.basic_func x
...
end
module rec B : A = struct
type t = int
val basic_func (x : t) = ...
val complex_func (x : t) =
let module Impl = MyFunctor(B) in
Impl.complex_impl x
end
And now I get the error (for x at line Impl.complex_impl x) :
This expression has type t = int but an expression was expected of type B.t
Edit 2 : I solved this second problem with the following code :
module rec B :
A with type t = int
= struct
type t = int
...
end
You can use recursive modules just like you'd write recursive let bindings
module type A = sig
val basic_func : unit -> int
val complex_func : unit -> int
end
module MyFunctor =
functor (SomeA : A) ->
struct
let complex_impl = SomeA.basic_func
end
module rec B : A = struct
let basic_func () = 0
let complex_func () =
let module Impl = MyFunctor(B) in
Impl.complex_impl ()
end
Note (a) the module rec bit in the definition of B and (b) that I am required to provide a module signature for a recursive module definition.
# B.basic_func ();;
- : int = 0
# B.complex_func ();;
- : int = 0
There's a small caveat, however, in that this only works because the signature A has only values which are function types. It is thus known as a "safe module". If basic_func and complex_func were values instead of function types then it would fail upon compilation
Error: Cannot safely evaluate the definition
of the recursively-defined module B

Can we pass functor as an argument to another functor?

I want to know if we can have a local module inside the module. This can be achieved if a functor can be passed as an argument to another functor. But I am not sure if we can do that.
My apologies if this is a vague question.
Thanks.
Yes, it is possible to define higher-order functors. Here is a simple example of a functor that applies its first argument to its second argument:
module App (F : functor (X: sig end) -> sig end) (X: sig end) = F (X)
This is however unrelated to the question of having local modules, which are very straightforward and do not require functors. The following example defines a submodule B that remains private to A:
module A : (sig val g : unit -> unit end) = struct
module B = struct
let f () = print_endline "Hello"
end
let g = B.f
end
let () = A.g () (* valid, prints Hello *)
let () = A.B.f () (* invalid *)

How handling a list of polymorphic variants?

Let two variant types :
type typeA =
| A1
| A2
;;
type typeB =
| B1 of typeA
| B2 of typeA
;;
and type-checking functions :
let isA1 = function A1 -> true | _ -> false;;
let isA2 = function A2 -> true | _ -> false;;
let isB1 = function B1 e -> true | _ -> false;;
let isB2 = function B2 e -> true | _ -> false;;
I'd like to create a list of those functions to check elements of type A or B
as they're of different types, I need polymorphic variants and I get :
type filterA =
{
handleA : typeA -> bool;
};;
type filterB =
{
handleB : typeB -> bool;
};;
type filterslist = [`FilterA of filterA | `FilterB of filterB] list ;;
let filters1 = [`FilterA { handleA = isA1 }; `FilterB { handleB = isB1 }] ;;
So now I want to iterate over filters1 to check the type of the argument
I tried :
let exec_filters filters event = List.iter (fun fil -> match fil with `FilterA -> fil.handleA event; ()| `FilterB -> fil.handleB event; () ) filters;;
but it's not appreciated :
Error: This expression has type [< `FilterA | `FilterB ]
but an expression was expected of type filterA
How can I handle this ?
The fact that you're using "type checking predicates" similar to Scheme or instanceOf indicates that there is probably something very wrong with your code. OCaml is a statically typed language, you should not:
iterate over filters1 to check the type of the argument I tried
Why are you doing this? If you are trying to handle multiple types, the way to do it is to use polymorphism. Polymorphic variants can be helpful for this, but I'm still not convinced that your code isn't just written in a strange way.
I think your code should read like:
let exec_filters filters event =
List.iter
(fun fil -> match fil with
| `FilterA fA -> fA.handleA event; ()
| `FilterB fB -> fB.handleB event; () )
filters;;
EDIT: However, this won't typecheck, since event can't have types typeA and typeB...
Why not make your initial variants (typeA and typeB) polymorphic?
What are you trying to do?
When you say
match fil with
`FilterA -> ...
You seem to expect that this will change the type of fil, but that's not how it works. The expression with the type filterA appears inside the pattern. You want something more like this:
match fil with
`FilterA { handleA = h } -> h event
I'm not sure I see the purpose of having your handlers return bool if you're going to use List.iter to execute them. This will return unit, and the bool values are going to be discarded.
Edit
There's a deeper typing problem, explained well by Ptival. So even if you fix your patterns you'll still need to rethink your plan. One possible thing to do would be to use variants (not necessarily polymorphic variants, by the way) to track the types of the events.