The aim of the module described below is to implement a module which once initiated by an integer n does all the operations based on the value of n.
module ReturnSetZero =
functor ( Elt : int ) ->
struct
let rec sublist b e l =
match l with
[] -> failwith "sublist"
| h :: t ->
let tail = if e = 0 then [] else sublist (b - 1) (e - 1) t in
if b > 0 then tail else h :: tail
let rec zerol = 0:: zerol
let zeron = sublist 0 n zerol
(*other operations based on n which is selected once when the module is initialized*)
end;;
Error: Unbound module type int
What is the issue here? Is there an alternate implementation which is more effective/intuitive?
A functor maps modules to modules. An integer is not a module, so you cannot use it to as a functor parameter.
You need to define a module type:
module type WITH_INTEGER = sig
val integer : int
end
module PrintInteger =
functor (Int:WITH_INTEGER) -> struct
let print_my_integer () = print_int Int.integer
end
Of course, unless your module needs to expose types that are dependent on the value of the integer (or you have to expose a lot of values dependent on that integer), you're probably better off with a plain function that takes that integer as an argument:
let my_function integer =
let data = complex_precomputations integer in
function arg -> do_something_with arg data
This lets you run the complex pre-computations only once on the integer (when you pass it to the function).
Related
I am a beginner in OCaml and I'm trying to understand functors, I'm developing a "general sort function" with functors that can takes array, list, string and return an ordered list, array, string.
Can someone help me with this?
I've done this
module type Comparable= sig
type t
val compare : t -> t -> int
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
end;;
module Make_sort(S: Comparable)= struct
type t= S.t
type et= S.t list
let order t= function
|[] -> 0
|a::b -> S.fold_left (S.compare (a t)(b t)) ;;
end;;
First of all, I think that your intuition is correct but there is small confusion between the value level and the type level, ie: S.compare (a t)(b t) this expression is not valid (a and b) must be functions, this why I think that you try to give the sense of 'a t.
But, I understand what you try to do, so here is a small primer on functor (function from module to module), using a small subset of your example.
First, in order to sort we need to define how to order
Exactly as you did, we can start with a signature (COMPARABLE) which handle the "notion of comparison". For example:
module type COMPARABLE = sig
(** something which is comparable. *)
type t
(** [compare x y] returns 1 if x > y, 0 if x = 0 and -1 if x < 0 *)
val compare : t -> t -> int
end
With this signature, it is easy to define module which are comparable, for example, for Int:
module Int_comparable :
COMPARABLE with type t = int =
struct
type t = int
let compare x y =
if x > y then 1
else if x = 0 then 0
else -1
end
Note that module are candidate for a signature only if the module match the signature so de anotation : COMPARABLE with type t = int is not very necessary. And, since Int (the module from the stdlib) already implement compare and a type t, it is not necessary to define it. You can just pass Int when you need a comparable.
Now, we can define somethign "sortable"
In this very small example, something which is comparable seems to be sortable. In other words, if I have a COMPARABLE, I can sort. This relation (If I have X, I can have Y) seems quite suitable for using a functor (so, I give you a COMPARABLE and you give me something sortable). Here is a proposition:
module Sortable (C : COMPARABLE) : sig
(** if something is comparable, it is sortable. *)
type t = C.t
(** [max_of x y] returns the greater between x and y. *)
val max_of : t -> t -> t
(** [min_of x y] returns the lower between x and y. *)
val min_of : t -> t -> t
(** [sort x y] returns an ordered tuple [(max_of x y, min_of x y)]. *)
val sort : t -> t -> (t * t)
end = struct
type t = C.t
let max_of x y =
let value = C.compare x y in
if value > 0 then x
else y
let min_of x y =
let value = C.compare x y in
if value < 0 then x
else y
let sort x y =
if (C.compare x y) >= 0 then (y, x) else (x, y)
end
It is probably possible to add more helpers in the module, but I'll keep the implementation as simple as possible. So now, if I want have sortable capabilities for Int.t I can just use the module Int (from stdlib: https://caml.inria.fr/pub/docs/manual-ocaml/libref/Int.html) which has a type t and compare like this
module Sortable_int = Sortable (Int)
Now, you have the basis. For traversing using Sort, you can implement a signature (Foldable for example) and I think you have all the bricks in your hands to generalize the logic of sorting collections (modulo a little algorithmic!)
this is a question about ocaml lists and tuples. I have some 2-tuples of numbers (either integers or floats) and I want to convert it to a list of lists (with 2 elements). Assuming that I have defined a num type Int of int | Float of float, the conversion should give the following:
((1,1.0),(0.4,1),(0,0)) => [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
or more precisely
let a = (1,1.0) and b = (0.4,1) and c = (0,0) in
myconversion (a,b,c) ;;
=> [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
the point being the values a, b, c... are defined in several places in the source files (by people who use different signatures for their tuples).
The difficulty here is that I don't know the types of the elements of the 2-tuples (int or float, that varies depending on the tuple).
Your input data can't be represented in OCaml as you describe it. OCaml is strongly typed. For example, your example input list is an invalid value in OCaml:
# [(1,1.0);(0.4,1);(0,0)];;
Error: This expression has type float but an expression was expected of type
int
So what you describe as the essence of your problem (not knowing the types) is in fact not possible. You'll have to use some other method of representing the input. For example, you could just use floats for everything. Or you could use pairs of strings.
Update
The answer for the rewritten question is the same. In OCaml it's not possible not to know the type of something statically; i.e., at the time you're writing the program (unless it can be any type at all). It's not possible (or necessary) to query the type of something at runtime. So your question doesn't have an answer (at least as far as I can see).
For OCaml, you have to think with the type system rather than against it. After a while you start to really like it (or at least that's how it worked for me). I'd start by writing down the type you want your function myconverstion to have.
Update 2
I'll repeat my advice to treat your inputs as strings. Assuming you've parsed your input up into pairs of strings, here's some code that does what you want:
let myconversion coords =
let c1 s =
if String.contains s '.' then
Float (float_of_string s)
else
Int (int_of_string s)
in
let cp (a, b) = [c1 a; c1 b] in
List.map cp coords
Here's how it works for your input (reinterpreted as strings):
# myconversion [("1", "1.0"); ("0.4", "1"); ("0", "0")];;
- : fi list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
Update 3
Here's some (crude) code that parses a file of numbers into coordinates represented as pairs of strings. It should work as long as the tuples in the input are well formed.
let coords fname =
let ic = open_in fname in
let len = in_channel_length ic in
let buf = Buffer.create 128 in
let () = Buffer.add_channel buf ic len in
let () = close_in ic in
let s = Buffer.contents buf in
let nums = Str.(split (regexp "[^0-9.]+") s) in
let rec mkcoords sofar = function
| [] | [_] -> List.rev sofar
| a :: b :: rest -> mkcoords ((a, b) :: sofar) rest
in
mkcoords [] nums
There are two distinct problems in your setup:
you don't know the type of the tuples parameters
you want to pass them as a single n-ary tuple
For problem 2, you would have to write a function for that type specifically, whereas you could mimic a type level list type by nesting couple of tuples:
myconversion a,(b,c) ;;
The reason is that with that setup, you could write a recursive polymorphic function on the type level list:
val myconversion : type a b. (a,b) -> num list
There would still be a problem on the last element though.
So, assuming that you could pass a sequence to your conversion function, and have it process elements of that sequence one by one, you would still need to find a way of selecting the proper function of pair conversion from the tuple type: that's basically ad-hoc polymorphism, ie. you would need to be able to overload a function on its parameters' types(1). Unfortunately, OCaml doesn't support that out of the box.
One possibility would be perhaps (I have no experience doing that) to implement an extension which would extract the type information of a given expression, and generate the correct code to process it in your own code.
A flexible technique consists in having that extension generate an algebraic description of the tuples types, and use that description as an equality witness in the code which will process the tuples:
type _ w =
| U : (unit * unit) w
| IF : 'a w -> ((int * float) * 'a) w
| FI : 'a w -> ((float * int) * 'a) w
(* other constructors if necessary *)
(* data *)
let a = 1,1.0
let b = 2.0, 2
let c = 3.0, 3
let d = 4, 4.0
let l = a,(b, (c,(d,((),()))))
(* witness *)
let w = IF (FI (FI (IF U)))
(* the type parameter of w should be the same as l type *)
let rec conv : type a b. (a * b) w -> (a * b) -> num list = fun w (x, xs) ->
match w with
U -> []
| IF w' -> let i,f = x in (Int I)::(Float f)::(conv w' xs)
(* etc *)
Here, we encode the type level nil list as (unit * unit) w.
A coalgebraic approach would require to register function overloads to the conversion function polymorphic signature within the extension, and let it pick the right one from the function overload dictionary.
There's a discussion on that topic on the LtU site.
Thanks to everybody who answered. I finally found a solution, using a bit of magic:
# type num = Int of int | Float of float;;
# let to_num x = if Obj.is_int (Obj.repr x) then
Int (Obj.magic (Obj.repr x) : int)
else
Float ((Obj.magic (Obj.repr x) : float));;
# let pair_to_num (a,b) = [to_num a; to_num b];;
# let myconversion (a,b,c) = [pair_to_num a; pair_to_num b; pair_to_num c];;
and the test:
# myconversion ((1,1.0),(0.4,1),(0,0));;
- : num list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
# myconversion ((0,0),(1,1.0),(0.4,1));;
- : num list list = [[Int 0; Int 0]; [Int 1; Float 1.]; [Float 0.4; Int 1]]
Magic, the order does not matter and the type is recorded! I can then follow didier's idea to get rid of the pair of superfluous parentheses.
I've get the follow code about the functors in OCaml:
type comparison = Less | Equal | Greater;;
module type ORDERED_TYPE =
sig
type t
val compare: t -> t -> comparison
end
;;
module Set =
functor (Elt: ORDERED_TYPE) ->
struct
type element = Elt.t
type set = element list
let empty = []
let rec add x s =
match s with
| [] -> [x]
| hd :: tl ->
match Elt.compare x hd with
| Equal -> s
| Less -> x :: s
| Greater -> hd :: add x tl
let rec member x s =
match s with
| [] -> false
| hd :: tl ->
match Elt.compare x hd with
| Equal -> true
| Less -> false
| Greater -> member x tl
end
;;
module OrderedString : ORDERED_TYPE =
struct
type t = string
let compare x y =
if x = y then Equal
else if x < y then Less
else Greater
end
;;
module StringSet = Set(OrderedString);;
let out = StringSet.member "foo" (StringSet.add "foo" StringSet.empty);; (*compile error, where "foo" is expected OrderedString.t but actually is string*)
The above error can be avoided by eliminating the : ORDERED_TYPE in module OrderedString : ORDERED_TYPE =
Just can't understand why.
Analogously, if there is any type in a module like
module A = struct type t = string end;;
How can I specify a string value as the type A.t but not an actual string
Thanks.
You can look at how it is done in the standard library : set.mli.
The signature of the functor is
module Make (Ord : OrderedType) : S with type elt = Ord.t
the with type elt = Ord.t part indicates that the elt type is not abstract.
As mentioned by Tomash, you're lacking a type constraint, but not in the functor signature (there isn't any in your code in fact), but in the argument you're giving to it. Basically, when you write
module OrderedString : ORDERED_TYPE = struct ... end
the definition of the type t in OrderedString will be abstracted away, since t is an abstract type in the ORDERED_TYPE signature. What you want here is to say that OrderedString is indeed an implementation of ORDERED_TYPE, but with a known type t. This is exactly what you'll get with
module OrderedString: ORDERED_TYPE with type t = string = struct ... end
I would like to make my code generic over strings and arrays (any indexable type really) using the following signature:
module type Indexable = sig
type 'a t
val get : int -> 'a t -> 'a
end
module MyCode (I : Indexable) = struct ... end
But of course I cannot apply my signature to strings as follows:
module StrMyCode = MyCode(struct
type 'a t = string
let get i a = a.[i]
end)
Is there any way to fix this issue? Or perhaps a different aprroach? I know I can use arrays of characters in the worst case but I'd rather save my code from ugly casts and this is something that was on my mind before so I'd like to get a clear answer for this.
GADT can be used with the functorized approach:
module type Indexable = sig
type 'a t
val get: int -> 'a t -> 'a
end
module MyCode(I:Indexable) = struct
let head x = I.get 0 x
end
Arrays can of course be made Indexable trivially:
module IndexableArray = struct
type 'a t = 'a array
let get i x = x.(i)
end
For string, you can just use a GADT with a single constructor. Note however, that you have to put some type annotation for get in order to force the polymorphic type (otherwise, the inferred type is int -> char t -> char):
module IndexableString = struct
type 'a t = String: string -> char t
let of_string s = String s
let get: type a. int -> a t -> a =
fun i s -> match s with String s -> s.[i]
end
Here is something I made using GADTs. I'm just wrapping my head around them, so there may be something a little wrong here. But it seems to work as far as I can see (with OCaml 4):
type _ indexable =
| A : 'a array -> 'a indexable
| C : string -> char indexable
let index (type s) (x: s indexable) i : s =
match x with
| A a -> a.(i)
| C s -> s.[i]
let main () =
let x = A [| 1; 2 |] in
let y = C "abc" in
Printf.printf "%d\n" (index x 0);
Printf.printf "%c\n" (index y 1)
If I load into the toplevel, I get this:
val index : 'a indexable -> int -> 'a = <fun>
val main : unit -> unit = <fun>
# main ();;
1
b
- : unit = ()
#
This might not be as general as what you're looking for.
If you declare the element type of the indexable as a separate type, you can do something like this:
module type Indexable = sig
type t
type elt
val get : int -> t -> elt
end
module IndexableString : Indexable = struct
type t = string
type elt = char
let get i a = a.[i]
end
module MyCode (I : Indexable) = struct
(* My code implementation *)
end
module StrMyCode = MyCode(IndexableString)
For arrays, you can do more or less the same:
module ArrayIndexable = struct
type elt = char
type t = char array
let get i a = a.(i)
end
Now, if you wish to retain some flexibility with arrays, you may change the above into a functor:
module ArrayIndexable (E : sig type e end) : Indexable with type elt = E.e =
struct
type elt = e
type t = elt array
let get i a = a.(i)
end
It is more verbose than the polymorphic version you are looking for, but it let you encode both "indexable" types uniformly.
Is it really true that OCaml doesn't have a function which converts from a list to a set?
If that is the case, is it possible to make a generic function list_to_set? I've tried to make a polymorphic set without luck.
Fundamental problem: Lists can contain elements of any types. Sets (assuming you mean the Set module of the standard library), in contrary, rely on a element comparison operation to remain balanced trees. You cannot hope to convert a t list to a set if you don't have a comparison operation on t.
Practical problem: the Set module of the standard library is functorized: it takes as input a module representing your element type and its comparison operation, and produces as output a module representing the set. Making this work with the simple parametric polymoprhism of lists is a bit sport.
To do this, the easiest way is to wrap your set_of_list function in a functor, so that it is itself parametrized by a comparison function.
module SetOfList (E : Set.OrderedType) = struct
module S = Set.Make(E)
let set_of_list li =
List.fold_left (fun set elem -> S.add elem set) S.empty li
end
You can then use for example with the String module, which provides a suitable compare function.
module SoL = SetOfList(String);;
SoL.S.cardinal (SoL.set_of_list ["foo"; "bar"; "baz"]);; (* returns 3 *)
It is also possible to use different implementation of sets which are non-functorized, such as Batteries and Extlib 'PSet' implementation (documentation). The functorized design is advised because it has better typing guarantees -- you can't mix sets of the same element type using different comparison operations.
NB: of course, if you already have a given set module, instantiated form the Set.Make functor, you don't need all this; but you conversion function won't be polymorphic. For example assume I have the StringSet module defined in my code:
module StringSet = Set.Make(String)
Then I can write stringset_of_list easily, using StringSet.add and StringSet.empty:
let stringset_of_list li =
List.fold_left (fun set elem -> StringSet.add elem set) StringSet.empty li
In case you're not familiar with folds, here is a direct, non tail-recursive recursive version:
let rec stringset_of_list = function
| [] -> StringSet.empty
| hd::tl -> StringSet.add hd (stringset_of_list tl)
Ocaml 3.12 has extensions (7,13 Explicit naming of type variables and 7,14 First-class modules) that make it possible to instantiate and pass around modules for polymorphic values.
In this example, the make_set function returns a Set module for a given comparison function and the build_demo function constructs a set given a module and a list of values:
let make_set (type a) compare =
let module Ord = struct
type t = a
let compare = compare
end
in (module Set.Make (Ord) : Set.S with type elt = a)
let build_demo (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
let set = List.fold_right S.add xs S.empty in
Printf.printf "%b\n" (S.cardinal set = List.length xs)
let demo (type a) xs = build_demo (make_set compare) xs
let _ = begin demo ['a', 'b', 'c']; demo [1, 2, 3]; end
This doesn't fully solve the problem, though, because the compiler doesn't allow the return value to have a type that depends on the module argument:
let list_to_set (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
List.fold_right S.add xs S.empty
Error: This `let module' expression has type S.t
In this type, the locally bound module name S escapes its scope
A possible work-around is to return a collection of functions that operate on the hidden set value:
let list_to_add_mem_set (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
let set = ref (List.fold_right S.add xs S.empty) in
let add x = set := S.add x !set in
let mem x = S.mem x !set in
(add, mem)
If you don't mind a very crude approach, you can use the polymorphic hash table interface. A hash table with an element type of unit is just a set.
# let set_of_list l =
let res = Hashtbl.create (List.length l)
in let () = List.iter (fun x -> Hashtbl.add res x ()) l
in res;;
val set_of_list : 'a list -> ('a, unit) Hashtbl.t = <fun>
# let a = set_of_list [3;5;7];;
val a : (int, unit) Hashtbl.t = <abstr>
# let b = set_of_list ["yes";"no"];;
val b : (string, unit) Hashtbl.t = <abstr>
# Hashtbl.mem a 5;;
- : bool = true
# Hashtbl.mem a 6;;
- : bool = false
# Hashtbl.mem b "no";;
- : bool = true
If you just need to test membership, this might be good enough. If you wanted other set operations (like union and intersection) this isn't a very nice solution. And it's definitely not very elegant from a typing standpoint.
Just extend the original type, as shown in
http://www.ffconsultancy.com/ocaml/benefits/modules.html
for the List module:
module StringSet = Set.Make (* define basic type *)
(struct
type t = string
let compare = Pervasives.compare
end)
module StringSet = struct (* extend type with more operations *)
include StringSet
let of_list l =
List.fold_left
(fun s e -> StringSet.add e s)
StringSet.empty l
end;;
Using the core library you could do something like:
let list_to_set l =
List.fold l ~init:(Set.empty ~comparator:Comparator.Poly.comparator)
~f:Set.add |> Set.to_list
So for example:
list_to_set [4;6;3;6;3;4;3;8;2]
-> [2; 3; 4; 6; 8]
Or:
list_to_set ["d";"g";"d";"a"]
-> ["a"; "d"; "g"]