不确定在 OCaml 中创建函数时如何解决类型错误

Unsure how to address type error when creating a function in OCaml

下面的例子解释了代码应该做什么,我在下面提供了错误消息。这是针对 class 的 pset,因此我非常感谢任何代码解决方案附带的解释!对我来说最重要的是我理解它,因为我们下周有期中考试,从长远来看,仅仅把我的一部分 pset 正确并不能帮助我 运行。

(* the student's name and year *)
type name = string
type year = int
type student = name * year

(*  filter_by_year : returns the names of the students in a given year
 *         Example : let students = [("Joe",2010);("Bob",2010);("Tom",2013)];;
 *                   filter_by_year students 2010 => ["Joe";"Bob"] *)
let filter_by_year (slist:student list) (yr:year) : name list =
    let newlist = List.filter ~f:(fun x -> match x with
        | (a,b) -> b = yr) slist in 
            List.fold_right ~init:[] ~f:(fun x r-> match x with
                | (a,_) -> r :: a)
;;

错误:此表达式的类型为“列表” 但表达式应为 'a 类型 类型变量 'a 出现在 'a 列表中

首先让我们尝试以更具可读性的方式重写您的代码

let filter_by_year (slist:student list) (yr:year) : name list =
    let newlist = List.filter slist ~f:(fun (a,b) -> b = yr) in
    List.fold_right newlist ~init:[] ~f:(fun (a,_) r -> r :: a)

可以直接在形参中进行模式匹配,所以不用写

fun x -> match x with
  | (a,_) -> a = d

你可以写:

fun (a,_) -> a = d

当代码干净时,可以更容易地找到错误。当您向右折叠时(这是 CS51,对吗?),您使用的是 cons 运算符 ::,它需要左侧的列表元素和右侧的列表。看来你选错了方向。

您的错误来自错误使用 cons 运算符 ::。另外,你本可以做得更好!

请注意,您的 List.fold_right 的行为与 List.map 完全相同。所以你可以使用它并且更简洁:

let filter_by_year (slist:student list) (yr:year) : name list =
    let newlist = List.filter slist ~f:(fun (a,b) -> b = yr) in
    List.map newlist ~f:fst

我们还可以注意到,当您只能遍历一次时,您却对列表进行了两次遍历(这次使用 fold_right):

let filter_by_year slist yr =
  List.fold_right slist ~init:[]
  ~f:(fun (a,b) result -> if b = yr then a::result else result )

请注意,如果你想做一个真正的应用程序,你应该使用一些其他的数据结构来避免遍历整个 "database"。