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
有人可以向我解释我在做什么错吗?
答案 0 :(得分:3)
smallest h::t
等效于(smallest h)::t
。也就是说,它将smallest
应用于自变量h
,然后将其放在列表t
之前。这使OCaml抱怨应该生成一个整数时正在生成一个列表。您想要的是smallest (h::t)
。
假定此函数获取一个int列表,如果列表中有一个正整数,则返回最小的int;如果列表中没有正整数,则引发异常Not_found。
即使使用上述修复程序,该功能也不会执行此操作。相反,如果存在至少一个肯定元素,它将在列表中找到 largest 元素。这是因为您总是在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
表达式的一种更复杂的方式,在这种情况下,您甚至不需要{{1 }}。换句话说,以上等同于:
let
依次相当于:
let x = a in
if x > 0 then x else raise Not_found
答案 1 :(得分:0)
经过一番思考,我能够回答自己的问题。
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 && h > 0
then smallest (h::t)
else smallest (b::t)`