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

时间:2015-02-23 17:57:24

标签: types ocaml

以下示例解释了代码应该执行的操作,并在其下方提供了错误消息。这是针对课程的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出现在列表

2 个答案:

答案 0 :(得分:1)

首先让我们尝试以更易读的方式重写代码

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运算符::,它需要左侧的列表元素和右侧的列表。看起来你选择了错误的一面。

答案 1 :(得分:0)

您的错误来自于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 )

请注意,如果您想要创建一个真正的应用程序,您应该使用其他一些数据结构来避免遍历整个“数据库”。