首页 > 解决方案 > OCaml,了解错误消息

问题描述

let rec smallest l =
    match l with
    | [] -> raise Not_found
    | [a] -> (fun x -> if x > 0 then x else raise Not_found) a
    | h::b::t -> 
        if h > b then smallest h::t
        else smallest b::t`

如果列表中存在正整数,则此函数假定采用int list并返回最小值,如果列表中没有正整数,则int引发异常。Not_found

当我尝试这个时,我得到以下错误,smallest h::t在第三个匹配模式中找到了下划线:

错误:此表达式具有类型'a list ,但表达式应为类型int

有人可以向我解释我做错了什么吗?

标签: exceptiontypeserror-handlingpattern-matchingocaml

解决方案


smallest h::t相当于(smallest h)::t。也就是说,它适用smallest于参数h,然后将其添加到 list t。这使 OCaml 抱怨说,当您应该生成一个整数时,您正在生成一个列表。你想要的是smallest (h::t).

该函数假设获取一个 int 列表,如果列表中有一个正整数,则返回最小的 int;如果列表中没有正整数,则引发异常 Not_found。

即使使用上述修复程序,该功能也不会这样做。相反,如果至少有一个正元素,它将在列表中找到最大的元素。那是因为你总是在你的if. 如果您切换它,以便它始终采用较小的元素,那么只要列表中至少有一个非正元素,它就会失败。

解决这个问题的一种方法是只选择一个元素作为列表的新头,如果它是正的并且小于当前的头,或者它是正的并且当前的头是负的。

然而,获得与您的描述匹配的函数的另一种可能更简洁的方法是首先定义一个函数,该函数从任何非空列表中取出最小元素(忽略它是否为正),然后定义另一个调用第一个函数的函数过滤列表以仅包含正面元素后的功能。像这样:

let smallest_positive xs = smallest (List.filter (fun x -> x > 0) xs)

PS:这与您的问题无关,但以下表达式看起来很奇怪:

(fun x -> if x > 0 then x else raise Not_found) a

在 OCaml 中通常很少有理由创建一个函数来立即应用它——这只是一种更复杂的编写let表达式的方式,在这种情况下你甚至不需要let. 换句话说,以上等价于:

let x = a in
if x > 0 then x else raise Not_found

这又相当于:

if a > 0 then a else raise Not_found

推荐阅读