以下示例解释了代码应该执行的操作,并在其下方提供了错误消息。这是针对课程的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出现在列表
中答案 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 )
请注意,如果您想要创建一个真正的应用程序,您应该使用其他一些数据结构来避免遍历整个“数据库”。