2014-07-09 104 views
3

我開始用haskell編程。我正在開發的程序只是將總數與兩個元素相加,例如:無法與實際類型`[([Char],a0)]'匹配'預期類型'([Char],t0)'Haskell

[("book",10),("cookies",2),("icecream",5)] 

這應該返回「17」。在這裏,我我的代碼:

total [] = [] 
total ([("c",e)]:y) = total y ++ [e] 

但是,儘管GHCI運行它給我這個錯誤:

<interactive>:80:8: 
    Couldn't match expected type `[([Char], a0)]' 
       with actual type `([Char], t0)' 
    In the expression: ("livro", 10) 
    In the first argument of `total', namely 
     `[("livro", 10), ("bolachas", 2), ("gelado", 5)]' 
    In the expression: 
     total [("livro", 10), ("bolachas", 2), ("gelado", 5)] 

<interactive>:80:21: 
    Couldn't match expected type `[([Char], a0)]' 
       with actual type `([Char], t1)' 
    In the expression: ("bolachas", 2) 
    In the first argument of `total', namely 
     `[("livro", 10), ("bolachas", 2), ("gelado", 5)]' 
    In the expression: 
     total [("livro", 10), ("bolachas", 2), ("gelado", 5)] 

<interactive>:80:36: 
    Couldn't match expected type `[([Char], a0)]' 
       with actual type `([Char], t2)' 
    In the expression: ("gelado", 5) 
    In the first argument of `total', namely 
     `[("livro", 10), ("bolachas", 2), ("gelado", 5)]' 
    In the expression: 
     total [("livro", 10), ("bolachas", 2), ("gelado", 5)] 

這可能是非常簡單的,但作爲一個初學者我沒能解決這個問題。

回答

6

在行:

total ([("c",e)]:y) = total y ++ [e] 

([("c",e)]:y)不會做你想做的。它匹配一個非空列表,其中第一個元素也是一個列表(因爲[...]),並且該子列表中只有一個元素,它是第一個元素等於"c"的對。爲了匹配你想要什麼,你需要寫:

total ((c,e):y) = total y ++ [e] 

然而,這仍然無法做你想做的,因爲它構造都在輸入列表中的e值的列表。綜上所述在一起,你需要做的:

total [] = 0 
total ((c,e):y) = total y + e 
+0

謝謝,它現在可以工作(: – magamig

4

除了什麼@jwodder說,請注意,這裏還有另一種方式來處理這個問題。不要思考/如何/你會計算出所需的值,而應該考慮/做些什麼:將每個列表項的第二個元素取出,然後將這些元素相加。

所以你可以從編寫兩個函數開始,一個函數接受一列元組產生所有第二元素的列表,另一個函數計算給定數字列表的總和。一個良好的開端是拿出類型簽名,但定義的功能,以評估undefined:使用這些

-- Takes a list of tuples and returns all the second elements 
getSecondElements :: [(String, Int)] -> [Int] 
getSecondElements someList = undefined 

-- Computes the sum of a given list of integers 
sumOfIntList :: [Int] -> Int 
sumOfIntList someInts = undefined 

,定義你的功能很簡單:

total myList = sumOfIntList (getSecondElements myList) 

您可以通過ghci中運行這個和它會進行類型檢查,這是一個好兆頭。當您嘗試實際使用total時,您會看到一個錯誤,因爲其他兩個函數只是undefined

在你去考慮如何實現它們之前,最好先看看它們是否已經存在。您可以搜索Hoogle以獲取類型簽名,並且它將挖掘與該簽名匹配的函數。 getSecondElements的簽名不會產生任何命中,但第二個簽名會產生大量命中,並且大多數命中甚至根本不會談論Int:Hoogle非常聰明,可以理解處理任意類型的函數列表(例如:lengthhead)也可能適用。如果向下滾動頁面,則會看到已有的sum函數已經存在!對於第一個函數,你可以重複這個過程(如果你喜歡,可以遞歸地):爲了得到列表中的所有第二元組元素,你首先需要一個函數,它獲得元組的第二個元素,像

getSecondElement :: (String, Int) -> Int 
getSecondElement = undefined 

和另一個將其應用於列表的所有元素的函數。我將略過一點:用於獲取2元組的第二個元素的標準函數被稱爲snd,並且用於收集在列表的所有元素上調用函數的結果的函數被稱爲map。嘗試運行

:t map snd 
在ghci中

看到map snd類型:

map snd :: [(a, b)] -> [b] 

...這是我們getSecondElements功能的類型的通用版本!因此,兩者缺件是map sndsum,這給:

-- Takes a list of tuples and returns all the second elements 
getSecondElements :: [(String, Int)] -> [Int] 
getSecondElements someList = map snd someList 

-- Computes the sum of a given list of integers 
sumOfIntList :: [Int] -> Int 
sumOfIntList someInts = sum 

不是有兩個額外的功能,你還可以在map sndsum直接來定義total

total someList = sum (map snd someList) 

...可以縮短爲

total = sum . map snd 

不錯,是嗎?

相關問題