我需要創建一個從課程串列中讀取的函式(如下圖所示),并回傳哪些課程擁有最多的編程語言。
這是清單
progLanguages =
[ ("CptS121" , ["C"]),
("CptS122" , ["C "]),
("CptS223" , ["C "]),
("CptS233" , ["Java"]),
("CptS321" , ["C#"]),
("CptS322" , ["Python", "JavaScript"]),
("CptS355" , ["Haskell", "Python", "PostScript", "Java"]),
("CptS360" , ["C"]),
("CptS370" , ["Java"]),
("CptS315" , ["Python"]),
("CptS411" , ["C", "C "]),
("CptS451" , ["Python", "C#", "SQL"]),
("CptS475" , ["Python", "R"])
]
它需要與以下兼容
The type of the max_count function should be compatible with one of the following:
max_count :: [(a1, [a2])] -> (a1, Int)
max_count :: Foldable t => [(a1, t a2)] -> (a1, Int)
到目前為止,我已經嘗試了以下代碼
max_count [] = error "bad"
max_count [x] = x
max_count (x:xs) = x max_helper (max_count xs)
where
max_helper (a,b) (a',b')
| length b > length b' = (a, length b)
| otherwise = (a', length b')
這一點都沒有奏效,我對該怎么做一無所知。任何幫助表示贊賞。
uj5u.com熱心網友回復:
您的主要問題是您假設max_helper將類/語言串列對作為其第二個引數,而當它采用由回傳的類/語言計數max_count時。(您也錯誤地申請x了max_helper,而不是相反。
max_count :: [(a1, [a2])] -> (a1, Int)
max_count [] = error "bad"
max_count [(a, b)] = (a, length b)
max_count (x:xs) = max_helper x (max_count xs)
where
max_helper (a,bs) (a', b')
| length bs > b' = (a, length bs)
| otherwise = (a', b')
但是,您可以更明確地定義它。首先,您不關心實際的語言,只關心它們的數量。利用以下事實替換串列的長度fmap f (a, b) == (a, f b):
> map (fmap length) progLanguages
[("CptS121",1),("CptS122",1),("CptS223",1),("CptS233",1),("CptS321",1),("CptS322",2),("CptS355",4),("CptS360",1),("CptS370",1),("CptS315",1),("CptS411",2),("CptS451",3),("CptS475",2)]
現在你想要的是這個串列的最大值,但是使用一個忽略類名并且只查看長度的比較函式。您可以使用以下方法構造這樣的函式Data.Ord.comparing:
-- "b" > "a", but 1 < 2
> comparing snd ("b", 1), ("a", 2)
LT
您可以將此比較功能與Data.List.maximumBy:
> import Data.List
> import Data.Ord
> max_count = maximumBy (comparing snd) . map (fmap length)
> max_count progLanguages
("CptS355",4)
> :t max_count
max_count :: Foldable t => [(a1, t a2)] -> (a1, Int)
uj5u.com熱心網友回復:
您可以foldr在累加器變數中使用和保存最大條目的資訊:
maxCount :: Foldable t => [(a1, t a2)] -> (a1, Int)
maxCount [] = error "bad"
maxCount ((c,cs):l) = foldr opr (c, length cs) ((c,cs):l)
where
opr (c', xs) (c'', n)
| length xs > n = (c', length xs)
| otherwise = (c'', n)
我認為這error "bad"是不好的做法,我們可以使用Maybe:
maxCount' :: Foldable t => [(a1, t a2)] -> Maybe (a1, Int)
maxCount' [] = Nothing
maxCount' ((c,cs):l) = Just $ foldr opr (c, length cs) ((c,cs):l)
where
opr (c', xs) (c'', n)
| length xs > n = (c', length xs)
| otherwise = (c'', n)
uj5u.com熱心網友回復:
在這種情況下,功能foldr是最好的。你的方法也是可行的。只需要徹底理解編譯器的錯誤資訊。在這種情況下,我建議您不要使用 where 子句并max_helper全域實作該功能。我不知道你是否有意
max_helper1 :: Foldable t => (a1, t a2) -> (a1, Int) -> (a1, Int)
要么
max_helper2 :: (a1, Int) -> (a1, Int) -> (a1, Int)
有很多可能性。max_count由于遞回,第二個引數最好與 的輸出值相同。
罐子的左側max_count看起來像這樣:
max_count (x:xs)
要么
max_count ((x,y):xs)
.
右側可能包含:
max_helper12 ... (max_count xs)
必須用變體替換句點x或(x,length y)根據變體替換句點。
我還注意到,對于max_helper1,長度可能會重復計算,并且在 Haskell 中效率不高。因此,我建議只計算一次:
max_helper1 (a,b) (a',b')
| b'' > b' = (a, b'')
| otherwise = (a', b')
where
b'' = length b
另外,嘗試更正終止規則:
max_count [(x,y)] = (x,length y)
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/427269.html
標籤:哈斯克尔
上一篇:如何將多個元素放入'elem'
下一篇:部分型別家庭申請
