2012-08-05 49 views
0

我試圖解決與輸入的分數揹包問題,無法匹配實際類型期望的類型`(T1,T2,T0)」`[A0]`

[("label 1", value, weight), ("label 2", value, weight), ...] 

和輸出,

[("label 1", value, solution_weight), ("label 2", value, solution_weight), ...] 

,但我不斷收到錯誤computeKnapsack

"Couldn't match expected type `(t1, t2, t0)' with actual type `[a0]`" 

我無法理解的問題可能是什麼。我試圖創建一個3條目元組列表。我怎樣才能讓它停止期待一個3入口元組?

fst3 (a,b,c) = a 
snd3 (a,b,c) = b 
trd3 (a,b,c) = c 
fst4 (a,b,c,d) = a 
snd4 (a,b,c,d) = b 
trd4 (a,b,c,d) = c 
qud4 (a,b,c,d) = d 

sortFrac (a1, b1, c1, d1) (a2, b2, c2, d2) 
    | d1 > d2 = GT 
    | d1 <= d2 = LT 

fracKnap (x:xs) = 
    fractionalKnapsack (x:xs) [] 

fractionalKnapsack (x:xs) fracList = 
    if length (x:xs) <= 1 
     then computeKnapsack (sortBy sortFrac (((fst3 x),(snd3 x),(trd3 x),(snd3 x)/(trd3 x)):fracList)) 100 
     else fractionalKnapsack xs (((fst3 x),(snd3 x),(trd3 x),(snd3 x)/(trd3 x)):fracList) 

computeKnapsack (x:xs) weightLeft = 
    if length (x:xs) <= 1 
     then (fst4 x, snd4 x, ((floor (weightLeft/(qud4 x)))*(qud4 x))) 
     else (fst4 x, snd4 x, ((floor (weightLeft/(qud4 x)))*(qud4 x))):(computeKnapsack xs (weightLeft-(floor (weightLeft/(qud4 x))*(qud4 x)))) 
+5

請不要使用這些醜陋的'fst''snd''trd''qud'函數來重寫它,這真的很難理解正在發生的事情。每個元組條目必須有某種含義,將其描述爲一種記錄類型('data KnapsackItem = KnapsackItem {propA :: Foo,propB :: Bar,propC :: Quu}') – leftaroundabout 2012-08-05 17:00:55

+0

真的很難說什麼4元組應該代表,使其真的很難遵循您的代碼 – 2012-08-05 17:27:57

回答

7

then分支computeKnapsack結果是一個3元組,但在else分支它是一個3元組列表。我想爲你改寫computeKnapsack

computeKnapsack (x:xs) weightLeft = 
    if length (x:xs) <= 1 
     then [(fst4 x, snd4 x, ((floor (weightLeft/(qud4 x)))*(qud4 x)))] 
     else (fst4 x, snd4 x, ((floor (weightLeft/(qud4 x)))*(qud4 x))) : (computeKnapsack xs (weightLeft-(floor (weightLeft/(qud4 x))*(qud4 x)))) 

首先,我要說的話會發生什麼,如果第一個參數computeKnapsack是空列表::

computeKnapsack []  _   = [] 
computeKnapsack (x:xs) weightLeft = 
    (fst4 x, snd4 x, ((floor (weightLeft/(qud4 x)))*(qud4 x))) : (computeKnapsack xs (weightLeft-(floor (weightLeft/(qud4 x))*(qud4 x)))) 

它使我們,我會跟你的版本有固定的錯誤啓動擺脫if-測試,使代碼更簡潔,更易於理解。

接下來,我將解構x

computeKnapsack []    _   = [] 
computeKnapsack ((a,b,_,d):xs) weightLeft = 
    (a, b, ((floor (weightLeft/d))*d)) : (computeKnapsack xs (weightLeft-(floor (weightLeft/d)*d))) 

你可能更願意遵循leftaroundabout的建議來創建,而不是有意義的名字,一個記錄類型。但是如果你繼續使用元組,通過模式匹配解構它比使用你的fst4snd4等函數更加清晰。

同樣,代碼現在更短,更容易理解,但它可能會幫助,如果我們不是abd使用更有意義的名稱。

我們可以繼續在此背景下:

computeKnapsack []    _   = [] 
computeKnapsack ((a,b,_,d):xs) weightLeft = (a, b, weight) : (computeKnapsack xs (weightLeft - weight)) 
    where weight = floor (weightLeft/d) * d 

在這裏,我發現這是在兩個不同的地方被計算的值相同,而提取的價值到它自己的命名變量。 weight只需計算一次而不是兩次,因此computeKnapsack現在稍微更高效。更重要的是,我現在明白computeKnapsack正在做什麼。

我明白你是Haskell的新手。請將此作爲建設性的建議,告訴您如何編寫更清晰的Haskell代碼。

0

一個在fractionalKnapsack當時引發錯誤的問題。 在該行中,您可以使用元組作爲輸入而不是list調用函數computeKnapsack

+0

謝謝。我如何使sortBy sortFrac(((fst3 x),(snd3 x),(trd3 x),(snd3 x)/(trd3 x)):fracList)列表?我認爲通過將它加入到fracList這是一個[]它會使它成爲一個列表>< – user1577039 2012-08-05 17:13:22

2

我已經採取了清理你的computeKnapsack功能的自由,所以你可以更清楚地看到問題:

computeKnapsack (x:xs) weightLeft = 
let e = (fst4 x, snd4 x, floor (weightLeft/qud4 x) * qud4 x) 
    in if length (x:xs) <= 1 
    then e 
    else e:computeKnapsack xs (weightLeft - floor (weightLeft/qud4 x) * qud4 x) 

我的變化是純粹的化妝品。即使經過我的更改,您的computeKnapsack功能仍然存在問題,算法錯誤,編碼風格不正確。

從重寫版本中可以看出,您的if語句有兩個分支,一個返回一個元組,另一個返回一個元組列表,另一個返回元組列表。你可以簡單地通過改變第一分支與單個元素返回一個列表修復:

computeKnapsack (x:xs) weightLeft = 
let e = (fst4 x, snd4 x, floor (weightLeft/qud4 x) * qud4 x) 
    in if length (x:xs) <= 1 
    then [e] 
    else e:computeKnapsack xs (weightLeft - floor (weightLeft/qud4 x) * qud4 x) 

此外,您提交第三個問題來StackOverflow上之前,請花時間來完成了Haskell簡明教程喜歡http://learnyouahaskell.com/這將有助於解決您的許多問題。

相關問題