【问题标题】:Why can't the compiler match this function type?为什么编译器不能匹配这个函数类型?
【发布时间】:2014-01-18 12:39:15
【问题描述】:

我无法解释自己的 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

新年快乐!

【问题讨论】:

标签: ocaml


【解决方案1】:

嗯,nlucaroni 已经指出,Optional argument in a method with ocaml 已经以更简单的形式回答了这个问题,但这里是我通过阅读该页面得到的简短描述。

您对exec 的调用将其推断为string -&gt; 'a。这一点不像 Postgresql 连接的 exec 方法的类型,后者具有三个可选参数。解决它的一种方法是执行您所做的操作:声明 conn 参数的类型。您也可以只声明exec 方法的可选参数,可能是这样的:

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

【讨论】:

  • 所以这是必须给编译器以便推断类型的最少信息?我仍然感到惊讶,在我看来这些类型(有或没有可选参数)是兼容的,编译器应该接受它(参见编译器错误消息)。这没有意义吗?
  • 我认为关键是?myoption: 'a -&gt; string -&gt; 'b 类型没有被string -&gt; 'b 包含。仅仅因为您没有在调用中传递任何可选参数并不意味着类型有效。你可以想象一个类型系统,你的程序是正确的,但在 OCaml 中却不是。 (注:我不是类型理论家,只是一个狂热的实践者。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-30
  • 2020-11-01
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多