我猜你有一個數據結構定義爲
data Movie = Movie String Int [(String, Int)]
雖然這個工作,它可以是一個有點麻煩與當你有很多領域的工作。相反,你可以利用類型別名和記錄語法作爲
type Name = String
type Year = Int
type Rating = Int
data Movie = Movie
{ mName :: Name
, mYear :: Year
, mRatings :: [(Name, Rating)]
} deriving (Eq, Show)
現在事情更加明確,更容易處理。 mName
,mYear
和mRatings
函數將採取Movie
並從中返回相應的字段。你的Movie
構造函數仍然以相同的方式工作,所以它不會破壞現有的代碼。
要計算評分的平均值,真要提取的電影所有的評級,並將其聚合成列表的功能:
ratings :: Movie -> [Rating]
ratings mov = map snd $ mRatings mov
然後你只需要一個average
功能。這將是一個有點不同,因爲你無法計算的Int
小號直接的平均水平,你就必須轉換爲浮點類型:
average :: [Rating] -> Float -- Double precision isn't really needed here
average rs = fromIntegral (sum rs)/fromIntegral (length rs)
的fromIntegral
功能轉換的Int
到Float
(實際類型簽名有點更一般)。由於Int
的sum
是Int
而列表的length
總是Int
,所以您需要將兩者都轉換。
現在你只需撰寫這些成一個單一的功能:
movieAvgRating :: Movie -> Float
movieAvgRating = average . ratings
現在,如果你需要計算的平均收視率幾部電影,你可以申請ratings
他們每個人,他們聚集到一個單一的收視率列表,然後致電average
。我建議看看concatMap
函數。你會想要做像
moviesAvgRating :: [Movie] -> Float
moviesAvgRating movs = average $ ???
嗨,謝謝你的迴應!我只會問到目前爲止的部分:這些{}與其他括號有什麼不同?與評分相伴的名字是球迷的名字,所以我認爲我會添加一個新的類型Fan = String並且使mRatings :: [(Fan,Rating)]? – Chillo
@Chillo大括號表示[記錄語法](http://learnyouahaskell.com/making-own-own-types-and-typeclasses),它只是一種命名構造函數字段的方法。如果你願意,你當然可以編寫另一個'type Fan = String',這是完全可以接受的。 – bheklilr
函數movieAvgRating = average。收視率讓我有點困惑,你如何指定正在評級的電影?它不會看起來像'movieAvgRating mov = average(ratings mov)'?由於評分功能需要電影輸入。另外,這個功能是什麼。運營商服務? – Chillo