簡體   English   中英

列表遞歸 - Haskell

[英]Recursion over Lists - Haskell

基本上我有這個練習:回憶一下上周的StudentMark類型同義詞。 寫一個遞歸函數:

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

它給出了特定學生的分數列表; 例如:

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

這就是我編寫函數的方式:

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”字符串不同,則不起作用。 我想了解為什么以及如何才能完成這項工作? 謝謝!

輕松修復

只需改變守衛| otherwise = listMarks std xs | otherwise = listMarks std xs 我也會在上面的警衛中改變它,因為| std == fst x = snd x : listMarks std xs | std == fst x = snd x : listMarks std xs as yes,它們是相同的,但它更清楚你想要實現的目標。 所以你的代碼將是:

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]

基本上,您根據第一個元素過濾列表,然后返回第二個元素。

高階函數

使用更高階函數mapfilterfold ,您可以執行遞歸和lcs,但通常看起來更整潔。 您希望再次根據第一個元素過濾列表,然后返回第二個元素。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM