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!)
Related
for an example, if a function receives a function as a factor and iterates it twice
func x = f(f(x))
I have totally no idea of how the code should be written
You just pass the function as a value. E.g.:
let apply_twice f x = f (f x)
should do what you expect. We can try it out by testing on the command line:
utop # apply_twice ((+) 1) 100
- : int = 102
The (+) 1 term is the function that adds one to a number (you could also write it as (fun x -> 1 + x)). Also remember that a function in OCaml does not need to be evaluated with all its parameters. If you evaluate apply_twice only with the function you receive a new function that can be evaluated on a number:
utop # let add_two = apply_twice ((+) 1) ;;
val add_two : int -> int = <fun>
utop # add_two 1000;;
- : int = 1002
To provide a better understanding: In OCaml, functions are first-class
values. Just like int is a value, 'a -> 'a -> 'a is a value (I
suppose you are familiar with function signatures). So, how do you
implement a function that returns a function? Well, let's rephrase it:
As functions = values in OCaml, we could phrase your question in three
different forms:
[1] a function that returns a function
[2] a function that returns a value
[3] a value that returns a value
Note that those are all equivalent; I just changed terms.
[2] is probably the most intuitive one for you.
First, let's look at how OCaml evaluates functions (concrete example):
let sum x y = x + y
(val sum: int -> int -> int = <fun>)
f takes in two int's and returns an int (Intuitively speaking, a
functional value is a value, that can evaluate further if you provide
values). This is the reason you can do stuff like this:
let partial_sum = sum 2
(int -> int = <fun>)
let total_sum = partial_sum 3 (equivalent to: let total_sum y = 3 + y)
(int = 5)
partial_sum is a function, that takes in only one int and returns
another int. So we already provided one argument of the function,
now one is still missing, so it's still a functional value. If that is
still not clear, look into it more. (Hint: f x = x is equivalent to
f = fun x -> x) Let's come back to your question. The simplest
function, that returns a function is the function itself:
let f x = x
(val f:'a -> 'a = <fun>)
f
('a -> 'a = <fun>)
let f x = x Calling f without arguments returns f itself. Say you
wanted to concatenate two functions, so f o g, or f(g(x)):
let g x = (* do something *)
(val g: 'a -> 'b)
let f x = (* do something *)
(val f: 'a -> 'b)
let f_g f g x = f (g x)
(val f_g: ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>)
('a -> 'b): that's f, ('c -> 'a): that's g, c: that's x.
Exercise: Think about why the particular signatures have to be like that. Because let f_g f g x = f (g x) is equivalent to let f_g = fun f -> fun g -> fun x -> f (g x), and we do not provide
the argument x, we have created a function concatenation. Play around
with providing partial arguments, look at the signature, and there
will be nothing magical about functions returning functions; or:
functions returning values.
I want to count how many "u"s are in a list. An example of the function call would be
countu(["u"; "a"; "x"], 0);;
:-int = 1
The code I have is
let rec countu = fun(x, y) ->
if List.length (List.hd x) == 0 then y
else if List.hd x == "u" then countu(List.tl x, y+1)
else countu(List.tl x, y);;
I understand why I'm getting the problem. Ocaml wants a 'a list, but because I am comparing it to a string, it makes it a string. It will also get mad when I recall countu with y+1, because again, it wants a non-specified unit instead of an integer. How do I get around this. I want the signature to look like
val countups : string list * int -> int = <fun>
You have:
if List.length (List.hd x) == 0 then ...
But this only makes sense if x is a list of lists. Your x is a list of strings.
Possibly what you want is just this:
if List.length x = 0 then ...
As a side comment, the equality comparison operator in OCaml is =. The == operator is for special cases, and you shouldn't use it without having a good reason.
I'm encoding a form of van Laarhoven lenses in OCaml, but am having difficulty due to the value restriction.
The relevant code is as follows:
module Optic : sig
type (-'s, +'t, +'a, -'b) t
val lens : ('s -> 'a) -> ('s -> 'b -> 't) -> ('s, 't, 'a, 'b) t
val _1 : ('a * 'x, 'b * 'x, 'a, 'b) t
end = struct
type (-'s, +'t, +'a, -'b) t =
{ op : 'r . ('a -> ('b -> 'r) -> 'r) -> ('s -> ('t -> 'r) -> 'r) }
let lens get set =
let op cont this read = cont (get this) (fun b -> read (set this b))
in { op }
let _1 = let build (_, b) a = (a, b) in lens fst build
end
Here I am representing a lens as a higher order type, a transformer of CPS-transformed functions ('a -> 'b) -> ('s -> 't) (as was suggested here and discussed here). The functions lens, fst, and build all have fully generalized types but their composition lens fst build does not.
Error: Signature mismatch:
...
Values do not match:
val _1 : ('_a * '_b, '_c * '_b, '_a, '_c) t
is not included in
val _1 : ('a * 'x, 'b * 'x, 'a, 'b) t
As shown in the gist, it's perfectly possible to write _1
let _1 = { op = fun cont (a, x) read -> cont a (fun b -> read (b, x)) }
but having to manually construct these lenses each time is tedious and it would be nice to build them using higher order functions like lens.
Is there any way around the value restriction here?
The value restriction is a limitation of the OCaml type system that prevents some polymorphic values from being generalized, i.e. having a type that is universally quantified over all type variables. This is done to preserve soundness of the type system in the presence of mutable references and side effects.
In your case, the value restriction applies to the _1 value, which is defined as the result of applying the lens function to two other functions, fst and build. The lens function is polymorphic, but its result is not, because it depends on the type of the arguments it receives. Therefore, the type of _1 is not fully generalized, and it cannot be given the type signature you expect.
There are a few possible ways to work around the value restriction in this case:
Use explicit type annotations to specify the type variables you want to generalize. For example, you can write:
let _1 : type a b x. (a * x, b * x, a, b) Optic.t = lens fst (fun (_, b) a -> (a, b))
This tells the compiler that you want to generalize over the type variables a, b, and x, and that the type of _1 should be a lens that works on pairs with any types for the first and second components.
Use functors to abstract over the type variables and delay the instantiation of the lens function. For example, you can write:
module MakeLens (A : sig type t end) (B : sig type t end) (X : sig type t end) = struct
let _1 = lens fst (fun (_, b) a -> (a, b))
end
This defines a functor that takes three modules as arguments, each defining a type t, and returns a module that contains a value _1 of type (A.t * X.t, B.t * X.t, A.t, B.t) Optic.t. You can then apply this functor to different modules to get different instances of _1. For example, you can write:
module IntLens = MakeLens (struct type t = int end) (struct type t = int end) (struct type t = string end)
let _1_int = IntLens._1
This gives you a value _1_int of type (int * string, int * string, int, int) Optic.t.
Use records instead of tuples to represent the data types you want to manipulate with lenses. Records have named fields, which can be accessed and updated using the dot notation, and they are more amenable to polymorphism than tuples. For example, you can write:
type ('a, 'x) pair = { first : 'a; second : 'x }
let lens_first = lens (fun p -> p.first) (fun p b -> { p with first = b })
let lens_second = lens (fun p -> p.second) (fun p b -> { p with second = b })
This defines two lenses, lens_first and lens_second, that work on any record type that has a first and a second field, respectively. You can then use them to manipulate different kinds of records, without having to worry about the value restriction. For example, you can write:
type point = { x : int; y : int }
type person = { name : string; age : int }
let p = { x = 1; y = 2 }
let q = lens_first.op (fun x f -> x + 1) p (fun p -> p)
(* q is { x = 2; y = 2 } *)
let r = { name = "Alice"; age = 25 }
let s = lens_second.op (fun x f -> x + 1) r (fun r -> r)
(* s is { name = "Alice"; age = 26 } *)
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 am new to OCaml and I am trying to write a function to do this:
(4,a)(1,b)(2,c)(2,a)(1,d)(4,e) --> ((4 a) b (2 c) (2 a) d (4 e))
and this is what I wrote:
let rec transform l =
match l with
| (x,y)::t -> if x = 1 then y::transform(t) else [x; y]::transform(t)
| [] -> []
I put it in the ocaml interpreter but error generated like this:
Error: This expression has type int list
but an expression was expected of type int
Could anyone give some help?
Your example transformation doesn't make it clear what the types of the values are supposed to be.
If they're supposed to be lists, the result isn't a possible list in OCaml. OCaml lists are homogeneous, i.e., all the elements of the list have the same type. This is (in essence) what the compiler is complaining about.
Update
Looking at your code, the problem is here:
if x = 1
then y :: transform (t)
else [x; y] :: transform t
Let's say the type of y is 'a. The expression after then seems to have type 'a list, because y is the head of the list. The expression after else seems to have type 'a list list, because a list containing y is the head of the list. These aren't the same type.
The main problem is to decide how to represent something as either (4 a) or b. The usual OCaml way to represent something-or-something-else is variants, so let's define one of those:
type 'a element =
| Single of 'a
| Count of int * 'a
let rec transform = function
| [] -> []
| (x,y)::t ->
if x = 1 then Single y::transform t
else Count (x, y)::transform t
Note that this won't print in quite the way you want, unless you register a printer with the toplevel.
Or better:
let compact (x, y) =
if x = 1 then Single y else Count (x, y)
let transform list = List.map compact list