Easy Fix
Просто смените охрану | otherwise = 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]
По сути, вы фильтруете список на основе первогоэлемент, а затем вы возвращаете второй.
Функции более высокого порядка
С функциями более высокого порядка map
, filter
и fold
вы можете сделать столько же, сколько рекурсия и lcs, но часто выглядит аккуратнее.Вы хотите снова отфильтровать список по первому элементу, а затем вернуть второй.
listMarks'' :: String -> [StudentMark] -> [Int]
listMarks'' str = map snd . filter (\(n,_) -> n == str)