为什么编译器不能匹配这个函数类型?

时间:2013-12-31 15:44:43

标签: ocaml

我对OCaml编译器有一个问题,我无法自己解释。以下代码将无法编译:

open Postgresql

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

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

它出现以下错误:

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

(第8行是最后一行)

但是下面的代码编译没有错误(并且在代码的完整版本中按预期工作):

open Postgresql

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

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

唯一的区别是我在get_nodes函数中指定了conn参数的类型。

有人了解这里发生了什么吗?这是我第一次自己指定一个类型以使代码工作,我是每天的OCaml用户......

另外,我没有在错误消息中看到为什么涉及的类型不兼容,这里是exec函数的类型:

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

和Postgresql.result中的get_all函数的类型:

method get_all : string array array
新年快乐!

1 个答案:

答案 0 :(得分:3)

嗯,nlucaroni已经指出,Optional argument in a method with ocaml已经以更简单的形式回答了这个问题,但这里只是简要介绍了我通过阅读该页面所获得的内容。

您对exec的来电会为其提供推断类型string -> 'a。这完全不像Postgresql连接的exec方法的类型,它有三个可选参数。修复它的一种方法是执行您所做的操作:声明conn参数的类型。您也可以声明exec方法的可选参数,可能是这样的:

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