2017-03-10 53 views
1

我是一個初學者是Haskell和我試圖做,可以給加薪一個人與一個特定的初始工資的功能,如下圖所示:如何更新Haskell列表中的特定元組?

*Main> giveRaise 'A' 200 [('A',"Al",1000),('B',"Bob",1500)] 

這將給出一個答案這樣的:

[('A',"Al",1200),('B',"Bob",1500)] 

到目前爲止我的代碼是這樣的,但我不斷收到一個錯誤,當我嘗試用N來提高初始的「g」:

giveRaise :: Char -> Int -> [(Char, String, Int)] -> [(Char, String, Int)] 
giveRaise g n [(g, z, m)] 
= [(g, z, (m + n))] 
+0

@Willem Van Onsem感謝您的幫助,我現在開始更好地理解這個問題。但是,當我嘗試使用您建議的代碼時,我仍然不斷收到錯誤:「函數giveRaise中的非窮舉模式」。由於我是初學者,我不知道這意味着什麼。我更新的代碼到目前爲止是:giveRaise ::字符 - >內部 - > [(CHAR,字符串,整數)〕 - > [(CHAR,字符串,整數)] giveRaise PA N((PB,Z,M):尾) | pa == pb =(pb,z,m + n):尾部 |否則=(PB,Z,M):giveRaise PAñ尾 –

+0

那麼問題是你做了什麼時,人不能在列表中找到? –

+0

@WillemVanOnsem在給出的元組列表中,我們正在改變的元組將永遠在那裏。這些幫助有用? –

回答

5

你要牛逼o修改列表中的任意元素,這樣最壞的情況下,您將不得不循環。由於遞歸是在Haskell中循環的方式,因此您編寫giveRaise一個子句是奇怪的。當使用遞歸,你總是有兩種類型的條款:

  • 一個基本情況:我們已經找到的人,並給他們加薪;和
  • a 遞歸案例:我們目前尚未找到此人,因此一直在尋找它。

基本情況很簡單:

giveRaise pa n ((pb,z,m):tail) | pa == pb = (pb,z,m+n):tail

在Prolog您可以使用相同的變量在統一(二郎,平等檢查)完成。這在Haskell中是不允許的。在Haskell中,使用後衛(如| pa == pb)來確定兩個人是否相同。

現在有另一種選擇:pa不是pb。在otherwise情況下,我們執行遞歸和列表中的進一步搜索,所以:

       | otherwise = (pb,z,m):giveRaise pa n tail

或者把一起:

giveRaise pa n ((pb,z,m):tail) | pa == pb = (pb,z,m+n):tail 
           | otherwise = (pb,z,m):giveRaise pa n tail

有最後我們不得不考慮到最後一種情況:什麼如果我們到達名單的最後並且沒有找到該人員,我們該怎麼辦?我們可以簡單地忽略,並返回像空列表:

giveRaise _ _ [] = [] 

,或者我們可以拋出error

giveRaise _ _ [] = error "Could not give a raise." 

因此,我們可以實現它想:

giveRaise pa n ((pb,z,m):tail) | pa == pb = (pb,z,m+n):tail 
           | otherwise = (pb,z,m):giveRaise pa n tail 
giveRaise _ _ [] = error "Could not give a raise."

最後請注意,此功能將僅向具有給定標識符的第一人加油。 並不是所有標識符都是的人。然而,我認爲這些標識符是唯一的。

+1

我想你應該如果兩個人在列表中具有相同的標識符「pb」,則只有第一個(按列表順序)獲得加分。 – epsilonhalbe

+0

@epsilonhalbe:是的好點。我在答案的末尾添加了一個註釋。 –

2

「做東西到列表中的一個元素」是一樣的「做別的到列表中的每個元素」,其中別的東西當元素是一個你重新尋找和什麼都沒有當它不是。換句話說,將此操作構造爲map是有意義的。

giveRaise :: Char -> Int -> [(Char, String, Int)] -> [(Char, String, Int)] 
giveRaise x amt = map raise 
    where raise (y, n, salary) 
      | x == y = (y, n, salary + amt) 
      | otherwise = (y, n, salary)