【问题标题】:OCaml, Understanding error messageOCaml,了解错误消息
【发布时间】:2018-07-23 16:14:10
【问题描述】:
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 类型的表达式

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

【问题讨论】:

    标签: exception types error-handling pattern-matching ocaml


    【解决方案1】:

    smallest h::t 等价于(smallest h)::t。也就是说,它将smallest 应用于参数h,然后将其添加到列表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
    

    【讨论】:

    • @JunghwanOh 抱歉,打错了。
    【解决方案2】:

    经过一番思考,我能够回答我自己的问题。

    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)`
    

    【讨论】:

      猜你喜欢
      • 2018-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多