简体   繁体   中英

Recursion over Lists - Haskell

Basically I have this exercise: Recall the StudentMark type synonym from last week. Write a recursive function:

listMarks :: String -> [StudentMark] -> [Int]

which gives a list of the marks for a particular student; for example:

listMarks "Joe" [("Joe", 45), ("Sam", 70), ("Joe", 52)] = [45,52]

This was the way I wrote the function:

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

This does not work if a string from the list is different from the "std" string. I would like to understand why and how could I make this work? Thank you!

Easy Fix

Just change the guard | otherwise = listMarks std xs | otherwise = listMarks std xs . I would also change it in the guard above, as | std == fst x = snd x : listMarks std xs | std == fst x = snd x : listMarks std xs as yes, they are equal, but it makes it more clear what you want to achieve. so your code would be:

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

Better Versions

As you can see, you ae calling the function with always the same first argument, so it's highly likely you can write a neater version. Here are two quick ideas:

List Comprehension

Personally my favourite, list comprehensions are very versitile and clear:

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

Basically you filter the list based on the first element, and then you return the second one.

Higher Order Functions

With higher order functions map , filter and fold , you can do as much as recursion and lcs, but often looks tidier. You want to, again, filter the list based on the first element, and then you return the second one.

listMarks'' :: String -> [StudentMark] -> [Int]
listMarks'' str =  map snd . filter (\(n,_) -> n == str)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM