Fabian Pijcke
Fabian Pijcke

Reputation: 3210

Why can't the compiler match this function type?

I have an issue with the OCaml compiler I can't explain myself. The following code won't compile:

open Postgresql

let get_nodes conn =
  ignore (conn#exec "SELECT * FROM node_full")

let () =
  let c = new connection () in
  ignore (get_nodes c)

It gives the following error:

File "test.ml", line 8, characters 20-21:
Error: This expression has type Postgresql.connection
       but an expression was expected of type < exec : string -> 'a; .. >
       Types for method exec are incompatible

(Line 8 is the last line)

But the following piece of code compiles without error (and works as expected, in the full version of the code):

open Postgresql

let get_nodes (conn:connection) =
  ignore (conn#exec "SELECT * FROM node_full")

let () =
  let c = new connection () in
  ignore (get_nodes c)

The only difference is that I specified the type of the conn parameter in the get_nodes function.

Does someone understand what is going on here ? This is the first time I have to specify a type myself in order to make the code work, and I am a daily OCaml user ...

Additionnaly, I don't see, in the error message, why the types involved are not compatible, here is the type of the exec function:

method exec :
  ?expect:Postgresql.result_status list ->
  ?params:string array ->
  ?binary_params:bool array ->
  string -> Postgresql.result

and the type of the get_all function from Postgresql.result:

method get_all : string array array

Happy new year !

Upvotes: 4

Views: 152

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66808

Well, nlucaroni has pointed out that this has been answered in a simpler form at Optional argument in a method with ocaml, but here's a short description of what I got by reading that page.

Your call to exec gives it the inferred type string -> 'a. This isn't at all like the type of the exec method of a Postgresql connection, which has three optional parameters. One way to fix it is to do what you did: declare the type of the conn parameter. You could also just declare the optional parameters of the exec method, maybe something like this:

ignore (
    (conn#exec :
        ?expect: 'a ->
        ?params: 'b ->
        ?binary_params: 'c ->
        string -> 'd) "SELECT * FROM node_full"
 )

Upvotes: 3

Related Questions