Can't store partial function with a Map parameter as a Map value - ocaml

I'm trying to create a Map from string to a partial function. The function takes as its parameter a Map of the same type, but only later when the entry is retrieved. I'd like to find an entry in the map and pass the map as I apply the function, but I can't figure out how to satisfy the compiler. Here's a trivial example:
module M = Map.Make(String)
let () =
let f m = M.cardinal m in
let m = M.add "key" f M.empty in
(M.find "key" m) m |> string_of_int |> print_endline
The compiler complains with this error:
33 | (M.find "key" m) m |> string_of_int |> print_endline
^
Error: This expression has type ('a M.t -> int) M.t
but an expression was expected of type 'a M.t
The type variable 'a occurs inside 'a M.t -> int
The expression type seems correct, but I'm not sure why it's expecting a 'a M.t.

If you think of the type of m you'll see that it's recursive. Inside m are stored functions that accept values of the same type as m.
So, you need to allow recursive types with the -rectypes flag if you want this to work:
$ rlwrap ocaml -rectypes
# module M = Map.Make(String)
. . .
# let () =
let f m = M.cardinal m in
let m = M.add "key" f M.empty in
(M.find "key" m) m |> string_of_int |> print_endline;;
1

Related

Ocaml user-defined type pattern matching

Here is my type definition:
type ('type1, 'type2) symbol =
| N of 'type1
| T of 'type2
Here are some types:
type mysub =| Abc | Bcd | Def
I also have a list [N Abc;N Bcd; T"("].
What I want to do is that throw away all items of type T, and also throw away 'type1 or 'type2. So the desired result is [Abc; Bcd]
But when I try this piece of code:
List.map (fun x-> match x with N (a)->a |T (b) ->b ) (List.filter (fun x->match x with
N (type1) ->true |T (type2) -> false) [N Abc;N Bcd; T"("]);;
it gives me the following message:
Error: This expression has type (mysub, string) symbol list
but an expression was expected of type
(mysub, mysub) symbol list
Type string is not compatible with type mysub.
How can I fix it?
In this fragment
List.map
(fun x -> match x with
N a -> a
T b -> b
)
The return types aren't the same for the two match cases. If there were any T b elements in the list, the b would be a string, and the compiler doesn't know there aren't any such elements. Since you know there aren't any, you could fix this by supplying something other than b as the result for that case. Something like this:
List.map
(fun x -> match x with
N a -> a
T _ -> Abc
)
Or even this:
List.map
(fun x -> match x with
N a -> a
T _ -> failwith "This can't happen"
)

Ocaml : Function with 'a option error

I have this simple function which drives me crazy:
it should be a function of this type :
myfunction : (int * int list) list -> int -> int
For each tuples of the first argument :
When the second argument matches the first element of the tuple then the function return the last element of the list in the tuple.
If no matches it should return -1.
let rec myfunction alist anum =
let last_e l =
let len = List.length l in
List.nth l (len - 1) in
match alist with
| [] -> -1
| (n , ln) :: q -> if n = anum then last_e ln
else myfunction q anum
But my function does not work and I have this error message in utop:
Error: This expression has type 'a option but an expression was expected of type int
I don't know where the "option" type comes from.
This can happen if you are using some OCaml toplevel (e.g. utop) and you have these lines in your .ocamlinit file
#require "core.top" ;;
open Core.Std ;;
This enables the Core libraries, where List.nth has type:
μ> List.nth;;
- : 'a list -> int -> 'a option = <fun>
instead of standard OCaml's List.nth : 'a list -> int -> 'a.
So, when you fire up your toplevel and say:
μ> #use "myfunction.ml";;
you get the same error you cited in the question.
By the way, if you'd like to keep using Core, there is a List.last function.

Unknown Type Error in OCaml

I'm attempting to create a new list of all the unique items from another list. My in_list function works properly and returns a value saying whether or not the value is found in the seen_list, but I can't for the life of me get this to compile.
let uniq x = match in_list x seen_list with
| true -> seen_list
| false -> seen_list#[x]
| _ -> seen_list
;;
List.iter uniq check_list;;
The problem is some sort of type error. Here it is:
Error: This expression has type int -> int list
but an expression was expected of type int -> unit
Type int list is not compatible with type unit
In essence you want to take the result returned by uniq and pass it as the list for the next call of uniq. To do this, you need to use a fold, or write your own recursion. The purpose of List.iter is just to call an imperative function for each element of a list. It doesn't combine the answers in any way. That's why you're getting a type error—your function isn't imperative. I.e., it doesn't return unit.
Perhaps this is what you want:
let rec uniq_list lst =
match lst with
| [] -> []
| x :: xs ->
let r = uniq_list xs in
if in_list x r then r else x :: r
Or, using List.fold_right (equivalent to the recursive function above):
let uniq_list lst =
List.fold_right
(fun x r -> if in_list x r then r else x :: r)
lst
[]
Or using List.fold_left which is tail-recursive:
let uniq_list lst =
List.fold_left
(fun r x -> if in_list x r then r else x :: r)
[]
lst
By the way, your in_list is equivalent to the standard library function List.mem.

OCaml error filter list using higher order functions

So I have this exercise:
filter (fun x -> x = 0) [(1,0);(2,1);(3,0);(4,1)];;
result int list [1;3]
So basically you have to match your x in fun with the second number in list and if its the same you create new list with the first number.
My solution but is wrong
let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [];;
I get the following error when i want to try the code:
Error: This expression has type int but an expression was expected of
type
int -> bool
I can't reproduce the problem you report. Here's what I see when I try your code:
$ ocaml
OCaml version 4.02.1
# let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [] ;;
val filter : 'a -> ('b * 'a) list -> 'b list = <fun>
# filter 0 [(1,0); (2,1); (3,0)];;
- : int list = [1]
There are no errors, but it gets the wrong answer. That's what I would expect looking at your code.
The error that you are getting is saying that somewhere the compiler is expecting an int -> bool function, but you are giving it an int. The reason you get this error is because you have an equality (f = snd x), where f is of type int -> bool and snd x is of type int. both arguments given to the equality must be of the same type. Instead, what you want to do is simply branch on the result of applying f to the second element of x, such as:
let rec filter f = function
| []->[]
| x::l -> if f (snd x) then fst x :: filter f l else [];;
That said, I would recommend using pattern matching instead of fst and snd, such as:
let rec filter f l =
match l with
| [] -> []
| (x,y)::l -> if f y then x :: filter f l else filter f l
Note that f y will return something of type bool, which will then determine which branch to take.
Altough Matts answer is right. It's good to just reuse existing functions instead of writing a special from the ground up:
[(1,0);(2,1);(3,0);(4,1)]
|> List.filter (fun (_, x) -> x = 0)
|> List.map fst

Convert 'a list to a Set?

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"]