Search code examples
listsortingmoduleocaml

OCaml online: List.sort compare is not working


I am testing the following OCaml's online environment: https://try.ocamlpro.com/

However, my algorithms are failing because of the use of List.sort compare x, where x is a list of integers. I have tested the following basic code List.sort compare [2; 3; 1];; and seen it throws an error:

Error: This expression has type ('a -> 'a -> int) -> 'a list -> 'a list -> int
but an expression was expected of type
  ('a -> 'a -> int) -> ('a -> 'a -> int) -> int
Type 'a list is not compatible with type 'a -> 'a -> int 

The online environment specifies it is OCaml 4.13.1, so does this mean compare is deprecated? In that case, how can I substitute it?


EDIT:

I have seen the following:

If you just write List.sort compare [2; 3; 1];; in the online environment, then it returns the correct output - : int list = [1; 2; 3].

However, if you load the List module with open List, then the error above is thrown.


Solution

  • As noted in the comments, by opening the List module, you've now shadowed Stdlib.compare (or Pervasives.compare) with List.compare, and the following no longer works.

    sort compare [2; 3; 1]
    

    There are a few solutions to this.

    Don't open List

    Without opening List, you can successfully refer to the polymorphic compare from Stdlib or Pervasives.

    List.sort compare [2; 3; 1]
    

    We can give List a shorter name if it's preferable.

    module L = List
    

    Then write:

    L.sort compare [2; 3; 1]
    

    Open List and explicitly refer to Stdlib.compare

    When we open List, its compare shadows the polymorphic compare, but that function is still there.

    sort Stdlib.compare [2; 3; 1]
    

    That's pretty unwieldly. You're probably just better off with List.sort compare [2; 3; 1].

    Of course, in this case you don't really need the polymorphic compare. You just need to compare integers.

    sort Int.compare [2; 3; 1]
    

    That's not so bad.

    Rename compare

    You could bind Stdlib.compare to a different name. Either before or after opening List.

    let cmp = compare
    
    open List
    
    let l = sort cmp [2; 3; 1]
    
    open List
    
    let cmp = Stdlib.compare
    
    let l = sort cmp [2; 3; 1]