List 列表上的递归-Haskell

List 列表上的递归-Haskell,list,haskell,recursion,tuples,List,Haskell,Recursion,Tuples,基本上我有这个练习:回忆上周的StudentMark类型同义词。编写一个递归函数: listMarks :: String -> [StudentMark] -> [Int] type StudentMark = (String, Int) listMarks :: String -> [StudentMark] -> [Int] listMarks _ [] = [] listMarks std (x:xs) | std == fst x = snd x : li

基本上我有这个练习:回忆上周的StudentMark类型同义词。编写一个递归函数:

listMarks :: String -> [StudentMark] -> [Int]
type StudentMark = (String, Int)
listMarks :: String -> [StudentMark] -> [Int]
listMarks _ [] = []
listMarks std (x:xs)
  | std == fst x = snd x : listMarks (fst x) xs
  | otherwise = listMarks (fst x) xs
它给出了一个特定学生的分数列表;例如:

listMarks "Joe" [("Joe", 45), ("Sam", 70), ("Joe", 52)] = [45,52]
这就是我编写函数的方式:

listMarks :: String -> [StudentMark] -> [Int]
type StudentMark = (String, Int)
listMarks :: String -> [StudentMark] -> [Int]
listMarks _ [] = []
listMarks std (x:xs)
  | std == fst x = snd x : listMarks (fst x) xs
  | otherwise = listMarks (fst x) xs
如果列表中的字符串与“std”字符串不同,则此操作无效。我想了解我为什么以及如何才能做到这一点?谢谢大家!

容易解决 只需更改防护装置
|否则=listMarks std xs
。我还想在上面的保护中更改它,因为std==fst x=snd x:listMarks std xs是的,它们是相等的,但它更清楚地表明了您想要实现什么。所以你的代码应该是:

type StudentMark = (String, Int)
listMarks :: String -> [StudentMark] -> [Int]
listMarks _ [] = []
listMarks std (x:xs)
  | std == fst x = snd x : listMarks std xs
  | otherwise = listMarks std xs
更好的版本 正如您所看到的,您总是使用相同的第一个参数调用函数,因此很有可能编写更简洁的版本。以下是两个简单的想法:

列表理解 就我个人而言,我最喜欢的是,列表理解非常多样且清晰:

listMarks' :: String -> [StudentMark] -> [Int]
listMarks' str marks = [m |(n,m) <- marks, n==str]

我能看不出那个错误吗?很明显啊哈,非常感谢!我认为
过滤器的lambda也可以是无点的:
(==str.fst)
。这是否更具可读性有些争议。(警告:我实际上并没有试图编译它)