【问题标题】:Calling OCaml functions like: 'a hash_entry list array -> string -> 'a -> unit调用 OCaml 函数,例如:'a hash_entry list array -> string -> 'a -> unit
【发布时间】:2021-08-23 14:17:23
【问题描述】:

我正在阅读一本关于 OCaml 的书,我是 OCaml 的新手,所以我正在做练习和示例——尽管并非所有内容都能编译。 在这种情况下,我今晚的项目是一个哈希表的示例,它可以编译并且非常有趣,但我无法让它工作。

let random_numbers =
  [|0x316666;   0x2d331c;   0x4de673;   0x63a91e;   0x87bee8|]
let random_length = Array.length random_numbers
type hash_info = { mutable hash_index : int; mutable hash_value : int }
let hash_char info c =
  let i = Char.code c in
  let index = (info.hash_index + i + 1) mod random_length in
info.hash_value <- (info.hash_value * 3) lxor random_numbers.(index);
info.hash_index <- index
let hash s =
  let info = { hash_index = 0; hash_value = 0 } in
  for i = 0 to String.length s - 1 do
    hash_char info s.[i]
  done;
  info.hash_value
type 'a hash_entry = { key : string; value : 'a }
type 'a hash_table = 'a hash_entry list array
let create () =
  Array.make 101 []
let add table key value =
  let index = (hash key) mod (Array.length table) in
  table.(index) <- { key = key; value = value } :: table.(index)
let rec find_entry key = function
  { key = key' ; value = value } :: _ when key' = key -> value
  | _ :: entries -> find_entry key entries
  | [] -> raise Not_found
let find table key =
    let index = (hash key) mod (Array.length table) in
    find_entry key table.(index);;

不幸的是,作者会说'a string -&gt; unit 会这样做或那样做,而实际上并非如此。例如,这是我正在处理的:

utop # add = { key = "9999999" ; value = "one of these days" };;
Line 1, characters 6-55:
Error: This expression has type string hash_entry
       but an expression was expected of type
         'a hash_entry list array -> string -> 'a -> unit

我对这些冗长的陈述感到沮丧。这是什么意思?

'a hash_entry list array -> string -> 'a -> unit

我不是要求定义它的部分,我如何使用这个语句来调用函数?我知道理解这部分当然很重要,这些东西是如何工作的?几天过去了,再举一个例子,我一直在期待类型单元,“类型单元”到底应该是什么? 具体来说,我如何生成这个(知道它需要一个键/值对):

'a hash_entry list array -> string -> 'a -> unit

【问题讨论】:

  • 一个函数有一个使用-&gt;表示的类型。例如,一个接受一个整数并返回一个整数的函数的类型为int -&gt; int。除非在 OCaml 中明确指定类型(这种情况很少见),否则您不会在自己的代码中编写此表示法,但理解它对于调试程序至关重要。
  • 在函数接受多个参数的情况下,函数的类型签名有多个-&gt;。接受字符串和整数并返回浮点数的函数的类型为string -&gt; int -&gt; float。这个函数是柯里化的。我们可以给它一个字符串和一个整数,然后返回一个浮点数,或者你可以给它更少的参数,然后返回一个函数来接受剩余的参数。在我提到的人为设计的示例中,只给它字符串将返回一个类型为 int -&gt; float 的函数。
  • 向本书作者报告错误代码是个好主意。
  • 如果你的代码没有解释类型,这是一本很差的书,你应该换一本。

标签: arrays ocaml hashtable ml


【解决方案1】:

这是您遇到问题的表达式:

add = { key = "9999999" ; value = "one of these days" }

这是一个表达式,但不是对add 的调用。 add 是一个有 3 个参数的函数,因此调用如下所示:

add mytable mykey myvalue

相反,这个表达式是一个比较,即它测试两个事物是否相等。这是因为表达式中唯一的运算符是=,即相等比较运算符。

由于add 是一个函数,它甚至不是与记录进行比较的正确类型,这是比较右侧显示的内容。所以这就是为什么你会从解释器那里得到一个错误。

如果你想测试一个 add 调用,它看起来更像这样:

# let table = create ();;
val table : '_weak1 list array = ...
# add table "mykey" "myvalue";;
- : unit = ()
# find table "mykey";;
- : string = "myvalue"

【讨论】:

    【解决方案2】:

    斯科菲尔德先生的指示导致了这一点:

    val create : unit -> 'a list array = <fun>
    val add : 'a hash_entry list array -> string -> 'a -> unit = <fun>
    val find_entry : string -> 'a hash_entry list -> 'a = <fun>
    val find : 'a hash_entry list array -> string -> 'a = <fun>
    ─( 19:55:55 )─< command 30 >─────────────────────────────────────{ counter: 0 }─
    utop # let table = create ();;
    val table : '_weak2 list array =
      [|[]; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; 
        []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; 
        []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; 
        []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; 
        []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; 
        []; []; []; []; []; []; []; []; []; []; []; []; []; []; []; []|]
    ─( 20:14:42 )─< command 31 >─────────────────────────────────────{ counter: 0 }─
    utop # add table "mykey" "myvalue";;
    - : unit = ()
    ─( 20:14:58 )─< command 32 >─────────────────────────────────────{ counter: 0 }─
    utop # find table "mykey";;
    - : string = "myvalue"
    ─( 20:15:15 )─< command 33 >─────────────────────────────────────{ counter: 0 }─
    

    val create (unit -> 'a list array = ) val add ('a hash_entry list array -> string -> 'a -> unit = ) 和 val find('a hash_entry list array -> string -> 'a = )

    谢谢杰弗里·斯科菲尔德

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多