Expression works in utop but won't build

Hi all!

I’m doing Advent of Code and I’ve chosen to play with OCaml. It’s mostly been a good experience so far. But I’ve got some code that seems to work in utop but when I copy/paste it into my project it won’t build.

module List = struct
  include List

  (* ... *)

  let group_by key_fun list =
    let compare_fst x y = compare (fst x) (fst y) in
    let ordered_pairs = list |> List.map (fun x -> (key_fun x, x)) |> List.sort compare_fst in
    ordered_pairs

(There’s more to this function, but this is the snippet that won’t build.)

When I run this in utop, I get:

utop # let group_by key_fun list =
    let compare_fst x y = compare (fst x) (fst y) in
    let ordered_pairs = list |> List.map (fun x -> (key_fun x, x)) |> List.sort compare_fst in
    ordered_pairs;;
utop # group_by (fun n -> Int.rem n 3) [1; 2; 3; 4; 5];;
- : (int * int) list = [(0, 3); (1, 1); (1, 4); (2, 2); (2, 5)]

But when I copy/paste this into my project, I get the following error:

File "lib/lib.ml", line 20, characters 80-91:
20 |     let ordered_pairs = list |> List.map (fun x -> (key_fun x, x)) |> List.sort compare_fst in
                                                                                     ^^^^^^^^^^^
Error: This expression has type
         ('a -> 'a -> int) * 'b -> 'a t * 'c -> 'a t -> int
       but an expression was expected of type
         ('a -> 'a -> int) * 'b -> ('a -> 'a -> int) * 'b -> int
       Type 'a t is not compatible with type 'a -> 'a -> int

Can someone explain what’s going on? Much appreciated!

In the first snippet, you have include List, which means that all of the elements from the List module are in scope. That includes List.compare, which has a different type than the global compare. So in the file, compare refers to List.compare : ('a -> 'a -> int) -> 'a list -> 'a list -> int;

whereas in utop, since you’re not pasting in the whole module (with the include List), compare refers to compare : 'a -> 'a -> int.

2 Likes

Thanks, @bcc32! I changed all my instances of compare to Stdlib.compare and that solved my issue.

Clearly I need to get used to OCaml’s namespacing rules.