Ocaml:将列表的第一个元素大写的功能

时间:2018-08-26 11:44:20

标签: ocaml

我有以下功能(来自Real World Ocaml书),可以很好地与核心库一起使用:

 let upcase_first_entry line =
  match String.split ~on:',' line with
  | [] -> assert false
  | first :: rest -> String.concat ~sep: "," (String.uppercase first :: rest);;

所以当我评估时:

upcase_first_entry ("one,two");;

我得到:

- : string = "ONE,two"

根据我对函数的理解,首先将字符串转换为字符串列表,然后应用大写函数,最后将输出转换回字符串。 所以我尝试了以下功能:

List.map ~f:(fun (first :: last) -> (String.uppercase first :: last)) ["one","two"];; 

我直接将列表传递给函数。但是我收到以下错误:

Error: This pattern matches values of type 'a list
       but a pattern was expected which matches values of type
         string * string

有人可以指导我为什么会引发错误吗?

1 个答案:

答案 0 :(得分:1)

直接在解释器中输入参数["one", "two"]会得到

- : (string * string) list = [("one", "two")]

即,字符串对列表不是字符串列表。您可能打算键入["one"; "two"],即string list。在OCaml中,即使没有给出括号,,也会用于创建对和其他元组。

下一个问题是List.map将函数应用于列表的每个元素并创建一个新列表。在这种情况下,它期望将f映射到某物的string。但是您的匿名函数将字符串列表映射到字符串列表(string list -> string list)。

在这种情况下,最简单的解决方案可能是不使用List.map,而只是将函数应用于参数。

(fun (first :: last) -> (String.uppercase first :: last)) ["one";"two"]

结果警告表明缺少一个案例。实际上,没有为空列表定义匿名函数。对于给定的参数而言,这无关紧要,但是通常,最好定义应该发生的情况,这样可以避免警告:

(function (first :: last) -> (String.uppercase first :: last) | [] -> []) ["one";"two"]