如何在ocaml中指定函数参数和返回类型作为List?

时间:2018-03-03 10:37:58

标签: list ocaml

我目前正在教自己ocaml编程语言类,我正在尝试弄清楚如何指定函数参数并将类型返回为List

我创建了一个程序,通过char将每个char存储在char中来读取文件List,反转列表然后返回List

当前代码:

(* 
   Creating a function that will read all the chars 
   in a file passed in from the command argument.
   This function takes a parameter of type List.
   This function will return a List. 
*)

let read_file (char_List : List) : List =
    let char_in = open_in Sys.argv.(1) in   (* Creating a file point/in_channel *)
  try
    while true do
      let c = input_char char_in in     (* Getting char from the file *)
        char_List := c :: !char_List    (* Storing the char in the list *)
    done
  with End_of_file ->
        char_List := List.rev !char_List;   (* End of file was reaching reversing char list *)
        close_in char_in;                   (* Closing the file pointer/in_channel *)
;;

(* Storing the result of read_file to buffer which buffer is of type list *)
let buffer = ref [] in
      read_file(buffer);

      print_string "\nThe length of the buffer is: ";
      print_int (List.length !buffer); (* Printing length of the list *)
      print_string ("\n\n");
      List.iter print_char !buffer;    (* Iterating through the list and print each element *)

如果我删除指定参数类型并返回List类型,则代码按预期运行。然而;我想指定参数的类型和返回类型为List

如何将函数参数和返回类型指定为List

2 个答案:

答案 0 :(得分:2)

首先,List是一个不是类型的模块,所以你可能意味着list。但是,您不能仅使用list进行注释,因为列表本身不是类型:您不希望有一个不可知事物的列表,而是一个已知类型的元素列表。例如,在您的情况下,您有一个字符列表,可以写为char list。同样,整数列表将被键入int list

更准确地说,list本身不是一个类型,而是一个类型构造函数,它将列表元素的类型作为参数,并返回此类元素列表的类型。

P.S。 :如果您正在学习OCaml,您可以尝试重写代码而不使用引用来习惯更实用的样式。

答案 1 :(得分:2)

正如@octachron正确指出的那样,List在ocaml中不是正确的类型。你可能意味着'a list。查看代码,您可以通过解决以下2点来纠正您的代码:

  • 正确的功能签名如下, let read_file (char_List: 'char list ref) : 'char list =
  • 完成后添加!char_List!char_List

您更正的代码可能如下所示,

let read_file (char_List: 'char list ref) : 'char list =
    let char_in = open_in Sys.argv.(1) in   (* Creating a file point/in_channel *)
  try
    while true do
      let c = input_char char_in in     (* Getting char from the file *)
      char_List := c :: !char_List    (* Storing the char in the list *)
    done;
    !char_List
  with End_of_file ->
    char_List := List.rev !char_List;   (* End of file was reaching reversing char list *)
    close_in char_in;                   (* Closing the file pointer/in_channel *)
    !char_List

虽然这有效,但您可能希望在ocaml中使用更实用的方法。没有变异和递归函数的版本可以实现如下:

let get_chars file =
  let rec loop ic acc =
    match Pervasives.input_char ic with
    | c -> loop ic (c::acc)
    | exception(End_of_file) -> List.rev acc
  in
  let ic = Pervasives.open_in file in
  loop ic []

然后在ocaml toploop(repl)中你可以执行这样的功能

  • get_chars "/tmp/union_find.ml";;

或者

  • get_chars Sys.argv.(1) ;;