Search code examples
ocamlpartial-application

Why does `let f : int -> int list -> int list = (::);;` fail?


I would think that OCaml would read the following as an instance of partial application, and store the function as f. However, the compiler complains that the function is applied to too few arguments. Any insight into this would be appreciated, thank you.

let f : int -> int list -> int list = (::);;

Solution

  • The value :: in OCaml is a constructor rather than a general function. As such it requires following arguments (in parentheses). You can use it in the (::) form, but it must be followed by two values in parentheses:

    # ( :: ) (3, []);;
    - : int list = [3]
    

    The same is true of other constructors, like say Some:

    # let f : 'a -> 'a option = Some
    Error: The constructor Some expects 1 argument(s),
           but is applied here to 0 argument(s)
    

    You can of course define your function like this:

    let f : int -> int list -> int list = fun a b -> (::) (a, b)
    

    Or this:

    let f : int -> int list -> int list = fun a b -> a :: b
    

    Or even like this:

    let f : int -> int list -> int list = List.cons
    

    (Other languages, notably Haskell, treat constructors the same as functions. So you can have partially applied constructors, etc. In my opinion this is esthetically superior, i.e., it seems more elegant.)