首页 > 解决方案 > OCaml 断言失败

问题描述

大家好,我是 OCaml 的新手,遇到了一些问题。所以我试图做一个递归函数,它接受一个非空列表并返回最后一个元素。我的列表可以是任何数据类型。这是我现在所拥有的,它目前在断言语句中失败,说“这个表达式的类型是 int,但表达式应该是 int 类型的列表。

let rec last l = match l with

[] -> []

|[x] -> [x]

|_::t -> last t ;;

assert(last [1; 2; 3; 4] = 4);;

assert(last ["a"; "b"; "c"; "d"] = "d");;

标签: ocaml

解决方案


我经常发现处理这种类型错误的一个好方法是用我希望它具有的类型显式注释函数 - 在这种情况下,我希望你希望第一行是这样的:

let rec last: 'a list -> 'a = fun l -> match l with

这样,错误变为:

File "1/hest.ml", line 5, characters 9-10:
5 | |[x] -> [x]
             ^
Error: This expression has type 'a list
       but an expression was expected of type 'a
       The type variable 'a occurs inside 'a list

这是一个更有帮助的错误。问题是,正如@PatJ 在他的回答中所写,当您编写函数时,您实际上返回了一个包含一个元素的列表(或没有元素,当列表为空时),但您对该函数的使用似乎表明您只想要最后一个元素。

您可以:

  1. 更改函数的用法,因此断言与值进行比较,[4]["d"]不仅仅是值。
  2. 将函数更改为返回Some xandNone而不是[x]and [],并将断言更改为针对Some 1and进行断言Some "d"
  3. 将函数更改为 returnx而不是[x]并在空列表情况下引发异常 - 那将是:failwith "empty list"

我认为第二种解决方案是最自然的。

如果您选择异常,则将函数重命名为last_exn将向用户传达他们必须注意函数可能会抛出的信息。


推荐阅读